jettypod 4.4.118 → 4.4.121
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env +4 -3
- package/Cargo.lock +6450 -0
- package/Cargo.toml +35 -0
- package/README.md +5 -1
- package/TAURI-MIGRATION-PLAN.md +840 -0
- package/apps/dashboard/app/connect-claude/page.tsx +5 -6
- package/apps/dashboard/app/decision/[id]/page.tsx +63 -58
- package/apps/dashboard/app/demo/gates/page.tsx +43 -45
- package/apps/dashboard/app/design-system/page.tsx +868 -0
- package/apps/dashboard/app/globals.css +80 -4
- package/apps/dashboard/app/install-claude/page.tsx +4 -6
- package/apps/dashboard/app/login/page.tsx +72 -54
- package/apps/dashboard/app/page.tsx +101 -48
- package/apps/dashboard/app/settings/page.tsx +61 -13
- package/apps/dashboard/app/signup/page.tsx +242 -0
- package/apps/dashboard/app/subscribe/page.tsx +0 -2
- package/apps/dashboard/app/tests/page.tsx +37 -4
- package/apps/dashboard/app/welcome/page.tsx +13 -16
- package/apps/dashboard/app/work/[id]/page.tsx +117 -118
- package/apps/dashboard/app/work/[id]/proof/page.tsx +1489 -0
- package/apps/dashboard/components/AppShell.tsx +92 -85
- package/apps/dashboard/components/CardMenu.tsx +45 -12
- package/apps/dashboard/components/ClaudePanel.tsx +771 -850
- package/apps/dashboard/components/ClaudePanelInput.tsx +43 -15
- package/apps/dashboard/components/ConnectClaudeScreen.tsx +17 -34
- package/apps/dashboard/components/CopyableId.tsx +3 -4
- package/apps/dashboard/components/DetailReviewActions.tsx +100 -0
- package/apps/dashboard/components/DragContext.tsx +134 -63
- package/apps/dashboard/components/DraggableCard.tsx +3 -5
- package/apps/dashboard/components/DropZone.tsx +6 -7
- package/apps/dashboard/components/EditableDetailDescription.tsx +7 -13
- package/apps/dashboard/components/EditableDetailTitle.tsx +6 -13
- package/apps/dashboard/components/EditableTitle.tsx +26 -7
- package/apps/dashboard/components/ElapsedTimer.tsx +66 -0
- package/apps/dashboard/components/EpicGroup.tsx +359 -0
- package/apps/dashboard/components/GateCard.tsx +79 -17
- package/apps/dashboard/components/GateChoiceCard.tsx +15 -18
- package/apps/dashboard/components/InstallClaudeScreen.tsx +15 -32
- package/apps/dashboard/components/JettyLoader.tsx +37 -0
- package/apps/dashboard/components/KanbanBoard.tsx +368 -958
- package/apps/dashboard/components/KanbanCard.tsx +740 -0
- package/apps/dashboard/components/LazyCard.tsx +62 -0
- package/apps/dashboard/components/LazyMarkdown.tsx +11 -0
- package/apps/dashboard/components/MainNav.tsx +38 -73
- package/apps/dashboard/components/MessageBlock.tsx +468 -0
- package/apps/dashboard/components/ModeStartCard.tsx +15 -16
- package/apps/dashboard/components/OnboardingWelcome.tsx +213 -0
- package/apps/dashboard/components/PlaceholderCard.tsx +3 -4
- package/apps/dashboard/components/ProjectSwitcher.tsx +30 -30
- package/apps/dashboard/components/PrototypeTimeline.tsx +72 -51
- package/apps/dashboard/components/RealTimeKanbanWrapper.tsx +406 -388
- package/apps/dashboard/components/RealTimeTestsWrapper.tsx +373 -235
- package/apps/dashboard/components/ReviewFooter.tsx +139 -0
- package/apps/dashboard/components/SessionList.tsx +19 -19
- package/apps/dashboard/components/SubscribeContent.tsx +91 -47
- package/apps/dashboard/components/TestTree.tsx +16 -16
- package/apps/dashboard/components/TipCard.tsx +16 -17
- package/apps/dashboard/components/Toast.tsx +5 -6
- package/apps/dashboard/components/TypeIcon.tsx +55 -0
- package/apps/dashboard/components/ViewModeToolbar.tsx +104 -0
- package/apps/dashboard/components/WaveCompletionAnimation.tsx +52 -65
- package/apps/dashboard/components/WelcomeScreen.tsx +19 -35
- package/apps/dashboard/components/WorkItemHeader.tsx +4 -5
- package/apps/dashboard/components/WorkItemTree.tsx +11 -32
- package/apps/dashboard/components/settings/AccountSection.tsx +55 -35
- package/apps/dashboard/components/settings/AiContextSection.tsx +89 -0
- package/apps/dashboard/components/settings/ContextDocumentsSection.tsx +317 -0
- package/apps/dashboard/components/settings/EnvVarsSection.tsx +74 -152
- package/apps/dashboard/components/settings/GeneralSection.tsx +162 -56
- package/apps/dashboard/components/settings/ProjectStackSection.tsx +948 -0
- package/apps/dashboard/components/settings/SettingsLayout.tsx +4 -5
- package/apps/dashboard/components/ui/Button.tsx +104 -0
- package/apps/dashboard/components/ui/Input.tsx +78 -0
- package/apps/dashboard/components.json +1 -1
- package/apps/dashboard/contexts/ClaudeSessionContext.tsx +711 -418
- package/apps/dashboard/contexts/ConnectionStatusContext.tsx +25 -5
- package/apps/dashboard/contexts/UsageContext.tsx +87 -32
- package/apps/dashboard/dev.sh +35 -0
- package/apps/dashboard/eslint.config.mjs +9 -9
- package/apps/dashboard/hooks/useKanbanAnimation.ts +29 -0
- package/apps/dashboard/hooks/useKanbanUndo.ts +83 -0
- package/apps/dashboard/hooks/useWebSocket.ts +138 -83
- package/apps/dashboard/index.html +73 -0
- package/apps/dashboard/lib/constants.ts +43 -0
- package/apps/dashboard/lib/data-bridge.ts +722 -0
- package/apps/dashboard/lib/db.ts +69 -1265
- package/apps/dashboard/lib/environment-config.ts +173 -0
- package/apps/dashboard/lib/environment-verification.ts +119 -0
- package/apps/dashboard/lib/kanban-utils.ts +270 -0
- package/apps/dashboard/lib/proof-run.ts +495 -0
- package/apps/dashboard/lib/proof-scenario-runner.ts +346 -0
- package/apps/dashboard/lib/run-migrations.js +27 -2
- package/apps/dashboard/lib/service-recovery.ts +326 -0
- package/apps/dashboard/lib/session-state-machine.ts +1 -0
- package/apps/dashboard/lib/session-state-utils.ts +0 -164
- package/apps/dashboard/lib/session-stream-manager.ts +308 -134
- package/apps/dashboard/lib/shadows.ts +7 -0
- package/apps/dashboard/lib/stream-manager-registry.ts +46 -6
- package/apps/dashboard/lib/tauri-bridge.ts +102 -0
- package/apps/dashboard/lib/tauri.ts +106 -0
- package/apps/dashboard/lib/utils.ts +6 -0
- package/apps/dashboard/next-env.d.ts +1 -1
- package/apps/dashboard/package.json +21 -32
- package/apps/dashboard/public/bug-icon.png +0 -0
- package/apps/dashboard/public/buoy-icon.png +0 -0
- package/apps/dashboard/public/fonts/Satoshi-Variable.woff2 +0 -0
- package/apps/dashboard/public/fonts/Satoshi-VariableItalic.woff2 +0 -0
- package/apps/dashboard/public/in-flight-seagull.png +0 -0
- package/apps/dashboard/public/jetty-icon-loading-alt.svg +11 -0
- package/apps/dashboard/public/jetty-icon-loading.svg +11 -0
- package/apps/dashboard/public/jettypod_logo.png +0 -0
- package/apps/dashboard/public/pier-icon.png +0 -0
- package/apps/dashboard/public/star-icon.png +0 -0
- package/apps/dashboard/public/wrench-icon.png +0 -0
- package/apps/dashboard/scripts/tauri-build.js +228 -0
- package/apps/dashboard/scripts/upload-tauri-to-r2.js +125 -0
- package/apps/dashboard/scripts/ws-server.js +191 -0
- package/apps/dashboard/src/main.tsx +12 -0
- package/apps/dashboard/src/router.tsx +107 -0
- package/apps/dashboard/src/vite-env.d.ts +1 -0
- package/apps/dashboard/tsconfig.json +7 -12
- package/apps/dashboard/tsconfig.tsbuildinfo +1 -1
- package/apps/dashboard/vite.config.ts +33 -0
- package/apps/update-server/src/index.ts +228 -80
- package/claude-hooks/global-guardrails.js +14 -13
- package/crates/jettypod-cli/Cargo.toml +19 -0
- package/crates/jettypod-cli/src/commands.rs +1249 -0
- package/crates/jettypod-cli/src/main.rs +595 -0
- package/crates/jettypod-core/Cargo.toml +26 -0
- package/crates/jettypod-core/build.rs +98 -0
- package/crates/jettypod-core/migrations/V1__baseline.sql +197 -0
- package/crates/jettypod-core/migrations/V2__work_items_indexes.sql +6 -0
- package/crates/jettypod-core/migrations/V3__qa_steps.sql +2 -0
- package/crates/jettypod-core/src/auth.rs +294 -0
- package/crates/jettypod-core/src/config.rs +397 -0
- package/crates/jettypod-core/src/db/mod.rs +507 -0
- package/crates/jettypod-core/src/db/recovery.rs +114 -0
- package/crates/jettypod-core/src/db/startup.rs +101 -0
- package/crates/jettypod-core/src/db/validate.rs +149 -0
- package/crates/jettypod-core/src/error.rs +76 -0
- package/crates/jettypod-core/src/git.rs +458 -0
- package/crates/jettypod-core/src/lib.rs +20 -0
- package/crates/jettypod-core/src/sessions.rs +625 -0
- package/crates/jettypod-core/src/skills.rs +556 -0
- package/crates/jettypod-core/src/work.rs +1086 -0
- package/crates/jettypod-core/src/worktree.rs +628 -0
- package/crates/jettypod-core/src/ws.rs +767 -0
- package/cucumber-test.cjs +6 -0
- package/cucumber.js +9 -3
- package/docs/COMMAND_REFERENCE.md +34 -0
- package/hooks/post-checkout +32 -75
- package/hooks/post-merge +111 -10
- package/jest.setup.js +1 -0
- package/jettypod.js +145 -116
- package/lib/bdd-preflight.js +96 -0
- package/lib/chore-taxonomy.js +33 -10
- package/lib/database.js +36 -16
- package/lib/db-watcher.js +1 -1
- package/lib/git-hooks/pre-commit +1 -1
- package/lib/jettypod-backup.js +27 -4
- package/lib/merge-lock.js +111 -253
- package/lib/migrations/027-plan-at-creation-column.js +3 -1
- package/lib/migrations/029-remove-autoincrement.js +307 -0
- package/lib/migrations/029-rename-corrupted-to-cleaned.js +149 -0
- package/lib/migrations/030-rejection-round-columns.js +54 -0
- package/lib/migrations/031-session-isolation-index.js +17 -0
- package/lib/migrations/index.js +47 -4
- package/lib/schema.js +10 -5
- package/lib/seed-onboarding.js +1 -1
- package/lib/update-command/index.js +9 -175
- package/lib/work-commands/index.js +144 -19
- package/lib/work-tracking/index.js +148 -27
- package/lib/worktree-diagnostics.js +16 -16
- package/lib/worktree-facade.js +1 -1
- package/lib/worktree-manager.js +8 -8
- package/lib/worktree-reconciler.js +5 -5
- package/package.json +9 -2
- package/scripts/ndjson-to-cucumber-json.js +152 -0
- package/scripts/postinstall.js +25 -0
- package/skills-templates/bug-mode/SKILL.md +79 -20
- package/skills-templates/bug-planning/SKILL.md +25 -29
- package/skills-templates/chore-mode/SKILL.md +171 -69
- package/skills-templates/chore-mode/verification.js +51 -10
- package/skills-templates/chore-planning/SKILL.md +47 -18
- package/skills-templates/design-system-selection/SKILL.md +273 -0
- package/skills-templates/epic-planning/SKILL.md +82 -48
- package/skills-templates/external-transition/SKILL.md +47 -47
- package/skills-templates/feature-planning/SKILL.md +173 -74
- package/skills-templates/production-mode/SKILL.md +69 -49
- package/skills-templates/request-routing/SKILL.md +4 -4
- package/skills-templates/simple-improvement/SKILL.md +74 -29
- package/skills-templates/speed-mode/SKILL.md +217 -141
- package/skills-templates/stable-mode/SKILL.md +148 -89
- package/apps/dashboard/README.md +0 -36
- package/apps/dashboard/app/api/claude/[workItemId]/message/route.ts +0 -386
- package/apps/dashboard/app/api/claude/[workItemId]/pin/route.ts +0 -24
- package/apps/dashboard/app/api/claude/[workItemId]/route.ts +0 -167
- package/apps/dashboard/app/api/claude/sessions/[sessionId]/content/route.ts +0 -52
- package/apps/dashboard/app/api/claude/sessions/[sessionId]/message/route.ts +0 -378
- package/apps/dashboard/app/api/claude/sessions/[sessionId]/pin/route.ts +0 -24
- package/apps/dashboard/app/api/claude/sessions/cleanup/route.ts +0 -34
- package/apps/dashboard/app/api/claude/sessions/route.ts +0 -184
- package/apps/dashboard/app/api/decisions/[id]/route.ts +0 -25
- package/apps/dashboard/app/api/internal/set-project/route.ts +0 -17
- package/apps/dashboard/app/api/kanban/route.ts +0 -15
- package/apps/dashboard/app/api/settings/env-vars/route.ts +0 -125
- package/apps/dashboard/app/api/settings/general/route.ts +0 -21
- package/apps/dashboard/app/api/tests/route.ts +0 -9
- package/apps/dashboard/app/api/tests/run/route.ts +0 -82
- package/apps/dashboard/app/api/tests/run/stream/route.ts +0 -71
- package/apps/dashboard/app/api/tests/undefined/route.ts +0 -9
- package/apps/dashboard/app/api/usage/route.ts +0 -17
- package/apps/dashboard/app/api/work/[id]/description/route.ts +0 -21
- package/apps/dashboard/app/api/work/[id]/epic/route.ts +0 -21
- package/apps/dashboard/app/api/work/[id]/order/route.ts +0 -21
- package/apps/dashboard/app/api/work/[id]/status/route.ts +0 -21
- package/apps/dashboard/app/api/work/[id]/title/route.ts +0 -21
- package/apps/dashboard/app/layout.tsx +0 -43
- package/apps/dashboard/components/UpgradeBanner.tsx +0 -29
- package/apps/dashboard/electron/ipc-handlers.js +0 -1028
- package/apps/dashboard/electron/main.js +0 -2124
- package/apps/dashboard/electron/preload.js +0 -123
- package/apps/dashboard/electron/session-manager.js +0 -141
- package/apps/dashboard/electron-builder.config.js +0 -357
- package/apps/dashboard/hooks/useClaudeSessions.ts +0 -299
- package/apps/dashboard/lib/claude-process-manager.ts +0 -492
- package/apps/dashboard/lib/db-bridge.ts +0 -282
- package/apps/dashboard/lib/prototypes.ts +0 -202
- package/apps/dashboard/lib/test-results-db.ts +0 -307
- package/apps/dashboard/lib/tests.ts +0 -282
- package/apps/dashboard/next.config.js +0 -50
- package/apps/dashboard/postcss.config.mjs +0 -7
- package/apps/dashboard/public/file.svg +0 -1
- package/apps/dashboard/public/globe.svg +0 -1
- package/apps/dashboard/public/next.svg +0 -1
- package/apps/dashboard/public/vercel.svg +0 -1
- package/apps/dashboard/public/window.svg +0 -1
- package/apps/dashboard/scripts/download-node.js +0 -104
- package/apps/dashboard/scripts/upload-to-r2.js +0 -89
- package/docs/bdd-guidance.md +0 -390
|
@@ -0,0 +1,868 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useState } from 'react';
|
|
4
|
+
import { Button } from '@/components/ui/Button';
|
|
5
|
+
import { shadow } from '@/lib/shadows';
|
|
6
|
+
|
|
7
|
+
function Section({ title, description, children }: { title: string; description?: string; children: React.ReactNode }) {
|
|
8
|
+
return (
|
|
9
|
+
<section className="space-y-6">
|
|
10
|
+
<div>
|
|
11
|
+
<h2 className="text-xl font-semibold tracking-tight text-zinc-900 dark:text-zinc-100 pb-3">
|
|
12
|
+
{title}
|
|
13
|
+
</h2>
|
|
14
|
+
{description && <p className="text-base text-zinc-500 mt-1">{description}</p>}
|
|
15
|
+
</div>
|
|
16
|
+
{children}
|
|
17
|
+
</section>
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function ColorSwatch({ name, value, cssVar }: { name: string; value: string; cssVar: string }) {
|
|
22
|
+
return (
|
|
23
|
+
<div className="flex items-center gap-4">
|
|
24
|
+
<div
|
|
25
|
+
className="w-14 h-14 rounded-2xl shrink-0"
|
|
26
|
+
style={{ backgroundColor: value }}
|
|
27
|
+
/>
|
|
28
|
+
<div>
|
|
29
|
+
<div className="text-base font-medium text-zinc-900 dark:text-zinc-100">{name}</div>
|
|
30
|
+
<div className="text-xs text-zinc-500 font-mono">{cssVar}</div>
|
|
31
|
+
</div>
|
|
32
|
+
</div>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function Card({ children, className = '', hover = false }: { children: React.ReactNode; className?: string; hover?: boolean }) {
|
|
37
|
+
return (
|
|
38
|
+
<div
|
|
39
|
+
className={`bg-card rounded-2xl p-8 ${hover ? 'transition-shadow duration-200 ease-out hover:shadow-lg' : ''} ${className}`}
|
|
40
|
+
style={{ boxShadow: shadow.md }}
|
|
41
|
+
>
|
|
42
|
+
{children}
|
|
43
|
+
</div>
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export default function DesignSystemPage() {
|
|
48
|
+
const [dark, setDark] = useState(false);
|
|
49
|
+
const [loadingDemo, setLoadingDemo] = useState(false);
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<div className={dark ? 'dark' : ''}>
|
|
53
|
+
{/* Focus style for inputs — can't do :focus with inline styles */}
|
|
54
|
+
<style>{`
|
|
55
|
+
.ds-input:focus {
|
|
56
|
+
border-color: #819D9F !important;
|
|
57
|
+
box-shadow: 0 0 0 3px rgba(129, 157, 159, 0.15) !important;
|
|
58
|
+
outline: none;
|
|
59
|
+
}
|
|
60
|
+
.ds-input {
|
|
61
|
+
transition: border-color 200ms ease-out, box-shadow 200ms ease-out;
|
|
62
|
+
}
|
|
63
|
+
@keyframes shimmer {
|
|
64
|
+
0% { background-position: -200% 0; }
|
|
65
|
+
100% { background-position: 200% 0; }
|
|
66
|
+
}
|
|
67
|
+
.skeleton {
|
|
68
|
+
background: linear-gradient(90deg, #f4f4f5 25%, #e4e4e7 50%, #f4f4f5 75%);
|
|
69
|
+
background-size: 200% 100%;
|
|
70
|
+
animation: shimmer 1.5s ease-in-out infinite;
|
|
71
|
+
border-radius: 8px;
|
|
72
|
+
}
|
|
73
|
+
`}</style>
|
|
74
|
+
|
|
75
|
+
<div className="flex-1 overflow-y-auto bg-background text-foreground">
|
|
76
|
+
{/* Header */}
|
|
77
|
+
<header className="sticky top-0 z-10 border-b border-zinc-200 dark:border-zinc-800 bg-white dark:bg-zinc-900 px-8 py-6 flex items-center justify-between">
|
|
78
|
+
<div>
|
|
79
|
+
<h1 className="text-2xl font-bold tracking-tight text-zinc-900 dark:text-zinc-100">Design System</h1>
|
|
80
|
+
<p className="text-base text-zinc-500 mt-1">JettyPod component & token reference</p>
|
|
81
|
+
</div>
|
|
82
|
+
<button
|
|
83
|
+
onClick={() => setDark(!dark)}
|
|
84
|
+
className="px-3 py-1.5 text-base font-medium rounded-lg transition-colors duration-200 hover:bg-zinc-100 dark:hover:bg-zinc-800 text-zinc-600 dark:text-zinc-400"
|
|
85
|
+
style={{ border: '2px solid #18181b' }}
|
|
86
|
+
>
|
|
87
|
+
{dark ? 'Light mode' : 'Dark mode'}
|
|
88
|
+
</button>
|
|
89
|
+
</header>
|
|
90
|
+
|
|
91
|
+
<div className="max-w-5xl mx-auto px-8 py-16 space-y-20">
|
|
92
|
+
|
|
93
|
+
{/* ─── Border Philosophy ─── */}
|
|
94
|
+
<Section title="0. Border Philosophy" description="Binary borders — thick and intentional, or nothing at all. No thin decorative borders.">
|
|
95
|
+
<Card>
|
|
96
|
+
<div className="grid grid-cols-2 gap-8">
|
|
97
|
+
<div className="space-y-3">
|
|
98
|
+
<div className="text-xs font-mono text-zinc-400">Has border (thick, intentional)</div>
|
|
99
|
+
<div className="space-y-2 text-base text-zinc-700 dark:text-zinc-300">
|
|
100
|
+
<p><strong>Inputs</strong> — 2px dark, defines the interactive area</p>
|
|
101
|
+
<p><strong>Header nav</strong> — 1px bottom, structural anchor</p>
|
|
102
|
+
<p><strong>Selected/active states</strong> — 2px brand color</p>
|
|
103
|
+
<p><strong>Outlined buttons</strong> — 2px dark, same weight as inputs</p>
|
|
104
|
+
<p><strong>Callout left-edge</strong> — 3px accent stripe</p>
|
|
105
|
+
</div>
|
|
106
|
+
</div>
|
|
107
|
+
<div className="space-y-3">
|
|
108
|
+
<div className="text-xs font-mono text-zinc-400">No border (use bg + shadow instead)</div>
|
|
109
|
+
<div className="space-y-2 text-base text-zinc-700 dark:text-zinc-300">
|
|
110
|
+
<p><strong>Cards</strong> — white on warm canvas is enough contrast</p>
|
|
111
|
+
<p><strong>Containers</strong> — shadows provide depth</p>
|
|
112
|
+
<p><strong>Sections</strong> — spacing separates, not lines</p>
|
|
113
|
+
<p><strong>Filled buttons</strong> — fill color defines the shape</p>
|
|
114
|
+
</div>
|
|
115
|
+
</div>
|
|
116
|
+
</div>
|
|
117
|
+
<div style={{ paddingTop: '24px' }}>
|
|
118
|
+
<div className="text-xs font-mono text-zinc-400" style={{ marginBottom: '12px' }}>Visual comparison</div>
|
|
119
|
+
<div className="grid grid-cols-2 gap-8">
|
|
120
|
+
<div className="rounded-xl p-6 space-y-3" style={{ border: '1px solid #e4e4e7' }}>
|
|
121
|
+
<div className="text-xs text-zinc-400">Old: thin borders everywhere</div>
|
|
122
|
+
<div className="rounded-lg p-4 text-base text-zinc-600" style={{ border: '1px solid #e4e4e7' }}>Bordered card</div>
|
|
123
|
+
<div className="rounded-lg p-4 text-base text-zinc-600" style={{ border: '1px solid #e4e4e7' }}>Bordered card</div>
|
|
124
|
+
</div>
|
|
125
|
+
<div className="bg-card rounded-2xl p-6 space-y-3" style={{ boxShadow: shadow.md }}>
|
|
126
|
+
<div className="text-xs text-zinc-400">New: no borders, shadow + bg contrast</div>
|
|
127
|
+
<div className="bg-zinc-50 dark:bg-zinc-800 rounded-xl p-4 text-base text-zinc-600">Borderless card</div>
|
|
128
|
+
<div className="bg-zinc-50 dark:bg-zinc-800 rounded-xl p-4 text-base text-zinc-600">Borderless card</div>
|
|
129
|
+
</div>
|
|
130
|
+
</div>
|
|
131
|
+
</div>
|
|
132
|
+
</Card>
|
|
133
|
+
</Section>
|
|
134
|
+
|
|
135
|
+
{/* ─── Brand Palette ─── */}
|
|
136
|
+
<Section title="1. Brand Palette" description="Three colors, three shades each — solid, tint (backgrounds), and text (on tint)">
|
|
137
|
+
<Card>
|
|
138
|
+
<div className="space-y-8">
|
|
139
|
+
{/* Primary */}
|
|
140
|
+
<div className="space-y-3">
|
|
141
|
+
<div className="text-base font-semibold text-zinc-900 dark:text-zinc-100">Primary</div>
|
|
142
|
+
<div className="grid grid-cols-3 gap-4">
|
|
143
|
+
<div className="space-y-2">
|
|
144
|
+
<div className="w-full h-20 rounded-2xl" style={{ backgroundColor: '#819D9F' }} />
|
|
145
|
+
<div className="text-xs font-mono text-zinc-500">Solid · #819D9F</div>
|
|
146
|
+
<div className="text-xs text-zinc-400">Buttons, fills, borders</div>
|
|
147
|
+
</div>
|
|
148
|
+
<div className="space-y-2">
|
|
149
|
+
<div className="w-full h-20 rounded-2xl" style={{ backgroundColor: '#E8EEEF' }} />
|
|
150
|
+
<div className="text-xs font-mono text-zinc-500">Tint · #E8EEEF</div>
|
|
151
|
+
<div className="text-xs text-zinc-400">Card backgrounds, badges</div>
|
|
152
|
+
</div>
|
|
153
|
+
<div className="space-y-2">
|
|
154
|
+
<div className="w-full h-20 rounded-2xl flex items-center justify-center" style={{ backgroundColor: '#E8EEEF' }}>
|
|
155
|
+
<span className="text-base font-semibold" style={{ color: '#4A6365' }}>Text on tint</span>
|
|
156
|
+
</div>
|
|
157
|
+
<div className="text-xs font-mono text-zinc-500">Text · #4A6365</div>
|
|
158
|
+
<div className="text-xs text-zinc-400">Labels on tinted backgrounds</div>
|
|
159
|
+
</div>
|
|
160
|
+
</div>
|
|
161
|
+
</div>
|
|
162
|
+
|
|
163
|
+
{/* Accent */}
|
|
164
|
+
<div className="space-y-3">
|
|
165
|
+
<div className="text-base font-semibold text-zinc-900 dark:text-zinc-100">Accent</div>
|
|
166
|
+
<div className="grid grid-cols-3 gap-4">
|
|
167
|
+
<div className="space-y-2">
|
|
168
|
+
<div className="w-full h-20 rounded-2xl" style={{ backgroundColor: '#E57A44' }} />
|
|
169
|
+
<div className="text-xs font-mono text-zinc-500">Solid · #E57A44</div>
|
|
170
|
+
<div className="text-xs text-zinc-400">CTA buttons, warm emphasis</div>
|
|
171
|
+
</div>
|
|
172
|
+
<div className="space-y-2">
|
|
173
|
+
<div className="w-full h-20 rounded-2xl" style={{ backgroundColor: '#FCEEE6' }} />
|
|
174
|
+
<div className="text-xs font-mono text-zinc-500">Tint · #FCEEE6</div>
|
|
175
|
+
<div className="text-xs text-zinc-400">Banners, callout backgrounds</div>
|
|
176
|
+
</div>
|
|
177
|
+
<div className="space-y-2">
|
|
178
|
+
<div className="w-full h-20 rounded-2xl flex items-center justify-center" style={{ backgroundColor: '#FCEEE6' }}>
|
|
179
|
+
<span className="text-base font-semibold" style={{ color: '#9E4A1E' }}>Text on tint</span>
|
|
180
|
+
</div>
|
|
181
|
+
<div className="text-xs font-mono text-zinc-500">Text · #9E4A1E</div>
|
|
182
|
+
<div className="text-xs text-zinc-400">Labels on tinted backgrounds</div>
|
|
183
|
+
</div>
|
|
184
|
+
</div>
|
|
185
|
+
</div>
|
|
186
|
+
|
|
187
|
+
{/* Highlight */}
|
|
188
|
+
<div className="space-y-3">
|
|
189
|
+
<div className="text-base font-semibold text-zinc-900 dark:text-zinc-100">Highlight</div>
|
|
190
|
+
<div className="grid grid-cols-3 gap-4">
|
|
191
|
+
<div className="space-y-2">
|
|
192
|
+
<div className="w-full h-20 rounded-2xl" style={{ backgroundColor: '#E3D985' }} />
|
|
193
|
+
<div className="text-xs font-mono text-zinc-500">Solid · #E3D985</div>
|
|
194
|
+
<div className="text-xs text-zinc-400">Borders, dots, selection</div>
|
|
195
|
+
</div>
|
|
196
|
+
<div className="space-y-2">
|
|
197
|
+
<div className="w-full h-20 rounded-2xl" style={{ backgroundColor: '#F9F7E8' }} />
|
|
198
|
+
<div className="text-xs font-mono text-zinc-500">Tint · #F9F7E8</div>
|
|
199
|
+
<div className="text-xs text-zinc-400">Badge backgrounds, callouts</div>
|
|
200
|
+
</div>
|
|
201
|
+
<div className="space-y-2">
|
|
202
|
+
<div className="w-full h-20 rounded-2xl flex items-center justify-center" style={{ backgroundColor: '#F9F7E8' }}>
|
|
203
|
+
<span className="text-base font-semibold" style={{ color: '#8B7D2F' }}>Text on tint</span>
|
|
204
|
+
</div>
|
|
205
|
+
<div className="text-xs font-mono text-zinc-500">Text · #8B7D2F</div>
|
|
206
|
+
<div className="text-xs text-zinc-400">Labels on tinted backgrounds</div>
|
|
207
|
+
</div>
|
|
208
|
+
</div>
|
|
209
|
+
</div>
|
|
210
|
+
|
|
211
|
+
{/* Official Black */}
|
|
212
|
+
<div className="space-y-3">
|
|
213
|
+
<div className="text-base font-semibold text-zinc-900 dark:text-zinc-100">Official Black</div>
|
|
214
|
+
<div className="grid grid-cols-3 gap-4">
|
|
215
|
+
<div className="space-y-2">
|
|
216
|
+
<div className="w-full h-20 rounded-2xl" style={{ backgroundColor: '#18181b' }} />
|
|
217
|
+
<div className="text-xs font-mono text-zinc-500">Black · #18181b (zinc-900)</div>
|
|
218
|
+
<div className="text-xs text-zinc-400">Text, input borders, outlined buttons</div>
|
|
219
|
+
</div>
|
|
220
|
+
</div>
|
|
221
|
+
</div>
|
|
222
|
+
|
|
223
|
+
{/* Usage examples */}
|
|
224
|
+
<div style={{ paddingTop: '24px' }}>
|
|
225
|
+
<div className="text-xs font-mono text-zinc-400" style={{ marginBottom: '16px' }}>In context</div>
|
|
226
|
+
<div className="flex items-center gap-4 flex-wrap">
|
|
227
|
+
<span className="inline-flex items-center px-3 py-1 rounded-full text-xs font-medium" style={{ backgroundColor: '#E8EEEF', color: '#4A6365' }}>Primary badge</span>
|
|
228
|
+
<span className="inline-flex items-center px-3 py-1 rounded-full text-xs font-medium" style={{ backgroundColor: '#FCEEE6', color: '#9E4A1E' }}>Accent badge</span>
|
|
229
|
+
<span className="inline-flex items-center px-3 py-1 rounded-full text-xs font-medium" style={{ backgroundColor: '#F9F7E8', color: '#8B7D2F' }}>Highlight badge</span>
|
|
230
|
+
<div className="flex items-center gap-2 px-4 py-3 rounded-xl" style={{ backgroundColor: '#F9F7E8', borderLeft: '3px solid #E3D985' }}>
|
|
231
|
+
<span className="text-base" style={{ color: '#8B7D2F' }}>Callout with thick left border.</span>
|
|
232
|
+
</div>
|
|
233
|
+
</div>
|
|
234
|
+
</div>
|
|
235
|
+
</div>
|
|
236
|
+
</Card>
|
|
237
|
+
</Section>
|
|
238
|
+
|
|
239
|
+
{/* ─── Surface Hierarchy ─── */}
|
|
240
|
+
<Section title="2. Surface Hierarchy" description="Three layers: warm canvas → white cards → content. No borders needed — bg contrast does the work.">
|
|
241
|
+
<div className="space-y-4">
|
|
242
|
+
<div className="bg-background rounded-2xl p-8">
|
|
243
|
+
<div className="text-xs font-mono text-zinc-400 mb-4">--background · oklch(0.98 0.002 80) · warm cream canvas</div>
|
|
244
|
+
<div className="bg-card rounded-2xl p-8" style={{ boxShadow: shadow.md }}>
|
|
245
|
+
<div className="text-xs font-mono text-zinc-400 mb-3">--card · oklch(1 0 0) · pure white card (no border, shadow only)</div>
|
|
246
|
+
<p className="text-base text-zinc-700">Content lives here. White floats above the warm canvas with a subtle shadow.</p>
|
|
247
|
+
</div>
|
|
248
|
+
</div>
|
|
249
|
+
</div>
|
|
250
|
+
|
|
251
|
+
<div className="grid grid-cols-2 gap-6 mt-6">
|
|
252
|
+
<ColorSwatch name="Background (canvas)" value="oklch(0.98 0.002 80)" cssVar="--background" />
|
|
253
|
+
<ColorSwatch name="Card / Header" value="oklch(1 0 0)" cssVar="--card / bg-white" />
|
|
254
|
+
<ColorSwatch name="Sidebar" value="oklch(0.985 0 0)" cssVar="--sidebar" />
|
|
255
|
+
<ColorSwatch name="Muted" value="oklch(0.97 0 0)" cssVar="--muted" />
|
|
256
|
+
<ColorSwatch name="Foreground" value="oklch(0.145 0 0)" cssVar="--foreground" />
|
|
257
|
+
<ColorSwatch name="Muted Foreground" value="oklch(0.556 0 0)" cssVar="--muted-foreground" />
|
|
258
|
+
<ColorSwatch name="Destructive" value="oklch(0.577 0.245 27.325)" cssVar="--destructive" />
|
|
259
|
+
</div>
|
|
260
|
+
</Section>
|
|
261
|
+
|
|
262
|
+
{/* ─── Elevation Scale ─── */}
|
|
263
|
+
<Section title="3. Elevation Scale" description="Three shadow levels for depth hierarchy, plus an overlay level for modals and popovers.">
|
|
264
|
+
<Card>
|
|
265
|
+
<div className="grid grid-cols-4 gap-6">
|
|
266
|
+
{([
|
|
267
|
+
{ name: 'sm', desc: 'Resting — subtle cards, badges', value: shadow.sm },
|
|
268
|
+
{ name: 'md', desc: 'Default — cards, containers', value: shadow.md },
|
|
269
|
+
{ name: 'lg', desc: 'Raised — hovered cards, dropdowns', value: shadow.lg },
|
|
270
|
+
{ name: 'overlay', desc: 'Overlay — modals, dialogs', value: shadow.overlay },
|
|
271
|
+
] as const).map((s) => (
|
|
272
|
+
<div key={s.name} className="text-center space-y-3">
|
|
273
|
+
<div className="bg-white dark:bg-zinc-800 rounded-2xl h-24 w-full" style={{ boxShadow: s.value }} />
|
|
274
|
+
<div>
|
|
275
|
+
<div className="text-base font-mono text-zinc-900 dark:text-zinc-100 font-medium">{s.name}</div>
|
|
276
|
+
<div className="text-xs text-zinc-400 mt-0.5">{s.desc}</div>
|
|
277
|
+
</div>
|
|
278
|
+
</div>
|
|
279
|
+
))}
|
|
280
|
+
</div>
|
|
281
|
+
<div className="text-xs font-mono text-zinc-400 mt-8">Cards transition from md → lg on hover (200ms ease-out)</div>
|
|
282
|
+
</Card>
|
|
283
|
+
</Section>
|
|
284
|
+
|
|
285
|
+
{/* ─── Typography ─── */}
|
|
286
|
+
<Section title="4. Typography" description="Dramatic type hierarchy — large display headings with tight tracking, smaller sizes for body and UI">
|
|
287
|
+
<Card>
|
|
288
|
+
<div className="space-y-8">
|
|
289
|
+
<div className="space-y-4">
|
|
290
|
+
<div className="text-xs font-mono text-zinc-400">Font: Satoshi (--font-sans)</div>
|
|
291
|
+
<div className="space-y-6">
|
|
292
|
+
<div>
|
|
293
|
+
<p className="text-4xl font-bold tracking-tight text-zinc-900 dark:text-zinc-100">Display — 4xl bold tight</p>
|
|
294
|
+
<p className="text-xs font-mono text-zinc-400 mt-1">Hero headings, landing pages, empty states · tracking-tight (-0.025em)</p>
|
|
295
|
+
</div>
|
|
296
|
+
<div>
|
|
297
|
+
<p className="text-3xl font-bold tracking-tight text-zinc-900 dark:text-zinc-100">Page Title — 3xl bold tight</p>
|
|
298
|
+
<p className="text-xs font-mono text-zinc-400 mt-1">Top-level page headings · tracking-tight (-0.025em)</p>
|
|
299
|
+
</div>
|
|
300
|
+
<div>
|
|
301
|
+
<p className="text-2xl font-semibold tracking-tight text-zinc-900 dark:text-zinc-100">Section Heading — 2xl semibold tight</p>
|
|
302
|
+
<p className="text-xs font-mono text-zinc-400 mt-1">Major content sections · tracking-tight (-0.025em)</p>
|
|
303
|
+
</div>
|
|
304
|
+
<div>
|
|
305
|
+
<p className="text-xl font-semibold tracking-tight text-zinc-900 dark:text-zinc-100">Subsection — xl semibold tight</p>
|
|
306
|
+
<p className="text-xs font-mono text-zinc-400 mt-1">Card titles, subsections · tracking-tight (-0.025em)</p>
|
|
307
|
+
</div>
|
|
308
|
+
<div>
|
|
309
|
+
<p className="text-lg font-medium text-zinc-900 dark:text-zinc-100">Label — lg medium</p>
|
|
310
|
+
<p className="text-xs font-mono text-zinc-400 mt-1">Form group labels, list headers</p>
|
|
311
|
+
</div>
|
|
312
|
+
<div>
|
|
313
|
+
<p className="text-base text-zinc-700 dark:text-zinc-300">Body — base regular</p>
|
|
314
|
+
<p className="text-xs font-mono text-zinc-400 mt-1">Primary body text</p>
|
|
315
|
+
</div>
|
|
316
|
+
<div>
|
|
317
|
+
<p className="text-sm text-zinc-500">Secondary — sm muted</p>
|
|
318
|
+
<p className="text-xs font-mono text-zinc-400 mt-1">Descriptions, helper text, UI labels</p>
|
|
319
|
+
</div>
|
|
320
|
+
<div>
|
|
321
|
+
<p className="text-xs text-zinc-400">Caption — xs muted</p>
|
|
322
|
+
<p className="text-xs font-mono text-zinc-400 mt-1">Timestamps, metadata, fine print</p>
|
|
323
|
+
</div>
|
|
324
|
+
</div>
|
|
325
|
+
</div>
|
|
326
|
+
<div style={{ paddingTop: '24px' }} className="space-y-3">
|
|
327
|
+
<div className="text-xs font-mono text-zinc-400">Font: Geist Mono (--font-mono)</div>
|
|
328
|
+
<p className="font-mono text-base text-zinc-700 dark:text-zinc-300">Monospace for code, IDs, technical values</p>
|
|
329
|
+
</div>
|
|
330
|
+
<div style={{ paddingTop: '24px' }} className="space-y-3">
|
|
331
|
+
<div className="text-xs font-mono text-zinc-400">Button text sizes</div>
|
|
332
|
+
<div className="flex items-center gap-4">
|
|
333
|
+
<Button size="sm">sm: text-sm</Button>
|
|
334
|
+
<Button size="default">default: text-sm</Button>
|
|
335
|
+
<Button size="lg">lg: text-base</Button>
|
|
336
|
+
</div>
|
|
337
|
+
</div>
|
|
338
|
+
</div>
|
|
339
|
+
</Card>
|
|
340
|
+
</Section>
|
|
341
|
+
|
|
342
|
+
{/* ─── Motion & Easing ─── */}
|
|
343
|
+
<Section title="5. Motion & Easing" description="Consistent timing and easing for all interactive elements. Fast enough to feel responsive, slow enough to notice.">
|
|
344
|
+
<Card>
|
|
345
|
+
<div className="space-y-6">
|
|
346
|
+
<div className="grid grid-cols-3 gap-6">
|
|
347
|
+
<div className="space-y-2">
|
|
348
|
+
<div className="text-base font-medium text-zinc-900 dark:text-zinc-100">Duration</div>
|
|
349
|
+
<div className="space-y-1 text-base text-zinc-600 dark:text-zinc-400">
|
|
350
|
+
<p><span className="font-mono text-xs">100ms</span> — micro-interactions (opacity)</p>
|
|
351
|
+
<p><span className="font-mono text-xs">200ms</span> — default (buttons, cards, inputs)</p>
|
|
352
|
+
<p><span className="font-mono text-xs">300ms</span> — layout shifts, panels</p>
|
|
353
|
+
</div>
|
|
354
|
+
</div>
|
|
355
|
+
<div className="space-y-2">
|
|
356
|
+
<div className="text-base font-medium text-zinc-900 dark:text-zinc-100">Easing</div>
|
|
357
|
+
<div className="space-y-1 text-base text-zinc-600 dark:text-zinc-400">
|
|
358
|
+
<p><span className="font-mono text-xs">ease-out</span> — default (feels snappy)</p>
|
|
359
|
+
<p><span className="font-mono text-xs">ease-in-out</span> — layout animations</p>
|
|
360
|
+
</div>
|
|
361
|
+
</div>
|
|
362
|
+
<div className="space-y-2">
|
|
363
|
+
<div className="text-base font-medium text-zinc-900 dark:text-zinc-100">Properties</div>
|
|
364
|
+
<div className="space-y-1 text-base text-zinc-600 dark:text-zinc-400">
|
|
365
|
+
<p>Never <span className="font-mono text-xs">transition-all</span></p>
|
|
366
|
+
<p>Specify: <span className="font-mono text-xs">color, background, border, shadow, transform, opacity</span></p>
|
|
367
|
+
</div>
|
|
368
|
+
</div>
|
|
369
|
+
</div>
|
|
370
|
+
<div style={{ paddingTop: '16px' }}>
|
|
371
|
+
<div className="text-xs font-mono text-zinc-400 mb-4">Live — hover these cards to see shadow transition</div>
|
|
372
|
+
<div className="grid grid-cols-3 gap-4">
|
|
373
|
+
{['Resting', 'Hover me', 'Hover me too'].map((label, i) => (
|
|
374
|
+
<div
|
|
375
|
+
key={label}
|
|
376
|
+
className="bg-white dark:bg-zinc-800 rounded-2xl p-6 text-center text-base text-zinc-600 dark:text-zinc-400 cursor-default transition-shadow duration-200 ease-out"
|
|
377
|
+
style={{ boxShadow: i === 0 ? shadow.md : shadow.md }}
|
|
378
|
+
onMouseEnter={(e) => { if (i > 0) e.currentTarget.style.boxShadow = shadow.lg; }}
|
|
379
|
+
onMouseLeave={(e) => { if (i > 0) e.currentTarget.style.boxShadow = shadow.md; }}
|
|
380
|
+
>
|
|
381
|
+
{label}
|
|
382
|
+
</div>
|
|
383
|
+
))}
|
|
384
|
+
</div>
|
|
385
|
+
</div>
|
|
386
|
+
</div>
|
|
387
|
+
</Card>
|
|
388
|
+
</Section>
|
|
389
|
+
|
|
390
|
+
{/* ─── Border Radius ─── */}
|
|
391
|
+
<Section title="6. Border Radius" description="Two tiers: rounded-2xl (16px) for cards and containers, rounded-xl (12px) for buttons and inputs">
|
|
392
|
+
<Card>
|
|
393
|
+
<div className="grid grid-cols-3 gap-6">
|
|
394
|
+
{([
|
|
395
|
+
{ name: 'rounded-lg', desc: '8px — menus, tooltips', highlight: false },
|
|
396
|
+
{ name: 'rounded-xl', desc: '12px — buttons, inputs, badges', highlight: true },
|
|
397
|
+
{ name: 'rounded-2xl', desc: '16px — cards, containers, panels', highlight: true },
|
|
398
|
+
] as const).map((r) => (
|
|
399
|
+
<div key={r.name} className="text-center space-y-3">
|
|
400
|
+
<div className={`${r.name} ${r.highlight ? 'bg-zinc-100' : 'bg-zinc-50'} h-20 w-full`} style={r.highlight ? { border: '2px solid #27272a' } : undefined} />
|
|
401
|
+
<div>
|
|
402
|
+
<div className={`text-base font-mono ${r.highlight ? 'text-zinc-900 dark:text-zinc-100 font-medium' : 'text-zinc-500'}`}>{r.name}</div>
|
|
403
|
+
<div className="text-xs text-zinc-400 mt-0.5">{r.desc}</div>
|
|
404
|
+
</div>
|
|
405
|
+
</div>
|
|
406
|
+
))}
|
|
407
|
+
</div>
|
|
408
|
+
<div style={{ marginTop: '32px', paddingTop: '24px' }}>
|
|
409
|
+
<div className="text-xs font-mono text-zinc-400" style={{ marginBottom: '16px' }}>In context</div>
|
|
410
|
+
<div className="flex gap-6 items-start">
|
|
411
|
+
<div className="flex-1 bg-zinc-50 dark:bg-zinc-800 rounded-2xl p-6 space-y-3">
|
|
412
|
+
<div className="text-base font-medium text-zinc-900 dark:text-zinc-100">Card (no border, bg contrast)</div>
|
|
413
|
+
<input
|
|
414
|
+
type="text"
|
|
415
|
+
placeholder="Input (thick border) — click to see focus"
|
|
416
|
+
className="ds-input w-full text-base bg-white dark:bg-zinc-800"
|
|
417
|
+
style={{ padding: '16px 20px', borderRadius: '12px', border: '2px solid #27272a' }}
|
|
418
|
+
/>
|
|
419
|
+
<Button fullWidth>Button (no border, solid fill)</Button>
|
|
420
|
+
</div>
|
|
421
|
+
<div className="w-48 bg-white dark:bg-zinc-800 rounded-lg p-1.5 space-y-0.5" style={{ boxShadow: shadow.lg }}>
|
|
422
|
+
<div className="text-xs text-zinc-400 px-2 py-1">Menu (shadow, no border)</div>
|
|
423
|
+
<Button variant="menu">Option One</Button>
|
|
424
|
+
<Button variant="menu">Option Two</Button>
|
|
425
|
+
</div>
|
|
426
|
+
</div>
|
|
427
|
+
</div>
|
|
428
|
+
</Card>
|
|
429
|
+
</Section>
|
|
430
|
+
|
|
431
|
+
{/* ─── Button Variants ─── */}
|
|
432
|
+
<Section title="7. Button Variants">
|
|
433
|
+
<Card>
|
|
434
|
+
<div className="space-y-8">
|
|
435
|
+
{/* Primary */}
|
|
436
|
+
<div className="space-y-3">
|
|
437
|
+
<div className="text-xs font-mono text-zinc-400">variant="primary" (default) — Solid #819D9F, main actions</div>
|
|
438
|
+
<div className="flex items-center gap-4 flex-wrap">
|
|
439
|
+
<Button size="sm">Small</Button>
|
|
440
|
+
<Button size="default">Default</Button>
|
|
441
|
+
<Button size="lg">Large</Button>
|
|
442
|
+
<Button disabled>Disabled</Button>
|
|
443
|
+
<Button fullWidth>Full Width</Button>
|
|
444
|
+
</div>
|
|
445
|
+
</div>
|
|
446
|
+
|
|
447
|
+
{/* Secondary */}
|
|
448
|
+
<div className="space-y-3">
|
|
449
|
+
<div className="text-xs font-mono text-zinc-400">variant="secondary" — 2px #18181b border, secondary actions</div>
|
|
450
|
+
<div className="flex items-center gap-4 flex-wrap">
|
|
451
|
+
<Button variant="secondary" size="sm">Small</Button>
|
|
452
|
+
<Button variant="secondary">Default</Button>
|
|
453
|
+
<Button variant="secondary" size="lg">Large</Button>
|
|
454
|
+
<Button variant="secondary" disabled>Disabled</Button>
|
|
455
|
+
</div>
|
|
456
|
+
</div>
|
|
457
|
+
|
|
458
|
+
{/* Ghost */}
|
|
459
|
+
<div className="space-y-3">
|
|
460
|
+
<div className="text-xs font-mono text-zinc-400">variant="ghost" — No border, tertiary / inline</div>
|
|
461
|
+
<div className="flex items-center gap-4 flex-wrap">
|
|
462
|
+
<Button variant="ghost" size="sm">Small</Button>
|
|
463
|
+
<Button variant="ghost">Default</Button>
|
|
464
|
+
<Button variant="ghost" size="lg">Large</Button>
|
|
465
|
+
<Button variant="ghost" disabled>Disabled</Button>
|
|
466
|
+
</div>
|
|
467
|
+
</div>
|
|
468
|
+
|
|
469
|
+
{/* Destructive */}
|
|
470
|
+
<div className="space-y-3">
|
|
471
|
+
<div className="text-xs font-mono text-zinc-400">variant="destructive" — 2px red border, dangerous actions</div>
|
|
472
|
+
<div className="flex items-center gap-4 flex-wrap">
|
|
473
|
+
<Button variant="destructive" size="sm">Delete</Button>
|
|
474
|
+
<Button variant="destructive">Delete Item</Button>
|
|
475
|
+
<Button variant="destructive" size="lg">Delete Everything</Button>
|
|
476
|
+
<Button variant="destructive" disabled>Disabled</Button>
|
|
477
|
+
</div>
|
|
478
|
+
</div>
|
|
479
|
+
|
|
480
|
+
{/* Accent */}
|
|
481
|
+
<div className="space-y-3">
|
|
482
|
+
<div className="text-xs font-mono text-zinc-400">variant="accent" — Solid #E57A44, upgrade / special CTA</div>
|
|
483
|
+
<div className="flex items-center gap-4 flex-wrap">
|
|
484
|
+
<Button variant="accent" size="sm">Upgrade</Button>
|
|
485
|
+
<Button variant="accent">Upgrade Plan</Button>
|
|
486
|
+
<Button variant="accent" size="lg">Upgrade Now</Button>
|
|
487
|
+
</div>
|
|
488
|
+
</div>
|
|
489
|
+
|
|
490
|
+
{/* Menu */}
|
|
491
|
+
<div className="space-y-3">
|
|
492
|
+
<div className="text-xs font-mono text-zinc-400">variant="menu" — Full-width, left-aligned, dropdown items</div>
|
|
493
|
+
<div className="w-56 bg-white dark:bg-zinc-800 rounded-lg p-1.5 space-y-0.5" style={{ boxShadow: shadow.lg }}>
|
|
494
|
+
<Button variant="menu">Open Project</Button>
|
|
495
|
+
<Button variant="menu">Settings</Button>
|
|
496
|
+
<Button variant="menu">Log Out</Button>
|
|
497
|
+
</div>
|
|
498
|
+
</div>
|
|
499
|
+
|
|
500
|
+
{/* Loading */}
|
|
501
|
+
<div className="space-y-3">
|
|
502
|
+
<div className="text-xs font-mono text-zinc-400">loading=true — Spinner + disabled, any variant</div>
|
|
503
|
+
<div className="flex items-center gap-4 flex-wrap">
|
|
504
|
+
<Button loading>Saving...</Button>
|
|
505
|
+
<Button variant="secondary" loading>Loading...</Button>
|
|
506
|
+
<Button variant="accent" loading>Processing...</Button>
|
|
507
|
+
<Button
|
|
508
|
+
onClick={() => { setLoadingDemo(true); setTimeout(() => setLoadingDemo(false), 2000); }}
|
|
509
|
+
loading={loadingDemo}
|
|
510
|
+
>
|
|
511
|
+
{loadingDemo ? 'Saving...' : 'Click to demo'}
|
|
512
|
+
</Button>
|
|
513
|
+
</div>
|
|
514
|
+
</div>
|
|
515
|
+
</div>
|
|
516
|
+
</Card>
|
|
517
|
+
</Section>
|
|
518
|
+
|
|
519
|
+
{/* ─── Hover, Active & Disabled ─── */}
|
|
520
|
+
<Section title="8. Hover, Active & Disabled States" description="Hover to preview, click and hold for active press. Disabled buttons are desaturated.">
|
|
521
|
+
<Card>
|
|
522
|
+
<div className="space-y-8">
|
|
523
|
+
<div className="grid grid-cols-2 gap-6">
|
|
524
|
+
<div className="space-y-2">
|
|
525
|
+
<Button size="lg" fullWidth>Primary — brightness(1.05)</Button>
|
|
526
|
+
<div className="text-xs text-zinc-400 text-center">hover: subtle brighten · active: scale(0.98)</div>
|
|
527
|
+
</div>
|
|
528
|
+
<div className="space-y-2">
|
|
529
|
+
<Button variant="secondary" size="lg" fullWidth>Secondary — bg-zinc-50</Button>
|
|
530
|
+
<div className="text-xs text-zinc-400 text-center">hover: subtle fill · active: scale(0.98)</div>
|
|
531
|
+
</div>
|
|
532
|
+
<div className="space-y-2">
|
|
533
|
+
<Button variant="ghost" size="lg" fullWidth>Ghost — bg-zinc-100</Button>
|
|
534
|
+
<div className="text-xs text-zinc-400 text-center">hover: light fill · active: scale(0.98)</div>
|
|
535
|
+
</div>
|
|
536
|
+
<div className="space-y-2">
|
|
537
|
+
<Button variant="destructive" size="lg" fullWidth>Destructive — bg-red-50</Button>
|
|
538
|
+
<div className="text-xs text-zinc-400 text-center">hover: red tint fill · active: scale(0.98)</div>
|
|
539
|
+
</div>
|
|
540
|
+
</div>
|
|
541
|
+
<div style={{ paddingTop: '16px' }}>
|
|
542
|
+
<div className="text-xs font-mono text-zinc-400 mb-4">Disabled states — opacity(0.4) + grayscale</div>
|
|
543
|
+
<div className="flex items-center gap-4 flex-wrap">
|
|
544
|
+
<Button disabled>Primary</Button>
|
|
545
|
+
<Button variant="secondary" disabled>Secondary</Button>
|
|
546
|
+
<Button variant="ghost" disabled>Ghost</Button>
|
|
547
|
+
<Button variant="destructive" disabled>Destructive</Button>
|
|
548
|
+
<Button variant="accent" disabled>Accent</Button>
|
|
549
|
+
</div>
|
|
550
|
+
</div>
|
|
551
|
+
</div>
|
|
552
|
+
</Card>
|
|
553
|
+
</Section>
|
|
554
|
+
|
|
555
|
+
{/* ─── Input Focus States ─── */}
|
|
556
|
+
<Section title="9. Input Focus States" description="Click into each input to see the focus transition. Border shifts to primary color with a soft glow.">
|
|
557
|
+
<Card>
|
|
558
|
+
<div className="space-y-6">
|
|
559
|
+
<div className="grid grid-cols-2 gap-8">
|
|
560
|
+
<div className="space-y-2">
|
|
561
|
+
<div className="text-xs font-mono text-zinc-400">Resting — 2px #18181b</div>
|
|
562
|
+
<input
|
|
563
|
+
type="text"
|
|
564
|
+
placeholder="Click me to focus..."
|
|
565
|
+
className="ds-input w-full text-base bg-white dark:bg-zinc-900"
|
|
566
|
+
style={{ padding: '16px 20px', borderRadius: '12px', border: '2px solid #27272a' }}
|
|
567
|
+
/>
|
|
568
|
+
</div>
|
|
569
|
+
<div className="space-y-2">
|
|
570
|
+
<div className="text-xs font-mono text-zinc-400">Focused — 2px #819D9F + glow</div>
|
|
571
|
+
<input
|
|
572
|
+
type="text"
|
|
573
|
+
placeholder="Already showing focus style"
|
|
574
|
+
className="w-full text-base bg-white dark:bg-zinc-900"
|
|
575
|
+
style={{ padding: '16px 20px', borderRadius: '12px', border: '2px solid #819D9F', boxShadow: '0 0 0 3px rgba(129, 157, 159, 0.15)', outline: 'none' }}
|
|
576
|
+
readOnly
|
|
577
|
+
/>
|
|
578
|
+
</div>
|
|
579
|
+
</div>
|
|
580
|
+
<div className="text-xs text-zinc-400">
|
|
581
|
+
Transition: <span className="font-mono">border-color 200ms ease-out, box-shadow 200ms ease-out</span>
|
|
582
|
+
</div>
|
|
583
|
+
</div>
|
|
584
|
+
</Card>
|
|
585
|
+
</Section>
|
|
586
|
+
|
|
587
|
+
{/* ─── Focus Rings ─── */}
|
|
588
|
+
<Section title="10. Focus Rings" description="Tab through these buttons to see focus-visible rings">
|
|
589
|
+
<Card>
|
|
590
|
+
<div className="flex items-center gap-4 flex-wrap">
|
|
591
|
+
<Button>Primary</Button>
|
|
592
|
+
<Button variant="secondary">Secondary</Button>
|
|
593
|
+
<Button variant="ghost">Ghost</Button>
|
|
594
|
+
<Button variant="destructive">Destructive</Button>
|
|
595
|
+
<Button variant="accent">Accent</Button>
|
|
596
|
+
</div>
|
|
597
|
+
<div className="text-xs text-zinc-400 mt-4">
|
|
598
|
+
All variants: ring-2 ring-zinc-400 ring-offset-2
|
|
599
|
+
</div>
|
|
600
|
+
</Card>
|
|
601
|
+
</Section>
|
|
602
|
+
|
|
603
|
+
{/* ─── Loading States ─── */}
|
|
604
|
+
<Section title="11. Loading States" description="Skeleton shimmer for content placeholders, spinner for actions in progress.">
|
|
605
|
+
<Card>
|
|
606
|
+
<div className="space-y-8">
|
|
607
|
+
{/* Skeleton */}
|
|
608
|
+
<div className="space-y-3">
|
|
609
|
+
<div className="text-xs font-mono text-zinc-400">Skeleton shimmer — content placeholders</div>
|
|
610
|
+
<div className="bg-zinc-50 dark:bg-zinc-800 rounded-2xl p-6 space-y-4 max-w-md">
|
|
611
|
+
<div className="flex items-center gap-3">
|
|
612
|
+
<div className="skeleton w-10 h-10 rounded-full shrink-0" />
|
|
613
|
+
<div className="flex-1 space-y-2">
|
|
614
|
+
<div className="skeleton h-4 w-3/4" />
|
|
615
|
+
<div className="skeleton h-3 w-1/2" />
|
|
616
|
+
</div>
|
|
617
|
+
</div>
|
|
618
|
+
<div className="skeleton h-4 w-full" />
|
|
619
|
+
<div className="skeleton h-4 w-5/6" />
|
|
620
|
+
<div className="skeleton h-10 w-28" style={{ borderRadius: '12px' }} />
|
|
621
|
+
</div>
|
|
622
|
+
</div>
|
|
623
|
+
|
|
624
|
+
{/* Spinner */}
|
|
625
|
+
<div className="space-y-3">
|
|
626
|
+
<div className="text-xs font-mono text-zinc-400">Inline spinner — 2px border, currentColor, animate-spin</div>
|
|
627
|
+
<div className="flex items-center gap-6">
|
|
628
|
+
<div className="flex items-center gap-2 text-base text-zinc-600 dark:text-zinc-400">
|
|
629
|
+
<span className="inline-block w-4 h-4 rounded-full animate-spin" style={{ border: '2px solid currentColor', borderTopColor: 'transparent' }} />
|
|
630
|
+
Small (16px)
|
|
631
|
+
</div>
|
|
632
|
+
<div className="flex items-center gap-2 text-base text-zinc-600 dark:text-zinc-400">
|
|
633
|
+
<span className="inline-block w-5 h-5 rounded-full animate-spin" style={{ border: '2px solid currentColor', borderTopColor: 'transparent' }} />
|
|
634
|
+
Medium (20px)
|
|
635
|
+
</div>
|
|
636
|
+
<div className="flex items-center gap-2 text-base text-zinc-600 dark:text-zinc-400">
|
|
637
|
+
<span className="inline-block w-6 h-6 rounded-full animate-spin" style={{ border: '2px solid currentColor', borderTopColor: 'transparent' }} />
|
|
638
|
+
Large (24px)
|
|
639
|
+
</div>
|
|
640
|
+
</div>
|
|
641
|
+
</div>
|
|
642
|
+
|
|
643
|
+
{/* Loading buttons */}
|
|
644
|
+
<div className="space-y-3">
|
|
645
|
+
<div className="text-xs font-mono text-zinc-400">Button loading prop — auto-disables + shows spinner</div>
|
|
646
|
+
<div className="flex items-center gap-4 flex-wrap">
|
|
647
|
+
<Button loading>Saving...</Button>
|
|
648
|
+
<Button variant="secondary" loading>Loading...</Button>
|
|
649
|
+
<Button variant="destructive" loading>Deleting...</Button>
|
|
650
|
+
<Button variant="accent" loading>Processing...</Button>
|
|
651
|
+
</div>
|
|
652
|
+
</div>
|
|
653
|
+
</div>
|
|
654
|
+
</Card>
|
|
655
|
+
</Section>
|
|
656
|
+
|
|
657
|
+
{/* ─── Toast / Notification Patterns ─── */}
|
|
658
|
+
<Section title="12. Toast & Notification Patterns" description="Static examples of feedback messages. Success uses primary tint, error uses destructive, info uses highlight.">
|
|
659
|
+
<Card>
|
|
660
|
+
<div className="space-y-4 max-w-md">
|
|
661
|
+
{/* Success */}
|
|
662
|
+
<div className="flex items-start gap-3 px-4 py-3 rounded-xl" style={{ backgroundColor: '#E8EEEF' }}>
|
|
663
|
+
<span className="text-base mt-0.5" style={{ color: '#4A6365' }}>✓</span>
|
|
664
|
+
<div>
|
|
665
|
+
<div className="text-base font-medium" style={{ color: '#4A6365' }}>Changes saved</div>
|
|
666
|
+
<div className="text-sm mt-0.5" style={{ color: '#4A6365', opacity: 0.7 }}>Your project settings have been updated.</div>
|
|
667
|
+
</div>
|
|
668
|
+
</div>
|
|
669
|
+
|
|
670
|
+
{/* Error */}
|
|
671
|
+
<div className="flex items-start gap-3 px-4 py-3 rounded-xl bg-red-50 dark:bg-red-950">
|
|
672
|
+
<span className="text-base mt-0.5 text-red-600 dark:text-red-400">✗</span>
|
|
673
|
+
<div>
|
|
674
|
+
<div className="text-base font-medium text-red-700 dark:text-red-300">Failed to save</div>
|
|
675
|
+
<div className="text-sm mt-0.5 text-red-600 dark:text-red-400" style={{ opacity: 0.8 }}>Network error. Please try again.</div>
|
|
676
|
+
</div>
|
|
677
|
+
</div>
|
|
678
|
+
|
|
679
|
+
{/* Info */}
|
|
680
|
+
<div className="flex items-start gap-3 px-4 py-3 rounded-xl" style={{ backgroundColor: '#F9F7E8' }}>
|
|
681
|
+
<span className="text-base mt-0.5" style={{ color: '#8B7D2F' }}>ⓘ</span>
|
|
682
|
+
<div>
|
|
683
|
+
<div className="text-base font-medium" style={{ color: '#8B7D2F' }}>New version available</div>
|
|
684
|
+
<div className="text-sm mt-0.5" style={{ color: '#8B7D2F', opacity: 0.7 }}>Restart to apply the latest update.</div>
|
|
685
|
+
</div>
|
|
686
|
+
</div>
|
|
687
|
+
|
|
688
|
+
{/* Warning / Accent */}
|
|
689
|
+
<div className="flex items-start gap-3 px-4 py-3 rounded-xl" style={{ backgroundColor: '#FCEEE6' }}>
|
|
690
|
+
<span className="text-base mt-0.5" style={{ color: '#9E4A1E' }}>⚠</span>
|
|
691
|
+
<div>
|
|
692
|
+
<div className="text-base font-medium" style={{ color: '#9E4A1E' }}>Approaching limit</div>
|
|
693
|
+
<div className="text-sm mt-0.5" style={{ color: '#9E4A1E', opacity: 0.7 }}>You've used 90% of your free tier.</div>
|
|
694
|
+
</div>
|
|
695
|
+
</div>
|
|
696
|
+
</div>
|
|
697
|
+
</Card>
|
|
698
|
+
</Section>
|
|
699
|
+
|
|
700
|
+
{/* ─── Composition Examples ─── */}
|
|
701
|
+
<Section title="13. Composition Examples" description="How components look together — cards use shadow + bg, not borders">
|
|
702
|
+
|
|
703
|
+
{/* Card with actions */}
|
|
704
|
+
<Card hover>
|
|
705
|
+
<div className="space-y-4">
|
|
706
|
+
<div className="text-xs font-mono text-zinc-400">Card with button group (hover for shadow lift)</div>
|
|
707
|
+
<div className="bg-zinc-50 dark:bg-zinc-800 rounded-2xl p-8 space-y-6">
|
|
708
|
+
<div>
|
|
709
|
+
<h3 className="text-lg font-semibold tracking-tight text-zinc-900 dark:text-zinc-100">Project Settings</h3>
|
|
710
|
+
<p className="text-base text-zinc-500 mt-2">Configure your project preferences and integrations.</p>
|
|
711
|
+
</div>
|
|
712
|
+
<div className="flex gap-3 justify-end">
|
|
713
|
+
<Button variant="ghost">Cancel</Button>
|
|
714
|
+
<Button>Save Changes</Button>
|
|
715
|
+
</div>
|
|
716
|
+
</div>
|
|
717
|
+
</div>
|
|
718
|
+
</Card>
|
|
719
|
+
|
|
720
|
+
{/* Destructive confirmation */}
|
|
721
|
+
<Card hover>
|
|
722
|
+
<div className="space-y-4">
|
|
723
|
+
<div className="text-xs font-mono text-zinc-400">Destructive confirmation dialog</div>
|
|
724
|
+
<div className="bg-zinc-50 dark:bg-zinc-800 rounded-2xl p-8 space-y-6 max-w-md">
|
|
725
|
+
<div>
|
|
726
|
+
<h3 className="text-lg font-semibold tracking-tight text-zinc-900 dark:text-zinc-100">Delete Project?</h3>
|
|
727
|
+
<p className="text-base text-zinc-500 mt-2">This action cannot be undone. All data will be permanently removed.</p>
|
|
728
|
+
</div>
|
|
729
|
+
<div className="flex gap-3 justify-end">
|
|
730
|
+
<Button variant="secondary">Cancel</Button>
|
|
731
|
+
<Button variant="destructive">Delete</Button>
|
|
732
|
+
</div>
|
|
733
|
+
</div>
|
|
734
|
+
</div>
|
|
735
|
+
</Card>
|
|
736
|
+
|
|
737
|
+
{/* Upgrade banner */}
|
|
738
|
+
<Card hover>
|
|
739
|
+
<div className="space-y-4">
|
|
740
|
+
<div className="text-xs font-mono text-zinc-400">Upgrade banner</div>
|
|
741
|
+
<div className="rounded-2xl p-8 flex items-center justify-between gap-8" style={{ backgroundColor: '#FCEEE6' }}>
|
|
742
|
+
<div>
|
|
743
|
+
<h3 className="text-lg font-semibold tracking-tight" style={{ color: '#9E4A1E' }}>Unlock Unlimited Use</h3>
|
|
744
|
+
<p className="text-base mt-2" style={{ color: '#9E4A1E', opacity: 0.7 }}>You're on the free plan. Upgrade for full access.</p>
|
|
745
|
+
</div>
|
|
746
|
+
<Button variant="accent" size="lg">Upgrade</Button>
|
|
747
|
+
</div>
|
|
748
|
+
</div>
|
|
749
|
+
</Card>
|
|
750
|
+
|
|
751
|
+
{/* Form with inputs */}
|
|
752
|
+
<Card hover>
|
|
753
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: '16px' }}>
|
|
754
|
+
<div className="text-xs font-mono text-zinc-400">Form — inputs get thick borders, focus shifts to primary</div>
|
|
755
|
+
<div className="bg-zinc-50 dark:bg-zinc-800 rounded-2xl" style={{ padding: '32px', maxWidth: '512px' }}>
|
|
756
|
+
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '16px', marginBottom: '40px' }}>
|
|
757
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: '10px' }}>
|
|
758
|
+
<label className="text-lg font-semibold text-zinc-900 dark:text-zinc-100">First name</label>
|
|
759
|
+
<input
|
|
760
|
+
type="text"
|
|
761
|
+
className="ds-input text-base bg-white dark:bg-zinc-900"
|
|
762
|
+
style={{ padding: '16px 20px', borderRadius: '12px', border: '2px solid #27272a' }}
|
|
763
|
+
/>
|
|
764
|
+
</div>
|
|
765
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: '10px' }}>
|
|
766
|
+
<label className="text-lg font-semibold text-zinc-900 dark:text-zinc-100">Last name</label>
|
|
767
|
+
<input
|
|
768
|
+
type="text"
|
|
769
|
+
className="ds-input text-base bg-white dark:bg-zinc-900"
|
|
770
|
+
style={{ padding: '16px 20px', borderRadius: '12px', border: '2px solid #27272a' }}
|
|
771
|
+
/>
|
|
772
|
+
</div>
|
|
773
|
+
</div>
|
|
774
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: '10px', marginBottom: '40px' }}>
|
|
775
|
+
<label className="text-lg font-semibold text-zinc-900 dark:text-zinc-100">Email</label>
|
|
776
|
+
<input
|
|
777
|
+
type="email"
|
|
778
|
+
className="ds-input text-base bg-white dark:bg-zinc-900"
|
|
779
|
+
style={{ padding: '16px 20px', borderRadius: '12px', border: '2px solid #27272a', width: '100%' }}
|
|
780
|
+
/>
|
|
781
|
+
</div>
|
|
782
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: '10px', marginBottom: '40px' }}>
|
|
783
|
+
<label className="text-lg font-semibold text-zinc-900 dark:text-zinc-100">Password</label>
|
|
784
|
+
<input
|
|
785
|
+
type="password"
|
|
786
|
+
className="ds-input text-base bg-white dark:bg-zinc-900"
|
|
787
|
+
style={{ padding: '16px 20px', borderRadius: '12px', border: '2px solid #27272a', width: '100%' }}
|
|
788
|
+
/>
|
|
789
|
+
</div>
|
|
790
|
+
<div style={{ paddingTop: '16px' }}>
|
|
791
|
+
<Button fullWidth size="lg">Submit</Button>
|
|
792
|
+
</div>
|
|
793
|
+
</div>
|
|
794
|
+
</div>
|
|
795
|
+
</Card>
|
|
796
|
+
</Section>
|
|
797
|
+
|
|
798
|
+
{/* ─── Design Decisions ─── */}
|
|
799
|
+
<Section title="Design Decisions">
|
|
800
|
+
<Card>
|
|
801
|
+
<div className="space-y-6 text-base">
|
|
802
|
+
<p className="font-medium text-zinc-900 dark:text-zinc-100">Resolved</p>
|
|
803
|
+
<div className="space-y-4 text-zinc-700 dark:text-zinc-300">
|
|
804
|
+
<div className="flex gap-3">
|
|
805
|
+
<span className="text-green-600 dark:text-green-400 shrink-0 font-mono text-xs mt-0.5">DECIDED</span>
|
|
806
|
+
<p><strong>Border philosophy</strong> — Binary: thick (2px dark) on inputs, outlined buttons, and active states, or nothing. Cards use shadow + bg contrast.</p>
|
|
807
|
+
</div>
|
|
808
|
+
<div className="flex gap-3">
|
|
809
|
+
<span className="text-green-600 dark:text-green-400 shrink-0 font-mono text-xs mt-0.5">DECIDED</span>
|
|
810
|
+
<p><strong>Border radius tiers</strong> — rounded-2xl (16px) for cards, rounded-xl (12px) for buttons/inputs, rounded-lg (8px) for menus.</p>
|
|
811
|
+
</div>
|
|
812
|
+
<div className="flex gap-3">
|
|
813
|
+
<span className="text-green-600 dark:text-green-400 shrink-0 font-mono text-xs mt-0.5">DECIDED</span>
|
|
814
|
+
<p><strong>Spacing scale</strong> — Generous: p-8 card interiors, space-y-20 between page sections.</p>
|
|
815
|
+
</div>
|
|
816
|
+
<div className="flex gap-3">
|
|
817
|
+
<span className="text-green-600 dark:text-green-400 shrink-0 font-mono text-xs mt-0.5">DECIDED</span>
|
|
818
|
+
<p><strong>Typography</strong> — Satoshi with tracking-tight on all headings (xl+). Extended to 4xl display.</p>
|
|
819
|
+
</div>
|
|
820
|
+
<div className="flex gap-3">
|
|
821
|
+
<span className="text-green-600 dark:text-green-400 shrink-0 font-mono text-xs mt-0.5">DECIDED</span>
|
|
822
|
+
<p><strong>Input styling</strong> — Semibold text-lg labels, 2px dark border, generous padding. Focus: border shifts to #819D9F with soft glow.</p>
|
|
823
|
+
</div>
|
|
824
|
+
<div className="flex gap-3">
|
|
825
|
+
<span className="text-green-600 dark:text-green-400 shrink-0 font-mono text-xs mt-0.5">DECIDED</span>
|
|
826
|
+
<p><strong>Brand palette</strong> — Three colors with solid/tint/text shades: #819D9F (primary), #E57A44 (accent), #E3D985 (highlight).</p>
|
|
827
|
+
</div>
|
|
828
|
+
<div className="flex gap-3">
|
|
829
|
+
<span className="text-green-600 dark:text-green-400 shrink-0 font-mono text-xs mt-0.5">DECIDED</span>
|
|
830
|
+
<p><strong>Official black</strong> — #18181b (zinc-900). Text, input borders, outlined buttons.</p>
|
|
831
|
+
</div>
|
|
832
|
+
<div className="flex gap-3">
|
|
833
|
+
<span className="text-green-600 dark:text-green-400 shrink-0 font-mono text-xs mt-0.5">DECIDED</span>
|
|
834
|
+
<p><strong>Motion</strong> — 200ms ease-out default. Specific transition properties only (never transition-all). active:scale(0.98) for press.</p>
|
|
835
|
+
</div>
|
|
836
|
+
<div className="flex gap-3">
|
|
837
|
+
<span className="text-green-600 dark:text-green-400 shrink-0 font-mono text-xs mt-0.5">DECIDED</span>
|
|
838
|
+
<p><strong>Elevation</strong> — Four shadow levels: sm (resting), md (default cards), lg (hover/raised), overlay (modals). Cards lift md→lg on hover.</p>
|
|
839
|
+
</div>
|
|
840
|
+
<div className="flex gap-3">
|
|
841
|
+
<span className="text-green-600 dark:text-green-400 shrink-0 font-mono text-xs mt-0.5">DECIDED</span>
|
|
842
|
+
<p><strong>Disabled states</strong> — opacity(0.4) + grayscale. More refined than flat opacity-50.</p>
|
|
843
|
+
</div>
|
|
844
|
+
<div className="flex gap-3">
|
|
845
|
+
<span className="text-green-600 dark:text-green-400 shrink-0 font-mono text-xs mt-0.5">DECIDED</span>
|
|
846
|
+
<p><strong>Destructive button</strong> — 2px red border + red text. Matches outlined button weight, clearly communicates danger.</p>
|
|
847
|
+
</div>
|
|
848
|
+
</div>
|
|
849
|
+
<div style={{ paddingTop: '24px' }} className="space-y-4 text-zinc-700 dark:text-zinc-300">
|
|
850
|
+
<p className="font-medium text-zinc-900 dark:text-zinc-100">Still open</p>
|
|
851
|
+
<div className="flex gap-3">
|
|
852
|
+
<span className="font-mono text-xs mt-0.5" style={{ color: '#8B7D2F' }}>OPEN</span>
|
|
853
|
+
<p><strong>Sidebar warmth</strong> — Should --sidebar match the warm background tone, or stay cool neutral?</p>
|
|
854
|
+
</div>
|
|
855
|
+
<div className="flex gap-3">
|
|
856
|
+
<span className="font-mono text-xs mt-0.5" style={{ color: '#8B7D2F' }}>OPEN</span>
|
|
857
|
+
<p><strong>Focus ring color</strong> — Uniform zinc-400 for all, or variant-matched?</p>
|
|
858
|
+
</div>
|
|
859
|
+
</div>
|
|
860
|
+
</div>
|
|
861
|
+
</Card>
|
|
862
|
+
</Section>
|
|
863
|
+
|
|
864
|
+
</div>
|
|
865
|
+
</div>
|
|
866
|
+
</div>
|
|
867
|
+
);
|
|
868
|
+
}
|