design system token v0.2
This commit is contained in:
@@ -9,22 +9,60 @@
|
||||
|
||||
This skill gives you full context to generate pixel-perfect, on-brand UI using the Greyhaven Design System. Every component lives in `components/ui/`. Use semantic tokens, never raw colors. Follow the patterns exactly.
|
||||
|
||||
|
||||
---
|
||||
|
||||
## 1. Design Philosophy
|
||||
## Design Philosophy
|
||||
|
||||
- **Minimal and restrained**: Off-white + off-black + warm greys. One single accent color (orange). No gradients, no decorative color, no multiple accent hues.
|
||||
- **Typography-driven**: Source Serif 4/Pro (serif) for headings and body content. Aspekta/Inter (sans) for UI labels, buttons, navigation, and form elements.
|
||||
- **Typography-driven**: Source Serif 4/Pro (serif) for headings and body content. Aspekta (sans, self-hosted) for UI labels, buttons, navigation, and form elements.
|
||||
- **Calm, professional aesthetic**: Tight border-radii, subtle shadows, generous whitespace.
|
||||
- **Accessibility-first**: Built on Radix UI primitives for keyboard navigation, focus management, screen reader support. Visible focus rings, disabled states, ARIA attributes.
|
||||
- **Dark mode native**: Thoughtful dark theme using inverted warm greys. Orange accent persists across both modes. Toggled via `.dark` class.
|
||||
- **Framework-agnostic**: Pure React + Radix + Tailwind. No Next.js, no framework-specific imports.
|
||||
|
||||
---
|
||||
|
||||
## Font Setup
|
||||
|
||||
This design system uses two typefaces:
|
||||
|
||||
| Role | Font | Usage |
|
||||
|------|------|-------|
|
||||
| **Sans (UI)** | Aspekta (self-hosted) | Buttons, nav, labels, forms, metadata |
|
||||
| **Serif (Content)** | Source Serif 4/Pro | Headings, body text, reading content |
|
||||
|
||||
### Aspekta (required)
|
||||
|
||||
Aspekta font files live in `public/fonts/`. Add `@font-face` declarations to your global CSS:
|
||||
|
||||
```css
|
||||
/* Minimum set (covers font-weight 400-700) */
|
||||
@font-face { font-family: 'Aspekta'; font-weight: 400; font-display: swap; src: url('/fonts/Aspekta-400.woff2') format('woff2'); }
|
||||
@font-face { font-family: 'Aspekta'; font-weight: 500; font-display: swap; src: url('/fonts/Aspekta-500.woff2') format('woff2'); }
|
||||
@font-face { font-family: 'Aspekta'; font-weight: 600; font-display: swap; src: url('/fonts/Aspekta-600.woff2') format('woff2'); }
|
||||
@font-face { font-family: 'Aspekta'; font-weight: 700; font-display: swap; src: url('/fonts/Aspekta-700.woff2') format('woff2'); }
|
||||
|
||||
/* Or import all weights: */
|
||||
@import url('/fonts/font-face.css');
|
||||
```
|
||||
|
||||
### Font stack CSS variables
|
||||
|
||||
```css
|
||||
--font-sans: 'Aspekta', ui-sans-serif, system-ui, sans-serif;
|
||||
--font-serif: 'Source Serif 4', 'Source Serif Pro', Georgia, serif;
|
||||
```
|
||||
|
||||
### Tailwind usage
|
||||
|
||||
- `font-sans` — Aspekta (UI elements)
|
||||
- `font-serif` — Source Serif (content)
|
||||
|
||||
Install fonts via: `./skill/install.sh /path/to/your/project`
|
||||
|
||||
---
|
||||
|
||||
## 2. Token Quick Reference
|
||||
## Token Quick Reference
|
||||
|
||||
Source of truth: `tokens/*.json` (W3C DTCG format).
|
||||
|
||||
@@ -112,7 +150,7 @@ Source of truth: `tokens/*.json` (W3C DTCG format).
|
||||
|
||||
| Token | Value | Description |
|
||||
|-------|-------|-------------|
|
||||
| `typography.fontFamily.sans` | `["Aspekta","Inter","ui-sans-serif","system-ui","sans-serif"]` | UI labels, buttons, nav, forms — Aspekta primary, Inter fallback |
|
||||
| `typography.fontFamily.sans` | `["Aspekta","ui-sans-serif","system-ui","sans-serif"]` | UI labels, buttons, nav, forms — Aspekta self-hosted |
|
||||
| `typography.fontFamily.serif` | `["Source Serif 4","Source Serif Pro","Georgia","serif"]` | Headings, body content, reading — Source Serif primary |
|
||||
| `typography.fontFamily.mono` | `["ui-monospace","SFMono-Regular","Menlo","Monaco","Consolas","monospace"]` | Code blocks and monospaced content |
|
||||
| `typography.fontSize.xs` | `0.75rem` | 12px — metadata, fine print |
|
||||
@@ -192,10 +230,9 @@ Source of truth: `tokens/*.json` (W3C DTCG format).
|
||||
| `motion.easing.in` | `[0.4,0,1,1]` | Ease-in for exits |
|
||||
| `motion.easing.out` | `[0,0,0.2,1]` | Ease-out for entrances |
|
||||
|
||||
|
||||
---
|
||||
|
||||
## 3. Component Catalog (37 components)
|
||||
## Component Catalog (37 components)
|
||||
|
||||
All components live in `components/ui/`. Import with `@/components/ui/<name>`.
|
||||
|
||||
@@ -585,10 +622,9 @@ All components live in `components/ui/`. Import with `@/components/ui/<name>`.
|
||||
<PageLayout navbar={<Navbar />} footer={<Footer />}>Main content</PageLayout>
|
||||
```
|
||||
|
||||
|
||||
---
|
||||
|
||||
## 4. Composition Rules
|
||||
## Composition Rules
|
||||
|
||||
- **Card spacing**: `gap-6` between cards, `p-6` internal padding
|
||||
- **Section rhythm**: `py-16` between major page sections
|
||||
@@ -603,10 +639,9 @@ All components live in `components/ui/`. Import with `@/components/ui/<name>`.
|
||||
- **Slot naming**: All components use `data-slot="component-name"`
|
||||
- **Icon sizing**: `[&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0`
|
||||
|
||||
|
||||
---
|
||||
|
||||
## 5. Extension Protocol
|
||||
## Extension Protocol
|
||||
|
||||
When adding new components to the system:
|
||||
|
||||
@@ -630,24 +665,14 @@ import { cn } from '@/lib/utils'
|
||||
|
||||
const myComponentVariants = cva('base-classes', {
|
||||
variants: {
|
||||
variant: {
|
||||
default: 'default-classes',
|
||||
},
|
||||
size: {
|
||||
default: 'size-classes',
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: 'default',
|
||||
size: 'default',
|
||||
variant: { default: 'default-classes' },
|
||||
size: { default: 'size-classes' },
|
||||
},
|
||||
defaultVariants: { variant: 'default', size: 'default' },
|
||||
})
|
||||
|
||||
function MyComponent({
|
||||
className,
|
||||
variant,
|
||||
size,
|
||||
...props
|
||||
className, variant, size, ...props
|
||||
}: React.ComponentProps<'div'> & VariantProps<typeof myComponentVariants>) {
|
||||
return (
|
||||
<div
|
||||
|
||||
Reference in New Issue
Block a user