diff --git a/apps/web/src/components/sections/hero.tsx b/apps/web/src/components/sections/hero.tsx
index 61bf38b3f5..97815208e9 100644
--- a/apps/web/src/components/sections/hero.tsx
+++ b/apps/web/src/components/sections/hero.tsx
@@ -1,7 +1,7 @@
-import Image from "next/image";
import { CtaButton } from "@/components/ui/cta-button";
import Announcement from "../hero/Announcement";
import Demo from "../hero/Demo";
+import SparklesText from "../ui/sparkles-text";
export default function Hero() {
return (
@@ -11,9 +11,30 @@ export default function Hero() {
Hypercharge Notetaking
-
- Hypnote is a smart notepad that upgrades your notes by automatically
- transcribing and analyzing the conversation
+
+
+ HYPRNOTE
+ {" "}
+ is a smart notepad 🗒️
+
+
+ that combines notes with
+
+
+
+ voice recordings
+
+
+
+
+
+ to create{" "}
+
+
diff --git a/apps/web/src/components/ui/header-button.tsx b/apps/web/src/components/ui/header-button.tsx
index 2687d638ec..28eb6838d0 100644
--- a/apps/web/src/components/ui/header-button.tsx
+++ b/apps/web/src/components/ui/header-button.tsx
@@ -44,14 +44,12 @@ export function HeaderButton({ className }: HeaderButtonProps) {
variant="outline"
size="default"
className={cn(
- "inline-flex items-center justify-center gap-2 transition-all duration-200 rounded-xl relative",
+ "inline-flex items-center justify-center gap-2 transition-all duration-200 rounded-xl border border-gray-300 hover:border-gray-400",
{
- "bg-gradient-to-br from-[#f97316] to-[#6366f1] text-white border-transparent before:opacity-100":
+ "bg-gradient-to-br from-[#fbbf24] to-[#2563eb] text-white":
isScrolled,
- "border border-gray-300 before:opacity-0": !isScrolled,
},
- "hover:bg-gradient-to-br hover:from-[#f97316] hover:to-[#6366f1] hover:text-white hover:border-transparent hover:before:opacity-100",
- "before:content-[''] before:absolute before:inset-[1px] before:rounded-[10px] before:border before:border-white/30 before:transition-opacity before:duration-200",
+ "hover:bg-gradient-to-br hover:from-[#fbbf24] hover:to-[#2563eb] hover:text-white",
className,
)}
>
diff --git a/apps/web/src/components/ui/sparkles-text.tsx b/apps/web/src/components/ui/sparkles-text.tsx
new file mode 100644
index 0000000000..8d3e8a4a89
--- /dev/null
+++ b/apps/web/src/components/ui/sparkles-text.tsx
@@ -0,0 +1,152 @@
+"use client";
+
+import { CSSProperties, ReactElement, useEffect, useState } from "react";
+import { motion } from "framer-motion";
+
+import { cn } from "@/lib/utils";
+
+interface Sparkle {
+ id: string;
+ x: string;
+ y: string;
+ color: string;
+ delay: number;
+ scale: number;
+ lifespan: number;
+}
+
+interface SparklesTextProps {
+ /**
+ * @default
+ * @type ReactElement
+ * @description
+ * The component to be rendered as the text
+ * */
+ as?: ReactElement;
+
+ /**
+ * @default ""
+ * @type string
+ * @description
+ * The className of the text
+ */
+ className?: string;
+
+ /**
+ * @required
+ * @type string
+ * @description
+ * The text to be displayed
+ * */
+ text: string;
+
+ /**
+ * @default 10
+ * @type number
+ * @description
+ * The count of sparkles
+ * */
+ sparklesCount?: number;
+
+ /**
+ * @default "{first: '#9E7AFF', second: '#FE8BBB'}"
+ * @type string
+ * @description
+ * The colors of the sparkles
+ * */
+ colors?: {
+ first: string;
+ second: string;
+ };
+}
+
+const SparklesText: React.FC = ({
+ text,
+ colors = { first: "#9E7AFF", second: "#FE8BBB" },
+ className,
+ sparklesCount = 10,
+ ...props
+}) => {
+ const [sparkles, setSparkles] = useState([]);
+
+ useEffect(() => {
+ const generateStar = (): Sparkle => {
+ const starX = `${Math.random() * 100}%`;
+ const starY = `${Math.random() * 100}%`;
+ const color = Math.random() > 0.5 ? colors.first : colors.second;
+ const delay = Math.random() * 2;
+ const scale = Math.random() * 1 + 0.3;
+ const lifespan = Math.random() * 10 + 5;
+ const id = `${starX}-${starY}-${Date.now()}`;
+ return { id, x: starX, y: starY, color, delay, scale, lifespan };
+ };
+
+ const initializeStars = () => {
+ const newSparkles = Array.from({ length: sparklesCount }, generateStar);
+ setSparkles(newSparkles);
+ };
+
+ const updateStars = () => {
+ setSparkles((currentSparkles) =>
+ currentSparkles.map((star) => {
+ if (star.lifespan <= 0) {
+ return generateStar();
+ } else {
+ return { ...star, lifespan: star.lifespan - 0.1 };
+ }
+ }),
+ );
+ };
+
+ initializeStars();
+ const interval = setInterval(updateStars, 100);
+
+ return () => clearInterval(interval);
+ }, [colors.first, colors.second]);
+
+ return (
+
+
+ {sparkles.map((sparkle) => (
+
+ ))}
+ {text}
+
+
+ );
+};
+
+const Sparkle: React.FC = ({ id, x, y, color, delay, scale }) => {
+ return (
+
+
+
+ );
+};
+
+export default SparklesText;
diff --git a/apps/web/src/styles/pushable-button.css b/apps/web/src/styles/pushable-button.css
index 03a340dc06..9991709f76 100644
--- a/apps/web/src/styles/pushable-button.css
+++ b/apps/web/src/styles/pushable-button.css
@@ -1,5 +1,5 @@
.pushable {
- background: linear-gradient(135deg, #7c2d12, #312e81);
+ background: linear-gradient(135deg, #f59e0b, #1e3a8a);
border: none;
border-radius: 12px;
padding: 0;
@@ -16,7 +16,7 @@
padding: 12px 42px;
border-radius: 12px;
font-size: 1.25rem;
- background: linear-gradient(135deg, #f97316, #6366f1);
+ background: linear-gradient(135deg, #fbbf24, #2563eb);
color: white;
transform: translateY(-6px);
transition: transform 50ms;
@@ -28,7 +28,7 @@
position: absolute;
inset: 1px;
border-radius: 11px;
- border: 1px solid rgba(255, 255, 255, 0.3);
+ border: 1px solid rgba(255, 255, 255, 0.4);
pointer-events: none;
}