From 5320e2a80144b5260ef0fb90aaaf12947f845cad Mon Sep 17 00:00:00 2001 From: John Jeong Date: Tue, 17 Dec 2024 12:48:26 +0900 Subject: [PATCH 1/6] removed mute and added play/pause with media listening --- apps/desktop/src/components/AudioControls.tsx | 67 +++++++++++++++++++ apps/desktop/src/pages/Login.tsx | 39 ++--------- 2 files changed, 72 insertions(+), 34 deletions(-) create mode 100644 apps/desktop/src/components/AudioControls.tsx diff --git a/apps/desktop/src/components/AudioControls.tsx b/apps/desktop/src/components/AudioControls.tsx new file mode 100644 index 0000000000..bfad43814f --- /dev/null +++ b/apps/desktop/src/components/AudioControls.tsx @@ -0,0 +1,67 @@ +import { useState, useEffect } from "react"; +import { RiPlayFill, RiPauseFill } from "@remixicon/react"; + +export const AudioControls = () => { + const [isPlaying, setIsPlaying] = useState(true); + const [audio] = useState(new Audio("/bgm.mp3")); + + useEffect(() => { + audio.loop = true; + audio.play().catch((error) => console.log("Audio autoplay failed:", error)); + + // Set up media session + if ("mediaSession" in navigator) { + navigator.mediaSession.metadata = new MediaMetadata({ + title: "Hypr Background Music", + artist: "Hypr", + album: "Hypr App", + }); + + navigator.mediaSession.setActionHandler("play", () => { + setIsPlaying(true); + audio.play(); + }); + + navigator.mediaSession.setActionHandler("pause", () => { + setIsPlaying(false); + audio.pause(); + }); + } + + return () => { + audio.pause(); + audio.currentTime = 0; + + // Clean up media session handlers + if ("mediaSession" in navigator) { + navigator.mediaSession.setActionHandler("play", null); + navigator.mediaSession.setActionHandler("pause", null); + } + }; + }, [audio]); + + useEffect(() => { + if (isPlaying) { + audio.play().catch((error) => console.log("Audio play failed:", error)); + if ("mediaSession" in navigator) { + navigator.mediaSession.playbackState = "playing"; + } + } else { + audio.pause(); + if ("mediaSession" in navigator) { + navigator.mediaSession.playbackState = "paused"; + } + } + }, [isPlaying, audio]); + + return ( +
+ +
+ ); +}; diff --git a/apps/desktop/src/pages/Login.tsx b/apps/desktop/src/pages/Login.tsx index 1b4321b92d..14e66ddb52 100644 --- a/apps/desktop/src/pages/Login.tsx +++ b/apps/desktop/src/pages/Login.tsx @@ -1,29 +1,10 @@ -import { useState, useEffect } from "react"; -import { - RiGoogleFill, - RiAppleFill, - RiVolumeMuteFill, - RiVolumeUpFill, -} from "@remixicon/react"; +import { RiGoogleFill, RiAppleFill } from "@remixicon/react"; import { RetroGrid } from "../components/ui/retro-grid.tsx"; +import { AudioControls } from "../components/AudioControls"; +import { useState } from "react"; const Login = () => { - const [isMuted, setIsMuted] = useState(false); - const [audio] = useState(new Audio("/bgm.mp3")); - - useEffect(() => { - audio.loop = true; - audio.play().catch((error) => console.log("Audio autoplay failed:", error)); - - return () => { - audio.pause(); - audio.currentTime = 0; - }; - }, [audio]); - - useEffect(() => { - audio.muted = isMuted; - }, [isMuted, audio]); + const [isPlaying, setIsPlaying] = useState(true); const handleGoogleSignIn = () => { // Implement Google Sign In @@ -38,17 +19,7 @@ const Login = () => { return (
- - +

Welcome to Hypr

From 3d2014fbfee9ca5b350a6fd06e70ca7387eb60f2 Mon Sep 17 00:00:00 2001 From: John Jeong Date: Tue, 17 Dec 2024 13:18:51 +0900 Subject: [PATCH 2/6] grid updated --- apps/desktop/package.json | 1 + apps/desktop/src/components/AudioControls.tsx | 9 +- apps/desktop/src/components/ui/blur-fade.tsx | 67 +++++++ apps/desktop/src/components/ui/retro-grid.tsx | 1 - .../src/components/ui/shimmer-button.tsx | 96 +++++++++ .../src/components/ui/sparkles-text.tsx | 151 ++++++++++++++ apps/desktop/src/pages/Login.tsx | 60 +++--- apps/desktop/src/styles/global.css | 2 + apps/desktop/tailwind.config.js | 189 ++++++++++-------- pnpm-lock.yaml | 13 ++ 10 files changed, 480 insertions(+), 109 deletions(-) create mode 100644 apps/desktop/src/components/ui/blur-fade.tsx create mode 100644 apps/desktop/src/components/ui/shimmer-button.tsx create mode 100644 apps/desktop/src/components/ui/sparkles-text.tsx diff --git a/apps/desktop/package.json b/apps/desktop/package.json index a0a61fc244..fab39fe87e 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -39,6 +39,7 @@ "date-fns": "^4.1.0", "embla-carousel": "^8.5.1", "embla-carousel-react": "^8.5.1", + "framer-motion": "^11.15.0", "lucide-react": "^0.468.0", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/apps/desktop/src/components/AudioControls.tsx b/apps/desktop/src/components/AudioControls.tsx index bfad43814f..74b2b308f3 100644 --- a/apps/desktop/src/components/AudioControls.tsx +++ b/apps/desktop/src/components/AudioControls.tsx @@ -15,6 +15,13 @@ export const AudioControls = () => { title: "Hypr Background Music", artist: "Hypr", album: "Hypr App", + artwork: [ + { + src: "/favicon.ico", + sizes: "96x96", + type: "image/png", + }, + ], }); navigator.mediaSession.setActionHandler("play", () => { @@ -55,7 +62,7 @@ export const AudioControls = () => { }, [isPlaying, audio]); return ( -
+
- {/* Background Gradient */}
diff --git a/apps/desktop/src/components/ui/shimmer-button.tsx b/apps/desktop/src/components/ui/shimmer-button.tsx new file mode 100644 index 0000000000..a8dfe00c98 --- /dev/null +++ b/apps/desktop/src/components/ui/shimmer-button.tsx @@ -0,0 +1,96 @@ +import React, { CSSProperties } from "react"; + +import { cn } from "../../lib/utils"; + +export interface ShimmerButtonProps + extends React.ButtonHTMLAttributes { + shimmerColor?: string; + shimmerSize?: string; + borderRadius?: string; + shimmerDuration?: string; + background?: string; + className?: string; + children?: React.ReactNode; +} + +const ShimmerButton = React.forwardRef( + ( + { + shimmerColor = "#ffffff", + shimmerSize = "0.05em", + shimmerDuration = "3s", + borderRadius = "100px", + background = "rgba(0, 0, 0, 1)", + className, + children, + ...props + }, + ref, + ) => { + return ( + + ); + }, +); + +ShimmerButton.displayName = "ShimmerButton"; + +export default ShimmerButton; diff --git a/apps/desktop/src/components/ui/sparkles-text.tsx b/apps/desktop/src/components/ui/sparkles-text.tsx new file mode 100644 index 0000000000..7d959820ca --- /dev/null +++ b/apps/desktop/src/components/ui/sparkles-text.tsx @@ -0,0 +1,151 @@ +"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/desktop/src/pages/Login.tsx b/apps/desktop/src/pages/Login.tsx index 14e66ddb52..328b1af655 100644 --- a/apps/desktop/src/pages/Login.tsx +++ b/apps/desktop/src/pages/Login.tsx @@ -1,11 +1,11 @@ import { RiGoogleFill, RiAppleFill } from "@remixicon/react"; import { RetroGrid } from "../components/ui/retro-grid.tsx"; import { AudioControls } from "../components/AudioControls"; -import { useState } from "react"; +import BlurFade from "../components/ui/blur-fade.tsx"; +import SparklesText from "../components/ui/sparkles-text.tsx"; +import ShimmerButton from "../components/ui/shimmer-button.tsx"; const Login = () => { - const [isPlaying, setIsPlaying] = useState(true); - const handleGoogleSignIn = () => { // Implement Google Sign In console.log("Google Sign In clicked"); @@ -17,28 +17,42 @@ const Login = () => { }; return ( -
- +
+ + -
-

Welcome to Hypr

- - - - +
+ +

+ Welcome to{" "} + +

+
+ +
+ + + Continue with Google + + + + + Continue with Apple + +
); diff --git a/apps/desktop/src/styles/global.css b/apps/desktop/src/styles/global.css index 9b3e9b4497..951e088a34 100644 --- a/apps/desktop/src/styles/global.css +++ b/apps/desktop/src/styles/global.css @@ -1,3 +1,5 @@ +@import url('https://fonts.googleapis.com/css2?family=Racing+Sans+One&display=swap'); + @tailwind base; @tailwind components; @tailwind utilities; diff --git a/apps/desktop/tailwind.config.js b/apps/desktop/tailwind.config.js index 96c4c46f7e..cdd608a90e 100644 --- a/apps/desktop/tailwind.config.js +++ b/apps/desktop/tailwind.config.js @@ -3,90 +3,111 @@ export default { darkMode: ["class"], content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"], theme: { - extend: { - colors: { - background: "hsl(var(--background))", - border: "hsl(var(--border))", - foreground: "hsl(var(--foreground))", - card: { - DEFAULT: "hsl(var(--card))", - foreground: "hsl(var(--card-foreground))", - }, - popover: { - DEFAULT: "hsl(var(--popover))", - foreground: "hsl(var(--popover-foreground))", - }, - primary: { - DEFAULT: "hsl(var(--primary))", - foreground: "hsl(var(--primary-foreground))", - }, - secondary: { - DEFAULT: "hsl(var(--secondary))", - foreground: "hsl(var(--secondary-foreground))", - }, - muted: { - DEFAULT: "hsl(var(--muted))", - foreground: "hsl(var(--muted-foreground))", - }, - accent: { - DEFAULT: "hsl(var(--accent))", - foreground: "hsl(var(--accent-foreground))", - }, - destructive: { - DEFAULT: "hsl(var(--destructive))", - foreground: "hsl(var(--destructive-foreground))", - }, - input: "hsl(var(--input))", - ring: "hsl(var(--ring))", - chart: { - 1: "hsl(var(--chart-1))", - 2: "hsl(var(--chart-2))", - 3: "hsl(var(--chart-3))", - 4: "hsl(var(--chart-4))", - 5: "hsl(var(--chart-5))", - }, - }, - fontFamily: { - sans: [ - "-apple-system", - "BlinkMacSystemFont", - "Apple SD Gothic Neo", - "Pretendard", - "system-ui", - "sans-serif", - ], - }, - keyframes: { - marquee: { - "0%": { - transform: "translateX(100%)", - }, - "100%": { - transform: "translateX(-100%)", - }, - }, - grid: { - "0%": { - transform: "translateY(-50%)", - }, - "100%": { - transform: "translateY(0)", - }, - }, - }, - animation: { - marquee: "marquee 10s linear infinite", - grid: "grid 15s linear infinite", - }, - transitionTimingFunction: { - "ease-in-out-expo": "cubic-bezier(0.87, 0, 0.13, 1)", - }, - borderRadius: { - lg: "var(--radius)", - md: "calc(var(--radius) - 2px)", - sm: "calc(var(--radius) - 4px)", - }, - }, + extend: { + colors: { + background: 'hsl(var(--background))', + border: 'hsl(var(--border))', + foreground: 'hsl(var(--foreground))', + card: { + DEFAULT: 'hsl(var(--card))', + foreground: 'hsl(var(--card-foreground))' + }, + popover: { + DEFAULT: 'hsl(var(--popover))', + foreground: 'hsl(var(--popover-foreground))' + }, + primary: { + DEFAULT: 'hsl(var(--primary))', + foreground: 'hsl(var(--primary-foreground))' + }, + secondary: { + DEFAULT: 'hsl(var(--secondary))', + foreground: 'hsl(var(--secondary-foreground))' + }, + muted: { + DEFAULT: 'hsl(var(--muted))', + foreground: 'hsl(var(--muted-foreground))' + }, + accent: { + DEFAULT: 'hsl(var(--accent))', + foreground: 'hsl(var(--accent-foreground))' + }, + destructive: { + DEFAULT: 'hsl(var(--destructive))', + foreground: 'hsl(var(--destructive-foreground))' + }, + input: 'hsl(var(--input))', + ring: 'hsl(var(--ring))', + chart: { + '1': 'hsl(var(--chart-1))', + '2': 'hsl(var(--chart-2))', + '3': 'hsl(var(--chart-3))', + '4': 'hsl(var(--chart-4))', + '5': 'hsl(var(--chart-5))' + } + }, + fontFamily: { + sans: [ + '-apple-system', + 'BlinkMacSystemFont', + 'Apple SD Gothic Neo', + 'Pretendard', + 'system-ui', + 'sans-serif' + ] + }, + keyframes: { + marquee: { + '0%': { + transform: 'translateX(100%)' + }, + '100%': { + transform: 'translateX(-100%)' + } + }, + grid: { + '0%': { + transform: 'translateY(-50%)' + }, + '100%': { + transform: 'translateY(0)' + } + }, + 'shimmer-slide': { + to: { + transform: 'translate(calc(100cqw - 100%), 0)' + } + }, + 'spin-around': { + '0%': { + transform: 'translateZ(0) rotate(0)' + }, + '15%, 35%': { + transform: 'translateZ(0) rotate(90deg)' + }, + '65%, 85%': { + transform: 'translateZ(0) rotate(270deg)' + }, + '100%': { + transform: 'translateZ(0) rotate(360deg)' + } + } + }, + animation: { + marquee: 'marquee 10s linear infinite', + grid: 'grid 15s linear infinite', + 'shimmer-slide': 'shimmer-slide var(--speed) ease-in-out infinite alternate', + 'spin-around': 'spin-around calc(var(--speed) * 2) infinite linear' + }, + transitionTimingFunction: { + 'ease-in-out-expo': 'cubic-bezier(0.87, 0, 0.13, 1)' + }, + borderRadius: { + lg: 'var(--radius)', + md: 'calc(var(--radius) - 2px)', + sm: 'calc(var(--radius) - 4px)' + } + } }, plugins: [require("@tailwindcss/typography"), require("tailwindcss-animate")], }; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 134b1a473f..3965239c57 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -92,6 +92,9 @@ importers: embla-carousel-react: specifier: ^8.5.1 version: 8.5.1(react@18.3.1) + framer-motion: + specifier: ^11.15.0 + version: 11.15.0(@emotion/is-prop-valid@0.8.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) lucide-react: specifier: ^0.468.0 version: 0.468.0(react@18.3.1) @@ -6089,6 +6092,16 @@ snapshots: fraction.js@4.3.7: {} + framer-motion@11.15.0(@emotion/is-prop-valid@0.8.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + motion-dom: 11.14.3 + motion-utils: 11.14.3 + tslib: 2.8.1 + optionalDependencies: + '@emotion/is-prop-valid': 0.8.8 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + framer-motion@11.15.0(@emotion/is-prop-valid@0.8.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0): dependencies: motion-dom: 11.14.3 From dcac389e4a297dfe952e4389f5a0bc6191fe06a9 Mon Sep 17 00:00:00 2001 From: John Jeong Date: Tue, 17 Dec 2024 13:38:11 +0900 Subject: [PATCH 3/6] login page is good --- apps/desktop/index.html | 2 +- apps/desktop/src-tauri/tauri.conf.json | 2 +- .../src/components/ui/sparkles-text.tsx | 11 +- apps/desktop/tailwind.config.js | 211 +++++++++--------- 4 files changed, 113 insertions(+), 113 deletions(-) diff --git a/apps/desktop/index.html b/apps/desktop/index.html index dc0606a57e..2a8e1dc271 100644 --- a/apps/desktop/index.html +++ b/apps/desktop/index.html @@ -7,7 +7,7 @@ name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /> - Hypr - AI Notepad for Meetings + Hypr - Smart Notepad for Meetings diff --git a/apps/desktop/src-tauri/tauri.conf.json b/apps/desktop/src-tauri/tauri.conf.json index 713c637a40..50087d5d47 100644 --- a/apps/desktop/src-tauri/tauri.conf.json +++ b/apps/desktop/src-tauri/tauri.conf.json @@ -15,7 +15,7 @@ "decorations": true, "height": 800, "width": 1200, - "title": "Hypr - AI Notepad for Meetings" + "title": "Hypr - Smart Notepad for Meetings" } ], "security": { diff --git a/apps/desktop/src/components/ui/sparkles-text.tsx b/apps/desktop/src/components/ui/sparkles-text.tsx index 7d959820ca..08f1ad5f69 100644 --- a/apps/desktop/src/components/ui/sparkles-text.tsx +++ b/apps/desktop/src/components/ui/sparkles-text.tsx @@ -118,7 +118,9 @@ const SparklesText: React.FC = ({ {sparkles.map((sparkle) => ( ))} - {text} + + {text} +
); @@ -133,17 +135,14 @@ const Sparkle: React.FC = ({ id, x, y, color, delay, scale }) => { animate={{ opacity: [0, 1, 0], scale: [0, scale, 0], - rotate: [75, 120, 150], + rotate: [-30, 0, 30], }} transition={{ duration: 0.8, repeat: Infinity, delay }} width="21" height="21" viewBox="0 0 21 21" > - + ); }; diff --git a/apps/desktop/tailwind.config.js b/apps/desktop/tailwind.config.js index cdd608a90e..e5c8fbe6d0 100644 --- a/apps/desktop/tailwind.config.js +++ b/apps/desktop/tailwind.config.js @@ -3,111 +3,112 @@ export default { darkMode: ["class"], content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"], theme: { - extend: { - colors: { - background: 'hsl(var(--background))', - border: 'hsl(var(--border))', - foreground: 'hsl(var(--foreground))', - card: { - DEFAULT: 'hsl(var(--card))', - foreground: 'hsl(var(--card-foreground))' - }, - popover: { - DEFAULT: 'hsl(var(--popover))', - foreground: 'hsl(var(--popover-foreground))' - }, - primary: { - DEFAULT: 'hsl(var(--primary))', - foreground: 'hsl(var(--primary-foreground))' - }, - secondary: { - DEFAULT: 'hsl(var(--secondary))', - foreground: 'hsl(var(--secondary-foreground))' - }, - muted: { - DEFAULT: 'hsl(var(--muted))', - foreground: 'hsl(var(--muted-foreground))' - }, - accent: { - DEFAULT: 'hsl(var(--accent))', - foreground: 'hsl(var(--accent-foreground))' - }, - destructive: { - DEFAULT: 'hsl(var(--destructive))', - foreground: 'hsl(var(--destructive-foreground))' - }, - input: 'hsl(var(--input))', - ring: 'hsl(var(--ring))', - chart: { - '1': 'hsl(var(--chart-1))', - '2': 'hsl(var(--chart-2))', - '3': 'hsl(var(--chart-3))', - '4': 'hsl(var(--chart-4))', - '5': 'hsl(var(--chart-5))' - } - }, - fontFamily: { - sans: [ - '-apple-system', - 'BlinkMacSystemFont', - 'Apple SD Gothic Neo', - 'Pretendard', - 'system-ui', - 'sans-serif' - ] - }, - keyframes: { - marquee: { - '0%': { - transform: 'translateX(100%)' - }, - '100%': { - transform: 'translateX(-100%)' - } - }, - grid: { - '0%': { - transform: 'translateY(-50%)' - }, - '100%': { - transform: 'translateY(0)' - } - }, - 'shimmer-slide': { - to: { - transform: 'translate(calc(100cqw - 100%), 0)' - } - }, - 'spin-around': { - '0%': { - transform: 'translateZ(0) rotate(0)' - }, - '15%, 35%': { - transform: 'translateZ(0) rotate(90deg)' - }, - '65%, 85%': { - transform: 'translateZ(0) rotate(270deg)' - }, - '100%': { - transform: 'translateZ(0) rotate(360deg)' - } - } - }, - animation: { - marquee: 'marquee 10s linear infinite', - grid: 'grid 15s linear infinite', - 'shimmer-slide': 'shimmer-slide var(--speed) ease-in-out infinite alternate', - 'spin-around': 'spin-around calc(var(--speed) * 2) infinite linear' - }, - transitionTimingFunction: { - 'ease-in-out-expo': 'cubic-bezier(0.87, 0, 0.13, 1)' - }, - borderRadius: { - lg: 'var(--radius)', - md: 'calc(var(--radius) - 2px)', - sm: 'calc(var(--radius) - 4px)' - } - } + extend: { + colors: { + background: "hsl(var(--background))", + border: "hsl(var(--border))", + foreground: "hsl(var(--foreground))", + card: { + DEFAULT: "hsl(var(--card))", + foreground: "hsl(var(--card-foreground))", + }, + popover: { + DEFAULT: "hsl(var(--popover))", + foreground: "hsl(var(--popover-foreground))", + }, + primary: { + DEFAULT: "hsl(var(--primary))", + foreground: "hsl(var(--primary-foreground))", + }, + secondary: { + DEFAULT: "hsl(var(--secondary))", + foreground: "hsl(var(--secondary-foreground))", + }, + muted: { + DEFAULT: "hsl(var(--muted))", + foreground: "hsl(var(--muted-foreground))", + }, + accent: { + DEFAULT: "hsl(var(--accent))", + foreground: "hsl(var(--accent-foreground))", + }, + destructive: { + DEFAULT: "hsl(var(--destructive))", + foreground: "hsl(var(--destructive-foreground))", + }, + input: "hsl(var(--input))", + ring: "hsl(var(--ring))", + chart: { + 1: "hsl(var(--chart-1))", + 2: "hsl(var(--chart-2))", + 3: "hsl(var(--chart-3))", + 4: "hsl(var(--chart-4))", + 5: "hsl(var(--chart-5))", + }, + }, + fontFamily: { + sans: [ + "-apple-system", + "BlinkMacSystemFont", + "Apple SD Gothic Neo", + "Pretendard", + "system-ui", + "sans-serif", + ], + }, + keyframes: { + marquee: { + "0%": { + transform: "translateX(100%)", + }, + "100%": { + transform: "translateX(-100%)", + }, + }, + grid: { + "0%": { + transform: "translateY(-50%)", + }, + "100%": { + transform: "translateY(0)", + }, + }, + "shimmer-slide": { + to: { + transform: "translate(calc(100cqw - 100%), 0)", + }, + }, + "spin-around": { + "0%": { + transform: "translateZ(0) rotate(0)", + }, + "15%, 35%": { + transform: "translateZ(0) rotate(90deg)", + }, + "65%, 85%": { + transform: "translateZ(0) rotate(270deg)", + }, + "100%": { + transform: "translateZ(0) rotate(360deg)", + }, + }, + }, + animation: { + marquee: "marquee 10s linear infinite", + grid: "grid 15s linear infinite", + "shimmer-slide": + "shimmer-slide var(--speed) ease-in-out infinite alternate", + "spin-around": "spin-around calc(var(--speed) * 2) infinite linear", + }, + transitionTimingFunction: { + "ease-in-out-expo": "cubic-bezier(0.87, 0, 0.13, 1)", + }, + borderRadius: { + lg: "var(--radius)", + md: "calc(var(--radius) - 2px)", + sm: "calc(var(--radius) - 4px)", + }, + }, }, plugins: [require("@tailwindcss/typography"), require("tailwindcss-animate")], }; From 0f74006b20d5cf25720f627a70ef7e896a4056fc Mon Sep 17 00:00:00 2001 From: John Jeong Date: Tue, 17 Dec 2024 17:41:12 +0900 Subject: [PATCH 4/6] wip - landing page --- apps/web/package.json | 1 - apps/web/src/app/globals.css | 68 ++++++++ apps/web/src/components/hero/Announcement.tsx | 12 ++ apps/web/src/components/hero/Demo.tsx | 47 ++++++ apps/web/src/components/hero/LogoCard.tsx | 8 + apps/web/src/components/sections/cta.tsx | 5 +- apps/web/src/components/sections/hero.tsx | 43 +----- apps/web/src/components/sections/pricing.tsx | 66 ++++---- .../components/ui/animated-gradient-text.tsx | 25 +++ apps/web/src/components/ui/button.tsx | 31 ++-- apps/web/src/components/ui/cta-button.tsx | 2 +- apps/web/src/components/ui/header-button.tsx | 11 +- apps/web/src/components/ui/marquee.tsx | 51 ++++++ .../web/src/components/ui/pushable-button.tsx | 6 +- apps/web/src/components/ui/word-rotate.tsx | 49 ++++++ apps/web/src/data/logoData.ts | 8 + apps/web/tailwind.config.ts | 145 ++++++++++++------ pnpm-lock.yaml | 8 - 18 files changed, 439 insertions(+), 147 deletions(-) create mode 100644 apps/web/src/components/hero/Announcement.tsx create mode 100644 apps/web/src/components/hero/Demo.tsx create mode 100644 apps/web/src/components/hero/LogoCard.tsx create mode 100644 apps/web/src/components/ui/animated-gradient-text.tsx create mode 100644 apps/web/src/components/ui/marquee.tsx create mode 100644 apps/web/src/components/ui/word-rotate.tsx create mode 100644 apps/web/src/data/logoData.ts diff --git a/apps/web/package.json b/apps/web/package.json index 674a9c00ca..7d4234b9f6 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -18,7 +18,6 @@ "@remixicon/react": "^4.5.0", "@types/mdx": "^2.0.13", "class-variance-authority": "^0.7.1", - "classnames": "^2.5.1", "clsx": "^2.0.0", "framer-motion": "^11.15.0", "next": "15.1.0", diff --git a/apps/web/src/app/globals.css b/apps/web/src/app/globals.css index c3a7bf1dac..45648ad692 100644 --- a/apps/web/src/app/globals.css +++ b/apps/web/src/app/globals.css @@ -4,13 +4,72 @@ @layer base { :root { + --background: 0 0% 100%; + --foreground: 222.2 84% 4.9%; + + --card: 0 0% 100%; + --card-foreground: 222.2 84% 4.9%; + + --popover: 0 0% 100%; + --popover-foreground: 222.2 84% 4.9%; + + --primary: 222.2 47.4% 11.2%; + --primary-foreground: 210 40% 98%; + + --secondary: 210 40% 96.1%; + --secondary-foreground: 222.2 47.4% 11.2%; + + --muted: 210 40% 96.1%; + --muted-foreground: 215.4 16.3% 46.9%; + + --accent: 210 40% 96.1%; + --accent-foreground: 222.2 47.4% 11.2%; + + --destructive: 0 84.2% 60.2%; + --destructive-foreground: 210 40% 98%; + + --border: 214.3 31.8% 91.4%; + --input: 214.3 31.8% 91.4%; + --ring: 222.2 84% 4.9%; + + --radius: 0.5rem; + --color-1: 0 100% 63%; --color-2: 270 100% 63%; --color-3: 210 100% 63%; --color-4: 195 100% 63%; --color-5: 90 100% 63%; } + .dark { + --background: 222.2 84% 4.9%; + --foreground: 210 40% 98%; + + --card: 222.2 84% 4.9%; + --card-foreground: 210 40% 98%; + + --popover: 222.2 84% 4.9%; + --popover-foreground: 210 40% 98%; + + --primary: 210 40% 98%; + --primary-foreground: 222.2 47.4% 11.2%; + + --secondary: 217.2 32.6% 17.5%; + --secondary-foreground: 210 40% 98%; + + --muted: 217.2 32.6% 17.5%; + --muted-foreground: 215 20.2% 65.1%; + + --accent: 217.2 32.6% 17.5%; + --accent-foreground: 210 40% 98%; + + --destructive: 0 62.8% 30.6%; + --destructive-foreground: 210 40% 98%; + + --border: 217.2 32.6% 17.5%; + --input: 217.2 32.6% 17.5%; + --ring: 212.7 26.8% 83.9%; + --color-1: 0 100% 63%; --color-2: 270 100% 63%; --color-3: 210 100% 63%; @@ -18,3 +77,12 @@ --color-5: 90 100% 63%; } } + +@layer base { + * { + @apply border-border; + } + body { + @apply bg-background text-foreground; + } +} diff --git a/apps/web/src/components/hero/Announcement.tsx b/apps/web/src/components/hero/Announcement.tsx new file mode 100644 index 0000000000..dffab570d6 --- /dev/null +++ b/apps/web/src/components/hero/Announcement.tsx @@ -0,0 +1,12 @@ +import AnimatedGradientText from "../ui/animated-gradient-text"; + +export default function Announcement() { + return ( + + ⚡️ + + Hyprnote is now in public beta! + + + ); +} diff --git a/apps/web/src/components/hero/Demo.tsx b/apps/web/src/components/hero/Demo.tsx new file mode 100644 index 0000000000..e481a43c48 --- /dev/null +++ b/apps/web/src/components/hero/Demo.tsx @@ -0,0 +1,47 @@ +export default function Demo() { + return ( +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+ ); +} diff --git a/apps/web/src/components/hero/LogoCard.tsx b/apps/web/src/components/hero/LogoCard.tsx new file mode 100644 index 0000000000..ebcdedb51b --- /dev/null +++ b/apps/web/src/components/hero/LogoCard.tsx @@ -0,0 +1,8 @@ +export default function LogoCard() { + return ( +
+ logo +

R

+
+ ); +} diff --git a/apps/web/src/components/sections/cta.tsx b/apps/web/src/components/sections/cta.tsx index 8a2402e9ec..0c0f422fcf 100644 --- a/apps/web/src/components/sections/cta.tsx +++ b/apps/web/src/components/sections/cta.tsx @@ -5,11 +5,10 @@ export default function CtaSection() {

- Ready to transform your meeting notes? + Start Typing Now

- Join thousands of professionals who are already using HyprNote to - capture and understand their meetings better. + Take notes smarter, faster, and more efficiently

diff --git a/apps/web/src/components/sections/hero.tsx b/apps/web/src/components/sections/hero.tsx index ee95462ef9..61bf38b3f5 100644 --- a/apps/web/src/components/sections/hero.tsx +++ b/apps/web/src/components/sections/hero.tsx @@ -1,51 +1,24 @@ import Image from "next/image"; import { CtaButton } from "@/components/ui/cta-button"; +import Announcement from "../hero/Announcement"; +import Demo from "../hero/Demo"; export default function Hero() { return (
-
- - Now with offline support for English -
+ -

- Your AI Meeting Assistant - - that actually understands your conversations - -

+

Hypercharge Notetaking

-

- HyprNote uses advanced AI to capture every detail of your meetings, - lectures, and video calls. Get instant summaries, action items, and - searchable transcripts - all without inviting any bots. +

+ Hypnote is a smart notepad that upgrades your notes by automatically + transcribing and analyzing the conversation

-
- HyprNote Interface -
- -
-

- Trusted by innovative teams at -

-
- Stanford - MIT - Harvard -
-
+
); diff --git a/apps/web/src/components/sections/pricing.tsx b/apps/web/src/components/sections/pricing.tsx index 7c43e85bd6..07062fcdfe 100644 --- a/apps/web/src/components/sections/pricing.tsx +++ b/apps/web/src/components/sections/pricing.tsx @@ -18,12 +18,12 @@ interface BillingPlan { export default function Pricing() { const [billingCycle, setBillingCycle] = useState<"monthly" | "yearly">( - "monthly", + "monthly" ); const [currentPlan, setCurrentPlan] = useState<"Free" | "Pro" | "Business">( - "Free", + "Free" ); - const [daysLeft, setDaysLeft] = useState(14); // 남은 무료 사용 기간 (일) + const [daysLeft, setDaysLeft] = useState(14); // Remaining free trial days const billingPlans: BillingPlan[] = [ { @@ -34,11 +34,11 @@ export default function Pricing() { yearly: 0, }, features: [ - // 1. 기본 기능 - "노트 작성 및 편집", - "영어 음성 인식", - "기본 AI 기능", - "2주 무료 체험", + // 1. Basic features + "Note creation and editing", + "English speech recognition", + "Basic AI features", + "2-week free trial", ], }, { @@ -49,14 +49,14 @@ export default function Pricing() { yearly: 8, }, features: [ - // 2. 고급 기능 - "무제한 음성 인식", - "다국어 지원", - "오프라인 모드 (영어)", - "고급 AI 기능", - // 3. 협업 기능 - "노트 공유 링크", - "앱 연동 (노션, 슬랙 등)", + // 2. Advanced features + "Unlimited speech recognition", + "Multi-language support", + "Offline mode (English)", + "Advanced AI features", + // 3. Collaboration features + "Note sharing links", + "App integrations (Notion, Slack, etc.)", ], }, { @@ -67,15 +67,15 @@ export default function Pricing() { yearly: 12, }, features: [ - // 1. Pro 기능 포함 - "Pro 플랜의 모든 기능", - // 2. 팀 기능 - "팀 워크스페이스", - "상세 접근 권한 설정", - "공유 노트 수정 권한", - // 3. 관리 기능 - "팀 단위 결제", - "사용 현황 대시보드", + // 1. Including Pro features + "All Pro plan features", + // 2. Team features + "Team workspace", + "Detailed access control", + "Shared note editing permissions", + // 3. Management features + "Team billing", + "Usage dashboard", ], isComingSoon: true, }, @@ -84,16 +84,16 @@ export default function Pricing() { const getButtonText = ( planLevel: number, currentLevel: number, - planType: "Free" | "Pro" | "Business", + planType: "Free" | "Pro" | "Business" ) => { if (planType === "Free" && currentPlan === "Free") { if (daysLeft > 0) { - return `${daysLeft}일 남음`; + return `${daysLeft} days left`; } - return "기간 만료"; + return "Trial expired"; } - if (planLevel === currentLevel) return "사용중"; - return planLevel > currentLevel ? "업그레이드" : "다운그레이드"; + if (planLevel === currentLevel) return "Current plan"; + return planLevel > currentLevel ? "Upgrade" : "Downgrade"; }; const getPlanLevel = (planType: "Free" | "Pro" | "Business") => { @@ -152,7 +152,7 @@ export default function Pricing() { )} {currentPlan === plan.type && !plan.isComingSoon && ( - 현재 플랜 + Current Plan )} @@ -166,7 +166,7 @@ export default function Pricing() { ] } - /월 + /month
); -}; +} export default PushableButton; diff --git a/apps/web/src/components/ui/word-rotate.tsx b/apps/web/src/components/ui/word-rotate.tsx new file mode 100644 index 0000000000..3df340ef11 --- /dev/null +++ b/apps/web/src/components/ui/word-rotate.tsx @@ -0,0 +1,49 @@ +"use client"; + +import { useEffect, useState } from "react"; +import { AnimatePresence, HTMLMotionProps, motion } from "framer-motion"; +import { cn } from "@/lib/utils"; + +interface WordRotateProps { + words: string[]; + duration?: number; + framerProps?: HTMLMotionProps<"span">; + className?: string; +} + +export default function WordRotate({ + words, + duration = 2500, + framerProps = { + initial: { opacity: 0, y: -50 }, + animate: { opacity: 1, y: 0 }, + exit: { opacity: 0, y: 50 }, + transition: { duration: 0.25, ease: "easeOut" }, + }, + className, +}: WordRotateProps) { + const [index, setIndex] = useState(0); + + useEffect(() => { + const interval = setInterval(() => { + setIndex((prevIndex) => (prevIndex + 1) % words.length); + }, duration); + + // Clean up interval on unmount + return () => clearInterval(interval); + }, [words, duration]); + + return ( +
+ + + {words[index]} + + +
+ ); +} diff --git a/apps/web/src/data/logoData.ts b/apps/web/src/data/logoData.ts new file mode 100644 index 0000000000..717c9b12ce --- /dev/null +++ b/apps/web/src/data/logoData.ts @@ -0,0 +1,8 @@ +export const universities = [ + { title: "UC Berkeley", file: "BerkeleyIcon" }, + { title: "Stanford", file: "StanfordIcon" }, + { title: "UC Berkeley", file: "BerkeleyIcon" }, + { title: "UC Berkeley", file: "BerkeleyIcon" }, + { title: "UC Berkeley", file: "BerkeleyIcon" }, + { title: "UC Berkeley", file: "BerkeleyIcon" }, +]; diff --git a/apps/web/tailwind.config.ts b/apps/web/tailwind.config.ts index 8030867755..c4fe1d0f3f 100644 --- a/apps/web/tailwind.config.ts +++ b/apps/web/tailwind.config.ts @@ -8,82 +8,137 @@ export default { "./src/app/**/*.{js,ts,jsx,tsx,mdx}", ], theme: { + container: { + center: true, + padding: "2rem", + screens: { + "2xl": "1400px", + }, + }, extend: { colors: { - background: "hsl(var(--background))", - foreground: "hsl(var(--foreground))", + background: 'hsl(var(--background))', + foreground: 'hsl(var(--foreground))', card: { - DEFAULT: "hsl(var(--card))", - foreground: "hsl(var(--card-foreground))", + DEFAULT: 'hsl(var(--card))', + foreground: 'hsl(var(--card-foreground))' }, popover: { - DEFAULT: "hsl(var(--popover))", - foreground: "hsl(var(--popover-foreground))", + DEFAULT: 'hsl(var(--popover))', + foreground: 'hsl(var(--popover-foreground))' }, primary: { - DEFAULT: "hsl(var(--primary))", - foreground: "hsl(var(--primary-foreground))", + DEFAULT: 'hsl(var(--primary))', + foreground: 'hsl(var(--primary-foreground))' }, secondary: { - DEFAULT: "hsl(var(--secondary))", - foreground: "hsl(var(--secondary-foreground))", + DEFAULT: 'hsl(var(--secondary))', + foreground: 'hsl(var(--secondary-foreground))' }, muted: { - DEFAULT: "hsl(var(--muted))", - foreground: "hsl(var(--muted-foreground))", + DEFAULT: 'hsl(var(--muted))', + foreground: 'hsl(var(--muted-foreground))' }, accent: { - DEFAULT: "hsl(var(--accent))", - foreground: "hsl(var(--accent-foreground))", + DEFAULT: 'hsl(var(--accent))', + foreground: 'hsl(var(--accent-foreground))' }, destructive: { - DEFAULT: "hsl(var(--destructive))", - foreground: "hsl(var(--destructive-foreground))", + DEFAULT: 'hsl(var(--destructive))', + foreground: 'hsl(var(--destructive-foreground))' }, - border: "hsl(var(--border))", - input: "hsl(var(--input))", - ring: "hsl(var(--ring))", + border: 'hsl(var(--border))', + input: 'hsl(var(--input))', + ring: 'hsl(var(--ring))', chart: { - "1": "hsl(var(--chart-1))", - "2": "hsl(var(--chart-2))", - "3": "hsl(var(--chart-3))", - "4": "hsl(var(--chart-4))", - "5": "hsl(var(--chart-5))", - }, - "color-1": "hsl(var(--color-1))", - "color-2": "hsl(var(--color-2))", - "color-3": "hsl(var(--color-3))", - "color-4": "hsl(var(--color-4))", - "color-5": "hsl(var(--color-5))", + '1': 'hsl(var(--chart-1))', + '2': 'hsl(var(--chart-2))', + '3': 'hsl(var(--chart-3))', + '4': 'hsl(var(--chart-4))', + '5': 'hsl(var(--chart-5))' + }, + 'color-1': 'hsl(var(--color-1))', + 'color-2': 'hsl(var(--color-2))', + 'color-3': 'hsl(var(--color-3))', + 'color-4': 'hsl(var(--color-4))', + 'color-5': 'hsl(var(--color-5))' }, borderRadius: { - lg: "var(--radius)", - md: "calc(var(--radius) - 2px)", - sm: "calc(var(--radius) - 4px)", + lg: 'var(--radius)', + md: 'calc(var(--radius) - 2px)', + sm: 'calc(var(--radius) - 4px)' }, fontFamily: { - "racing-sans": ["var(--font-racing-sans)"], + 'racing-sans': [ + 'var(--font-racing-sans)' + ] }, animation: { - pulse: "pulse var(--duration) ease-out infinite", - rainbow: "rainbow var(--speed, 2s) infinite linear", + pulse: 'pulse var(--duration) ease-out infinite', + rainbow: 'rainbow var(--speed, 2s) infinite linear', + gradient: 'gradient 8s linear infinite', + marquee: 'marquee var(--duration) infinite linear', + 'marquee-vertical': 'marquee-vertical var(--duration) linear infinite', + "accordion-down": "accordion-down 0.2s ease-out", + "accordion-up": "accordion-up 0.2s ease-out", }, keyframes: { pulse: { - "0%, 100%": { - boxShadow: "0 0 0 0 var(--pulse-color)", - }, - "50%": { - boxShadow: "0 0 0 8px var(--pulse-color)", + '0%, 100%': { + boxShadow: '0 0 0 0 var(--pulse-color)' }, + '50%': { + boxShadow: '0 0 0 8px var(--pulse-color)' + } }, rainbow: { - "0%": { - "background-position": "0%", + '0%': { + 'background-position': '0%' + }, + '100%': { + 'background-position': '200%' + } + }, + gradient: { + to: { + backgroundPosition: 'var(--bg-size) 0' + } + }, + marquee: { + from: { + transform: 'translateX(0)' }, - "100%": { - "background-position": "200%", + to: { + transform: 'translateX(calc(-100% - var(--gap)))' + } + }, + 'marquee-vertical': { + from: { + transform: 'translateY(0)' }, + to: { + transform: 'translateY(calc(-100% - var(--gap)))' + } + }, + "accordion-down": { + from: { height: "0" }, + to: { height: "var(--radix-accordion-content-height)" }, + }, + "accordion-up": { + from: { height: "var(--radix-accordion-content-height)" }, + to: { height: "0" }, + }, + } + }, + components: { + button: { + padding: '0.5rem 1rem', + borderRadius: 'var(--radius)', + fontWeight: '500', + cursor: 'pointer', + disabled: { + opacity: 0.5, + cursor: 'not-allowed', }, }, }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3965239c57..ed9a92b143 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -189,9 +189,6 @@ importers: class-variance-authority: specifier: ^0.7.1 version: 0.7.1 - classnames: - specifier: ^2.5.1 - version: 2.5.1 clsx: specifier: ^2.0.0 version: 2.1.1 @@ -1909,9 +1906,6 @@ packages: class-variance-authority@0.7.1: resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==} - classnames@2.5.1: - resolution: {integrity: sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==} - client-only@0.0.1: resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} @@ -5506,8 +5500,6 @@ snapshots: dependencies: clsx: 2.1.1 - classnames@2.5.1: {} - client-only@0.0.1: {} clsx@2.1.1: {} From 2d50eff286c4af8d82df284cb6108ca405b82dd7 Mon Sep 17 00:00:00 2001 From: yujonglee Date: Tue, 17 Dec 2024 19:07:08 +0900 Subject: [PATCH 5/6] format --- .../src/components/ui/shimmer-button.tsx | 4 +- apps/desktop/src/styles/global.css | 2 +- apps/web/src/components/sections/pricing.tsx | 8 +- .../components/ui/animated-gradient-text.tsx | 2 +- apps/web/src/components/ui/button.tsx | 2 +- apps/web/src/components/ui/header-button.tsx | 2 +- apps/web/tailwind.config.ts | 130 +++++++++--------- 7 files changed, 74 insertions(+), 76 deletions(-) diff --git a/apps/desktop/src/components/ui/shimmer-button.tsx b/apps/desktop/src/components/ui/shimmer-button.tsx index a8dfe00c98..8aacad5fd2 100644 --- a/apps/desktop/src/components/ui/shimmer-button.tsx +++ b/apps/desktop/src/components/ui/shimmer-button.tsx @@ -55,9 +55,9 @@ const ShimmerButton = React.forwardRef( )} > {/* spark */} -
+
{/* spark before */} -
+
{children} diff --git a/apps/desktop/src/styles/global.css b/apps/desktop/src/styles/global.css index 951e088a34..d48d503e2b 100644 --- a/apps/desktop/src/styles/global.css +++ b/apps/desktop/src/styles/global.css @@ -1,4 +1,4 @@ -@import url('https://fonts.googleapis.com/css2?family=Racing+Sans+One&display=swap'); +@import url("https://fonts.googleapis.com/css2?family=Racing+Sans+One&display=swap"); @tailwind base; @tailwind components; diff --git a/apps/web/src/components/sections/pricing.tsx b/apps/web/src/components/sections/pricing.tsx index 07062fcdfe..b271ebf2a1 100644 --- a/apps/web/src/components/sections/pricing.tsx +++ b/apps/web/src/components/sections/pricing.tsx @@ -18,10 +18,10 @@ interface BillingPlan { export default function Pricing() { const [billingCycle, setBillingCycle] = useState<"monthly" | "yearly">( - "monthly" + "monthly", ); const [currentPlan, setCurrentPlan] = useState<"Free" | "Pro" | "Business">( - "Free" + "Free", ); const [daysLeft, setDaysLeft] = useState(14); // Remaining free trial days @@ -84,7 +84,7 @@ export default function Pricing() { const getButtonText = ( planLevel: number, currentLevel: number, - planType: "Free" | "Pro" | "Business" + planType: "Free" | "Pro" | "Business", ) => { if (planType === "Free" && currentPlan === "Free") { if (daysLeft > 0) { @@ -180,7 +180,7 @@ export default function Pricing() { {getButtonText( plan.level, getPlanLevel(currentPlan), - plan.type + plan.type, )} diff --git a/apps/web/src/components/ui/animated-gradient-text.tsx b/apps/web/src/components/ui/animated-gradient-text.tsx index e3bb6882a5..cf42d9ad33 100644 --- a/apps/web/src/components/ui/animated-gradient-text.tsx +++ b/apps/web/src/components/ui/animated-gradient-text.tsx @@ -12,7 +12,7 @@ export default function AnimatedGradientText({
{os === "Windows" diff --git a/apps/web/tailwind.config.ts b/apps/web/tailwind.config.ts index c4fe1d0f3f..dc232a724b 100644 --- a/apps/web/tailwind.config.ts +++ b/apps/web/tailwind.config.ts @@ -17,108 +17,106 @@ export default { }, extend: { colors: { - background: 'hsl(var(--background))', - foreground: 'hsl(var(--foreground))', + background: "hsl(var(--background))", + foreground: "hsl(var(--foreground))", card: { - DEFAULT: 'hsl(var(--card))', - foreground: 'hsl(var(--card-foreground))' + DEFAULT: "hsl(var(--card))", + foreground: "hsl(var(--card-foreground))", }, popover: { - DEFAULT: 'hsl(var(--popover))', - foreground: 'hsl(var(--popover-foreground))' + DEFAULT: "hsl(var(--popover))", + foreground: "hsl(var(--popover-foreground))", }, primary: { - DEFAULT: 'hsl(var(--primary))', - foreground: 'hsl(var(--primary-foreground))' + DEFAULT: "hsl(var(--primary))", + foreground: "hsl(var(--primary-foreground))", }, secondary: { - DEFAULT: 'hsl(var(--secondary))', - foreground: 'hsl(var(--secondary-foreground))' + DEFAULT: "hsl(var(--secondary))", + foreground: "hsl(var(--secondary-foreground))", }, muted: { - DEFAULT: 'hsl(var(--muted))', - foreground: 'hsl(var(--muted-foreground))' + DEFAULT: "hsl(var(--muted))", + foreground: "hsl(var(--muted-foreground))", }, accent: { - DEFAULT: 'hsl(var(--accent))', - foreground: 'hsl(var(--accent-foreground))' + DEFAULT: "hsl(var(--accent))", + foreground: "hsl(var(--accent-foreground))", }, destructive: { - DEFAULT: 'hsl(var(--destructive))', - foreground: 'hsl(var(--destructive-foreground))' + DEFAULT: "hsl(var(--destructive))", + foreground: "hsl(var(--destructive-foreground))", }, - border: 'hsl(var(--border))', - input: 'hsl(var(--input))', - ring: 'hsl(var(--ring))', + border: "hsl(var(--border))", + input: "hsl(var(--input))", + ring: "hsl(var(--ring))", chart: { - '1': 'hsl(var(--chart-1))', - '2': 'hsl(var(--chart-2))', - '3': 'hsl(var(--chart-3))', - '4': 'hsl(var(--chart-4))', - '5': 'hsl(var(--chart-5))' - }, - 'color-1': 'hsl(var(--color-1))', - 'color-2': 'hsl(var(--color-2))', - 'color-3': 'hsl(var(--color-3))', - 'color-4': 'hsl(var(--color-4))', - 'color-5': 'hsl(var(--color-5))' + "1": "hsl(var(--chart-1))", + "2": "hsl(var(--chart-2))", + "3": "hsl(var(--chart-3))", + "4": "hsl(var(--chart-4))", + "5": "hsl(var(--chart-5))", + }, + "color-1": "hsl(var(--color-1))", + "color-2": "hsl(var(--color-2))", + "color-3": "hsl(var(--color-3))", + "color-4": "hsl(var(--color-4))", + "color-5": "hsl(var(--color-5))", }, borderRadius: { - lg: 'var(--radius)', - md: 'calc(var(--radius) - 2px)', - sm: 'calc(var(--radius) - 4px)' + lg: "var(--radius)", + md: "calc(var(--radius) - 2px)", + sm: "calc(var(--radius) - 4px)", }, fontFamily: { - 'racing-sans': [ - 'var(--font-racing-sans)' - ] + "racing-sans": ["var(--font-racing-sans)"], }, animation: { - pulse: 'pulse var(--duration) ease-out infinite', - rainbow: 'rainbow var(--speed, 2s) infinite linear', - gradient: 'gradient 8s linear infinite', - marquee: 'marquee var(--duration) infinite linear', - 'marquee-vertical': 'marquee-vertical var(--duration) linear infinite', + pulse: "pulse var(--duration) ease-out infinite", + rainbow: "rainbow var(--speed, 2s) infinite linear", + gradient: "gradient 8s linear infinite", + marquee: "marquee var(--duration) infinite linear", + "marquee-vertical": "marquee-vertical var(--duration) linear infinite", "accordion-down": "accordion-down 0.2s ease-out", "accordion-up": "accordion-up 0.2s ease-out", }, keyframes: { pulse: { - '0%, 100%': { - boxShadow: '0 0 0 0 var(--pulse-color)' + "0%, 100%": { + boxShadow: "0 0 0 0 var(--pulse-color)", + }, + "50%": { + boxShadow: "0 0 0 8px var(--pulse-color)", }, - '50%': { - boxShadow: '0 0 0 8px var(--pulse-color)' - } }, rainbow: { - '0%': { - 'background-position': '0%' + "0%": { + "background-position": "0%", + }, + "100%": { + "background-position": "200%", }, - '100%': { - 'background-position': '200%' - } }, gradient: { to: { - backgroundPosition: 'var(--bg-size) 0' - } + backgroundPosition: "var(--bg-size) 0", + }, }, marquee: { from: { - transform: 'translateX(0)' + transform: "translateX(0)", }, to: { - transform: 'translateX(calc(-100% - var(--gap)))' - } + transform: "translateX(calc(-100% - var(--gap)))", + }, }, - 'marquee-vertical': { + "marquee-vertical": { from: { - transform: 'translateY(0)' + transform: "translateY(0)", }, to: { - transform: 'translateY(calc(-100% - var(--gap)))' - } + transform: "translateY(calc(-100% - var(--gap)))", + }, }, "accordion-down": { from: { height: "0" }, @@ -128,17 +126,17 @@ export default { from: { height: "var(--radix-accordion-content-height)" }, to: { height: "0" }, }, - } + }, }, components: { button: { - padding: '0.5rem 1rem', - borderRadius: 'var(--radius)', - fontWeight: '500', - cursor: 'pointer', + padding: "0.5rem 1rem", + borderRadius: "var(--radius)", + fontWeight: "500", + cursor: "pointer", disabled: { opacity: 0.5, - cursor: 'not-allowed', + cursor: "not-allowed", }, }, }, From b87c440093b9b587e60163584f42061fc7a92835 Mon Sep 17 00:00:00 2001 From: yujonglee Date: Tue, 17 Dec 2024 19:08:22 +0900 Subject: [PATCH 6/6] add types from proto --- apps/desktop/package.json | 1 + apps/desktop/src/types/index.ts | 1 + pnpm-lock.yaml | 3 +++ 3 files changed, 5 insertions(+) diff --git a/apps/desktop/package.json b/apps/desktop/package.json index fab39fe87e..e8ba8224ed 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -11,6 +11,7 @@ "format": "prettier --write ." }, "dependencies": { + "@hypr/proto": "workspace:*", "@radix-ui/react-dialog": "^1.1.3", "@radix-ui/react-dropdown-menu": "^2.1.3", "@radix-ui/react-form": "^0.1.1", diff --git a/apps/desktop/src/types/index.ts b/apps/desktop/src/types/index.ts index f97747f2ab..532bf71b7e 100644 --- a/apps/desktop/src/types/index.ts +++ b/apps/desktop/src/types/index.ts @@ -2,6 +2,7 @@ import type { Node as PMNode } from "@tiptap/pm/model"; export * from "./db"; export * from "./tauri"; +export * from "@hypr/proto"; // Google Calendar Event Type export interface CalendarEvent { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ed9a92b143..21b96a8254 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,6 +8,9 @@ importers: apps/desktop: dependencies: + '@hypr/proto': + specifier: workspace:* + version: link:../../packages/proto '@radix-ui/react-dialog': specifier: ^1.1.3 version: 1.1.3(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)