design system token v0.6
This commit is contained in:
@@ -61,7 +61,7 @@
|
||||
| `color.dark.primary-foreground` | `#f9f9f7` | Dark primary foreground |
|
||||
| `color.dark.secondary` | `#575753` | Dark secondary |
|
||||
| `color.dark.secondary-foreground` | `#f9f9f7` | Dark secondary text |
|
||||
| `color.dark.muted` | `#575753` | Dark muted |
|
||||
| `color.dark.muted` | `#2f2f2c` | Dark muted — grey.8 (distinct from grey.7 border so outlines on bg-muted surfaces remain visible) |
|
||||
| `color.dark.muted-foreground` | `#c4c4bd` | Dark muted text |
|
||||
| `color.dark.accent` | `#575753` | Dark accent/hover |
|
||||
| `color.dark.accent-foreground` | `#f9f9f7` | Dark accent text |
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
--secondary: 87 87 83;
|
||||
/* Dark secondary text */
|
||||
--secondary-foreground: 249 249 247;
|
||||
/* Dark muted */
|
||||
--muted: 87 87 83;
|
||||
/* Dark muted — grey.8 (distinct from grey.7 border so outlines on bg-muted surfaces remain visible) */
|
||||
--muted: 47 47 44;
|
||||
/* Dark muted text */
|
||||
--muted-foreground: 196 196 189;
|
||||
/* Dark accent/hover */
|
||||
|
||||
@@ -56,7 +56,7 @@ export const ColorTokens = {
|
||||
'dark.primary-foreground': '#f9f9f7',
|
||||
'dark.secondary': '#575753',
|
||||
'dark.secondary-foreground': '#f9f9f7',
|
||||
'dark.muted': '#575753',
|
||||
'dark.muted': '#2f2f2c',
|
||||
'dark.muted-foreground': '#c4c4bd',
|
||||
'dark.accent': '#575753',
|
||||
'dark.accent-foreground': '#f9f9f7',
|
||||
|
||||
63
components/ui/code.tsx
Normal file
63
components/ui/code.tsx
Normal file
@@ -0,0 +1,63 @@
|
||||
import * as React from 'react'
|
||||
import { cva, type VariantProps } from 'class-variance-authority'
|
||||
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const codeVariants = cva(
|
||||
'bg-muted border border-border font-mono text-foreground',
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
inline: 'rounded text-xs px-1.5 py-0.5',
|
||||
block: 'block rounded-md text-sm px-4 py-3 leading-relaxed break-all whitespace-pre-wrap',
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: 'inline',
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
interface CodeProps
|
||||
extends React.ComponentProps<'code'>,
|
||||
VariantProps<typeof codeVariants> {
|
||||
/**
|
||||
* Optional language hint for future syntax-highlighting support.
|
||||
* Emitted as `data-language` and as a `language-{lang}` class so
|
||||
* highlighters like Prism/Shiki can pick it up later.
|
||||
*/
|
||||
language?: string
|
||||
}
|
||||
|
||||
function Code({
|
||||
className,
|
||||
variant,
|
||||
language,
|
||||
...props
|
||||
}: CodeProps) {
|
||||
const element = (
|
||||
<code
|
||||
data-slot="code"
|
||||
data-language={language}
|
||||
className={cn(
|
||||
codeVariants({ variant, className }),
|
||||
language && `language-${language}`,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
|
||||
// For block variant, wrap in <pre> so copy-paste preserves whitespace
|
||||
// and screen readers announce it as a code block.
|
||||
if (variant === 'block') {
|
||||
return (
|
||||
<pre data-slot="code-block" className="not-prose">
|
||||
{element}
|
||||
</pre>
|
||||
)
|
||||
}
|
||||
|
||||
return element
|
||||
}
|
||||
|
||||
export { Code, codeVariants }
|
||||
@@ -177,6 +177,15 @@ export const COMPONENT_CATALOG: ComponentSpec[] = [
|
||||
props: 'variant?: "default" | "outline"; size?: "default" | "sm" | "lg"; pressed?: boolean',
|
||||
example: '<Toggle aria-label="Bold"><BoldIcon /></Toggle>',
|
||||
},
|
||||
{
|
||||
name: 'Code',
|
||||
file: 'components/ui/code.tsx',
|
||||
category: 'primitives',
|
||||
exports: ['Code', 'codeVariants'],
|
||||
description: 'Inline or block code snippet. Always use this instead of hand-rolling <code>/<pre> styling. Uses bg-muted + border-border so the outline stays visible in both light and dark modes. Block variant auto-wraps in <pre> for whitespace preservation and break-all for long commands.',
|
||||
props: 'variant?: "inline" | "block"; language?: string (optional, for future syntax highlighting)',
|
||||
example: '<p>Install with <Code>pnpm install</Code>.</p>\n\n<Code variant="block" language="bash">{`pnpm install\npnpm dev`}</Code>',
|
||||
},
|
||||
// ── Layout ──────────────────────────────────────────────────────────────
|
||||
{
|
||||
name: 'Card',
|
||||
|
||||
@@ -27,7 +27,7 @@ This project uses the **Greyhaven Design System**.
|
||||
|
||||
## Component Summary
|
||||
|
||||
37 components across 8 categories: primitives (10), layout (4), overlay (5), navigation (3), data (4), feedback (4), form (1), composition (6).
|
||||
38 components across 8 categories: primitives (11), layout (4), overlay (5), navigation (3), data (4), feedback (4), form (1), composition (6).
|
||||
|
||||
For full component specs, props, and examples, refer to the SKILL.md file or use the MCP `get_component(name)` tool.
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
> **Auto-generated** by `scripts/generate-skill.ts` -- DO NOT EDIT by hand.
|
||||
> Re-generate: `pnpm skill:build`
|
||||
>
|
||||
> **Components**: 37 | **Style**: shadcn/ui "new-york"
|
||||
> **Components**: 38 | **Style**: shadcn/ui "new-york"
|
||||
> **Stack**: React 19, Radix UI, Tailwind CSS v4, CVA, tailwind-merge, clsx, Lucide icons
|
||||
> **Framework-agnostic**: No Next.js imports. Works with Vite, Remix, Astro, CRA, or any React setup.
|
||||
|
||||
@@ -125,7 +125,7 @@ Source of truth: `tokens/*.json` (W3C DTCG format).
|
||||
| `color.dark.primary-foreground` | `{color.primitive.off-white}` | Dark primary foreground |
|
||||
| `color.dark.secondary` | `{color.primitive.grey.7}` | Dark secondary |
|
||||
| `color.dark.secondary-foreground` | `{color.primitive.off-white}` | Dark secondary text |
|
||||
| `color.dark.muted` | `{color.primitive.grey.7}` | Dark muted |
|
||||
| `color.dark.muted` | `{color.primitive.grey.8}` | Dark muted — grey.8 (distinct from grey.7 border so outlines on bg-muted surfaces remain visible) |
|
||||
| `color.dark.muted-foreground` | `{color.primitive.grey.3}` | Dark muted text |
|
||||
| `color.dark.accent` | `{color.primitive.grey.7}` | Dark accent/hover |
|
||||
| `color.dark.accent-foreground` | `{color.primitive.off-white}` | Dark accent text |
|
||||
@@ -235,7 +235,7 @@ Source of truth: `tokens/*.json` (W3C DTCG format).
|
||||
|
||||
---
|
||||
|
||||
## Component Catalog (37 components)
|
||||
## Component Catalog (38 components)
|
||||
|
||||
All components live in `components/ui/`. Import with `@/components/ui/<name>`.
|
||||
|
||||
@@ -341,6 +341,19 @@ All components live in `components/ui/`. Import with `@/components/ui/<name>`.
|
||||
<Toggle aria-label="Bold"><BoldIcon /></Toggle>
|
||||
```
|
||||
|
||||
#### Code
|
||||
- **File**: `components/ui/code.tsx`
|
||||
- **Exports**: `Code`, `codeVariants`
|
||||
- **Description**: Inline or block code snippet. Always use this instead of hand-rolling <code>/<pre> styling. Uses bg-muted + border-border so the outline stays visible in both light and dark modes. Block variant auto-wraps in <pre> for whitespace preservation and break-all for long commands.
|
||||
- **Props**: `variant?: "inline" | "block"; language?: string (optional, for future syntax highlighting)`
|
||||
- **Example**:
|
||||
```tsx
|
||||
<p>Install with <Code>pnpm install</Code>.</p>
|
||||
|
||||
<Code variant="block" language="bash">{`pnpm install
|
||||
pnpm dev`}</Code>
|
||||
```
|
||||
|
||||
### Layout
|
||||
|
||||
#### Card
|
||||
|
||||
90
stories/Primitives/Code.stories.tsx
Normal file
90
stories/Primitives/Code.stories.tsx
Normal file
@@ -0,0 +1,90 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react'
|
||||
|
||||
import { Code } from '@/components/ui/code'
|
||||
|
||||
const meta = {
|
||||
title: 'Primitives/Code',
|
||||
component: Code,
|
||||
tags: ['autodocs'],
|
||||
parameters: { layout: 'centered' },
|
||||
argTypes: {
|
||||
variant: {
|
||||
control: 'select',
|
||||
options: ['inline', 'block'],
|
||||
},
|
||||
language: { control: 'text' },
|
||||
},
|
||||
} satisfies Meta<typeof Code>
|
||||
|
||||
export default meta
|
||||
type Story = StoryObj<typeof meta>
|
||||
|
||||
export const Inline: Story = {
|
||||
args: {
|
||||
variant: 'inline',
|
||||
children: 'pnpm install',
|
||||
},
|
||||
}
|
||||
|
||||
export const InlineInSentence: Story = {
|
||||
render: () => (
|
||||
<p className="font-serif text-base leading-relaxed max-w-prose">
|
||||
To get started, run <Code>pnpm install</Code> and then{' '}
|
||||
<Code>pnpm dev</Code> to start the development server on{' '}
|
||||
<Code>localhost:3000</Code>.
|
||||
</p>
|
||||
),
|
||||
}
|
||||
|
||||
export const Block: Story = {
|
||||
args: {
|
||||
variant: 'block',
|
||||
language: 'bash',
|
||||
children: `pnpm install
|
||||
pnpm dev
|
||||
pnpm build`,
|
||||
},
|
||||
}
|
||||
|
||||
export const BlockLongCommand: Story = {
|
||||
args: {
|
||||
variant: 'block',
|
||||
language: 'bash',
|
||||
children:
|
||||
'curl -fsSL https://example.com/install.sh | bash -s -- --prefix=/usr/local --no-color --very-long-flag-that-should-wrap',
|
||||
},
|
||||
}
|
||||
|
||||
export const BlockTypescript: Story = {
|
||||
args: {
|
||||
variant: 'block',
|
||||
language: 'ts',
|
||||
children: `import { Code } from '@/components/ui/code'
|
||||
|
||||
export function Example() {
|
||||
return <Code variant="block">Hello, world!</Code>
|
||||
}`,
|
||||
},
|
||||
}
|
||||
|
||||
export const AllVariants: Story = {
|
||||
render: () => (
|
||||
<div className="flex flex-col gap-6 max-w-2xl">
|
||||
<div>
|
||||
<p className="text-sm text-muted-foreground mb-2 font-sans">Inline</p>
|
||||
<p className="font-serif">
|
||||
Use <Code>cn()</Code> from <Code>@/lib/utils</Code> to merge Tailwind classes.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<p className="text-sm text-muted-foreground mb-2 font-sans">Block</p>
|
||||
<Code variant="block" language="bash">
|
||||
{`# install and run
|
||||
pnpm install
|
||||
pnpm dev`}
|
||||
</Code>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
}
|
||||
@@ -287,8 +287,8 @@
|
||||
},
|
||||
"muted": {
|
||||
"$type": "color",
|
||||
"$value": "{color.primitive.grey.7}",
|
||||
"$description": "Dark muted"
|
||||
"$value": "{color.primitive.grey.8}",
|
||||
"$description": "Dark muted — grey.8 (distinct from grey.7 border so outlines on bg-muted surfaces remain visible)"
|
||||
},
|
||||
"muted-foreground": {
|
||||
"$type": "color",
|
||||
|
||||
Reference in New Issue
Block a user