design system token v0.1

This commit is contained in:
Juan
2026-04-13 15:33:00 -05:00
parent 52b4156653
commit c3215945f2
63 changed files with 11562 additions and 181 deletions

View File

@@ -0,0 +1,111 @@
import type { Meta, StoryObj } from '@storybook/react'
import { CTASection } from '@/components/ui/cta-section'
import { Button } from '@/components/ui/button'
const meta = {
title: 'Composition/CTASection',
component: CTASection,
tags: ['autodocs'],
parameters: { layout: 'fullscreen' },
argTypes: {
variant: {
control: 'select',
options: ['centered', 'left-aligned'],
},
background: {
control: 'select',
options: ['default', 'muted', 'accent', 'subtle'],
},
},
} satisfies Meta<typeof CTASection>
export default meta
type Story = StoryObj<typeof meta>
const defaultActions = (
<>
<Button size="lg">Get Started</Button>
<Button size="lg" variant="outline">Contact Sales</Button>
</>
)
export const Default: Story = {
args: {
heading: 'Ready to get started?',
description: 'Join thousands of teams building better products with our design system.',
actions: defaultActions,
},
}
export const Centered: Story = {
args: {
variant: 'centered',
background: 'muted',
heading: 'Start building today',
description: 'Free for open source. Affordable for teams.',
actions: defaultActions,
},
}
export const LeftAligned: Story = {
args: {
variant: 'left-aligned',
background: 'muted',
heading: 'Need help getting started?',
description: 'Our team is ready to help you integrate the design system into your project.',
actions: (
<>
<Button size="lg">Talk to us</Button>
</>
),
},
}
export const AccentBackground: Story = {
args: {
variant: 'centered',
background: 'accent',
heading: 'Upgrade your workflow',
description: 'Take your team to the next level with our premium plan.',
actions: (
<>
<Button size="lg" variant="secondary">Start Free Trial</Button>
<Button
size="lg"
variant="outline"
className="border-primary-foreground/20 text-primary-foreground hover:bg-primary-foreground/10"
>
Learn More
</Button>
</>
),
},
}
export const SubtleBackground: Story = {
args: {
variant: 'centered',
background: 'subtle',
heading: 'Stay in the loop',
description: 'Subscribe to our newsletter for the latest updates and releases.',
actions: (
<Button size="lg">Subscribe</Button>
),
},
}
export const DefaultBackground: Story = {
args: {
variant: 'centered',
background: 'default',
heading: 'Questions? We have answers.',
description: 'Check out our documentation or reach out to our support team.',
actions: (
<>
<Button size="lg">View Docs</Button>
<Button size="lg" variant="ghost">Contact Support</Button>
</>
),
},
}

View File

@@ -0,0 +1,92 @@
import type { Meta, StoryObj } from '@storybook/react'
import { Footer } from '@/components/ui/footer'
import { Logo } from '@/components/ui/logo'
import { Button } from '@/components/ui/button'
const meta = {
title: 'Composition/Footer',
component: Footer,
tags: ['autodocs'],
parameters: { layout: 'fullscreen' },
argTypes: {
variant: {
control: 'select',
options: ['minimal', 'full'],
},
},
} satisfies Meta<typeof Footer>
export default meta
type Story = StoryObj<typeof meta>
export const Minimal: Story = {
args: {
variant: 'minimal',
logo: <Logo size="sm" />,
copyright: <>&copy; 2026 Greyhaven. All rights reserved.</>,
actions: (
<div className="flex gap-4 text-sm text-muted-foreground">
<a href="#" className="hover:text-foreground transition-colors">Privacy</a>
<a href="#" className="hover:text-foreground transition-colors">Terms</a>
<a href="#" className="hover:text-foreground transition-colors">Contact</a>
</div>
),
},
}
export const Full: Story = {
args: {
variant: 'full',
logo: <Logo size="md" />,
copyright: <>&copy; 2026 Greyhaven. All rights reserved.</>,
linkGroups: [
{
title: 'Product',
links: [
{ label: 'Features', href: '#' },
{ label: 'Pricing', href: '#' },
{ label: 'Changelog', href: '#' },
{ label: 'Docs', href: '#' },
],
},
{
title: 'Company',
links: [
{ label: 'About', href: '#' },
{ label: 'Blog', href: '#' },
{ label: 'Careers', href: '#' },
{ label: 'Contact', href: '#' },
],
},
{
title: 'Legal',
links: [
{ label: 'Privacy Policy', href: '#' },
{ label: 'Terms of Service', href: '#' },
{ label: 'Cookie Policy', href: '#' },
],
},
],
actions: (
<div className="flex gap-2">
<Button variant="ghost" size="sm">Twitter</Button>
<Button variant="ghost" size="sm">GitHub</Button>
<Button variant="ghost" size="sm">Discord</Button>
</div>
),
},
}
export const MinimalNoCopyright: Story = {
args: {
variant: 'minimal',
logo: <Logo size="sm" />,
actions: (
<div className="flex gap-4 text-sm text-muted-foreground">
<a href="#" className="hover:text-foreground transition-colors">Docs</a>
<a href="#" className="hover:text-foreground transition-colors">GitHub</a>
</div>
),
},
}

View File

@@ -0,0 +1,111 @@
import type { Meta, StoryObj } from '@storybook/react'
import { Hero } from '@/components/ui/hero'
import { Button } from '@/components/ui/button'
const meta = {
title: 'Composition/Hero',
component: Hero,
tags: ['autodocs'],
parameters: { layout: 'fullscreen' },
argTypes: {
variant: {
control: 'select',
options: ['centered', 'left-aligned', 'split'],
},
background: {
control: 'select',
options: ['default', 'muted', 'accent', 'dark'],
},
},
} satisfies Meta<typeof Hero>
export default meta
type Story = StoryObj<typeof meta>
const defaultActions = (
<>
<Button size="lg">Get Started</Button>
<Button size="lg" variant="outline">Learn More</Button>
</>
)
export const Centered: Story = {
args: {
variant: 'centered',
heading: 'Build better products with Greyhaven',
subheading:
'A modern design system that helps you create consistent, accessible, and beautiful user interfaces.',
actions: defaultActions,
},
}
export const LeftAligned: Story = {
args: {
variant: 'left-aligned',
heading: 'Ship faster with confidence',
subheading:
'Pre-built components, design tokens, and patterns so your team can focus on what matters.',
actions: defaultActions,
},
}
export const Split: Story = {
args: {
variant: 'split',
heading: 'Design meets engineering',
subheading:
'Bridging the gap between design and code with a shared language of components and tokens.',
actions: defaultActions,
media: (
<div className="w-full aspect-video bg-muted rounded-lg flex items-center justify-center text-muted-foreground">
Image / Media Placeholder
</div>
),
},
}
export const MutedBackground: Story = {
args: {
variant: 'centered',
background: 'muted',
heading: 'Welcome to the platform',
subheading: 'Everything you need to build and scale your project.',
actions: defaultActions,
},
}
export const AccentBackground: Story = {
args: {
variant: 'centered',
background: 'accent',
heading: 'Start building today',
subheading: 'Join thousands of developers using our design system.',
actions: defaultActions,
},
}
export const DarkBackground: Story = {
args: {
variant: 'centered',
background: 'dark',
heading: 'The future of design systems',
subheading: 'A bold new approach to building consistent user interfaces at scale.',
actions: (
<>
<Button size="lg" variant="secondary">Get Started</Button>
<Button size="lg" variant="outline" className="border-background/20 text-background hover:bg-background/10">
Learn More
</Button>
</>
),
},
}
export const WithoutActions: Story = {
args: {
variant: 'centered',
heading: 'A hero section without action buttons',
subheading: 'Sometimes you just need a heading and description.',
},
}

View File

@@ -0,0 +1,167 @@
import type { Meta, StoryObj } from '@storybook/react'
import { PageLayout } from '@/components/ui/page-layout'
import { Navbar, NavbarLink } from '@/components/ui/navbar'
import { Footer } from '@/components/ui/footer'
import { Hero } from '@/components/ui/hero'
import { Section } from '@/components/ui/section'
import { CTASection } from '@/components/ui/cta-section'
import { Logo } from '@/components/ui/logo'
import { Button } from '@/components/ui/button'
import {
Card,
CardHeader,
CardTitle,
CardDescription,
CardContent,
} from '@/components/ui/card'
const meta = {
title: 'Composition/PageLayout',
component: PageLayout,
tags: ['autodocs'],
parameters: { layout: 'fullscreen' },
} satisfies Meta<typeof PageLayout>
export default meta
type Story = StoryObj<typeof meta>
const navLinks = (
<>
<NavbarLink href="#" active>Home</NavbarLink>
<NavbarLink href="#">Features</NavbarLink>
<NavbarLink href="#">Pricing</NavbarLink>
<NavbarLink href="#">Docs</NavbarLink>
</>
)
const navActions = (
<>
<Button variant="ghost" size="sm">Log in</Button>
<Button size="sm">Sign up</Button>
</>
)
const sampleNavbar = (
<Navbar
variant="solid"
logo={<Logo size="sm" />}
actions={navActions}
>
{navLinks}
</Navbar>
)
const sampleFooter = (
<Footer
variant="minimal"
logo={<Logo size="sm" />}
copyright={<>&copy; 2026 Greyhaven. All rights reserved.</>}
actions={
<div className="flex gap-4 text-sm text-muted-foreground">
<a href="#" className="hover:text-foreground transition-colors">Privacy</a>
<a href="#" className="hover:text-foreground transition-colors">Terms</a>
</div>
}
/>
)
export const FullPage: Story = {
args: {
navbar: sampleNavbar,
footer: sampleFooter,
children: (
<>
<Hero
variant="centered"
heading="Build something great"
subheading="A complete design system for modern web applications."
actions={
<>
<Button size="lg">Get Started</Button>
<Button size="lg" variant="outline">View Docs</Button>
</>
}
/>
<Section
title="Features"
description="Everything you need to build beautiful interfaces."
>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
{['Components', 'Tokens', 'Patterns'].map((title) => (
<Card key={title}>
<CardHeader>
<CardTitle>{title}</CardTitle>
<CardDescription>
Pre-built {title.toLowerCase()} for rapid development.
</CardDescription>
</CardHeader>
<CardContent>
<p className="text-sm text-muted-foreground">
Fully customizable {title.toLowerCase()} that follow best practices.
</p>
</CardContent>
</Card>
))}
</div>
</Section>
<CTASection
background="muted"
heading="Ready to start?"
description="Get up and running in minutes."
actions={<Button size="lg">Get Started Free</Button>}
/>
</>
),
},
}
export const WithSidebar: Story = {
args: {
navbar: sampleNavbar,
footer: sampleFooter,
sidebar: (
<nav className="p-4 space-y-2">
<h3 className="font-semibold text-sm mb-4">Navigation</h3>
{['Dashboard', 'Projects', 'Team', 'Settings'].map((item) => (
<a
key={item}
href="#"
className="block px-3 py-2 text-sm rounded-md text-muted-foreground hover:text-foreground hover:bg-accent transition-colors"
>
{item}
</a>
))}
</nav>
),
children: (
<Section title="Dashboard" description="Overview of your workspace.">
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
{['Revenue', 'Users', 'Orders', 'Growth'].map((metric) => (
<Card key={metric}>
<CardHeader>
<CardTitle>{metric}</CardTitle>
<CardDescription>Last 30 days</CardDescription>
</CardHeader>
<CardContent>
<p className="text-2xl font-bold">1,234</p>
</CardContent>
</Card>
))}
</div>
</Section>
),
},
}
export const ContentOnly: Story = {
args: {
children: (
<Section title="Standalone Content" description="A page layout with no navbar or footer.">
<p className="text-muted-foreground">
This demonstrates the PageLayout component with only content, no navbar, sidebar, or footer.
</p>
</Section>
),
},
}

View File

@@ -0,0 +1,135 @@
import type { Meta, StoryObj } from '@storybook/react'
import { Section } from '@/components/ui/section'
import {
Card,
CardHeader,
CardTitle,
CardDescription,
CardContent,
} from '@/components/ui/card'
const meta = {
title: 'Composition/Section',
component: Section,
tags: ['autodocs'],
parameters: { layout: 'fullscreen' },
argTypes: {
variant: {
control: 'select',
options: ['default', 'highlighted', 'accent'],
},
width: {
control: 'select',
options: ['narrow', 'default', 'wide', 'full'],
},
},
} satisfies Meta<typeof Section>
export default meta
type Story = StoryObj<typeof meta>
const sampleCards = (
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
{['Design', 'Develop', 'Deploy'].map((title) => (
<Card key={title}>
<CardHeader>
<CardTitle>{title}</CardTitle>
<CardDescription>Description for the {title.toLowerCase()} phase.</CardDescription>
</CardHeader>
<CardContent>
<p className="text-sm text-muted-foreground">
Content explaining the {title.toLowerCase()} process in detail.
</p>
</CardContent>
</Card>
))}
</div>
)
export const Default: Story = {
args: {
title: 'Our Process',
description: 'How we build great products from concept to delivery.',
children: sampleCards,
},
}
export const Highlighted: Story = {
args: {
variant: 'highlighted',
title: 'Featured Section',
description: 'This section uses a highlighted background to stand out.',
children: sampleCards,
},
}
export const Accent: Story = {
args: {
variant: 'accent',
title: 'Accent Section',
description: 'A subtle accent background to differentiate this area.',
children: sampleCards,
},
}
export const Narrow: Story = {
args: {
width: 'narrow',
title: 'Narrow Section',
description: 'Constrained width for focused reading.',
children: (
<p className="text-muted-foreground">
This is a narrow section with max-w-3xl. Useful for text-heavy content that
benefits from shorter line lengths for readability.
</p>
),
},
}
export const Wide: Story = {
args: {
width: 'wide',
title: 'Wide Section',
description: 'Extended width for content-rich layouts.',
children: sampleCards,
},
}
export const Full: Story = {
args: {
width: 'full',
variant: 'highlighted',
title: 'Full Width Section',
description: 'Spans the full width of the viewport.',
children: sampleCards,
},
}
export const NoHeader: Story = {
args: {
children: sampleCards,
},
}
export const AllCombinations: Story = {
render: () => (
<div>
{(['default', 'highlighted', 'accent'] as const).map((variant) =>
(['narrow', 'default', 'wide'] as const).map((width) => (
<Section
key={`${variant}-${width}`}
variant={variant}
width={width}
title={`${variant} / ${width}`}
description={`Section with variant="${variant}" and width="${width}".`}
>
<div className="h-20 rounded-lg border-2 border-dashed border-muted-foreground/25 flex items-center justify-center text-sm text-muted-foreground">
Content area
</div>
</Section>
)),
)}
</div>
),
}