diff --git a/frontend/components.json b/frontend/components.json index 9041a39..f158e77 100644 --- a/frontend/components.json +++ b/frontend/components.json @@ -1,14 +1,17 @@ { - "$schema": "https://shadcn-svelte.com/schema.json", - "style": "default", - "tailwind": { - "config": "tailwind.config.mjs", - "css": "src/styles/app.css", - "baseColor": "slate" - }, - "aliases": { - "components": "$lib/components", - "utils": "$lib/utils" - }, - "typescript": true -} \ No newline at end of file + "$schema": "https://next.shadcn-svelte.com/schema.json", + "style": "default", + "tailwind": { + "config": "tailwind.config.mjs", + "css": "src/styles/app.css", + "baseColor": "slate" + }, + "aliases": { + "components": "$lib/components", + "utils": "$lib/utils", + "ui": "$lib/components/ui", + "hooks": "$lib/hooks" + }, + "typescript": true, + "registry": "https://next.shadcn-svelte.com/registry" +} diff --git a/frontend/package.json b/frontend/package.json index bb5ad13..a574c57 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -27,6 +27,7 @@ "prettier-plugin-tailwindcss": "^0.6.11", "tailwind-merge": "^3.0.2", "tailwind-variants": "^1.0.0", + "tailwindcss-animate": "^1.0.7", "vaul-svelte": "^0.3.2" }, "pnpm": { diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml index cd2a498..8161afc 100644 --- a/frontend/pnpm-lock.yaml +++ b/frontend/pnpm-lock.yaml @@ -54,6 +54,9 @@ importers: tailwind-variants: specifier: ^1.0.0 version: 1.0.0(tailwindcss@3.4.17) + tailwindcss-animate: + specifier: ^1.0.7 + version: 1.0.7(tailwindcss@3.4.17) vaul-svelte: specifier: ^0.3.2 version: 0.3.2(svelte@5.22.6) @@ -1879,6 +1882,11 @@ packages: peerDependencies: tailwindcss: '*' + tailwindcss-animate@1.0.7: + resolution: {integrity: sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==} + peerDependencies: + tailwindcss: '>=3.0.0 || insiders' + tailwindcss@3.4.17: resolution: {integrity: sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==} engines: {node: '>=14.0.0'} @@ -4425,6 +4433,10 @@ snapshots: tailwind-merge: 3.0.2 tailwindcss: 3.4.17 + tailwindcss-animate@1.0.7(tailwindcss@3.4.17): + dependencies: + tailwindcss: 3.4.17 + tailwindcss@3.4.17: dependencies: '@alloc/quick-lru': 5.2.0 diff --git a/frontend/src/styles/app.css b/frontend/src/styles/app.css index 1460463..bcfda3c 100644 --- a/frontend/src/styles/app.css +++ b/frontend/src/styles/app.css @@ -1,73 +1,70 @@ @tailwind base; @tailwind components; @tailwind utilities; - + @layer base { :root { --background: 0 0% 100%; --foreground: 222.2 84% 4.9%; - --muted: 210 40% 96.1%; --muted-foreground: 215.4 16.3% 46.9%; - --popover: 0 0% 100%; --popover-foreground: 222.2 84% 4.9%; - --card: 0 0% 100%; --card-foreground: 222.2 84% 4.9%; - --border: 214.3 31.8% 91.4%; --input: 214.3 31.8% 91.4%; - --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%; - --accent: 210 40% 96.1%; --accent-foreground: 222.2 47.4% 11.2%; - --destructive: 0 72.2% 50.6%; --destructive-foreground: 210 40% 98%; - --ring: 222.2 84% 4.9%; - --radius: 0.5rem; + --sidebar-background: 0 0% 98%; + --sidebar-foreground: 240 5.3% 26.1%; + --sidebar-primary: 240 5.9% 10%; + --sidebar-primary-foreground: 0 0% 98%; + --sidebar-accent: 240 4.8% 95.9%; + --sidebar-accent-foreground: 240 5.9% 10%; + --sidebar-border: 220 13% 91%; + --sidebar-ring: 217.2 91.2% 59.8%; } - + .dark { --background: 222.2 84% 4.9%; --foreground: 210 40% 98%; - --muted: 217.2 32.6% 17.5%; --muted-foreground: 215 20.2% 65.1%; - --popover: 222.2 84% 4.9%; --popover-foreground: 210 40% 98%; - --card: 222.2 84% 4.9%; --card-foreground: 210 40% 98%; - --border: 217.2 32.6% 17.5%; --input: 217.2 32.6% 17.5%; - --primary: 210 40% 98%; --primary-foreground: 222.2 47.4% 11.2%; - --secondary: 217.2 32.6% 17.5%; --secondary-foreground: 210 40% 98%; - --accent: 217.2 32.6% 17.5%; --accent-foreground: 210 40% 98%; - --destructive: 0 62.8% 30.6%; --destructive-foreground: 210 40% 98%; - --ring: 212.7 26.8% 83.9%; + --sidebar-background: 240 5.9% 10%; + --sidebar-foreground: 240 4.8% 95.9%; + --sidebar-primary: 224.3 76.3% 48%; + --sidebar-primary-foreground: 0 0% 100%; + --sidebar-accent: 240 3.7% 15.9%; + --sidebar-accent-foreground: 240 4.8% 95.9%; + --sidebar-border: 240 3.7% 15.9%; + --sidebar-ring: 217.2 91.2% 59.8%; } } - + @layer base { * { @apply border-border; @@ -75,4 +72,5 @@ body { @apply bg-background text-foreground; } -} \ No newline at end of file +} + diff --git a/frontend/src/utils.ts b/frontend/src/utils.ts index 8871245..365058c 100644 --- a/frontend/src/utils.ts +++ b/frontend/src/utils.ts @@ -1,62 +1,6 @@ import { type ClassValue, clsx } from "clsx"; import { twMerge } from "tailwind-merge"; -import { cubicOut } from "svelte/easing"; -import type { TransitionConfig } from "svelte/transition"; export function cn(...inputs: ClassValue[]) { - return twMerge(clsx(inputs)); + return twMerge(clsx(inputs)); } - -type FlyAndScaleParams = { - y?: number; - x?: number; - start?: number; - duration?: number; -}; - -export const flyAndScale = ( - node: Element, - params: FlyAndScaleParams = { y: -8, x: 0, start: 0.95, duration: 150 } -): TransitionConfig => { - const style = getComputedStyle(node); - const transform = style.transform === "none" ? "" : style.transform; - - const scaleConversion = ( - valueA: number, - scaleA: [number, number], - scaleB: [number, number] - ) => { - const [minA, maxA] = scaleA; - const [minB, maxB] = scaleB; - - const percentage = (valueA - minA) / (maxA - minA); - const valueB = percentage * (maxB - minB) + minB; - - return valueB; - }; - - const styleToString = ( - style: Record - ): string => { - return Object.keys(style).reduce((str, key) => { - if (style[key] === undefined) return str; - return str + `${key}:${style[key]};`; - }, ""); - }; - - return { - duration: params.duration ?? 200, - delay: 0, - css: (t) => { - const y = scaleConversion(t, [0, 1], [params.y ?? 5, 0]); - const x = scaleConversion(t, [0, 1], [params.x ?? 0, 0]); - const scale = scaleConversion(t, [0, 1], [params.start ?? 0.95, 1]); - - return styleToString({ - transform: `${transform} translate3d(${x}px, ${y}px, 0) scale(${scale})`, - opacity: t - }); - }, - easing: cubicOut - }; -}; \ No newline at end of file diff --git a/frontend/tailwind.config.mjs b/frontend/tailwind.config.mjs index fa1cb36..c0483de 100644 --- a/frontend/tailwind.config.mjs +++ b/frontend/tailwind.config.mjs @@ -1,64 +1,96 @@ import { fontFamily } from "tailwindcss/defaultTheme"; +import tailwindcssAnimate from "tailwindcss-animate"; /** @type {import('tailwindcss').Config} */ const config = { - darkMode: ["class"], - content: ["./src/**/*.{html,js,svelte,ts}"], - safelist: ["dark"], - theme: { - container: { - center: true, - padding: "2rem", - screens: { - "2xl": "1400px" - } - }, - extend: { - colors: { - border: "hsl(var(--border) / )", - input: "hsl(var(--input) / )", - ring: "hsl(var(--ring) / )", - background: "hsl(var(--background) / )", - foreground: "hsl(var(--foreground) / )", - primary: { - DEFAULT: "hsl(var(--primary) / )", - foreground: "hsl(var(--primary-foreground) / )" - }, - secondary: { - DEFAULT: "hsl(var(--secondary) / )", - foreground: "hsl(var(--secondary-foreground) / )" - }, - destructive: { - DEFAULT: "hsl(var(--destructive) / )", - foreground: "hsl(var(--destructive-foreground) / )" - }, - muted: { - DEFAULT: "hsl(var(--muted) / )", - foreground: "hsl(var(--muted-foreground) / )" - }, - accent: { - DEFAULT: "hsl(var(--accent) / )", - foreground: "hsl(var(--accent-foreground) / )" - }, - popover: { - DEFAULT: "hsl(var(--popover) / )", - foreground: "hsl(var(--popover-foreground) / )" - }, - card: { - DEFAULT: "hsl(var(--card) / )", - foreground: "hsl(var(--card-foreground) / )" - } - }, - borderRadius: { - lg: "var(--radius)", - md: "calc(var(--radius) - 2px)", - sm: "calc(var(--radius) - 4px)" - }, - fontFamily: { - sans: [...fontFamily.sans] - } - } - }, + darkMode: ["class"], + content: ["./src/**/*.{html,js,svelte,ts,astro}"], + safelist: ["dark"], + theme: { + container: { + center: true, + padding: "2rem", + screens: { + "2xl": "1400px", + }, + }, + extend: { + colors: { + border: "hsl(var(--border) / )", + input: "hsl(var(--input) / )", + ring: "hsl(var(--ring) / )", + background: "hsl(var(--background) / )", + foreground: "hsl(var(--foreground) / )", + primary: { + DEFAULT: "hsl(var(--primary) / )", + foreground: "hsl(var(--primary-foreground) / )", + }, + secondary: { + DEFAULT: "hsl(var(--secondary) / )", + foreground: "hsl(var(--secondary-foreground) / )", + }, + destructive: { + DEFAULT: "hsl(var(--destructive) / )", + foreground: "hsl(var(--destructive-foreground) / )", + }, + muted: { + DEFAULT: "hsl(var(--muted) / )", + foreground: "hsl(var(--muted-foreground) / )", + }, + accent: { + DEFAULT: "hsl(var(--accent) / )", + foreground: "hsl(var(--accent-foreground) / )", + }, + popover: { + DEFAULT: "hsl(var(--popover) / )", + foreground: "hsl(var(--popover-foreground) / )", + }, + card: { + DEFAULT: "hsl(var(--card) / )", + foreground: "hsl(var(--card-foreground) / )", + }, + sidebar: { + DEFAULT: "hsl(var(--sidebar-background))", + foreground: "hsl(var(--sidebar-foreground))", + primary: "hsl(var(--sidebar-primary))", + "primary-foreground": "hsl(var(--sidebar-primary-foreground))", + accent: "hsl(var(--sidebar-accent))", + "accent-foreground": "hsl(var(--sidebar-accent-foreground))", + border: "hsl(var(--sidebar-border))", + ring: "hsl(var(--sidebar-ring))", + }, + }, + borderRadius: { + xl: "calc(var(--radius) + 4px)", + lg: "var(--radius)", + md: "calc(var(--radius) - 2px)", + sm: "calc(var(--radius) - 4px)", + }, + fontFamily: { + sans: [...fontFamily.sans], + }, + keyframes: { + "accordion-down": { + from: { height: "0" }, + to: { height: "var(--bits-accordion-content-height)" }, + }, + "accordion-up": { + from: { height: "var(--bits-accordion-content-height)" }, + to: { height: "0" }, + }, + "caret-blink": { + "0%,70%,100%": { opacity: "1" }, + "20%,50%": { opacity: "0" }, + }, + }, + animation: { + "accordion-down": "accordion-down 0.2s ease-out", + "accordion-up": "accordion-up 0.2s ease-out", + "caret-blink": "caret-blink 1.25s ease-out infinite", + }, + }, + }, + plugins: [tailwindcssAnimate], }; export default config;