tpmjs/DESIGN_SYSTEM.md
Ajax Davis 23d5159b28 refactor: replace raw HTML elements with design system components
- Replace <select>, <input>, <label>, <textarea> with UI components
- Update various dashboard and docs pages
- Simplify unsandbox package.json
- Add DESIGN_SYSTEM.md documentation
- Add Claude skills configuration
2026-01-16 16:52:44 +10:00

559 lines
14 KiB
Markdown

# TPMJS Design System Specification
> A technical, precise design system inspired by [turbopuffer.com](https://turbopuffer.com) - warm, monospace-driven, with generous whitespace and fieldset-style containers.
---
## Brand Direction
### Mood & Personality
- **Technical & Precise** - Engineering-focused, trustworthy, developer-first
- **Warm & Distinctive** - Not cold/corporate, the copper accent adds warmth
- **Confident & Minimal** - Let the content speak, reduce visual noise
### Reference Sites
- [turbopuffer.com](https://turbopuffer.com) - Primary inspiration
- Linear, Vercel - Secondary references for technical clarity
---
## Color Palette
### Primary Accent
```css
--color-accent: #A6592D; /* Copper/terracotta - primary brand color */
--color-accent-hover: #8B4A26; /* Darker copper for hover states */
--color-accent-light: #D4A574; /* Light copper for backgrounds/highlights */
```
### Gradient Header
```css
/* Warm gradient for top bar/hero sections */
--gradient-header: linear-gradient(135deg, #D4732A 0%, #8B3D1A 50%, #2D1810 100%);
```
### Neutral Palette
```css
/* Backgrounds */
--color-bg-primary: #FFFFFF; /* Main background */
--color-bg-secondary: #FAFAFA; /* Subtle sections */
--color-bg-elevated: #FFFFFF; /* Cards, elevated surfaces */
/* Text */
--color-text-primary: #1A1A1A; /* Primary text - near black */
--color-text-secondary: #666666; /* Secondary/muted text */
--color-text-tertiary: #999999; /* Placeholder, hints */
/* Borders */
--color-border: #E5E5E5; /* Default borders */
--color-border-strong: #CCCCCC; /* Emphasized borders */
--color-border-focus: #A6592D; /* Focus state - uses accent */
```
### Semantic Colors
```css
--color-success: #22C55E;
--color-error: #EF4444;
--color-warning: #F59E0B;
--color-info: #3B82F6;
```
### Dark Mode (Future)
```css
/* Dark mode should invert while keeping the warm accent */
--color-bg-primary-dark: #0D0D0D;
--color-bg-secondary-dark: #1A1A1A;
--color-text-primary-dark: #F5F5F5;
--color-border-dark: #333333;
```
---
## Typography
### Font Stack
**Headings & Code: Monospace**
```css
--font-mono: 'JetBrains Mono', 'IBM Plex Mono', 'Fira Code', monospace;
```
**Body Text: Sans-serif (for longer reading)**
```css
--font-sans: 'Inter', 'IBM Plex Sans', system-ui, sans-serif;
```
### Type Scale
| Element | Font | Size | Weight | Line Height | Letter Spacing |
|---------|------|------|--------|-------------|----------------|
| H1 | Mono | 48px (3rem) | 600 | 1.1 | -0.02em |
| H2 | Mono | 36px (2.25rem) | 600 | 1.2 | -0.01em |
| H3 | Mono | 24px (1.5rem) | 600 | 1.3 | 0 |
| H4 | Mono | 20px (1.25rem) | 600 | 1.4 | 0 |
| Body Large | Sans | 18px (1.125rem) | 400 | 1.7 | 0 |
| Body | Sans | 16px (1rem) | 400 | 1.7 | 0 |
| Body Small | Sans | 14px (0.875rem) | 400 | 1.6 | 0 |
| Caption | Sans | 12px (0.75rem) | 400 | 1.5 | 0.01em |
| Code | Mono | 14px (0.875rem) | 400 | 1.6 | 0 |
### Typography Rules
1. **Headings are lowercase** - "pricing", "faq", "tools" (not "Pricing", "FAQ", "Tools")
2. **Generous line-height** - Minimum 1.6 for body text, 1.7 preferred
3. **Bold sparingly** - Use weight 600 for emphasis, not 700+
4. **Monospace for data** - Numbers, metrics, technical values always in mono
### CSS Variables
```css
/* Font families */
--font-heading: var(--font-mono);
--font-body: var(--font-sans);
--font-code: var(--font-mono);
/* Font sizes */
--text-xs: 0.75rem; /* 12px */
--text-sm: 0.875rem; /* 14px */
--text-base: 1rem; /* 16px */
--text-lg: 1.125rem; /* 18px */
--text-xl: 1.25rem; /* 20px */
--text-2xl: 1.5rem; /* 24px */
--text-3xl: 2.25rem; /* 36px */
--text-4xl: 3rem; /* 48px */
/* Line heights */
--leading-tight: 1.2;
--leading-normal: 1.5;
--leading-relaxed: 1.7;
/* Font weights */
--font-normal: 400;
--font-medium: 500;
--font-semibold: 600;
```
---
## Spacing
### Spacing Scale
```css
--space-0: 0;
--space-1: 0.25rem; /* 4px */
--space-2: 0.5rem; /* 8px */
--space-3: 0.75rem; /* 12px */
--space-4: 1rem; /* 16px */
--space-5: 1.25rem; /* 20px */
--space-6: 1.5rem; /* 24px */
--space-8: 2rem; /* 32px */
--space-10: 2.5rem; /* 40px */
--space-12: 3rem; /* 48px */
--space-16: 4rem; /* 64px */
--space-20: 5rem; /* 80px */
--space-24: 6rem; /* 96px */
```
### Spacing Philosophy
- **Generous whitespace** - When in doubt, add more space
- **Vertical rhythm** - Use consistent spacing between sections (typically `--space-16` to `--space-24`)
- **Component padding** - Cards and containers use `--space-6` to `--space-8`
- **Text spacing** - Paragraphs separated by `--space-4` to `--space-6`
---
## Borders & Containers
### Border Radius
```css
--radius-none: 0; /* DEFAULT - sharp corners */
--radius-sm: 2px; /* Use sparingly for special cases */
--radius-md: 4px; /* Use sparingly for special cases */
```
**Rule: Default to 0 border-radius. Sharp corners are the brand.**
### Border Styles
**Dashed (Primary)**
```css
border: 1px dashed var(--color-border);
```
**Solid (Emphasis)**
```css
border: 2px solid var(--color-text-primary); /* Featured items */
```
### Fieldset-Style Containers
The signature container style with a label that "cuts into" the border:
```html
<fieldset class="fieldset-container">
<legend>section title</legend>
<!-- content -->
</fieldset>
```
```css
.fieldset-container {
border: 1px dashed var(--color-border);
padding: var(--space-6);
margin: 0;
}
.fieldset-container legend {
font-family: var(--font-mono);
font-size: var(--text-sm);
color: var(--color-text-secondary);
padding: 0 var(--space-2);
text-transform: lowercase;
}
```
### Container Variants
| Variant | Border | Background | Use Case |
|---------|--------|------------|----------|
| Default | 1px dashed | transparent | Most containers |
| Elevated | 1px dashed | white | Cards on gray bg |
| Featured | 2px solid | white | Highlighted item |
| Ghost | none | transparent | Minimal grouping |
---
## Components
### Buttons
**Primary Button (Accent)**
```css
.btn-primary {
background: var(--color-accent);
color: white;
border: none;
padding: var(--space-3) var(--space-6);
font-family: var(--font-mono);
font-size: var(--text-sm);
font-weight: var(--font-medium);
cursor: pointer;
transition: background 150ms ease;
}
.btn-primary:hover {
background: var(--color-accent-hover);
}
```
**Secondary Button (Outline)**
```css
.btn-secondary {
background: transparent;
color: var(--color-text-primary);
border: 1px solid var(--color-border);
padding: var(--space-3) var(--space-6);
font-family: var(--font-mono);
font-size: var(--text-sm);
font-weight: var(--font-medium);
cursor: pointer;
transition: border-color 150ms ease;
}
.btn-secondary:hover {
border-color: var(--color-text-primary);
}
```
**Button Sizes**
| Size | Padding | Font Size |
|------|---------|-----------|
| sm | `--space-2` `--space-4` | `--text-xs` |
| md | `--space-3` `--space-6` | `--text-sm` |
| lg | `--space-4` `--space-8` | `--text-base` |
### Links
```css
a {
color: var(--color-text-primary);
text-decoration: underline;
text-underline-offset: 3px;
transition: opacity 150ms ease;
}
a:hover {
opacity: 0.7;
}
```
**Rule: Links are underlined, not colored.** Use underline as the primary affordance.
### Inputs
```css
.input {
width: 100%;
padding: var(--space-3) var(--space-4);
border: 1px solid var(--color-border);
border-radius: var(--radius-none);
font-family: var(--font-mono);
font-size: var(--text-base);
background: white;
transition: border-color 150ms ease;
}
.input:focus {
outline: none;
border-color: var(--color-accent);
}
.input::placeholder {
color: var(--color-text-tertiary);
}
```
### Cards
```css
.card {
border: 1px dashed var(--color-border);
padding: var(--space-6);
background: white;
}
.card--featured {
border: 2px solid var(--color-text-primary);
}
.card__title {
font-family: var(--font-mono);
font-size: var(--text-lg);
font-weight: var(--font-semibold);
text-transform: lowercase;
margin-bottom: var(--space-2);
}
.card__description {
font-family: var(--font-sans);
font-size: var(--text-base);
color: var(--color-text-secondary);
line-height: var(--leading-relaxed);
}
```
### Badges
```css
.badge {
display: inline-flex;
align-items: center;
padding: var(--space-1) var(--space-3);
font-family: var(--font-mono);
font-size: var(--text-xs);
border: 1px solid currentColor;
text-transform: lowercase;
}
.badge--default { color: var(--color-text-secondary); }
.badge--success { color: var(--color-success); }
.badge--error { color: var(--color-error); }
.badge--warning { color: var(--color-warning); }
```
### Tables
```css
.table-container {
border: 1px dashed var(--color-border);
overflow: hidden;
}
.table {
width: 100%;
border-collapse: collapse;
font-family: var(--font-mono);
font-size: var(--text-sm);
}
.table th {
text-align: left;
padding: var(--space-4);
border-bottom: 1px dashed var(--color-border);
font-weight: var(--font-semibold);
text-transform: lowercase;
}
.table td {
padding: var(--space-4);
border-bottom: 1px dashed var(--color-border);
}
.table tr:last-child td {
border-bottom: none;
}
```
---
## Layout
### Container Widths
```css
--container-sm: 640px;
--container-md: 768px;
--container-lg: 1024px;
--container-xl: 1280px;
```
### Page Structure
```
┌─────────────────────────────────────────────┐
│ Gradient Header Bar (announcement) │
├─────────────────────────────────────────────┤
│ Navigation (sticky, white bg) │
├─────────────────────────────────────────────┤
│ │
│ Hero Section │
│ (generous padding: --space-24) │
│ │
├─────────────────────────────────────────────┤
│ │
│ Content Sections │
│ (separated by --space-16 to --space-24) │
│ │
│ ┌─ fieldset container ─────────────────┐ │
│ │ section title │ │
│ │ │ │
│ │ Content with generous padding │ │
│ │ │ │
│ └──────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────┘
```
---
## Interactions
### Hover States
- **Buttons**: Background color change (accent → darker)
- **Links**: Opacity reduction to 0.7
- **Cards**: Border color change (border → border-strong)
- **No transforms** - Avoid scale/translate on hover (too playful)
### Focus States
```css
*:focus-visible {
outline: 2px solid var(--color-accent);
outline-offset: 2px;
}
```
### Transitions
```css
--transition-fast: 150ms ease;
--transition-base: 200ms ease;
--transition-slow: 300ms ease;
```
**Rule: Keep transitions subtle and fast. No bouncy/spring animations.**
---
## Special Elements
### Gradient Header Bar
```css
.header-bar {
background: var(--gradient-header);
color: white;
padding: var(--space-2) var(--space-4);
font-family: var(--font-mono);
font-size: var(--text-sm);
text-align: center;
}
```
### Technical Diagrams
Use ASCII-style box diagrams with monospace font:
```
┌─────────────┐ ┌─────────────┐
│ client │─────▶│ API │
└─────────────┘ └─────────────┘
```
### Code Blocks
```css
.code-block {
background: var(--color-bg-secondary);
border: 1px dashed var(--color-border);
padding: var(--space-4);
font-family: var(--font-mono);
font-size: var(--text-sm);
overflow-x: auto;
}
```
### Sliders/Range Inputs
Custom styled with accent color, monospace tooltips showing values.
---
## Do's and Don'ts
### Do
- Use lowercase for headings
- Use dashed borders for containers
- Use generous whitespace
- Use monospace for technical content
- Use underlines for links
- Keep interactions subtle and fast
- Use the copper accent sparingly but confidently
### Don't
- Don't use rounded corners (except for special cases)
- Don't use drop shadows
- Don't use gradients (except header bar)
- Don't use icons where text works
- Don't use colored links
- Don't use bouncy animations
- Don't use multiple accent colors
---
## Implementation Priority
### Phase 1: Foundation
1. Update CSS variables (colors, spacing, typography)
2. Install fonts (JetBrains Mono, Inter)
3. Update base styles (reset, typography)
### Phase 2: Core Components
1. Button variants
2. Input/Form elements
3. Card/Container styles
4. Badge variants
### Phase 3: Layout
1. Fieldset-style containers
2. Page layouts with generous spacing
3. Navigation updates
4. Gradient header bar
### Phase 4: Polish
1. Table styles
2. Code blocks
3. Interactive elements (sliders, toggles)
4. Transitions and hover states
---
## References
- **Turbopuffer**: https://turbopuffer.com - Primary design inspiration
- **JetBrains Mono**: https://www.jetbrains.com/lp/mono/
- **Inter**: https://rsms.me/inter/
---
*Last updated: January 2025*
*Version: 1.0*