From 0df4c8c1f61870fa335243ded21d5d9bbb3c48af Mon Sep 17 00:00:00 2001 From: Felipe Cardoso Date: Wed, 5 Mar 2025 11:27:26 +0100 Subject: [PATCH] Add TailwindCSS utilities and update UI dependencies Introduce TailwindCSS utilities, animations, and theme configurations to enhance UI styling. Update dependencies to include Radix, clsx, lucide-react, and other utilities for improved design flexibility and component styling. Refactor global CSS, PostCSS config, and utils for streamlined development. --- frontend/components.json | 21 ++++++ frontend/package-lock.json | 103 ++++++++++++++++++++++++-- frontend/package.json | 15 +++- frontend/postcss.config.mjs | 9 ++- frontend/src/app/globals.css | 140 +++++++++++++++++++++++++++++++---- frontend/src/lib/utils.ts | 6 ++ 6 files changed, 265 insertions(+), 29 deletions(-) create mode 100644 frontend/components.json create mode 100644 frontend/src/lib/utils.ts diff --git a/frontend/components.json b/frontend/components.json new file mode 100644 index 0000000..ffe928f --- /dev/null +++ b/frontend/components.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "new-york", + "rsc": true, + "tsx": true, + "tailwind": { + "config": "", + "css": "src/app/globals.css", + "baseColor": "neutral", + "cssVariables": true, + "prefix": "" + }, + "aliases": { + "components": "@/components", + "utils": "@/lib/utils", + "ui": "@/components/ui", + "lib": "@/lib", + "hooks": "@/hooks" + }, + "iconLibrary": "lucide" +} \ No newline at end of file diff --git a/frontend/package-lock.json b/frontend/package-lock.json index d2a59d5..45f8056 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -10,17 +10,24 @@ "dependencies": { "@hey-api/client-axios": "^0.6.2", "@hey-api/client-fetch": "^0.8.3", + "@radix-ui/react-slot": "^1.1.2", "@tanstack/react-query": "^5.67.1", "axios": "^1.8.1", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", "jwt-decode": "^4.0.0", + "lucide-react": "^0.477.0", "next": "15.2.0", + "next-themes": "^0.4.4", "react": "^19.0.0", - "react-dom": "^19.0.0" + "react-dom": "^19.0.0", + "tailwind-merge": "^3.0.2", + "tailwindcss-animate": "^1.0.7" }, "devDependencies": { "@eslint/eslintrc": "^3", "@hey-api/openapi-ts": "^0.64.10", - "@tailwindcss/postcss": "^4", + "@tailwindcss/postcss": "^4.0.9", "@tanstack/react-query-devtools": "^5.67.1", "@types/node": "^20.17.23", "@types/react": "^19", @@ -29,10 +36,10 @@ "eslint-config-next": "15.2.0", "eslint-config-prettier": "^10.0.2", "eslint-plugin-prettier": "^5.2.3", - "next-themes": "^0.4.4", "openapi-typescript-codegen": "^0.29.0", + "postcss": "^8.5.3", "prettier": "^3.5.3", - "tailwindcss": "^4", + "tailwindcss": "^4.0.9", "typescript": "^5" } }, @@ -908,6 +915,39 @@ "url": "https://opencollective.com/unts" } }, + "node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz", + "integrity": "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slot": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.2.tgz", + "integrity": "sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@rtsao/scc": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", @@ -1264,7 +1304,7 @@ "version": "19.0.10", "resolved": "https://registry.npmjs.org/@types/react/-/react-19.0.10.tgz", "integrity": "sha512-JuRQ9KXLEjaUNjTWpzuR231Z2WpIwczOkBEIvbHNCzQefFIT0L8IqE6NV6ULLyC1SI/i234JnDoMkfg+RjQj2g==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "csstype": "^3.0.2" @@ -2032,12 +2072,33 @@ "consola": "^3.2.3" } }, + "node_modules/class-variance-authority": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz", + "integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==", + "license": "Apache-2.0", + "dependencies": { + "clsx": "^2.1.1" + }, + "funding": { + "url": "https://polar.sh/cva" + } + }, "node_modules/client-only": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", "license": "MIT" }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/color": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", @@ -2148,7 +2209,7 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/damerau-levenshtein": { @@ -4462,6 +4523,15 @@ "loose-envify": "cli.js" } }, + "node_modules/lucide-react": { + "version": "0.477.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.477.0.tgz", + "integrity": "sha512-yCf7aYxerFZAbd8jHJxjwe1j7jEMPptjnaOqdYeirFnEy85cNR3/L+o0I875CYFYya+eEVzZSbNuRk8BZPDpVw==", + "license": "ISC", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -4706,7 +4776,6 @@ "version": "0.4.4", "resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.4.4.tgz", "integrity": "sha512-LDQ2qIOJF0VnuVrrMSMLrWGjRMkq+0mpgl6e0juCLqdJ+oo8Q84JRWT6Wh11VDQKkMMe+dVzDKLWs5n87T+PkQ==", - "dev": true, "license": "MIT", "peerDependencies": { "react": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc", @@ -5910,13 +5979,31 @@ "url": "https://opencollective.com/unts" } }, + "node_modules/tailwind-merge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.0.2.tgz", + "integrity": "sha512-l7z+OYZ7mu3DTqrL88RiKrKIqO3NcpEO8V/Od04bNpvk0kiIFndGEoqfuzvj4yuhRkHKjRkII2z+KS2HfPcSxw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/dcastil" + } + }, "node_modules/tailwindcss": { "version": "4.0.9", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.0.9.tgz", "integrity": "sha512-12laZu+fv1ONDRoNR9ipTOpUD7RN9essRVkX36sjxuRUInpN7hIiHN4lBd/SIFjbISvnXzp8h/hXzmU8SQQYhw==", - "dev": true, "license": "MIT" }, + "node_modules/tailwindcss-animate": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz", + "integrity": "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==", + "license": "MIT", + "peerDependencies": { + "tailwindcss": ">=3.0.0 || insiders" + } + }, "node_modules/tapable": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", diff --git a/frontend/package.json b/frontend/package.json index b06a8c0..8f83da1 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -15,17 +15,24 @@ "dependencies": { "@hey-api/client-axios": "^0.6.2", "@hey-api/client-fetch": "^0.8.3", + "@radix-ui/react-slot": "^1.1.2", "@tanstack/react-query": "^5.67.1", "axios": "^1.8.1", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", "jwt-decode": "^4.0.0", + "lucide-react": "^0.477.0", "next": "15.2.0", + "next-themes": "^0.4.4", "react": "^19.0.0", - "react-dom": "^19.0.0" + "react-dom": "^19.0.0", + "tailwind-merge": "^3.0.2", + "tailwindcss-animate": "^1.0.7" }, "devDependencies": { "@eslint/eslintrc": "^3", "@hey-api/openapi-ts": "^0.64.10", - "@tailwindcss/postcss": "^4", + "@tailwindcss/postcss": "^4.0.9", "@tanstack/react-query-devtools": "^5.67.1", "@types/node": "^20.17.23", "@types/react": "^19", @@ -34,10 +41,10 @@ "eslint-config-next": "15.2.0", "eslint-config-prettier": "^10.0.2", "eslint-plugin-prettier": "^5.2.3", - "next-themes": "^0.4.4", "openapi-typescript-codegen": "^0.29.0", + "postcss": "^8.5.3", "prettier": "^3.5.3", - "tailwindcss": "^4", + "tailwindcss": "^4.0.9", "typescript": "^5" } } diff --git a/frontend/postcss.config.mjs b/frontend/postcss.config.mjs index c7bcb4b..df2cc95 100644 --- a/frontend/postcss.config.mjs +++ b/frontend/postcss.config.mjs @@ -1,5 +1,6 @@ -const config = { - plugins: ["@tailwindcss/postcss"], +/** @type {import('tailwindcss').Config} */ +export default { + plugins: { + "@tailwindcss/postcss": {}, + }, }; - -export default config; diff --git a/frontend/src/app/globals.css b/frontend/src/app/globals.css index 947a048..4723c09 100644 --- a/frontend/src/app/globals.css +++ b/frontend/src/app/globals.css @@ -1,24 +1,138 @@ -@import "tailwindcss"; +@import 'tailwindcss'; -@theme { - --font-sans: var(--font-geist-sans); - --font-mono: var(--font-geist-mono); -} +@plugin 'tailwindcss-animate'; + +@custom-variant dark (&:is(.dark *)); +@tailwind base; +@tailwind components; +@tailwind utilities; :root { - --background: #ffffff; - --foreground: #171717; + --foreground-rgb: 0, 0, 0; + --background-start-rgb: 245, 247, 250; + --background-end-rgb: 255, 255, 255; + --card: oklch(1 0 0); + --card-foreground: oklch(0.145 0 0); + --popover: oklch(1 0 0); + --popover-foreground: oklch(0.145 0 0); + --primary: oklch(0.205 0 0); + --primary-foreground: oklch(0.985 0 0); + --secondary: oklch(0.97 0 0); + --secondary-foreground: oklch(0.205 0 0); + --muted: oklch(0.97 0 0); + --muted-foreground: oklch(0.556 0 0); + --accent: oklch(0.97 0 0); + --accent-foreground: oklch(0.205 0 0); + --destructive: oklch(0.577 0.245 27.325); + --destructive-foreground: oklch(0.577 0.245 27.325); + --border: oklch(0.922 0 0); + --input: oklch(0.922 0 0); + --ring: oklch(0.708 0 0); + --chart-1: oklch(0.646 0.222 41.116); + --chart-2: oklch(0.6 0.118 184.704); + --chart-3: oklch(0.398 0.07 227.392); + --chart-4: oklch(0.828 0.189 84.429); + --chart-5: oklch(0.769 0.188 70.08); + --radius: 0.625rem; + --sidebar: oklch(0.985 0 0); + --sidebar-foreground: oklch(0.145 0 0); + --sidebar-primary: oklch(0.205 0 0); + --sidebar-primary-foreground: oklch(0.985 0 0); + --sidebar-accent: oklch(0.97 0 0); + --sidebar-accent-foreground: oklch(0.205 0 0); + --sidebar-border: oklch(0.922 0 0); + --sidebar-ring: oklch(0.708 0 0); + --background: oklch(1 0 0); + --foreground: oklch(0.145 0 0); } @media (prefers-color-scheme: dark) { :root { - --background: #0a0a0a; - --foreground: #ededed; + --foreground-rgb: 255, 255, 255; + --background-start-rgb: 15, 23, 42; + --background-end-rgb: 30, 41, 59; } } -body { - color: var(--foreground); - background: var(--background); - font-family: Arial, Helvetica, sans-serif; +.dark { + --background: oklch(0.145 0 0); + --foreground: oklch(0.985 0 0); + --card: oklch(0.145 0 0); + --card-foreground: oklch(0.985 0 0); + --popover: oklch(0.145 0 0); + --popover-foreground: oklch(0.985 0 0); + --primary: oklch(0.985 0 0); + --primary-foreground: oklch(0.205 0 0); + --secondary: oklch(0.269 0 0); + --secondary-foreground: oklch(0.985 0 0); + --muted: oklch(0.269 0 0); + --muted-foreground: oklch(0.708 0 0); + --accent: oklch(0.269 0 0); + --accent-foreground: oklch(0.985 0 0); + --destructive: oklch(0.396 0.141 25.723); + --destructive-foreground: oklch(0.637 0.237 25.331); + --border: oklch(0.269 0 0); + --input: oklch(0.269 0 0); + --ring: oklch(0.439 0 0); + --chart-1: oklch(0.488 0.243 264.376); + --chart-2: oklch(0.696 0.17 162.48); + --chart-3: oklch(0.769 0.188 70.08); + --chart-4: oklch(0.627 0.265 303.9); + --chart-5: oklch(0.645 0.246 16.439); + --sidebar: oklch(0.205 0 0); + --sidebar-foreground: oklch(0.985 0 0); + --sidebar-primary: oklch(0.488 0.243 264.376); + --sidebar-primary-foreground: oklch(0.985 0 0); + --sidebar-accent: oklch(0.269 0 0); + --sidebar-accent-foreground: oklch(0.985 0 0); + --sidebar-border: oklch(0.269 0 0); + --sidebar-ring: oklch(0.439 0 0); } + +@theme inline { + --color-background: var(--background); + --color-foreground: var(--foreground); + --color-card: var(--card); + --color-card-foreground: var(--card-foreground); + --color-popover: var(--popover); + --color-popover-foreground: var(--popover-foreground); + --color-primary: var(--primary); + --color-primary-foreground: var(--primary-foreground); + --color-secondary: var(--secondary); + --color-secondary-foreground: var(--secondary-foreground); + --color-muted: var(--muted); + --color-muted-foreground: var(--muted-foreground); + --color-accent: var(--accent); + --color-accent-foreground: var(--accent-foreground); + --color-destructive: var(--destructive); + --color-destructive-foreground: var(--destructive-foreground); + --color-border: var(--border); + --color-input: var(--input); + --color-ring: var(--ring); + --color-chart-1: var(--chart-1); + --color-chart-2: var(--chart-2); + --color-chart-3: var(--chart-3); + --color-chart-4: var(--chart-4); + --color-chart-5: var(--chart-5); + --radius-sm: calc(var(--radius) - 4px); + --radius-md: calc(var(--radius) - 2px); + --radius-lg: var(--radius); + --radius-xl: calc(var(--radius) + 4px); + --color-sidebar: var(--sidebar); + --color-sidebar-foreground: var(--sidebar-foreground); + --color-sidebar-primary: var(--sidebar-primary); + --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); + --color-sidebar-accent: var(--sidebar-accent); + --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); + --color-sidebar-border: var(--sidebar-border); + --color-sidebar-ring: var(--sidebar-ring); +} + +@layer base { + * { + @apply border-border outline-ring/50; + } + body { + @apply bg-background text-foreground; + } +} \ No newline at end of file diff --git a/frontend/src/lib/utils.ts b/frontend/src/lib/utils.ts new file mode 100644 index 0000000..bd0c391 --- /dev/null +++ b/frontend/src/lib/utils.ts @@ -0,0 +1,6 @@ +import { clsx, type ClassValue } from "clsx" +import { twMerge } from "tailwind-merge" + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)) +}