feat: first approach from tanel
This commit is contained in:
210
app/globals.css
Normal file
210
app/globals.css
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
57
app/layout.tsx
Normal file
57
app/layout.tsx
Normal file
@@ -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 (
|
||||
<html lang="en" className={`${sourceSerif.variable} ${inter.variable}`}>
|
||||
<body className="font-sans antialiased bg-background text-foreground">
|
||||
{children}
|
||||
</body>
|
||||
</html>
|
||||
)
|
||||
}
|
||||
148
app/page.tsx
Normal file
148
app/page.tsx
Normal file
@@ -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 (
|
||||
<div className="min-h-screen bg-background text-foreground">
|
||||
{/* Header */}
|
||||
<header className="border-b border-border bg-background sticky top-0 z-10">
|
||||
<div className="container mx-auto px-6 py-6 flex items-center justify-between">
|
||||
<svg width="1818" height="448" viewBox="0 0 1818 448" fill="none" xmlns="http://www.w3.org/2000/svg" className="h-[41px] w-auto">
|
||||
<g clipPath="url(#clip0_13_1414)">
|
||||
<path d="M625.8 313.476L623.156 286.907C614.009 302.244 592.449 317.924 559.067 317.924C504.436 317.924 455.996 277.76 455.996 208.662C455.996 139.564 507.08 99.7111 561.4 99.7111C612.204 99.7111 644.684 128.956 655.884 163.489L622.502 176.182C615.409 152.569 594.751 132.471 561.369 132.471C527.987 132.471 491.991 156.676 491.991 208.662C491.991 260.649 525.062 285.444 561.089 285.444C603.307 285.444 619.267 256.511 621.04 238.498H551.942V207.48H654.422V313.476H625.769H625.8Z" className="fill-foreground"/>
|
||||
<path d="M771.649 203.622C767.822 203.031 763.964 202.751 760.418 202.751C733.849 202.751 721.747 218.089 721.747 244.969V313.476H687.493V169.68H720.876V192.702C727.658 177.053 743.618 167.907 762.502 167.907C766.64 167.907 770.187 168.498 771.649 168.778V203.622Z" className="fill-foreground"/>
|
||||
<path d="M919.582 272.44C911.898 297.547 889.156 317.924 854.622 317.924C815.64 317.924 781.107 289.582 781.107 240.862C781.107 195.378 814.769 165.262 851.076 165.262C895.378 165.262 921.356 194.507 921.356 239.96C921.356 245.56 920.764 250.289 920.453 250.88H815.329C816.2 272.72 833.342 288.369 854.591 288.369C875.84 288.369 885.889 277.449 890.618 263.262L919.551 272.409L919.582 272.44ZM886.822 225.773C886.231 208.942 875 193.884 851.387 193.884C829.827 193.884 817.444 210.404 816.262 225.773H886.822Z" className="fill-foreground"/>
|
||||
<path d="M949.542 371.653L984.107 296.364L922.693 169.68H961.365L1002.71 260.618L1041.38 169.68H1077.69L986.16 371.653H949.542Z" className="fill-foreground"/>
|
||||
<path d="M1128.09 313.476H1093.84V99.68H1128.09V183.556C1137.83 170.862 1154.07 165.542 1169.12 165.542C1204.56 165.542 1221.67 190.929 1221.67 222.538V313.476H1187.42V228.418C1187.42 210.684 1179.45 196.529 1157.89 196.529C1139.01 196.529 1128.65 210.684 1128.06 229.009V313.476H1128.09Z" className="fill-foreground"/>
|
||||
<path d="M1288.56 231.093L1325.46 225.493C1333.73 224.311 1336.1 220.173 1336.1 215.164C1336.1 203.062 1327.82 193.324 1308.94 193.324C1290.05 193.324 1280.88 204.836 1279.41 219.302L1248.12 212.209C1250.76 187.413 1273.22 165.262 1308.66 165.262C1352.96 165.262 1369.79 190.369 1369.79 218.991V290.453C1369.79 303.458 1371.28 312.013 1371.56 313.476H1339.68C1339.4 312.573 1338.21 306.693 1338.21 295.151C1331.43 306.071 1317.24 317.893 1293.91 317.893C1263.8 317.893 1245.19 297.236 1245.19 274.493C1245.19 248.796 1264.08 234.64 1288.59 231.093H1288.56ZM1336.1 253.836V247.333L1298.61 252.933C1287.97 254.707 1279.41 260.618 1279.41 272.44C1279.41 282.178 1286.79 291.044 1300.38 291.044C1319.58 291.044 1336.1 281.898 1336.1 253.836Z" className="fill-foreground"/>
|
||||
<path d="M1465.52 313.476H1431.27L1372.81 169.68H1410.61L1448.69 272.44L1485.9 169.68H1521.92L1465.52 313.476Z" className="fill-foreground"/>
|
||||
<path d="M1663.08 272.44C1655.39 297.547 1632.65 317.924 1598.12 317.924C1559.13 317.924 1524.6 289.582 1524.6 240.862C1524.6 195.378 1558.26 165.262 1594.57 165.262C1638.87 165.262 1664.85 194.507 1664.85 239.96C1664.85 245.56 1664.26 250.289 1663.95 250.88H1558.82C1559.69 272.72 1576.84 288.369 1598.08 288.369C1619.33 288.369 1629.38 277.449 1634.11 263.262L1663.04 272.409L1663.08 272.44ZM1630.28 225.773C1629.69 208.942 1618.46 193.884 1594.85 193.884C1573.29 193.884 1560.91 210.404 1559.72 225.773H1630.28Z" className="fill-foreground"/>
|
||||
<path d="M1724.12 313.476H1689.86V169.68H1723.24V188.876C1732.7 172.356 1749.81 165.542 1765.77 165.542C1800.9 165.542 1817.73 190.929 1817.73 222.538V313.476H1783.48V228.418C1783.48 210.684 1775.51 196.529 1753.95 196.529C1734.48 196.529 1724.12 211.587 1724.12 230.471V313.444V313.476Z" className="fill-foreground"/>
|
||||
<path d="M345.582 100.551L287.498 66.4533H284.356L232.462 96.9111V34.0978L174.378 0H171.236L113.151 34.0978V96.9111L61.2578 66.4533H58.1156L0 100.551V102.791V347.013L58.0844 381.609H61.2578L113.12 350.747V413.467L171.204 448.062H174.378L232.462 413.467V350.747L284.324 381.609H287.498L345.582 347.013V100.551ZM59.6711 72.7378L111.627 103.258L59.6711 134.182L7.71556 103.258L59.6711 72.7378ZM6.22222 109.604L56.56 139.564V308.436L6.22222 337.991V109.604ZM56.56 315.653V373.427L7.71556 344.338L56.56 315.653ZM62.7822 373.427V315.653L111.627 344.338L62.7822 373.427ZM113.12 337.991L62.7822 308.436V139.564L113.12 109.604V337.991ZM226.24 102.791V163.333L175.902 133.778V73.1422L226.24 43.1822V102.791ZM172.791 200.604L120.836 169.68L172.791 139.16L224.747 169.68L172.791 200.604ZM175.902 65.8933V8.12L224.747 36.8044L175.902 65.8933ZM169.68 8.12V65.8933L120.836 36.8044L169.68 8.12ZM119.342 43.1511L169.68 73.1111V133.747L119.342 163.302V43.1511ZM119.342 176.027L169.68 205.987V374.858L119.342 404.413V176.027ZM169.68 382.076V439.849L120.836 410.76L169.68 382.076ZM175.902 439.849V382.076L224.747 410.76L175.902 439.849ZM226.24 404.413L175.902 374.858V205.987L226.24 176.027V404.413ZM289.022 74.5733L337.867 103.258L289.022 132.347V74.5733ZM282.8 74.5733V132.347L233.956 103.258L282.8 74.5733ZM232.462 109.604L282.8 139.564V308.436L232.462 337.991V109.604ZM285.911 375.293L233.956 344.338L285.911 313.818L337.867 344.338L285.911 375.293ZM339.36 337.991L289.022 308.436V139.564L339.36 109.604V337.991Z" className="fill-foreground"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_13_1414">
|
||||
<rect width="1817.73" height="448" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={toggleTheme}
|
||||
className="rounded-md bg-transparent"
|
||||
>
|
||||
{theme === "light" ? (
|
||||
<Moon className="h-4 w-4" />
|
||||
) : (
|
||||
<Sun className="h-4 w-4" />
|
||||
)}
|
||||
<span className="sr-only">Toggle theme</span>
|
||||
</Button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
{/* Main Content */}
|
||||
<main className="container mx-auto px-6 py-8">
|
||||
{/* Color Tokens */}
|
||||
<section className="mb-16">
|
||||
<SectionHeader
|
||||
title="Color Tokens"
|
||||
description="A restrained set of warm greys, off-black, and muted neutrals, with orange as the only accent."
|
||||
/>
|
||||
<ColorSwatches />
|
||||
</section>
|
||||
|
||||
{/* Typography */}
|
||||
<section className="mb-16">
|
||||
<SectionHeader
|
||||
title="Typography"
|
||||
description="Source Serif Pro for explanation and human-readable detail. Aspekta (displayed as Inter) for structure, navigation, and UI."
|
||||
/>
|
||||
<TypographySamples />
|
||||
</section>
|
||||
|
||||
{/* Component Matrix */}
|
||||
<section className="mb-16">
|
||||
<SectionHeader
|
||||
title="Component Library"
|
||||
description="Interactive elements with consistent styling across all states: default, hover, active, disabled."
|
||||
/>
|
||||
<ComponentMatrix />
|
||||
</section>
|
||||
|
||||
{/* Real-World Examples */}
|
||||
<section className="mb-16">
|
||||
<SectionHeader
|
||||
title="Real-World Examples"
|
||||
description="Complete UI patterns demonstrating how components work together in production."
|
||||
/>
|
||||
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
||||
{/* Consultation Form */}
|
||||
<div>
|
||||
<h4 className="font-sans text-sm font-semibold uppercase tracking-wide text-muted-foreground mb-4">
|
||||
Consultation Request Form
|
||||
</h4>
|
||||
<SampleForm />
|
||||
</div>
|
||||
|
||||
{/* Settings Card */}
|
||||
<div>
|
||||
<h4 className="font-sans text-sm font-semibold uppercase tracking-wide text-muted-foreground mb-4">
|
||||
System Settings
|
||||
</h4>
|
||||
<SettingsCard />
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
</main>
|
||||
|
||||
{/* Footer */}
|
||||
<footer className="border-t border-border py-8 bg-background">
|
||||
<div className="container mx-auto px-6">
|
||||
<div className="flex flex-col md:flex-row items-center justify-between gap-4">
|
||||
<p className="text-sm text-muted-foreground font-sans">
|
||||
Greyhaven Component Library v1.0
|
||||
</p>
|
||||
<div className="flex gap-6 font-sans text-sm">
|
||||
<a href="https://www.figma.com/slides/4batSeN5uxKYZZhizqOUIt/greyhaven---brand-guidelines?node-id=1-391&t=15wmJ30uBUDhIQXA-1" target="_blank" rel="noopener noreferrer" className="text-muted-foreground hover:text-primary transition-colors">
|
||||
Brand Guidelines
|
||||
</a>
|
||||
<a href="https://github.com/Monadical-SAS" target="_blank" rel="noopener noreferrer" className="text-muted-foreground hover:text-primary transition-colors">
|
||||
GitHub
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function SectionHeader({ title, description }: { title: string; description: string }) {
|
||||
return (
|
||||
<div className="mb-8">
|
||||
<h3 className="font-serif text-3xl font-semibold tracking-tight mb-3">{title}</h3>
|
||||
<p className="text-muted-foreground font-sans text-base max-w-2xl">{description}</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user