commit 0c21f55ddadd510b343e10456c6e9dd0f75f11e1 Author: Mathieu Virbel Date: Fri Jan 23 09:35:37 2026 -0500 feat: first approach from tanel diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f650315 --- /dev/null +++ b/.gitignore @@ -0,0 +1,27 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules + +# next.js +/.next/ +/out/ + +# production +/build + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# env files +.env* + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts \ No newline at end of file diff --git a/app/globals.css b/app/globals.css new file mode 100644 index 0000000..a0cb00b --- /dev/null +++ b/app/globals.css @@ -0,0 +1,210 @@ +@import 'tailwindcss'; +@import 'tw-animate-css'; + +@custom-variant dark (&:is(.dark *)); + +/* ============================================================================= + GREYHAVEN DESIGN TOKENS + Based on Greyhaven Brand Guidelines v1.0 + + Color Philosophy: + - Neutral and minimal scheme + - Off-black, warm grey, and white form the base + - Single accent (orange) used sparingly for active/important states + - No gradients, no decorative color + ============================================================================= */ + +:root { + /* Background & Foreground */ + --background: 240 240 236; /* Grey 1 #F0F0EC */ + --foreground: 22 22 20; /* Off-black #161614 */ + + /* Card */ + --card: 249 249 247; /* Off-white #F9F9F7 - elevated from background */ + --card-foreground: 22 22 20; + + /* Popover */ + --popover: 249 249 247; + --popover-foreground: 22 22 20; + + /* Primary - Orange accent (used sparingly) */ + --primary: 217 94 42; /* Orange #D95E2A */ + --primary-foreground: 249 249 247; /* Off-white */ + + /* Secondary */ + --secondary: 240 240 236; /* Grey 1 #F0F0EC */ + --secondary-foreground: 47 47 44; /* Grey 8 #2F2F2C */ + + /* Muted */ + --muted: 240 240 236; /* Grey 1 #F0F0EC */ + --muted-foreground: 87 87 83; /* Grey 7 #575753 */ + + /* Accent - Subtle grey for hover states */ + --accent: 221 221 215; /* Grey 2 #DDDDD7 */ + --accent-foreground: 22 22 20; /* Off-black */ + + /* Destructive */ + --destructive: 180 50 50; /* Muted red for destructive actions */ + --destructive-foreground: 249 249 247; + + /* Borders & Inputs */ + --border: 196 196 189; /* Grey 3 #C4C4BD */ + --input: 196 196 189; /* Grey 3 #C4C4BD */ + + /* Focus Ring */ + --ring: 217 94 42; /* Orange for focus states */ + + /* Charts - Warm neutral palette with orange accent */ + --chart-1: 217 94 42; /* Orange accent */ + --chart-2: 87 87 83; /* Grey 7 */ + --chart-3: 127 127 121; /* Grey 5 */ + --chart-4: 166 166 159; /* Grey 4 */ + --chart-5: 47 47 44; /* Grey 8 */ + + /* Radius - Tightened, no playful rounding */ + --radius: 0.375rem; + + /* Sidebar */ + --sidebar: 240 240 236; + --sidebar-foreground: 22 22 20; + --sidebar-primary: 217 94 42; + --sidebar-primary-foreground: 249 249 247; + --sidebar-accent: 196 196 189; + --sidebar-accent-foreground: 22 22 20; + --sidebar-border: 196 196 189; + --sidebar-ring: 217 94 42; +} + +/* ============================================================================= + DARK THEME + Guidelines: Negative/reverse usage via off-black and greys + ============================================================================= */ + +.dark { + /* Background & Foreground */ + --background: 22 22 20; /* Off-black #161614 */ + --foreground: 249 249 247; /* Off-white #F9F9F7 */ + + /* Card */ + --card: 47 47 44; /* Grey 8 #2F2F2C */ + --card-foreground: 249 249 247; + + /* Popover */ + --popover: 47 47 44; + --popover-foreground: 249 249 247; + + /* Primary - Orange accent (same in dark mode) */ + --primary: 217 94 42; /* Orange #D95E2A */ + --primary-foreground: 249 249 247; + + /* Secondary */ + --secondary: 87 87 83; /* Grey 7 #575753 */ + --secondary-foreground: 249 249 247; + + /* Muted */ + --muted: 87 87 83; /* Grey 7 #575753 */ + --muted-foreground: 196 196 189; /* Grey 3 #C4C4BD */ + + /* Accent - Subtle grey for hover states */ + --accent: 87 87 83; /* Grey 7 #575753 */ + --accent-foreground: 249 249 247; + + /* Destructive */ + --destructive: 180 50 50; + --destructive-foreground: 249 249 247; + + /* Borders & Inputs */ + --border: 87 87 83; /* Grey 7 */ + --input: 87 87 83; + + /* Focus Ring */ + --ring: 217 94 42; + + /* Charts */ + --chart-1: 217 94 42; + --chart-2: 196 196 189; + --chart-3: 166 166 159; + --chart-4: 127 127 121; + --chart-5: 240 240 236; + + /* Sidebar */ + --sidebar: 47 47 44; + --sidebar-foreground: 249 249 247; + --sidebar-primary: 217 94 42; + --sidebar-primary-foreground: 249 249 247; + --sidebar-accent: 87 87 83; + --sidebar-accent-foreground: 249 249 247; + --sidebar-border: 87 87 83; + --sidebar-ring: 217 94 42; +} + +/* ============================================================================= + THEME CONFIGURATION + Typography: Source Serif Pro (primary) + Aspekta (secondary/UI) + ============================================================================= */ + +@theme inline { + /* Typography - Using CSS variables from Next.js font loading */ + --font-sans: var(--font-inter), 'Inter', ui-sans-serif, system-ui, sans-serif; + --font-serif: var(--font-source-serif), 'Source Serif 4', 'Source Serif Pro', Georgia, serif; + --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; + + /* Color mappings */ + --color-background: rgb(var(--background)); + --color-foreground: rgb(var(--foreground)); + --color-card: rgb(var(--card)); + --color-card-foreground: rgb(var(--card-foreground)); + --color-popover: rgb(var(--popover)); + --color-popover-foreground: rgb(var(--popover-foreground)); + --color-primary: rgb(var(--primary)); + --color-primary-foreground: rgb(var(--primary-foreground)); + --color-secondary: rgb(var(--secondary)); + --color-secondary-foreground: rgb(var(--secondary-foreground)); + --color-muted: rgb(var(--muted)); + --color-muted-foreground: rgb(var(--muted-foreground)); + --color-accent: rgb(var(--accent)); + --color-accent-foreground: rgb(var(--accent-foreground)); + --color-destructive: rgb(var(--destructive)); + --color-destructive-foreground: rgb(var(--destructive-foreground)); + --color-border: rgb(var(--border)); + --color-input: rgb(var(--input)); + --color-ring: rgb(var(--ring)); + --color-chart-1: rgb(var(--chart-1)); + --color-chart-2: rgb(var(--chart-2)); + --color-chart-3: rgb(var(--chart-3)); + --color-chart-4: rgb(var(--chart-4)); + --color-chart-5: rgb(var(--chart-5)); + --radius-sm: calc(var(--radius) - 2px); + --radius-md: var(--radius); + --radius-lg: calc(var(--radius) + 2px); + --radius-xl: calc(var(--radius) + 4px); + --color-sidebar: rgb(var(--sidebar)); + --color-sidebar-foreground: rgb(var(--sidebar-foreground)); + --color-sidebar-primary: rgb(var(--sidebar-primary)); + --color-sidebar-primary-foreground: rgb(var(--sidebar-primary-foreground)); + --color-sidebar-accent: rgb(var(--sidebar-accent)); + --color-sidebar-accent-foreground: rgb(var(--sidebar-accent-foreground)); + --color-sidebar-border: rgb(var(--sidebar-border)); + --color-sidebar-ring: rgb(var(--sidebar-ring)); + + /* Greyhaven-specific colors for direct use */ + --color-greyhaven-orange: #D95E2A; + --color-greyhaven-offblack: #161614; + --color-greyhaven-offwhite: #F9F9F7; + --color-greyhaven-grey1: #F0F0EC; + --color-greyhaven-grey2: #DDDDD7; + --color-greyhaven-grey3: #C4C4BD; + --color-greyhaven-grey4: #A6A69F; + --color-greyhaven-grey5: #7F7F79; + --color-greyhaven-grey7: #575753; + --color-greyhaven-grey8: #2F2F2C; +} + +@layer base { + * { + @apply border-border outline-ring/50; + } + body { + @apply bg-background text-foreground; + } +} diff --git a/app/layout.tsx b/app/layout.tsx new file mode 100644 index 0000000..b9a7b25 --- /dev/null +++ b/app/layout.tsx @@ -0,0 +1,57 @@ +import type { Metadata } from 'next' +import { Source_Serif_4, Inter } from 'next/font/google' +import './globals.css' + +// Primary typeface: Source Serif Pro (using Source Serif 4 which is the updated version) +// Used for headings, body text, and reading content +const sourceSerif = Source_Serif_4({ + subsets: ["latin"], + variable: '--font-source-serif', + display: 'swap', +}) + +// Secondary typeface: Inter (Aspekta alternative from Google Fonts) +// Aspekta is the brand typeface, Inter is a suitable system alternative +// Used for UI labels, nav, buttons, small utility text +const inter = Inter({ + subsets: ["latin"], + variable: '--font-inter', + display: 'swap', +}) + +export const metadata: Metadata = { + title: 'Greyhaven Design System', + description: 'Visual Identity and Brand Guidelines - Greyhaven', + generator: 'v0.app', + icons: { + icon: [ + { + url: '/icon-light-32x32.png', + media: '(prefers-color-scheme: light)', + }, + { + url: '/icon-dark-32x32.png', + media: '(prefers-color-scheme: dark)', + }, + { + url: '/icon.svg', + type: 'image/svg+xml', + }, + ], + apple: '/apple-icon.png', + }, +} + +export default function RootLayout({ + children, +}: Readonly<{ + children: React.ReactNode +}>) { + return ( + + + {children} + + + ) +} diff --git a/app/page.tsx b/app/page.tsx new file mode 100644 index 0000000..824c7f1 --- /dev/null +++ b/app/page.tsx @@ -0,0 +1,148 @@ +"use client" + +import { useState } from "react" +import { ColorSwatches } from "@/components/design-system/color-swatches" +import { TypographySamples } from "@/components/design-system/typography-samples" +import { ComponentMatrix } from "@/components/design-system/component-matrix" +import { SampleForm } from "@/components/design-system/sample-form" +import { SettingsCard } from "@/components/design-system/settings-card" +import { Button } from "@/components/ui/button" +import { Moon, Sun } from "lucide-react" + +export default function DesignSystemPage() { + const [theme, setTheme] = useState<"light" | "dark">("light") + + const toggleTheme = () => { + const newTheme = theme === "light" ? "dark" : "light" + setTheme(newTheme) + document.documentElement.classList.toggle("dark", newTheme === "dark") + } + + return ( +
+ {/* Header */} +
+
+ + + + + + + + + + + + + + + + + + + + +
+
+ + {/* Main Content */} +
+ {/* Color Tokens */} +
+ + +
+ + {/* Typography */} +
+ + +
+ + {/* Component Matrix */} +
+ + +
+ + {/* Real-World Examples */} +
+ + +
+ {/* Consultation Form */} +
+

+ Consultation Request Form +

+ +
+ + {/* Settings Card */} +
+

+ System Settings +

+ +
+
+
+ + +
+ + {/* Footer */} + +
+ ) +} + +function SectionHeader({ title, description }: { title: string; description: string }) { + return ( +
+

{title}

+

{description}

+
+ ) +} diff --git a/components.json b/components.json new file mode 100644 index 0000000..4ee62ee --- /dev/null +++ b/components.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "new-york", + "rsc": true, + "tsx": true, + "tailwind": { + "config": "", + "css": "app/globals.css", + "baseColor": "neutral", + "cssVariables": true, + "prefix": "" + }, + "aliases": { + "components": "@/components", + "utils": "@/lib/utils", + "ui": "@/components/ui", + "lib": "@/lib", + "hooks": "@/hooks" + }, + "iconLibrary": "lucide" +} diff --git a/components/design-system/color-swatches.tsx b/components/design-system/color-swatches.tsx new file mode 100644 index 0000000..1be57d6 --- /dev/null +++ b/components/design-system/color-swatches.tsx @@ -0,0 +1,102 @@ +export function ColorSwatches() { + const primaryColors = [ + { name: "Off-white", hex: "#F9F9F7", rgb: "249 249 247", token: "--card" }, + { name: "Off-black", hex: "#161614", rgb: "22 22 20", token: "--foreground", dark: true }, + { name: "Orange", hex: "#D95E2A", rgb: "217 94 42", token: "--primary", dark: true }, + ] + + const greyScale = [ + { name: "Grey 1 (5%)", hex: "#F0F0EC", rgb: "240 240 236" }, + { name: "Grey 2 (10%)", hex: "#DDDDD7", rgb: "221 221 215" }, + { name: "Grey 3 (20%)", hex: "#C4C4BD", rgb: "196 196 189" }, + { name: "Grey 4 (50%)", hex: "#A6A69F", rgb: "166 166 159" }, + { name: "Grey 5 (60%)", hex: "#7F7F79", rgb: "127 127 121", dark: true }, + { name: "Grey 7 (70%)", hex: "#575753", rgb: "87 87 83", dark: true }, + { name: "Grey 8 (80%)", hex: "#2F2F2C", rgb: "47 47 44", dark: true }, + ] + + const semanticTokens = [ + { name: "Background", cssVar: "bg-background", className: "bg-background" }, + { name: "Foreground", cssVar: "bg-foreground", className: "bg-foreground", dark: true }, + { name: "Card", cssVar: "bg-card", className: "bg-card" }, + { name: "Muted", cssVar: "bg-muted", className: "bg-muted" }, + { name: "Secondary", cssVar: "bg-secondary", className: "bg-secondary" }, + { name: "Primary", cssVar: "bg-primary", className: "bg-primary", dark: true }, + { name: "Accent", cssVar: "bg-accent", className: "bg-accent" }, + { name: "Border", cssVar: "bg-border", className: "bg-border" }, + ] + + return ( +
+ {/* Primary Scheme */} +
+

+ Primary Scheme +

+
+ {primaryColors.map((color) => ( +
+
+ + {color.hex} + +
+
+

{color.name}

+

{color.token}

+
+
+ ))} +
+
+ + {/* Grey Scale */} +
+

+ Grey Scale +

+
+ {greyScale.map((color) => ( +
+
+ + {color.hex} + +
+
+

{color.name}

+
+
+ ))} +
+
+ + {/* Semantic Tokens */} +
+

+ Semantic Tokens +

+
+ {semanticTokens.map((token) => ( +
+
+ + {token.name} + +
+
+

{token.cssVar}

+
+
+ ))} +
+
+
+ ) +} diff --git a/components/design-system/component-matrix.tsx b/components/design-system/component-matrix.tsx new file mode 100644 index 0000000..622b500 --- /dev/null +++ b/components/design-system/component-matrix.tsx @@ -0,0 +1,488 @@ +"use client" + +import { Button } from "@/components/ui/button" +import { Input } from "@/components/ui/input" +import { Textarea } from "@/components/ui/textarea" +import { Checkbox } from "@/components/ui/checkbox" +import { Switch } from "@/components/ui/switch" +import { Badge } from "@/components/ui/badge" +import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select" +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from "@/components/ui/tooltip" +import { Label } from "@/components/ui/label" +import { + Plus, + Trash2, + Settings, + Mail, + Send, + Download, + Search, + X, + Check, + ChevronRight, + Edit, + Copy +} from "lucide-react" + +export function ComponentMatrix() { + return ( + +
+ {/* Buttons - All Variants */} +
+

+ Buttons — Variants +

+
+
+
+

Primary

+ +
+
+

Secondary

+ +
+
+

Outline

+ +
+
+

Ghost

+ +
+
+

Link

+ +
+
+

Destructive

+ +
+
+
+
+ + {/* Buttons - Sizes */} +
+

+ Buttons — Sizes +

+
+
+
+

Small

+ +
+
+

Default

+ +
+
+

Large

+ +
+
+
+
+ + {/* Buttons - States */} +
+

+ Buttons — States +

+
+
+ {/* Primary States */} +
+

Primary

+
+ + + + + +
+
+ {/* Outline States */} +
+

Outline

+
+ + + + +
+
+ {/* Destructive States */} +
+

Destructive

+
+ + + + +
+
+
+
+
+ + {/* Icon Buttons */} +
+

+ Icon Buttons +

+
+
+ {/* By Variant */} +
+

Variants

+
+ + + + + +
+
+ {/* By Size */} +
+

Sizes

+
+ + + +
+
+ {/* Disabled */} +
+

Disabled

+
+ + + +
+
+
+
+
+ + {/* Buttons with Icons */} +
+

+ Buttons with Icons +

+
+
+ {/* Leading Icons */} +
+

Leading Icon

+
+ + + + +
+
+ {/* Trailing Icons */} +
+

Trailing Icon

+
+ + + +
+
+ {/* Size Variations */} +
+

Sizes with Icons

+
+ + + +
+
+
+
+
+ + {/* Badges - Core Variants */} +
+

+ Badges — Core Variants +

+
+
+ Default + Secondary + Muted + Outline +
+
+
+ + {/* Badges - Tag & Value */} +
+

+ Badges — Tag & Value +

+
+
+ Tag + Category + 42 + $1,234 + 100% +
+
+
+ + {/* Badges - Semantic */} +
+

+ Badges — Semantic +

+
+
+ Success + Warning + Danger + Info +
+
+
+ + {/* Badges - Channel Pills */} +
+

+ Badges — Channel Pills +

+
+
+ WhatsApp + Email + Telegram + Zulip + Platform +
+
+
+ + {/* Badges on Muted Surface */} +
+

+ Badges — On Muted Surface +

+
+
+ Default + Secondary + Outline + Tag + Success + Info +
+
+
+ + {/* Inputs */} +
+

+ Inputs +

+
+
+
+

Default

+ +
+
+

With Value

+ +
+
+

Disabled

+ +
+
+ +
+

Textarea

+
+