chore: initial scaffold of KDC Design System
Lint / lint (push) Has been cancelled

Initial repository scaffold:
- design.md (google-labs-code/design.md format) as canonical token + guidelines source
- brand assets, foundations, tokens (W3C-style JSON)
- 12 component primitives, each with labeled anatomy.svg and spec README
- light / dark / high-contrast themes, web/mobile/email/print/presentation templates
- docs (getting started, principles, a11y, voice & tone, contributing)
- runnable web example, token build script stub, CI placeholder

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Paul Roberts
2026-04-29 19:01:53 +00:00
commit 16989d834c
114 changed files with 2011 additions and 0 deletions
+14
View File
@@ -0,0 +1,14 @@
name: Lint
on:
push:
branches: [main]
pull_request:
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 20 }
- run: npm ci || npm install
- run: npm run lint
+11
View File
@@ -0,0 +1,11 @@
node_modules/
dist/
build/
.cache/
.DS_Store
*.log
.env
.env.local
coverage/
.idea/
.vscode/
+10
View File
@@ -0,0 +1,10 @@
# Changelog
All notable changes to the KDC Design System will be documented in this file.
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and
this project adheres to [Semantic Versioning](https://semver.org/).
## [Unreleased]
### Added
- Initial repository scaffold: `design.md`, brand, foundations, components, themes, templates, docs.
+4
View File
@@ -0,0 +1,4 @@
* @kdc/design-system-maintainers
/brand/ @kdc/brand
/foundations/ @kdc/design-system-maintainers
/components/ @kdc/design-system-maintainers
+4
View File
@@ -0,0 +1,4 @@
Copyright (c) KDC. All rights reserved.
Placeholder license file. Replace with the appropriate license (MIT, Apache-2.0,
proprietary EULA, etc.) before public release.
+36
View File
@@ -0,0 +1,36 @@
# KDC Design System
The official design system for KDC — tokens, components, brand assets, and guidelines for building consistent KDC product and brand experiences.
> The single source of truth lives in [`design.md`](./design.md), which encodes the design tokens (colors, typography, spacing, radii, components) in the [google-labs-code/design.md](https://github.com/google-labs-code/design.md) format.
## Repository structure
```
KDCDesignSystem/
├── design.md # Canonical token + guidelines spec
├── brand/ # Logos, wordmarks, brand guidelines
├── tokens/ # Generated/exported design tokens
├── foundations/ # Color, type, spacing, motion, grid, breakpoints
├── assets/ # Fonts, icons, illustrations, images, patterns
├── components/ # Per-component specs and anatomy
├── themes/ # Light, dark, high-contrast theme overrides
├── templates/ # Web, mobile, email, print, presentation
├── docs/ # Getting started, principles, a11y, voice & tone
├── examples/ # Reference implementations
└── scripts/ # Token build / export scripts
```
## Quick start
1. Read [`docs/getting-started/README.md`](./docs/getting-started/README.md).
2. Skim [`design.md`](./design.md) for the token vocabulary.
3. Pick your platform under [`examples/`](./examples/).
## Status
Version: **alpha**. Tokens and components are still settling — expect breaking changes.
## Contributing
See [`docs/contributing/README.md`](./docs/contributing/README.md).
+3
View File
@@ -0,0 +1,3 @@
# backgrounds
Drop production-ready backgrounds here. Prefer SVG for vector and AVIF/WebP for raster.
View File
View File
+10
View File
@@ -0,0 +1,10 @@
# Inter
Place the licensed Inter font files here:
- Inter-Regular.woff2
- Inter-Medium.woff2
- Inter-SemiBold.woff2
- Inter-Bold.woff2
Include the upstream LICENSE alongside the binaries.
+10
View File
@@ -0,0 +1,10 @@
# Roboto-Mono
Place the licensed Roboto-Mono font files here:
- Roboto-Mono-Regular.woff2
- Roboto-Mono-Medium.woff2
- Roboto-Mono-SemiBold.woff2
- Roboto-Mono-Bold.woff2
Include the upstream LICENSE alongside the binaries.
+18
View File
@@ -0,0 +1,18 @@
/* KDC Design System — font-face declarations.
Self-host these files from /assets/fonts/. */
@font-face {
font-family: "Inter";
font-style: normal;
font-weight: 100 900;
font-display: swap;
src: url("./Inter/Inter-Regular.woff2") format("woff2");
}
@font-face {
font-family: "Roboto Mono";
font-style: normal;
font-weight: 400 700;
font-display: swap;
src: url("./Roboto-Mono/Roboto-Mono-Regular.woff2") format("woff2");
}
+8
View File
@@ -0,0 +1,8 @@
# Icons
The KDC icon library, organized by visual style:
- `ui/` — generic interface icons (24x24, stroke, currentColor).
- `outline/` — outlined version of the icon set.
- `filled/` — filled version of the icon set.
- `social/` — third-party brand icons (use per their respective brand rules).
+7
View File
@@ -0,0 +1,7 @@
# Icons · filled
Place 24x24 SVG icons for the **filled** set here. Each icon should:
- Use `viewBox="0 0 24 24"`
- Stroke or fill `currentColor`
- Have descriptive `<title>` and `aria-*` attributes when used directly
+7
View File
@@ -0,0 +1,7 @@
# Icons · outline
Place 24x24 SVG icons for the **outline** set here. Each icon should:
- Use `viewBox="0 0 24 24"`
- Stroke or fill `currentColor`
- Have descriptive `<title>` and `aria-*` attributes when used directly
+7
View File
@@ -0,0 +1,7 @@
# Icons · social
Place 24x24 SVG icons for the **social** set here. Each icon should:
- Use `viewBox="0 0 24 24"`
- Stroke or fill `currentColor`
- Have descriptive `<title>` and `aria-*` attributes when used directly
+7
View File
@@ -0,0 +1,7 @@
# Icons · ui
Place 24x24 SVG icons for the **ui** set here. Each icon should:
- Use `viewBox="0 0 24 24"`
- Stroke or fill `currentColor`
- Have descriptive `<title>` and `aria-*` attributes when used directly
+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg>

After

Width:  |  Height:  |  Size: 215 B

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></svg>

After

Width:  |  Height:  |  Size: 212 B

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 6 6 18M6 6l12 12"/></svg>

After

Width:  |  Height:  |  Size: 220 B

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="7"/><path d="m21 21-4.3-4.3"/></svg>

After

Width:  |  Height:  |  Size: 245 B

+3
View File
@@ -0,0 +1,3 @@
# illustrations
Drop production-ready illustrations here. Prefer SVG for vector and AVIF/WebP for raster.
+3
View File
@@ -0,0 +1,3 @@
# images
Drop production-ready images here. Prefer SVG for vector and AVIF/WebP for raster.
+3
View File
@@ -0,0 +1,3 @@
# patterns
Drop production-ready patterns here. Prefer SVG for vector and AVIF/WebP for raster.
+6
View File
@@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40" width="40" height="40">
<defs><pattern id="d" width="40" height="40" patternUnits="userSpaceOnUse">
<circle cx="2" cy="2" r="1.5" fill="#D9DCE3"/>
</pattern></defs>
<rect width="40" height="40" fill="url(#d)"/>
</svg>

After

Width:  |  Height:  |  Size: 288 B

+16
View File
@@ -0,0 +1,16 @@
# Brand
Logo lockups, wordmarks, and brand guidelines.
| Path | Purpose |
|------|---------|
| `logos/primary/` | Primary KDC mark — full color, on-light, on-dark variants. |
| `logos/secondary/` | Stacked / vertical lockups for square placements. |
| `logos/monochrome/`| Single-color black and white marks for print and embossing. |
| `logos/favicon/` | Browser, PWA, and OS icons. |
| `wordmarks/` | Typography-only KDC wordmark. |
| `icon-set/` | Small standalone brand glyphs. |
| `logos-source/` | Editable Adobe Illustrator / Figma / Sketch sources. |
| `brand-guidelines/`| Voice, photography, illustration style, do/don'ts. |
All logos in this folder are placeholders — replace with the official artwork before any production use.
+12
View File
@@ -0,0 +1,12 @@
# Brand Guidelines
Placeholder. Replace with the formal KDC brand book covering:
- Mission, vision, and personality
- Logo clear-space and minimum sizes
- Approved color usage
- Typography in marketing
- Photography & illustration direction
- Voice and tone
- Co-branding rules
- Do's and don'ts (with examples)
+4
View File
@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 240 80" width="240" height="80" role="img" aria-label="K">
<rect width="240" height="80" fill="#0B5FFF"/>
<text x="120" y="46" text-anchor="middle" font-family="Inter, Arial, sans-serif" font-size="20" font-weight="700" fill="#FFFFFF">K</text>
</svg>

After

Width:  |  Height:  |  Size: 308 B

View File
View File
View File
View File
+4
View File
@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="32" height="32">
<rect width="32" height="32" rx="6" fill="#0B5FFF"/>
<text x="16" y="22" text-anchor="middle" font-family="Inter, Arial, sans-serif" font-size="16" font-weight="800" fill="#FFFFFF">K</text>
</svg>

After

Width:  |  Height:  |  Size: 285 B

@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 240 80" width="240" height="80" role="img" aria-label="KDC">
<rect width="240" height="80" fill="#FFFFFF"/>
<text x="120" y="46" text-anchor="middle" font-family="Inter, Arial, sans-serif" font-size="20" font-weight="700" fill="#000000">KDC</text>
</svg>

After

Width:  |  Height:  |  Size: 312 B

@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 240 80" width="240" height="80" role="img" aria-label="KDC">
<rect width="240" height="80" fill="#000000"/>
<text x="120" y="46" text-anchor="middle" font-family="Inter, Arial, sans-serif" font-size="20" font-weight="700" fill="#FFFFFF">KDC</text>
</svg>

After

Width:  |  Height:  |  Size: 312 B

@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 240 80" width="240" height="80" role="img" aria-label="KDC">
<rect width="240" height="80" fill="#111827"/>
<text x="120" y="46" text-anchor="middle" font-family="Inter, Arial, sans-serif" font-size="20" font-weight="700" fill="#FFFFFF">KDC</text>
</svg>

After

Width:  |  Height:  |  Size: 312 B

@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 240 80" width="240" height="80" role="img" aria-label="KDC">
<rect width="240" height="80" fill="#FFFFFF"/>
<text x="120" y="46" text-anchor="middle" font-family="Inter, Arial, sans-serif" font-size="20" font-weight="700" fill="#0B5FFF">KDC</text>
</svg>

After

Width:  |  Height:  |  Size: 312 B

+4
View File
@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 240 80" width="240" height="80" role="img" aria-label="KDC">
<rect width="240" height="80" fill="#0B5FFF"/>
<text x="120" y="46" text-anchor="middle" font-family="Inter, Arial, sans-serif" font-size="20" font-weight="700" fill="#FFFFFF">KDC</text>
</svg>

After

Width:  |  Height:  |  Size: 312 B

@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 240 80" width="240" height="80" role="img" aria-label="KDC">
<rect width="240" height="80" fill="#0B5FFF"/>
<text x="120" y="46" text-anchor="middle" font-family="Inter, Arial, sans-serif" font-size="20" font-weight="700" fill="#FFFFFF">KDC</text>
</svg>

After

Width:  |  Height:  |  Size: 312 B

+4
View File
@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 240 80" width="240" height="80" role="img" aria-label="KDC">
<rect width="240" height="80" fill="#FFFFFF"/>
<text x="120" y="46" text-anchor="middle" font-family="Inter, Arial, sans-serif" font-size="20" font-weight="700" fill="#0B5FFF">KDC</text>
</svg>

After

Width:  |  Height:  |  Size: 312 B

+25
View File
@@ -0,0 +1,25 @@
# Alerts
Specification for the **alerts** primitive.
## Anatomy
TODO — drop `anatomy.svg` next to this file.
## Variants
- default
- (list per-component variants)
## States
default · hover · focus-visible · active/pressed · disabled · loading
## Tokens used
See `design.md``components.alerts.*`.
## Accessibility
- All interactive instances are keyboard-reachable.
- Focus state has ≥ 3:1 contrast against its background.
- Pair color with an icon or text to convey meaning.
## Do / Don't
- ✅ Use the canonical token references.
- ❌ Don't hardcode colors, sizes, or radii.
+73
View File
@@ -0,0 +1,73 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 360" width="760" height="360" font-family="Inter, Arial, sans-serif" role="img" aria-label="Alert anatomy">
<title>Alert anatomy</title>
<desc>Labeled diagram of a KDC alert: container, leading icon, title, body, action link, dismiss button, semantic variants.</desc>
<rect width="760" height="360" fill="#F7F8FA"/>
<!-- focus alert (warning) -->
<g>
<rect x="100" y="80" width="560" height="80" rx="8" fill="#FFFBEB" stroke="#F59E0B" stroke-opacity="0.4"/>
<!-- accent stripe -->
<rect x="100" y="80" width="4" height="80" fill="#F59E0B"/>
<!-- leading icon -->
<g transform="translate(120 100)" stroke="#B45309" stroke-width="1.8" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path d="M12 2 22 20H2z"/>
<path d="M12 9v5M12 17h.01"/>
</g>
<!-- title + body -->
<text x="156" y="108" fill="#111827" font-size="14" font-weight="700">Storage almost full</text>
<text x="156" y="128" fill="#374151" font-size="13">You're using 92% of your 50GB plan. Upgrade to keep syncing.</text>
<!-- action link -->
<text x="156" y="148" fill="#0B5FFF" font-size="13" font-weight="600">Upgrade plan →</text>
<!-- dismiss -->
<g transform="translate(628 96)" stroke="#6B7280" stroke-width="1.8" stroke-linecap="round" fill="none">
<path d="m4 4 12 12M16 4 4 16"/>
</g>
</g>
<!-- annotations -->
<g stroke="#374151" stroke-width="1" fill="none">
<line x1="100" y1="80" x2="80" y2="40"/>
<line x1="104" y1="120" x2="40" y2="180"/>
<line x1="132" y1="108" x2="60" y2="60"/>
<line x1="240" y1="108" x2="240" y2="40"/>
<line x1="240" y1="148" x2="240" y2="220"/>
<line x1="640" y1="100" x2="700" y2="40"/>
</g>
<g fill="#111827" font-size="13" font-weight="600">
<text x="80" y="34">1 · Container — semantic.* @ 8% bg, semantic.* @ 40% border</text>
<text x="40" y="194">2 · Accent stripe — 4px, semantic color at full strength (optional)</text>
<text x="60" y="54">3 · Leading icon — 24×24, semantic on-color</text>
<text x="240" y="34">4 · Title — typography.bodyS, bold</text>
<text x="240" y="234">5 · Action link — typography.bodyS, brand.primary, optional</text>
<text x="700" y="34" text-anchor="end">6 · Dismiss — 20×20, top-right, optional</text>
</g>
<!-- variants -->
<g transform="translate(100 220)">
<text x="0" y="0" fill="#6B7280" font-size="12" font-weight="700">VARIANTS</text>
<g transform="translate(0 12)">
<rect width="120" height="24" rx="6" fill="#E0F2FE" stroke="#0EA5E9" stroke-opacity="0.4"/>
<text x="60" y="16" text-anchor="middle" fill="#0369A1" font-size="11" font-weight="600">Info</text>
</g>
<g transform="translate(132 12)">
<rect width="120" height="24" rx="6" fill="#DCFCE7" stroke="#16A34A" stroke-opacity="0.4"/>
<text x="60" y="16" text-anchor="middle" fill="#16A34A" font-size="11" font-weight="600">Success</text>
</g>
<g transform="translate(264 12)">
<rect width="120" height="24" rx="6" fill="#FEF3C7" stroke="#F59E0B" stroke-opacity="0.4"/>
<text x="60" y="16" text-anchor="middle" fill="#B45309" font-size="11" font-weight="600">Warning</text>
</g>
<g transform="translate(396 12)">
<rect width="120" height="24" rx="6" fill="#FEE2E2" stroke="#DC2626" stroke-opacity="0.4"/>
<text x="60" y="16" text-anchor="middle" fill="#DC2626" font-size="11" font-weight="600">Danger</text>
</g>
</g>
<!-- token legend -->
<g transform="translate(40 300)">
<text x="0" y="0" font-size="12" font-weight="700" fill="#111827">Tokens</text>
<text x="0" y="16" font-size="12" fill="#374151">radius → rounded.md · padding → spacing.4 (16px) · icon-gap → spacing.3</text>
<text x="0" y="32" font-size="12" fill="#374151">role → "alert" (assertive) for danger, "status" (polite) for success/info</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.9 KiB

+25
View File
@@ -0,0 +1,25 @@
# Badges
Specification for the **badges** primitive.
## Anatomy
TODO — drop `anatomy.svg` next to this file.
## Variants
- default
- (list per-component variants)
## States
default · hover · focus-visible · active/pressed · disabled · loading
## Tokens used
See `design.md``components.badges.*`.
## Accessibility
- All interactive instances are keyboard-reachable.
- Focus state has ≥ 3:1 contrast against its background.
- Pair color with an icon or text to convey meaning.
## Do / Don't
- ✅ Use the canonical token references.
- ❌ Don't hardcode colors, sizes, or radii.
+55
View File
@@ -0,0 +1,55 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 360" width="760" height="360" font-family="Inter, Arial, sans-serif" role="img" aria-label="Badge anatomy">
<title>Badge anatomy</title>
<desc>Labeled diagram of a KDC badge: container, dot, label, semantic variants (neutral, success, warning, danger, info).</desc>
<rect width="760" height="360" fill="#F7F8FA"/>
<!-- focus example badge with dot + label -->
<g transform="translate(280 130)">
<rect x="0" y="0" width="120" height="24" rx="12" fill="#DCFCE7"/>
<circle cx="12" cy="12" r="4" fill="#16A34A"/>
<text x="22" y="16" fill="#16A34A" font-size="12" font-weight="600">Active</text>
</g>
<!-- variants row -->
<g transform="translate(40 220)">
<g><rect x="0" y="0" width="80" height="22" rx="11" fill="#EDEFF3"/>
<text x="40" y="15" text-anchor="middle" fill="#111827" font-size="11" font-weight="600">Neutral</text></g>
<g transform="translate(96 0)"><rect width="80" height="22" rx="11" fill="#DCFCE7"/>
<text x="40" y="15" text-anchor="middle" fill="#16A34A" font-size="11" font-weight="600">Success</text></g>
<g transform="translate(192 0)"><rect width="80" height="22" rx="11" fill="#FEF3C7"/>
<text x="40" y="15" text-anchor="middle" fill="#B45309" font-size="11" font-weight="600">Warning</text></g>
<g transform="translate(288 0)"><rect width="80" height="22" rx="11" fill="#FEE2E2"/>
<text x="40" y="15" text-anchor="middle" fill="#DC2626" font-size="11" font-weight="600">Danger</text></g>
<g transform="translate(384 0)"><rect width="80" height="22" rx="11" fill="#E0F2FE"/>
<text x="40" y="15" text-anchor="middle" fill="#0369A1" font-size="11" font-weight="600">Info</text></g>
<g transform="translate(480 0)"><rect width="22" height="22" rx="11" fill="#DC2626"/>
<text x="11" y="15" text-anchor="middle" fill="#FFFFFF" font-size="11" font-weight="700">3</text></g>
</g>
<!-- annotations on the focus badge -->
<g stroke="#374151" stroke-width="1" fill="none">
<line x1="280" y1="142" x2="180" y2="80"/>
<line x1="292" y1="142" x2="120" y2="120"/>
<line x1="320" y1="146" x2="180" y2="180"/>
<line x1="400" y1="142" x2="540" y2="80"/>
<line x1="400" y1="154" x2="540" y2="200"/>
</g>
<g fill="#111827" font-size="13" font-weight="600">
<text x="180" y="74">1 · Container — rounded.full, 2024 high</text>
<text x="120" y="114">2 · Dot — 8×8, semantic color (optional)</text>
<text x="180" y="194">3 · Label — typography.caption, semibold, semantic text color</text>
<text x="540" y="74">4 · Padding — 2 × 8 (text-only), 2 × 6 (with dot)</text>
<text x="540" y="194">5 · Count badge — same shape, fixed-width, inverse text</text>
</g>
<text x="40" y="208" fill="#6B7280" font-size="12" font-weight="700">VARIANTS</text>
<text x="40" y="270" fill="#6B7280" font-size="12">Pair each background with the matching foreground for AA contrast.</text>
<!-- token legend -->
<g transform="translate(40 300)">
<text x="0" y="0" font-size="12" font-weight="700" fill="#111827">Tokens</text>
<text x="0" y="16" font-size="12" fill="#374151">radius → rounded.full · typography → caption · height → 2024</text>
<text x="0" y="32" font-size="12" fill="#374151">success → semantic.success @ 16% bg / @ 100% text (apply same recipe per variant)</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.4 KiB

+25
View File
@@ -0,0 +1,25 @@
# Buttons
Specification for the **buttons** primitive.
## Anatomy
TODO — drop `anatomy.svg` next to this file.
## Variants
- default
- (list per-component variants)
## States
default · hover · focus-visible · active/pressed · disabled · loading
## Tokens used
See `design.md``components.buttons.*`.
## Accessibility
- All interactive instances are keyboard-reachable.
- Focus state has ≥ 3:1 contrast against its background.
- Pair color with an icon or text to convey meaning.
## Do / Don't
- ✅ Use the canonical token references.
- ❌ Don't hardcode colors, sizes, or radii.
+53
View File
@@ -0,0 +1,53 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 380" width="760" height="380" font-family="Inter, Arial, sans-serif" role="img" aria-label="Button anatomy">
<title>Button anatomy</title>
<desc>Labeled diagram of a KDC primary button: focus ring, container, corner radius, leading icon, label, and padding.</desc>
<!-- canvas -->
<rect width="760" height="380" fill="#F7F8FA"/>
<!-- focus ring (offset, dashed) -->
<rect x="294" y="166" width="232" height="68" rx="12"
fill="none" stroke="#0B5FFF" stroke-opacity="0.45" stroke-width="2" stroke-dasharray="4 4"/>
<!-- button container -->
<rect x="300" y="172" width="220" height="56" rx="8" fill="#0B5FFF"/>
<!-- leading icon (check) -->
<g transform="translate(324 188)" stroke="#FFFFFF" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" fill="none">
<path d="M20 6 9 17l-5-5"/>
</g>
<!-- label -->
<text x="360" y="207" fill="#FFFFFF" font-size="18" font-weight="600">Save changes</text>
<!-- annotation leader lines -->
<g stroke="#374151" stroke-width="1" fill="none">
<line x1="294" y1="166" x2="180" y2="90"/> <!-- focus ring -->
<line x1="336" y1="200" x2="180" y2="140"/> <!-- icon -->
<line x1="300" y1="172" x2="200" y2="270"/> <!-- container -->
<line x1="520" y1="172" x2="640" y2="90"/> <!-- corner radius -->
<line x1="430" y1="215" x2="560" y2="300"/> <!-- label -->
<line x1="324" y1="228" x2="324" y2="270"/> <!-- padding -->
<line x1="300" y1="265" x2="324" y2="265"/>
</g>
<!-- annotation text -->
<g fill="#111827" font-size="13" font-weight="600">
<text x="180" y="84">1 · Focus ring — 2px, offset 4px, brand.primary @ 45%</text>
<text x="180" y="134">2 · Leading icon — 24×24, currentColor</text>
<text x="80" y="284">3 · Container — colors.brand.primary, height 56</text>
<text x="640" y="84">4 · Corner radius — rounded.md (8px)</text>
<text x="560" y="316">5 · Label — typography.bodyM, semibold, text.inverse</text>
<text x="296" y="288" text-anchor="end">6 · Padding — 12 × 20</text>
</g>
<!-- token legend -->
<g transform="translate(40 332)">
<text x="0" y="0" font-size="12" font-weight="700" fill="#111827">Tokens</text>
<text x="0" y="18" font-size="12" fill="#374151">container.bg → colors.brand.primary</text>
<text x="260" y="18" font-size="12" fill="#374151">label → typography.bodyM · colors.text.inverse</text>
<text x="520" y="18" font-size="12" fill="#374151">radius → rounded.md (8px)</text>
<text x="0" y="36" font-size="12" fill="#374151">padding → spacing.3 / spacing.5 (12 × 20)</text>
<text x="260" y="36" font-size="12" fill="#374151">focus → brand.primary @ 45%, 2px, offset 4px</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

+25
View File
@@ -0,0 +1,25 @@
# Cards
Specification for the **cards** primitive.
## Anatomy
TODO — drop `anatomy.svg` next to this file.
## Variants
- default
- (list per-component variants)
## States
default · hover · focus-visible · active/pressed · disabled · loading
## Tokens used
See `design.md``components.cards.*`.
## Accessibility
- All interactive instances are keyboard-reachable.
- Focus state has ≥ 3:1 contrast against its background.
- Pair color with an icon or text to convey meaning.
## Do / Don't
- ✅ Use the canonical token references.
- ❌ Don't hardcode colors, sizes, or radii.
+57
View File
@@ -0,0 +1,57 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 420" width="760" height="420" font-family="Inter, Arial, sans-serif" role="img" aria-label="Card anatomy">
<title>Card anatomy</title>
<desc>Labeled diagram of a KDC card: container, media, title, body text, metadata, action area.</desc>
<rect width="760" height="420" fill="#F7F8FA"/>
<!-- card container with subtle elevation -->
<g>
<rect x="220" y="80" width="320" height="280" rx="12" fill="#FFFFFF"/>
<rect x="220" y="80" width="320" height="280" rx="12" fill="none" stroke="#EDEFF3"/>
</g>
<!-- media area -->
<rect x="220" y="80" width="320" height="120" rx="12" fill="#0B5FFF"/>
<rect x="220" y="170" width="320" height="30" fill="#0B5FFF"/>
<!-- title -->
<text x="244" y="232" fill="#111827" font-size="18" font-weight="700">Card title</text>
<!-- body -->
<text x="244" y="258" fill="#374151" font-size="14">A short summary of what this card</text>
<text x="244" y="276" fill="#374151" font-size="14">represents — keep it under two lines.</text>
<!-- metadata -->
<text x="244" y="304" fill="#6B7280" font-size="12">Updated 2 days ago · 3 min read</text>
<!-- action -->
<rect x="244" y="320" width="100" height="28" rx="6" fill="#0B5FFF"/>
<text x="294" y="338" text-anchor="middle" fill="#FFFFFF" font-size="12" font-weight="600">Read more</text>
<!-- annotations -->
<g stroke="#374151" stroke-width="1" fill="none">
<line x1="220" y1="80" x2="100" y2="60"/>
<line x1="380" y1="140" x2="640" y2="100"/>
<line x1="280" y1="232" x2="100" y2="220"/>
<line x1="380" y1="270" x2="640" y2="240"/>
<line x1="320" y1="304" x2="100" y2="320"/>
<line x1="344" y1="334" x2="640" y2="334"/>
</g>
<g fill="#111827" font-size="13" font-weight="600">
<text x="100" y="54">1 · Container — surface.background, rounded.lg, elevation.1</text>
<text x="640" y="94">2 · Media area — image / accent / illustration</text>
<text x="100" y="214">3 · Title — typography.headingM</text>
<text x="640" y="234">4 · Body — typography.bodyS, text.muted</text>
<text x="100" y="314">5 · Metadata — typography.caption, text.muted</text>
<text x="640" y="328">6 · Action area — primary or ghost button</text>
</g>
<!-- token legend -->
<g transform="translate(40 380)">
<text x="0" y="0" font-size="12" font-weight="700" fill="#111827">Tokens</text>
<text x="0" y="16" font-size="12" fill="#374151">container.bg → surface.background · radius → rounded.lg (12px)</text>
<text x="420" y="16" font-size="12" fill="#374151">padding → spacing.6 (24px)</text>
<text x="0" y="32" font-size="12" fill="#374151">elevation → elevation.1 · border → border.default (optional)</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

+25
View File
@@ -0,0 +1,25 @@
# Dropdowns
Specification for the **dropdowns** primitive.
## Anatomy
TODO — drop `anatomy.svg` next to this file.
## Variants
- default
- (list per-component variants)
## States
default · hover · focus-visible · active/pressed · disabled · loading
## Tokens used
See `design.md``components.dropdowns.*`.
## Accessibility
- All interactive instances are keyboard-reachable.
- Focus state has ≥ 3:1 contrast against its background.
- Pair color with an icon or text to convey meaning.
## Do / Don't
- ✅ Use the canonical token references.
- ❌ Don't hardcode colors, sizes, or radii.
+87
View File
@@ -0,0 +1,87 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 440" width="760" height="440" font-family="Inter, Arial, sans-serif" role="img" aria-label="Dropdown anatomy">
<title>Dropdown / Menu anatomy</title>
<desc>Labeled diagram of a KDC dropdown menu: trigger, menu surface, item, leading icon, shortcut, divider, group label, destructive item, hover state.</desc>
<rect width="760" height="440" fill="#F7F8FA"/>
<!-- trigger -->
<rect x="200" y="60" width="160" height="36" rx="8" fill="#FFFFFF" stroke="#D9DCE3"/>
<text x="216" y="83" fill="#111827" font-size="13" font-weight="600">Actions</text>
<g transform="translate(332 76)" stroke="#6B7280" stroke-width="1.8" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path d="m0 0 6 6 6-6"/>
</g>
<!-- menu surface -->
<g>
<rect x="200" y="108" width="240" height="240" rx="12" fill="#FFFFFF"/>
<rect x="200" y="108" width="240" height="240" rx="12" fill="none" stroke="#EDEFF3"/>
<!-- group label -->
<text x="216" y="130" fill="#6B7280" font-size="11" font-weight="700">PROJECT</text>
<!-- item -->
<rect x="208" y="138" width="224" height="32" rx="6" fill="#FFFFFF"/>
<g transform="translate(220 148)" stroke="#374151" stroke-width="1.6" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path d="M12 20h9"/><path d="M16.5 3.5a2.121 2.121 0 1 1 3 3L7 19l-4 1 1-4z"/>
</g>
<text x="248" y="160" fill="#111827" font-size="13">Rename</text>
<text x="416" y="160" text-anchor="end" fill="#6B7280" font-size="11">⌘R</text>
<!-- item (hover) -->
<rect x="208" y="174" width="224" height="32" rx="6" fill="#F7F8FA"/>
<g transform="translate(220 184)" stroke="#374151" stroke-width="1.6" fill="none" stroke-linecap="round" stroke-linejoin="round">
<rect x="0" y="2" width="14" height="18" rx="2"/>
<path d="M5 0h6v4H5z"/>
</g>
<text x="248" y="196" fill="#111827" font-size="13">Duplicate</text>
<text x="416" y="196" text-anchor="end" fill="#6B7280" font-size="11">⌘D</text>
<!-- divider -->
<line x1="216" y1="218" x2="424" y2="218" stroke="#EDEFF3"/>
<!-- group label 2 -->
<text x="216" y="236" fill="#6B7280" font-size="11" font-weight="700">DANGER</text>
<!-- destructive item -->
<rect x="208" y="244" width="224" height="32" rx="6" fill="#FFFFFF"/>
<g transform="translate(220 254)" stroke="#DC2626" stroke-width="1.6" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path d="M3 6h18M8 6V3h8v3M6 6l1 14h10l1-14"/>
</g>
<text x="248" y="266" fill="#DC2626" font-size="13" font-weight="600">Delete</text>
<text x="416" y="266" text-anchor="end" fill="#DC2626" font-size="11"></text>
<!-- disabled item -->
<rect x="208" y="282" width="224" height="32" rx="6" fill="#FFFFFF"/>
<g transform="translate(220 292)" stroke="#B8BDC9" stroke-width="1.6" fill="none" stroke-linecap="round" stroke-linejoin="round">
<circle cx="11" cy="11" r="9"/><path d="m4 4 14 14"/>
</g>
<text x="248" y="304" fill="#B8BDC9" font-size="13">Archive (coming soon)</text>
</g>
<!-- annotations -->
<g stroke="#374151" stroke-width="1" fill="none">
<line x1="280" y1="78" x2="540" y2="80"/>
<line x1="200" y1="108" x2="60" y2="120"/>
<line x1="216" y1="130" x2="60" y2="180"/>
<line x1="232" y1="190" x2="60" y2="230"/>
<line x1="416" y1="160" x2="540" y2="140"/>
<line x1="248" y1="266" x2="540" y2="280"/>
<line x1="248" y1="304" x2="540" y2="320"/>
</g>
<g fill="#111827" font-size="13" font-weight="600">
<text x="540" y="74">1 · Trigger — disclosure caret indicates menu</text>
<text x="60" y="114">2 · Surface — surface.background, rounded.lg, elevation.2</text>
<text x="60" y="174">3 · Group label — typography.caption, uppercase, text.muted</text>
<text x="60" y="224">4 · Hover state — surface.subtle, full-width</text>
<text x="540" y="134">5 · Shortcut — typography.caption, right-aligned</text>
<text x="540" y="274">6 · Destructive item — semantic.danger text + icon</text>
<text x="540" y="314">7 · Disabled — text.muted, non-interactive, skipped by keyboard</text>
</g>
<!-- token legend -->
<g transform="translate(40 380)">
<text x="0" y="0" font-size="12" font-weight="700" fill="#111827">Tokens</text>
<text x="0" y="16" font-size="12" fill="#374151">surface.bg → surface.background · radius → rounded.lg · elevation → elevation.2</text>
<text x="0" y="32" font-size="12" fill="#374151">item.height → 32 · item.padding → 8 × 12 · divider → border.default</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.6 KiB

+25
View File
@@ -0,0 +1,25 @@
# Forms
Specification for the **forms** primitive.
## Anatomy
TODO — drop `anatomy.svg` next to this file.
## Variants
- default
- (list per-component variants)
## States
default · hover · focus-visible · active/pressed · disabled · loading
## Tokens used
See `design.md``components.forms.*`.
## Accessibility
- All interactive instances are keyboard-reachable.
- Focus state has ≥ 3:1 contrast against its background.
- Pair color with an icon or text to convey meaning.
## Do / Don't
- ✅ Use the canonical token references.
- ❌ Don't hardcode colors, sizes, or radii.
+62
View File
@@ -0,0 +1,62 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 460" width="760" height="460" font-family="Inter, Arial, sans-serif" role="img" aria-label="Form anatomy">
<title>Form anatomy</title>
<desc>Labeled diagram of a KDC form: fieldset legend, field group with label, input, helper, required marker, submit/cancel actions.</desc>
<rect width="760" height="460" fill="#F7F8FA"/>
<!-- fieldset -->
<rect x="220" y="60" width="380" height="340" rx="12" fill="#FFFFFF" stroke="#EDEFF3"/>
<!-- legend -->
<text x="244" y="92" fill="#111827" font-size="16" font-weight="700">Account details</text>
<text x="244" y="112" fill="#6B7280" font-size="12">Used for sign-in and notifications.</text>
<!-- field 1 -->
<text x="244" y="148" fill="#111827" font-size="13" font-weight="600">Full name</text>
<text x="316" y="148" fill="#DC2626" font-size="13" font-weight="700">*</text>
<rect x="244" y="158" width="332" height="40" rx="8" fill="#FFFFFF" stroke="#D9DCE3"/>
<text x="256" y="184" fill="#111827" font-size="14">Patrick Kitchens</text>
<text x="244" y="216" fill="#6B7280" font-size="12">As it should appear on your invoices.</text>
<!-- field 2 (with error) -->
<text x="244" y="248" fill="#111827" font-size="13" font-weight="600">Email</text>
<text x="284" y="248" fill="#DC2626" font-size="13" font-weight="700">*</text>
<rect x="244" y="258" width="332" height="40" rx="8" fill="#FFFFFF" stroke="#DC2626" stroke-width="1.5"/>
<text x="256" y="284" fill="#111827" font-size="14">pwrkitchens</text>
<text x="244" y="316" fill="#DC2626" font-size="12">Enter a valid email address.</text>
<!-- actions -->
<line x1="244" y1="344" x2="576" y2="344" stroke="#EDEFF3"/>
<rect x="416" y="356" width="68" height="32" rx="6" fill="#F7F8FA" stroke="#D9DCE3"/>
<text x="450" y="376" text-anchor="middle" fill="#111827" font-size="12" font-weight="600">Cancel</text>
<rect x="496" y="356" width="80" height="32" rx="6" fill="#0B5FFF"/>
<text x="536" y="376" text-anchor="middle" fill="#FFFFFF" font-size="12" font-weight="600">Save</text>
<!-- annotation leaders -->
<g stroke="#374151" stroke-width="1" fill="none">
<line x1="220" y1="80" x2="100" y2="60"/>
<line x1="244" y1="148" x2="100" y2="120"/>
<line x1="320" y1="148" x2="100" y2="160"/>
<line x1="244" y1="216" x2="100" y2="220"/>
<line x1="576" y1="298" x2="660" y2="280"/>
<line x1="576" y1="316" x2="660" y2="340"/>
<line x1="576" y1="372" x2="660" y2="380"/>
</g>
<g fill="#111827" font-size="13" font-weight="600">
<text x="100" y="54">1 · Fieldset / section — legend + helper</text>
<text x="100" y="114">2 · Field label — typography.bodyS, semibold</text>
<text x="100" y="154">3 · Required marker — semantic.danger</text>
<text x="100" y="214">4 · Helper text — typography.caption, text.muted</text>
<text x="660" y="274">5 · Error border — semantic.danger, 1.5px</text>
<text x="660" y="334">6 · Error message — typography.caption, semantic.danger</text>
<text x="660" y="374">7 · Actions — primary right-most, cancel ghost</text>
</g>
<!-- token legend -->
<g transform="translate(40 420)">
<text x="0" y="0" font-size="12" font-weight="700" fill="#111827">Tokens</text>
<text x="0" y="16" font-size="12" fill="#374151">field.gap → spacing.2 (8px) between label/input/helper</text>
<text x="0" y="32" font-size="12" fill="#374151">stack.gap → spacing.5 (20px) between fields · section.padding → spacing.6 (24px)</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.5 KiB

+25
View File
@@ -0,0 +1,25 @@
# Inputs
Specification for the **inputs** primitive.
## Anatomy
TODO — drop `anatomy.svg` next to this file.
## Variants
- default
- (list per-component variants)
## States
default · hover · focus-visible · active/pressed · disabled · loading
## Tokens used
See `design.md``components.inputs.*`.
## Accessibility
- All interactive instances are keyboard-reachable.
- Focus state has ≥ 3:1 contrast against its background.
- Pair color with an icon or text to convey meaning.
## Do / Don't
- ✅ Use the canonical token references.
- ❌ Don't hardcode colors, sizes, or radii.
+67
View File
@@ -0,0 +1,67 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 380" width="760" height="380" font-family="Inter, Arial, sans-serif" role="img" aria-label="Input anatomy">
<title>Input anatomy</title>
<desc>Labeled diagram of a KDC text input: label, container, leading icon, placeholder/value, helper text, error state.</desc>
<rect width="760" height="380" fill="#F7F8FA"/>
<!-- field label -->
<text x="220" y="120" fill="#111827" font-size="13" font-weight="600">Email address</text>
<text x="416" y="120" fill="#6B7280" font-size="13">Optional</text>
<!-- container -->
<rect x="220" y="132" width="320" height="40" rx="8" fill="#FFFFFF" stroke="#D9DCE3"/>
<!-- leading icon (envelope-ish) -->
<g transform="translate(232 144)" stroke="#6B7280" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" fill="none">
<rect x="0" y="2" width="20" height="14" rx="2"/>
<path d="m0 4 10 7 10-7"/>
</g>
<!-- value text -->
<text x="262" y="158" fill="#111827" font-size="14">you@kdc.com</text>
<!-- trailing clear icon -->
<g transform="translate(516 144)" stroke="#6B7280" stroke-width="1.8" stroke-linecap="round" fill="none">
<circle cx="8" cy="8" r="8" stroke-opacity="0"/>
<path d="m4 4 8 8M12 4l-8 8"/>
</g>
<!-- helper text -->
<text x="220" y="190" fill="#6B7280" font-size="12">We'll never share your email.</text>
<!-- error variant -->
<text x="220" y="240" fill="#111827" font-size="13" font-weight="600">Email address</text>
<rect x="220" y="252" width="320" height="40" rx="8" fill="#FFFFFF" stroke="#DC2626" stroke-width="1.5"/>
<text x="232" y="278" fill="#DC2626" font-size="14">not-an-email</text>
<text x="220" y="310" fill="#DC2626" font-size="12">Enter a valid email address.</text>
<!-- annotation leaders -->
<g stroke="#374151" stroke-width="1" fill="none">
<line x1="220" y1="118" x2="100" y2="80"/>
<line x1="220" y1="132" x2="80" y2="160"/>
<line x1="240" y1="152" x2="120" y2="200"/>
<line x1="540" y1="152" x2="660" y2="80"/>
<line x1="220" y1="190" x2="100" y2="240"/>
<line x1="540" y1="252" x2="660" y2="220"/>
<line x1="540" y1="310" x2="660" y2="310"/>
</g>
<g fill="#111827" font-size="13" font-weight="600">
<text x="100" y="74">1 · Label — typography.bodyS, semibold</text>
<text x="80" y="154">2 · Container — surface.background, border.default, rounded.md</text>
<text x="120" y="218">3 · Leading icon — 20×20, text.muted</text>
<text x="660" y="74">4 · Trailing action (clear / reveal)</text>
<text x="100" y="234">5 · Helper text — typography.caption, text.muted</text>
<text x="660" y="214">6 · Error border — semantic.danger, 1.5px</text>
<text x="660" y="304">7 · Error message — semantic.danger</text>
</g>
<!-- token legend -->
<g transform="translate(40 340)">
<text x="0" y="0" font-size="12" font-weight="700" fill="#111827">Tokens</text>
<text x="0" y="16" font-size="12" fill="#374151">container.bg → surface.background · border → border.default</text>
<text x="380" y="16" font-size="12" fill="#374151">value → typography.bodyS · text.default</text>
<text x="0" y="32" font-size="12" fill="#374151">radius → rounded.md · padding 10 × 12 · height 40</text>
<text x="380" y="32" font-size="12" fill="#374151">error → semantic.danger</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.3 KiB

+25
View File
@@ -0,0 +1,25 @@
# Modals
Specification for the **modals** primitive.
## Anatomy
TODO — drop `anatomy.svg` next to this file.
## Variants
- default
- (list per-component variants)
## States
default · hover · focus-visible · active/pressed · disabled · loading
## Tokens used
See `design.md``components.modals.*`.
## Accessibility
- All interactive instances are keyboard-reachable.
- Focus state has ≥ 3:1 contrast against its background.
- Pair color with an icon or text to convey meaning.
## Do / Don't
- ✅ Use the canonical token references.
- ❌ Don't hardcode colors, sizes, or radii.
+63
View File
@@ -0,0 +1,63 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 440" width="760" height="440" font-family="Inter, Arial, sans-serif" role="img" aria-label="Modal anatomy">
<title>Modal anatomy</title>
<desc>Labeled diagram of a KDC modal: scrim, container, header, body, footer actions, close button.</desc>
<!-- scrim -->
<rect width="760" height="440" fill="#111827" fill-opacity="0.55"/>
<!-- modal container -->
<rect x="180" y="60" width="400" height="320" rx="16" fill="#FFFFFF"/>
<!-- header -->
<text x="204" y="100" fill="#111827" font-size="20" font-weight="700">Delete project</text>
<text x="204" y="118" fill="#6B7280" font-size="12">This action cannot be undone.</text>
<!-- close icon -->
<g transform="translate(540 80)" stroke="#6B7280" stroke-width="1.8" stroke-linecap="round" fill="none">
<path d="m4 4 12 12M16 4 4 16"/>
</g>
<!-- divider -->
<line x1="204" y1="138" x2="556" y2="138" stroke="#EDEFF3"/>
<!-- body -->
<text x="204" y="170" fill="#374151" font-size="14">Are you sure you want to delete</text>
<text x="204" y="190" fill="#374151" font-size="14">"Marketing Q3"? All associated data</text>
<text x="204" y="210" fill="#374151" font-size="14">will be permanently removed.</text>
<!-- footer divider -->
<line x1="204" y1="316" x2="556" y2="316" stroke="#EDEFF3"/>
<!-- footer actions -->
<rect x="396" y="332" width="68" height="32" rx="6" fill="#F7F8FA" stroke="#D9DCE3"/>
<text x="430" y="352" text-anchor="middle" fill="#111827" font-size="12" font-weight="600">Cancel</text>
<rect x="476" y="332" width="80" height="32" rx="6" fill="#DC2626"/>
<text x="516" y="352" text-anchor="middle" fill="#FFFFFF" font-size="12" font-weight="600">Delete</text>
<!-- annotations -->
<g stroke="#FFFFFF" stroke-width="1" fill="none">
<line x1="100" y1="40" x2="180" y2="40"/>
<line x1="180" y1="60" x2="100" y2="100"/>
<line x1="380" y1="100" x2="660" y2="60"/>
<line x1="544" y1="86" x2="660" y2="120"/>
<line x1="380" y1="200" x2="660" y2="200"/>
<line x1="380" y1="346" x2="660" y2="346"/>
</g>
<g fill="#FFFFFF" font-size="13" font-weight="600">
<text x="100" y="34">1 · Scrim — neutral.900 @ 55%</text>
<text x="100" y="116">2 · Container — surface.background, rounded.xl, elevation.3</text>
<text x="660" y="54">3 · Header — title + optional subtitle</text>
<text x="660" y="114">4 · Close — top-right, 20×20</text>
<text x="660" y="194">5 · Body — typography.bodyM, scrolls if tall</text>
<text x="660" y="340">6 · Footer — actions right-aligned, primary last</text>
</g>
<!-- token legend -->
<g transform="translate(40 400)">
<text x="0" y="0" font-size="12" font-weight="700" fill="#FFFFFF">Tokens</text>
<text x="0" y="16" font-size="12" fill="#EDEFF3">container.bg → surface.background · radius → rounded.xl (16px)</text>
<text x="420" y="16" font-size="12" fill="#EDEFF3">width → 480px (default modal)</text>
<text x="0" y="32" font-size="12" fill="#EDEFF3">scrim → neutral.900 @ 55% · elevation → elevation.3</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

+25
View File
@@ -0,0 +1,25 @@
# Navigation
Specification for the **navigation** primitive.
## Anatomy
TODO — drop `anatomy.svg` next to this file.
## Variants
- default
- (list per-component variants)
## States
default · hover · focus-visible · active/pressed · disabled · loading
## Tokens used
See `design.md``components.navigation.*`.
## Accessibility
- All interactive instances are keyboard-reachable.
- Focus state has ≥ 3:1 contrast against its background.
- Pair color with an icon or text to convey meaning.
## Do / Don't
- ✅ Use the canonical token references.
- ❌ Don't hardcode colors, sizes, or radii.
+61
View File
@@ -0,0 +1,61 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 360" width="760" height="360" font-family="Inter, Arial, sans-serif" role="img" aria-label="Navigation anatomy">
<title>Navigation (top bar) anatomy</title>
<desc>Labeled diagram of a KDC top navigation bar: logo, primary nav, search, user menu, active indicator.</desc>
<rect width="760" height="360" fill="#F7F8FA"/>
<!-- top bar -->
<rect x="40" y="80" width="680" height="64" rx="0" fill="#FFFFFF"/>
<line x1="40" y1="144" x2="720" y2="144" stroke="#EDEFF3"/>
<!-- logo -->
<rect x="64" y="100" width="40" height="24" rx="6" fill="#0B5FFF"/>
<text x="84" y="117" text-anchor="middle" fill="#FFFFFF" font-size="12" font-weight="800">KDC</text>
<!-- primary nav -->
<text x="156" y="117" fill="#111827" font-size="14" font-weight="600">Home</text>
<text x="220" y="117" fill="#0B5FFF" font-size="14" font-weight="700">Projects</text>
<text x="296" y="117" fill="#374151" font-size="14">Reports</text>
<text x="364" y="117" fill="#374151" font-size="14">Team</text>
<!-- active indicator under Projects -->
<rect x="220" y="135" width="60" height="3" rx="1.5" fill="#0B5FFF"/>
<!-- search -->
<rect x="448" y="98" width="180" height="28" rx="14" fill="#F7F8FA" stroke="#D9DCE3"/>
<g transform="translate(458 106)" stroke="#6B7280" stroke-width="1.8" fill="none" stroke-linecap="round">
<circle cx="6" cy="6" r="5"/>
<path d="m10 10 4 4"/>
</g>
<text x="478" y="117" fill="#6B7280" font-size="12">Search…</text>
<!-- avatar -->
<circle cx="676" cy="112" r="14" fill="#00C2A8"/>
<text x="676" y="117" text-anchor="middle" fill="#FFFFFF" font-size="11" font-weight="700">PK</text>
<!-- annotation leaders -->
<g stroke="#374151" stroke-width="1" fill="none">
<line x1="84" y1="100" x2="80" y2="40"/>
<line x1="240" y1="100" x2="280" y2="40"/>
<line x1="250" y1="138" x2="320" y2="200"/>
<line x1="538" y1="112" x2="540" y2="40"/>
<line x1="676" y1="98" x2="700" y2="40"/>
<line x1="380" y1="144" x2="380" y2="200"/>
</g>
<g fill="#111827" font-size="13" font-weight="600">
<text x="60" y="34">1 · Logo / brand mark</text>
<text x="260" y="34">2 · Primary nav — typography.bodyS</text>
<text x="320" y="216">3 · Active indicator — 3px bar, brand.primary</text>
<text x="500" y="34">4 · Search — pill, rounded.full, surface.subtle</text>
<text x="660" y="34" text-anchor="end">5 · User menu (avatar)</text>
<text x="380" y="216">6 · Bottom border — border.default</text>
</g>
<!-- token legend -->
<g transform="translate(40 300)">
<text x="0" y="0" font-size="12" font-weight="700" fill="#111827">Tokens</text>
<text x="0" y="16" font-size="12" fill="#374151">bar.bg → surface.background · height 64 · border-bottom → border.default</text>
<text x="0" y="32" font-size="12" fill="#374151">item → typography.bodyS · active → brand.primary · inactive → text.default/muted</text>
<text x="0" y="48" font-size="12" fill="#374151">search → rounded.full, surface.subtle, border.default</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

+25
View File
@@ -0,0 +1,25 @@
# Tables
Specification for the **tables** primitive.
## Anatomy
TODO — drop `anatomy.svg` next to this file.
## Variants
- default
- (list per-component variants)
## States
default · hover · focus-visible · active/pressed · disabled · loading
## Tokens used
See `design.md``components.tables.*`.
## Accessibility
- All interactive instances are keyboard-reachable.
- Focus state has ≥ 3:1 contrast against its background.
- Pair color with an icon or text to convey meaning.
## Do / Don't
- ✅ Use the canonical token references.
- ❌ Don't hardcode colors, sizes, or radii.
+81
View File
@@ -0,0 +1,81 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 420" width="760" height="420" font-family="Inter, Arial, sans-serif" role="img" aria-label="Table anatomy">
<title>Table anatomy</title>
<desc>Labeled diagram of a KDC data table: header row, sortable header, body row, zebra/hover, row selection, status cell, pagination.</desc>
<rect width="760" height="420" fill="#F7F8FA"/>
<!-- table container -->
<rect x="40" y="80" width="680" height="240" rx="12" fill="#FFFFFF"/>
<rect x="40" y="80" width="680" height="240" rx="12" fill="none" stroke="#EDEFF3"/>
<!-- header row -->
<rect x="40" y="80" width="680" height="40" rx="12" fill="#F7F8FA"/>
<rect x="40" y="100" width="680" height="20" fill="#F7F8FA"/>
<line x1="40" y1="120" x2="720" y2="120" stroke="#EDEFF3"/>
<!-- header checkbox -->
<rect x="60" y="94" width="14" height="14" rx="3" fill="#FFFFFF" stroke="#B8BDC9"/>
<!-- header labels -->
<text x="92" y="105" fill="#374151" font-size="12" font-weight="700">NAME ↑</text>
<text x="280" y="105" fill="#6B7280" font-size="12" font-weight="700">EMAIL</text>
<text x="500" y="105" fill="#6B7280" font-size="12" font-weight="700">STATUS</text>
<text x="640" y="105" fill="#6B7280" font-size="12" font-weight="700">ROLE</text>
<!-- body row 1 (selected) -->
<rect x="40" y="120" width="680" height="40" fill="#EFF4FF"/>
<rect x="60" y="134" width="14" height="14" rx="3" fill="#0B5FFF"/>
<path d="M64 141l3 3 6-6" stroke="#FFFFFF" stroke-width="1.6" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
<text x="92" y="145" fill="#111827" font-size="13">Patrick Kitchens</text>
<text x="280" y="145" fill="#374151" font-size="13">pwr@kdc.com</text>
<rect x="500" y="132" width="58" height="18" rx="9" fill="#DCFCE7"/>
<text x="529" y="145" text-anchor="middle" fill="#16A34A" font-size="11" font-weight="600">Active</text>
<text x="640" y="145" fill="#374151" font-size="13">Owner</text>
<!-- body row 2 -->
<line x1="40" y1="160" x2="720" y2="160" stroke="#EDEFF3"/>
<rect x="60" y="174" width="14" height="14" rx="3" fill="#FFFFFF" stroke="#B8BDC9"/>
<text x="92" y="185" fill="#111827" font-size="13">Ada Lovelace</text>
<text x="280" y="185" fill="#374151" font-size="13">ada@kdc.com</text>
<rect x="500" y="172" width="68" height="18" rx="9" fill="#FEF3C7"/>
<text x="534" y="185" text-anchor="middle" fill="#B45309" font-size="11" font-weight="600">Pending</text>
<text x="640" y="185" fill="#374151" font-size="13">Editor</text>
<!-- body row 3 -->
<line x1="40" y1="200" x2="720" y2="200" stroke="#EDEFF3"/>
<rect x="60" y="214" width="14" height="14" rx="3" fill="#FFFFFF" stroke="#B8BDC9"/>
<text x="92" y="225" fill="#111827" font-size="13">Grace Hopper</text>
<text x="280" y="225" fill="#374151" font-size="13">grace@kdc.com</text>
<rect x="500" y="212" width="64" height="18" rx="9" fill="#FEE2E2"/>
<text x="532" y="225" text-anchor="middle" fill="#DC2626" font-size="11" font-weight="600">Failed</text>
<text x="640" y="225" fill="#374151" font-size="13">Viewer</text>
<!-- pagination strip -->
<line x1="40" y1="280" x2="720" y2="280" stroke="#EDEFF3"/>
<text x="60" y="304" fill="#6B7280" font-size="12">Showing 13 of 124</text>
<text x="600" y="304" fill="#374151" font-size="12"> 1 2 3 4 </text>
<!-- annotations -->
<g stroke="#374151" stroke-width="1" fill="none">
<line x1="40" y1="100" x2="40" y2="40"/>
<line x1="120" y1="100" x2="200" y2="40"/>
<line x1="500" y1="140" x2="600" y2="40"/>
<line x1="60" y1="140" x2="20" y2="220"/>
<line x1="40" y1="140" x2="20" y2="180"/>
<line x1="40" y1="280" x2="20" y2="340"/>
</g>
<g fill="#111827" font-size="13" font-weight="600">
<text x="40" y="34">1 · Header row — surface.subtle, caption, uppercase</text>
<text x="200" y="34">2 · Sortable column — arrow indicates direction</text>
<text x="600" y="34">3 · Status pill — semantic colors (success/warning/danger)</text>
<text x="40" y="240">4 · Selected row — brand.primary @ 8% tint</text>
<text x="40" y="200">5 · Selection checkbox — header toggles all</text>
<text x="40" y="356">6 · Footer — count + pagination controls</text>
</g>
<!-- token legend -->
<g transform="translate(40 380)">
<text x="0" y="0" font-size="12" font-weight="700" fill="#111827">Tokens</text>
<text x="0" y="16" font-size="12" fill="#374151">row.height → 40 · cell.padding → 12 × 16 · divider → border.default</text>
<text x="0" y="32" font-size="12" fill="#374151">selected.bg → brand.primary @ 8% · hover.bg → surface.subtle</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.6 KiB

+25
View File
@@ -0,0 +1,25 @@
# Tabs
Specification for the **tabs** primitive.
## Anatomy
TODO — drop `anatomy.svg` next to this file.
## Variants
- default
- (list per-component variants)
## States
default · hover · focus-visible · active/pressed · disabled · loading
## Tokens used
See `design.md``components.tabs.*`.
## Accessibility
- All interactive instances are keyboard-reachable.
- Focus state has ≥ 3:1 contrast against its background.
- Pair color with an icon or text to convey meaning.
## Do / Don't
- ✅ Use the canonical token references.
- ❌ Don't hardcode colors, sizes, or radii.
+54
View File
@@ -0,0 +1,54 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 360" width="760" height="360" font-family="Inter, Arial, sans-serif" role="img" aria-label="Tabs anatomy">
<title>Tabs anatomy</title>
<desc>Labeled diagram of a KDC tab list: tab list, individual tab, active indicator, hover, disabled, panel, optional badge.</desc>
<rect width="760" height="360" fill="#F7F8FA"/>
<!-- tab list bar -->
<line x1="60" y1="160" x2="700" y2="160" stroke="#EDEFF3"/>
<!-- tabs -->
<g font-size="14">
<text x="80" y="148" fill="#0B5FFF" font-weight="700">Overview</text>
<rect x="76" y="156" width="84" height="3" rx="1.5" fill="#0B5FFF"/>
<text x="184" y="148" fill="#374151">Activity</text>
<g transform="translate(244 134)">
<rect width="22" height="18" rx="9" fill="#EDEFF3"/>
<text x="11" y="13" text-anchor="middle" fill="#111827" font-size="11" font-weight="700">12</text>
</g>
<text x="296" y="148" fill="#374151">Members</text>
<text x="384" y="148" fill="#B8BDC9">Billing</text>
</g>
<!-- panel -->
<rect x="60" y="180" width="640" height="100" rx="8" fill="#FFFFFF" stroke="#EDEFF3"/>
<text x="80" y="216" fill="#111827" font-size="14" font-weight="600">Overview</text>
<text x="80" y="240" fill="#374151" font-size="13">Panel content for the active tab.</text>
<!-- annotations -->
<g stroke="#374151" stroke-width="1" fill="none">
<line x1="60" y1="160" x2="40" y2="100"/>
<line x1="118" y1="158" x2="60" y2="60"/>
<line x1="120" y1="148" x2="200" y2="60"/>
<line x1="266" y1="143" x2="340" y2="60"/>
<line x1="396" y1="148" x2="540" y2="60"/>
<line x1="60" y1="180" x2="40" y2="300"/>
</g>
<g fill="#111827" font-size="13" font-weight="600">
<text x="40" y="94">1 · Tab list — bottom border separates from panel</text>
<text x="60" y="54">2 · Active indicator — 3px bar, brand.primary</text>
<text x="200" y="54">3 · Active label — brand.primary, semibold</text>
<text x="340" y="54">4 · Optional count — pill, surface.muted</text>
<text x="540" y="54">5 · Disabled tab — text.muted @ 60%, no hover</text>
<text x="40" y="316">6 · Panel — labelled by active tab via aria-controls</text>
</g>
<!-- token legend -->
<g transform="translate(40 300)">
<text x="0" y="0" font-size="12" font-weight="700" fill="#111827">Tokens</text>
<text x="0" y="16" font-size="12" fill="#374151">tab.height → 40 · tab.padding → 8 × 16 · active.bar → 3px brand.primary</text>
<text x="0" y="32" font-size="12" fill="#374151">label → typography.bodyS · inactive → text.default · disabled → text.muted @ 60%</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

+25
View File
@@ -0,0 +1,25 @@
# Tooltips
Specification for the **tooltips** primitive.
## Anatomy
TODO — drop `anatomy.svg` next to this file.
## Variants
- default
- (list per-component variants)
## States
default · hover · focus-visible · active/pressed · disabled · loading
## Tokens used
See `design.md``components.tooltips.*`.
## Accessibility
- All interactive instances are keyboard-reachable.
- Focus state has ≥ 3:1 contrast against its background.
- Pair color with an icon or text to convey meaning.
## Do / Don't
- ✅ Use the canonical token references.
- ❌ Don't hardcode colors, sizes, or radii.
+46
View File
@@ -0,0 +1,46 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 340" width="760" height="340" font-family="Inter, Arial, sans-serif" role="img" aria-label="Tooltip anatomy">
<title>Tooltip anatomy</title>
<desc>Labeled diagram of a KDC tooltip: trigger, container, arrow, label text, offset.</desc>
<rect width="760" height="340" fill="#F7F8FA"/>
<!-- trigger (icon button) -->
<rect x="356" y="200" width="48" height="48" rx="8" fill="#FFFFFF" stroke="#D9DCE3"/>
<g transform="translate(368 212)" stroke="#374151" stroke-width="1.8" fill="none" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="11"/>
<path d="M12 17V11M12 7h.01"/>
</g>
<!-- tooltip container above -->
<g>
<rect x="306" y="146" width="148" height="36" rx="6" fill="#111827"/>
<polygon points="380,182 374,190 386,190" fill="#111827"/>
<text x="380" y="170" text-anchor="middle" fill="#FFFFFF" font-size="12" font-weight="500">Save and continue</text>
</g>
<!-- offset indicator -->
<line x1="380" y1="190" x2="380" y2="200" stroke="#0B5FFF" stroke-width="1" stroke-dasharray="2 2"/>
<!-- annotations -->
<g stroke="#374151" stroke-width="1" fill="none">
<line x1="306" y1="160" x2="180" y2="120"/>
<line x1="380" y1="190" x2="500" y2="240"/>
<line x1="380" y1="170" x2="200" y2="200"/>
<line x1="356" y1="220" x2="200" y2="260"/>
<line x1="380" y1="195" x2="540" y2="200"/>
</g>
<g fill="#111827" font-size="13" font-weight="600">
<text x="180" y="114">1 · Container — neutral.900, rounded.sm, elevation.2</text>
<text x="500" y="254">2 · Arrow — 8×6 caret, same fill as container</text>
<text x="200" y="194">3 · Label — typography.caption, text.inverse, single line preferred</text>
<text x="200" y="254">4 · Trigger — focusable element (button / icon / link)</text>
<text x="540" y="194">5 · Offset — 8px gap from trigger</text>
</g>
<!-- token legend -->
<g transform="translate(40 290)">
<text x="0" y="0" font-size="12" font-weight="700" fill="#111827">Tokens</text>
<text x="0" y="16" font-size="12" fill="#374151">container.bg → neutral.900 · text → text.inverse · radius → rounded.sm</text>
<text x="0" y="32" font-size="12" fill="#374151">padding → 6 × 10 · delay.show → 200ms · delay.hide → 0ms · z-index above modals</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

+287
View File
@@ -0,0 +1,287 @@
---
version: alpha
name: KDC Design System
description: The official design system for KDC — tokens, components, and guidelines for building consistent KDC product and brand experiences.
colors:
brand.primary: "rgb(11, 95, 255)"
brand.primaryHover: "#0848C2"
brand.primaryPressed: "#063494"
brand.secondary: "#FF6B00"
brand.accent: "#00C2A8"
neutral.0: "#FFFFFF"
neutral.50: "#F7F8FA"
neutral.100: "#EDEFF3"
neutral.200: "#D9DCE3"
neutral.300: "#B8BDC9"
neutral.500: "#6B7280"
neutral.700: "#374151"
neutral.900: "#111827"
neutral.1000: "#000000"
semantic.success: "#16A34A"
semantic.warning: "#F59E0B"
semantic.danger: "#DC2626"
semantic.info: "#0EA5E9"
surface.background: "{colors.neutral.0}"
surface.subtle: "{colors.neutral.50}"
surface.muted: "{colors.neutral.100}"
text.default: "{colors.neutral.900}"
text.muted: "{colors.neutral.500}"
text.inverse: "{colors.neutral.0}"
border.default: "{colors.neutral.200}"
border.strong: "{colors.neutral.300}"
typography:
display:
fontFamily: "Inter"
fontSize: "48px"
fontWeight: 700
lineHeight: "56px"
letterSpacing: "-0.02em"
headingXL:
fontFamily: "Inter"
fontSize: "32px"
fontWeight: 700
lineHeight: "40px"
headingL:
fontFamily: "Inter"
fontSize: "24px"
fontWeight: 600
lineHeight: "32px"
headingM:
fontFamily: "Inter"
fontSize: "20px"
fontWeight: 600
lineHeight: "28px"
headingS:
fontFamily: "Inter"
fontSize: "16px"
fontWeight: 600
lineHeight: "24px"
bodyL:
fontFamily: "Inter"
fontSize: "18px"
fontWeight: 400
lineHeight: "28px"
bodyM:
fontFamily: "Inter"
fontSize: "16px"
fontWeight: 400
lineHeight: "24px"
bodyS:
fontFamily: "Inter"
fontSize: "14px"
fontWeight: 400
lineHeight: "20px"
caption:
fontFamily: "Inter"
fontSize: "12px"
fontWeight: 500
lineHeight: "16px"
letterSpacing: "0.02em"
mono:
fontFamily: "Roboto Mono"
fontSize: "14px"
fontWeight: 400
lineHeight: "20px"
rounded:
none: "0px"
xs: "2px"
sm: "4px"
md: "8px"
lg: "12px"
xl: "16px"
"2xl": "24px"
full: "9999px"
spacing:
"0": "0px"
"1": "4px"
"2": "8px"
"3": "12px"
"4": "16px"
"5": "20px"
"6": "24px"
"8": "32px"
"10": "40px"
"12": "48px"
"16": "64px"
"20": "80px"
"24": "96px"
components:
button.primary:
backgroundColor: "{colors.brand.primary}"
textColor: "{colors.text.inverse}"
typography: "{typography.bodyM}"
rounded: "{rounded.md}"
padding: "12px 20px"
height: "40px"
button.primaryHover:
backgroundColor: "{colors.brand.primaryHover}"
textColor: "{colors.text.inverse}"
button.primaryPressed:
backgroundColor: "{colors.brand.primaryPressed}"
textColor: "{colors.text.inverse}"
button.secondary:
backgroundColor: "{colors.surface.subtle}"
textColor: "{colors.text.default}"
typography: "{typography.bodyM}"
rounded: "{rounded.md}"
padding: "12px 20px"
height: "40px"
button.ghost:
backgroundColor: "transparent"
textColor: "{colors.brand.primary}"
typography: "{typography.bodyM}"
rounded: "{rounded.md}"
padding: "12px 20px"
height: "40px"
input.default:
backgroundColor: "{colors.surface.background}"
textColor: "{colors.text.default}"
typography: "{typography.bodyM}"
rounded: "{rounded.md}"
padding: "10px 12px"
height: "40px"
card.default:
backgroundColor: "{colors.surface.background}"
textColor: "{colors.text.default}"
rounded: "{rounded.lg}"
padding: "24px"
badge.default:
backgroundColor: "{colors.surface.muted}"
textColor: "{colors.text.default}"
typography: "{typography.caption}"
rounded: "{rounded.full}"
padding: "2px 8px"
height: "20px"
modal.default:
backgroundColor: "{colors.surface.background}"
textColor: "{colors.text.default}"
rounded: "{rounded.xl}"
padding: "24px"
width: "480px"
---
## Overview
The KDC Design System (KDS) is the source of truth for the visual and interaction language across all KDC products, marketing, and brand surfaces. It exists to make consistency cheap, accessibility default, and good design fast.
**Brand pillars**
- **Clear** — communication is direct and free of jargon.
- **Confident** — strong typography, decisive color, generous whitespace.
- **Human** — warm accents and approachable voice balance the precision.
KDS targets WCAG 2.2 AA at minimum across all components and themes.
## Colors
Color is organized in three layers:
1. **Brand** — primary identity colors (`brand.primary`, `brand.secondary`, `brand.accent`).
2. **Neutral** — a 12-step gray ramp powering surfaces, text, and borders.
3. **Semantic** — meaning-bearing colors for status: success, warning, danger, info.
Always reference *role* tokens (`text.default`, `surface.subtle`, `border.default`) in product code rather than raw palette values, so themes can swap without churn.
Contrast minimums:
- Body text on background: ≥ 4.5:1
- Large text and UI icons: ≥ 3:1
- Disabled/decorative content is exempt but should still be perceivable.
## Typography
The primary typeface is **Inter** (variable, 100900). The monospace companion is **Roboto Mono**, used only for code, tabular figures, and technical content.
The scale is a modular 8-step ramp (`caption``display`). Use semantic tokens (`headingL`, `bodyM`) — never hardcode `font-size`. Body copy defaults to `bodyM`/16px with a 1.5 line-height for readability. Display sizes use tighter tracking (`-0.02em`) to prevent airy letterspacing at large sizes.
Web fonts are self-hosted from `assets/fonts/` and preloaded for the two most common weights (400, 600).
## Layout
KDS is built on a **4px base unit**. All spacing, sizing, and layout dimensions are multiples of 4. The `spacing` scale exposes the curated set most commonly needed (`1``24`).
**Grid**
- 12-column responsive grid.
- Gutters: 16px (mobile) / 24px (tablet) / 32px (desktop).
- Max content width: 1200px, centered.
**Breakpoints**
| Token | Min width |
|-------|-----------|
| sm | 640px |
| md | 768px |
| lg | 1024px |
| xl | 1280px |
| 2xl | 1536px |
Layouts should be mobile-first and use logical properties (`inline-start`, `block-end`) for RTL readiness.
## Elevation & Depth
Elevation is conveyed through a small set of layered shadows plus subtle background shifts. Avoid using elevation for decoration — reserve it for affordance and hierarchy.
| Level | Use | Shadow |
|-------|-----|--------|
| 0 | flush surfaces, page background | none |
| 1 | cards, list rows | `0 1px 2px rgba(17,24,39,0.06)` |
| 2 | dropdowns, popovers | `0 4px 12px rgba(17,24,39,0.10)` |
| 3 | modals, dialogs | `0 16px 32px rgba(17,24,39,0.16)` |
| 4 | toasts, command bars | `0 24px 48px rgba(17,24,39,0.20)` |
In dark theme, shadows are de-emphasized and elevation is communicated primarily through lighter surface tints.
## Shapes
Corner radius is calibrated to component density:
- `xs` (2px) — chips, inline tags
- `sm` (4px) — inputs, small controls
- `md` (8px) — buttons, default surfaces
- `lg` (12px) — cards, sections
- `xl` (16px) — modals, sheets
- `2xl` (24px) — marketing surfaces, feature panels
- `full` — pills, avatars, circular buttons
Avoid mixing more than two radii in a single composition.
## Components
The component library lives under `components/` with one folder per primitive. Each folder ships:
- A spec (`README.md`) documenting variants, states, props, and a11y notes.
- Anatomy SVG/PNG.
- Implementation references (web/mobile, where applicable).
Core primitives shipped today:
- **Buttons** — primary, secondary, ghost, destructive; sizes sm/md/lg; loading & disabled states.
- **Inputs** — text, textarea, select, checkbox, radio, switch.
- **Cards** — default, elevated, outlined.
- **Modals** — dialog, sheet, drawer.
- **Navigation** — top bar, side nav, tabs, breadcrumbs, pagination.
- **Forms** — field, label, helper text, error message, fieldset.
- **Tables** — sortable, selectable, paginated.
- **Badges** — neutral, success, warning, danger, info.
- **Tooltips, Alerts, Tabs, Dropdowns**.
Every interactive component must define: default, hover, focus-visible, active/pressed, disabled, and (where relevant) loading.
## Do's and Don'ts
**Do**
- Use role tokens (`text.default`) over palette tokens (`neutral.900`).
- Pair every color with a contrast check before shipping.
- Lean on whitespace before adding rules, borders, or shadows.
- Keep motion under 250ms for UI feedback; ease-out for entrances, ease-in for exits.
- Provide focus-visible styles on every interactive element.
**Don't**
- Don't introduce off-system colors, fonts, or radii in product UI.
- Don't use color alone to convey meaning — always pair with icon or text.
- Don't stack more than two elevation levels in a single composition.
- Don't override component internals; extend via documented props/slots.
- Don't ship animations longer than 400ms on transactional UI.
+10
View File
@@ -0,0 +1,10 @@
# Accessibility
KDS targets **WCAG 2.2 AA**.
- Color contrast: ≥ 4.5:1 body, ≥ 3:1 large text and UI.
- Focus-visible on every interactive element.
- Don't rely on color alone — pair with icon/text.
- Honor `prefers-reduced-motion` — disable non-essential motion.
- Provide accessible names for all icons used standalone.
- Test with keyboard, screen reader (NVDA / VoiceOver), and 200% zoom.
+3
View File
@@ -0,0 +1,3 @@
# Changelog
See the project-level [`CHANGELOG.md`](../../CHANGELOG.md).
+16
View File
@@ -0,0 +1,16 @@
# Contributing
1. Open an issue describing the proposed change (token, component, doc).
2. Branch from `main`: `git checkout -b feat/<short-name>`.
3. Update `design.md` first — it is the source of truth.
4. Regenerate `tokens/` exports.
5. Add or update component documentation under `components/<name>/`.
6. Open a PR; the design-system maintainers (see `CODEOWNERS`) will review.
## PR checklist
- [ ] `design.md` updated
- [ ] Tokens regenerated
- [ ] Component spec updated (states + a11y)
- [ ] Changelog entry added under `[Unreleased]`
- [ ] Visual examples attached
+17
View File
@@ -0,0 +1,17 @@
# Getting Started
1. **Read** [`design.md`](../../design.md) — the canonical token spec.
2. **Pick** a platform from [`examples/`](../../examples/).
3. **Install** the fonts from [`assets/fonts/`](../../assets/fonts/).
4. **Import** the tokens from [`tokens/`](../../tokens/).
5. **Layer** a theme from [`themes/`](../../themes/).
## Local setup
```bash
# install
npm install
# regenerate tokens (when scripts/build-tokens.js is implemented)
npm run build:tokens
```
+7
View File
@@ -0,0 +1,7 @@
# Design Principles
1. **Clarity over cleverness** — the obvious solution is the right one.
2. **Consistency builds trust** — use system tokens, not bespoke values.
3. **Accessibility is the floor** — WCAG 2.2 AA is the minimum, not a goal.
4. **Whitespace is structural** — let layout breathe before adding rules.
5. **Motion is feedback** — animation explains state change, never decorates.
+12
View File
@@ -0,0 +1,12 @@
# Voice & Tone
**Voice (constant):** clear, confident, human.
**Tone (situational):** warm in onboarding, terse in errors, neutral in data.
## Writing rules
- Sentence case for headings, buttons, and labels.
- Active voice. "Save changes" not "Changes will be saved".
- Lead with what the user gets, not what we did.
- Numbers as digits (`3 items`, not `three items`).
- One idea per sentence in error messages.
+4
View File
@@ -0,0 +1,4 @@
# Examples · figma
Minimal reference implementation showing how to consume KDS tokens, fonts,
and components on figma.
+4
View File
@@ -0,0 +1,4 @@
# Examples · mobile
Minimal reference implementation showing how to consume KDS tokens, fonts,
and components on mobile.
+4
View File
@@ -0,0 +1,4 @@
# Examples · web
Minimal reference implementation showing how to consume KDS tokens, fonts,
and components on web.
+18
View File
@@ -0,0 +1,18 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>KDC Design System — Web Example</title>
<link rel="icon" href="../../brand/logos/favicon/favicon.svg" />
<link rel="stylesheet" href="../../assets/fonts/fonts.css" />
<link rel="stylesheet" href="./styles.css" />
</head>
<body>
<main class="container">
<h1 class="display">KDC Design System</h1>
<p class="body">A minimal page wired up to KDS tokens and fonts.</p>
<button class="btn-primary">Primary action</button>
</main>
</body>
</html>
+31
View File
@@ -0,0 +1,31 @@
:root {
--color-brand-primary: #0B5FFF;
--color-brand-primary-hover: #0848C2;
--color-text-default: #111827;
--color-surface-bg: #FFFFFF;
--radius-md: 8px;
--space-4: 16px;
--space-5: 20px;
}
body {
margin: 0;
font-family: "Inter", system-ui, sans-serif;
color: var(--color-text-default);
background: var(--color-surface-bg);
}
.container { max-width: 1200px; margin: 0 auto; padding: var(--space-5); }
.display { font-size: 48px; font-weight: 700; line-height: 56px; letter-spacing: -0.02em; }
.body { font-size: 16px; line-height: 24px; }
.btn-primary {
background: var(--color-brand-primary);
color: #fff;
border: 0;
border-radius: var(--radius-md);
padding: 12px 20px;
font: inherit;
cursor: pointer;
}
.btn-primary:hover { background: var(--color-brand-primary-hover); }
+8
View File
@@ -0,0 +1,8 @@
# Foundations · Breakpoints
Reference documentation for the **breakpoints** foundation. The canonical token values
live in [`../../design.md`](../../design.md) and the machine-readable export
in [`../../tokens/`](../../tokens/).
This page is for human-facing rationale: when to use which token, examples,
and platform notes.
+8
View File
@@ -0,0 +1,8 @@
# Foundations · Colors
Reference documentation for the **colors** foundation. The canonical token values
live in [`../../design.md`](../../design.md) and the machine-readable export
in [`../../tokens/`](../../tokens/).
This page is for human-facing rationale: when to use which token, examples,
and platform notes.
+13
View File
@@ -0,0 +1,13 @@
# Color Swatches
| Token | Hex | Preview |
|-------|-----|---------|
| `brand.primary` | `#0B5FFF` | 🟦 |
| `brand.secondary` | `#FF6B00` | 🟧 |
| `brand.accent` | `#00C2A8` | 🟩 |
| `neutral.0` | `#FFFFFF` | ⬜ |
| `neutral.900` | `#111827` | ⬛ |
| `semantic.success` | `#16A34A` | ✅ |
| `semantic.warning` | `#F59E0B` | ⚠️ |
| `semantic.danger` | `#DC2626` | 🛑 |
| `semantic.info` | `#0EA5E9` | ️ |
+8
View File
@@ -0,0 +1,8 @@
# Foundations · Elevation
Reference documentation for the **elevation** foundation. The canonical token values
live in [`../../design.md`](../../design.md) and the machine-readable export
in [`../../tokens/`](../../tokens/).
This page is for human-facing rationale: when to use which token, examples,
and platform notes.
+8
View File
@@ -0,0 +1,8 @@
# Foundations · Grid
Reference documentation for the **grid** foundation. The canonical token values
live in [`../../design.md`](../../design.md) and the machine-readable export
in [`../../tokens/`](../../tokens/).
This page is for human-facing rationale: when to use which token, examples,
and platform notes.
+8
View File
@@ -0,0 +1,8 @@
# Foundations · Motion
Reference documentation for the **motion** foundation. The canonical token values
live in [`../../design.md`](../../design.md) and the machine-readable export
in [`../../tokens/`](../../tokens/).
This page is for human-facing rationale: when to use which token, examples,
and platform notes.
+8
View File
@@ -0,0 +1,8 @@
# Foundations · Radius
Reference documentation for the **radius** foundation. The canonical token values
live in [`../../design.md`](../../design.md) and the machine-readable export
in [`../../tokens/`](../../tokens/).
This page is for human-facing rationale: when to use which token, examples,
and platform notes.
+8
View File
@@ -0,0 +1,8 @@
# Foundations · Spacing
Reference documentation for the **spacing** foundation. The canonical token values
live in [`../../design.md`](../../design.md) and the machine-readable export
in [`../../tokens/`](../../tokens/).
This page is for human-facing rationale: when to use which token, examples,
and platform notes.
+8
View File
@@ -0,0 +1,8 @@
# Foundations · Typography
Reference documentation for the **typography** foundation. The canonical token values
live in [`../../design.md`](../../design.md) and the machine-readable export
in [`../../tokens/`](../../tokens/).
This page is for human-facing rationale: when to use which token, examples,
and platform notes.
+12
View File
@@ -0,0 +1,12 @@
{
"name": "@kdc/design-system",
"version": "0.1.0-alpha.0",
"description": "KDC Design System — tokens, components, and brand assets.",
"private": true,
"scripts": {
"build:tokens": "node scripts/build-tokens.js",
"lint": "echo \"TODO: configure linter\"",
"test": "echo \"TODO: configure tests\""
},
"license": "UNLICENSED"
}
+7
View File
@@ -0,0 +1,7 @@
# Scripts
Build / export tooling for the design system.
| Script | Purpose |
|--------|---------|
| `build-tokens.js` | Convert `tokens/*.json` into platform outputs. |
+12
View File
@@ -0,0 +1,12 @@
#!/usr/bin/env node
/**
* KDC Design System — token build script (placeholder).
*
* Reads tokens/*.json and emits platform-specific outputs:
* - dist/tokens.css (CSS custom properties)
* - dist/tokens.scss (Sass variables)
* - dist/tokens.ts (TypeScript constants)
*
* Replace this stub with a real implementation (e.g. Style Dictionary).
*/
console.log("[kds] build-tokens: not implemented yet");
+4
View File
@@ -0,0 +1,4 @@
# Templates · email
Reference layouts for email experiences. Drop starter files here (HTML, MJML,
Keynote, InDesign, Figma) and document where each one applies.
+4
View File
@@ -0,0 +1,4 @@
# Templates · mobile
Reference layouts for mobile experiences. Drop starter files here (HTML, MJML,
Keynote, InDesign, Figma) and document where each one applies.
+4
View File
@@ -0,0 +1,4 @@
# Templates · presentation
Reference layouts for presentation experiences. Drop starter files here (HTML, MJML,
Keynote, InDesign, Figma) and document where each one applies.

Some files were not shown because too many files have changed in this diff Show More