From b3c6ff2f94874b56d162a997fa6079c4d3b6d629 Mon Sep 17 00:00:00 2001 From: Khalim Conn-Kowlessar Date: Fri, 2 Jun 2023 11:51:05 +0100 Subject: [PATCH] Got shadcn set up --- package-lock.json | 84 +++++++++++++++++++++++++ package.json | 5 ++ src/app/globals.css | 78 +++++++++++++++++++++++ src/app/layout.tsx | 10 ++- src/app/shadcn_components/ui/button.tsx | 55 ++++++++++++++++ src/app/shadcn_components/ui/card.tsx | 79 +++++++++++++++++++++++ src/lib/utils.ts | 6 ++ tailwind.config.js | 65 +++++++++++++++++++ 8 files changed, 381 insertions(+), 1 deletion(-) create mode 100644 src/app/shadcn_components/ui/button.tsx create mode 100644 src/app/shadcn_components/ui/card.tsx create mode 100644 src/lib/utils.ts diff --git a/package-lock.json b/package-lock.json index 5ca27d4..acea992 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,21 +10,26 @@ "dependencies": { "@headlessui/react": "^1.7.14", "@heroicons/react": "^2.0.18", + "@radix-ui/react-slot": "^1.0.2", "@tanstack/react-query": "^4.29.12", "@types/node": "20.2.3", "@types/react": "18.2.7", "@types/react-dom": "18.2.4", "autoprefixer": "10.4.14", + "class-variance-authority": "^0.6.0", "clsx": "^1.2.1", "eslint": "8.41.0", "eslint-config-next": "13.4.3", + "lucide-react": "^0.233.0", "next": "13.4.3", "next-auth": "^4.22.1", "next-axiom": "^0.17.0", "postcss": "8.4.23", "react": "18.2.0", "react-dom": "18.2.0", + "tailwind-merge": "^1.13.0", "tailwindcss": "3.3.2", + "tailwindcss-animate": "^1.0.5", "typescript": "5.0.4" } }, @@ -410,6 +415,41 @@ "url": "https://opencollective.com/unts" } }, + "node_modules/@radix-ui/react-compose-refs": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.1.tgz", + "integrity": "sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==", + "dependencies": { + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slot": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.2.tgz", + "integrity": "sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-compose-refs": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@rushstack/eslint-patch": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.3.0.tgz", @@ -1034,6 +1074,25 @@ "node": ">= 6" } }, + "node_modules/class-variance-authority": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.6.0.tgz", + "integrity": "sha512-qdRDgfjx3GRb9fpwpSvn+YaidnT7IUJNe4wt5/SWwM+PmUwJUhQRk/8zAyNro0PmVfmen2635UboTjIBXXxy5A==", + "dependencies": { + "clsx": "1.2.1" + }, + "funding": { + "url": "https://joebell.co.uk" + }, + "peerDependencies": { + "typescript": ">= 4.5.5 < 6" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/client-only": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", @@ -2803,6 +2862,14 @@ "node": ">=10" } }, + "node_modules/lucide-react": { + "version": "0.233.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.233.0.tgz", + "integrity": "sha512-r0jMHF0vPDq2wBbZ0B3rtIcBjDyWDKpHu+vAjD2OHn2WLUr3HN5IHovtO0EMgQXuSI7YrMZbjsEZWC2uBHr8nQ==", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -4111,6 +4178,15 @@ "url": "https://opencollective.com/unts" } }, + "node_modules/tailwind-merge": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-1.13.0.tgz", + "integrity": "sha512-mUTmDbcU+IhOvJ0c42eLQ/nRkvolTqfpVaVQRSxfJAv9TabS6Y2zW/1wKpKLdKzyL3Gh8j6NTLl6MWNmvOM6kA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/dcastil" + } + }, "node_modules/tailwindcss": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.2.tgz", @@ -4148,6 +4224,14 @@ "node": ">=14.0.0" } }, + "node_modules/tailwindcss-animate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tailwindcss-animate/-/tailwindcss-animate-1.0.5.tgz", + "integrity": "sha512-UU3qrOJ4lFQABY+MVADmBm+0KW3xZyhMdRvejwtXqYOL7YjHYxmuREFAZdmVG5LPe5E9CAst846SLC4j5I3dcw==", + "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/package.json b/package.json index b27abb6..1dcc122 100644 --- a/package.json +++ b/package.json @@ -11,21 +11,26 @@ "dependencies": { "@headlessui/react": "^1.7.14", "@heroicons/react": "^2.0.18", + "@radix-ui/react-slot": "^1.0.2", "@tanstack/react-query": "^4.29.12", "@types/node": "20.2.3", "@types/react": "18.2.7", "@types/react-dom": "18.2.4", "autoprefixer": "10.4.14", + "class-variance-authority": "^0.6.0", "clsx": "^1.2.1", "eslint": "8.41.0", "eslint-config-next": "13.4.3", + "lucide-react": "^0.233.0", "next": "13.4.3", "next-auth": "^4.22.1", "next-axiom": "^0.17.0", "postcss": "8.4.23", "react": "18.2.0", "react-dom": "18.2.0", + "tailwind-merge": "^1.13.0", "tailwindcss": "3.3.2", + "tailwindcss-animate": "^1.0.5", "typescript": "5.0.4" } } diff --git a/src/app/globals.css b/src/app/globals.css index 71f619b..6888ffc 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -19,3 +19,81 @@ body { color: rgb(var(--foreground-rgb)); } + +@layer base { + :root { + --background: 0 0% 100%; + --foreground: 222.2 47.4% 11.2%; + + --muted: 210 40% 96.1%; + --muted-foreground: 215.4 16.3% 46.9%; + + --popover: 0 0% 100%; + --popover-foreground: 222.2 47.4% 11.2%; + + --card: 0 0% 100%; + --card-foreground: 222.2 47.4% 11.2%; + + --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 100% 50%; + --destructive-foreground: 210 40% 98%; + + --ring: 215 20.2% 65.1%; + + --radius: 0.5rem; + } + + .dark { + --background: 224 71% 4%; + --foreground: 213 31% 91%; + + --muted: 223 47% 11%; + --muted-foreground: 215.4 16.3% 56.9%; + + --popover: 224 71% 4%; + --popover-foreground: 215 20.2% 65.1%; + + --card: 224 71% 4%; + --card-foreground: 213 31% 91%; + + --border: 216 34% 17%; + --input: 216 34% 17%; + + --primary: 210 40% 98%; + --primary-foreground: 222.2 47.4% 1.2%; + + --secondary: 222.2 47.4% 11.2%; + --secondary-foreground: 210 40% 98%; + + --accent: 216 34% 17%; + --accent-foreground: 210 40% 98%; + + --destructive: 0 63% 31%; + --destructive-foreground: 210 40% 98%; + + --ring: 216 34% 17%; + + --radius: 0.5rem; + } +} + +@layer base { + * { + @apply border-border; + } + body { + @apply bg-background text-foreground; + font-feature-settings: "rlig" 1, "calt" 1; + } +} diff --git a/src/app/layout.tsx b/src/app/layout.tsx index a362762..1174b80 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -3,6 +3,14 @@ import Provider from "./components/Provider"; import Nav from "./components/Navbar"; import { ReactQueryProvider } from "./ReactQueryProvider"; +import { Inter } from "next/font/google"; + +// If loading a variable font, you don't need to specify the font weight +const inter = Inter({ + subsets: ["latin"], + display: "swap", +}); + export const metadata = { title: "", description: "Start your retrofit journey today", @@ -18,7 +26,7 @@ export default function RootLayout({ // on small screens. return ( - + diff --git a/src/app/shadcn_components/ui/button.tsx b/src/app/shadcn_components/ui/button.tsx new file mode 100644 index 0000000..2ada851 --- /dev/null +++ b/src/app/shadcn_components/ui/button.tsx @@ -0,0 +1,55 @@ +import * as React from "react" +import { Slot } from "@radix-ui/react-slot" +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" + +const buttonVariants = cva( + "inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none ring-offset-background", + { + variants: { + variant: { + default: "bg-primary text-primary-foreground hover:bg-primary/90", + destructive: + "bg-destructive text-destructive-foreground hover:bg-destructive/90", + outline: + "border border-input hover:bg-accent hover:text-accent-foreground", + secondary: + "bg-secondary text-secondary-foreground hover:bg-secondary/80", + ghost: "hover:bg-accent hover:text-accent-foreground", + link: "underline-offset-4 hover:underline text-primary", + }, + size: { + default: "h-10 py-2 px-4", + sm: "h-9 px-3 rounded-md", + lg: "h-11 px-8 rounded-md", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, + } +) + +export interface ButtonProps + extends React.ButtonHTMLAttributes, + VariantProps { + asChild?: boolean +} + +const Button = React.forwardRef( + ({ className, variant, size, asChild = false, ...props }, ref) => { + const Comp = asChild ? Slot : "button" + return ( + + ) + } +) +Button.displayName = "Button" + +export { Button, buttonVariants } diff --git a/src/app/shadcn_components/ui/card.tsx b/src/app/shadcn_components/ui/card.tsx new file mode 100644 index 0000000..dff04b6 --- /dev/null +++ b/src/app/shadcn_components/ui/card.tsx @@ -0,0 +1,79 @@ +import * as React from "react" + +import { cn } from "@/lib/utils" + +const Card = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +Card.displayName = "Card" + +const CardHeader = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +CardHeader.displayName = "CardHeader" + +const CardTitle = React.forwardRef< + HTMLParagraphElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +

+)) +CardTitle.displayName = "CardTitle" + +const CardDescription = React.forwardRef< + HTMLParagraphElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +

+)) +CardDescription.displayName = "CardDescription" + +const CardContent = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +

+)) +CardContent.displayName = "CardContent" + +const CardFooter = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +CardFooter.displayName = "CardFooter" + +export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent } diff --git a/src/lib/utils.ts b/src/lib/utils.ts new file mode 100644 index 0000000..23af5b2 --- /dev/null +++ b/src/lib/utils.ts @@ -0,0 +1,6 @@ +import { ClassValue, clsx } from "clsx" +import { twMerge } from "tailwind-merge" + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)) +} diff --git a/tailwind.config.js b/tailwind.config.js index ae847ee..e20a48e 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -1,11 +1,21 @@ +const { fontFamily } = require("tailwindcss/defaultTheme"); /** @type {import('tailwindcss').Config} */ + module.exports = { + darkMode: ["class"], content: [ "./src/pages/**/*.{js,ts,jsx,tsx,mdx}", "./src/components/**/*.{js,ts,jsx,tsx,mdx}", "./src/app/**/*.{js,ts,jsx,tsx,mdx}", ], theme: { + container: { + center: true, + padding: "2rem", + screens: { + "2xl": "1400px", + }, + }, extend: { backgroundImage: { "gradient-radial": "radial-gradient(var(--tw-gradient-stops))", @@ -19,6 +29,39 @@ module.exports = { hovertan: "#947750", brandbrown: "#3d1e05", brandmidblue: "#3943b7", + 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))", + }, }, textColor: { brandblue: "#14163d", @@ -28,6 +71,28 @@ module.exports = { brandbrown: "#3d1e05", brandmidblue: "#3943b7", }, + borderRadius: { + lg: `var(--radius)`, + md: `calc(var(--radius) - 2px)`, + sm: "calc(var(--radius) - 4px)", + }, + fontFamily: { + sans: ["var(--font-sans)", ...fontFamily.sans], + }, + keyframes: { + "accordion-down": { + from: { height: 0 }, + to: { height: "var(--radix-accordion-content-height)" }, + }, + "accordion-up": { + from: { height: "var(--radix-accordion-content-height)" }, + to: { height: 0 }, + }, + }, + animation: { + "accordion-down": "accordion-down 0.2s ease-out", + "accordion-up": "accordion-up 0.2s ease-out", + }, }, }, variants: {