@1agh/maude 0.15.0
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/LICENSE +21 -0
- package/README.md +166 -0
- package/cli/bin/maude.exe +15 -0
- package/cli/bin/maude.mjs +45 -0
- package/cli/bin/mdcc.exe +10 -0
- package/cli/bin/mdcc.mjs +7 -0
- package/cli/cli-wrapper.cjs +67 -0
- package/cli/commands/config.mjs +94 -0
- package/cli/commands/design.mjs +386 -0
- package/cli/commands/help.mjs +57 -0
- package/cli/commands/init.mjs +178 -0
- package/cli/commands/version.mjs +7 -0
- package/cli/install.cjs +113 -0
- package/cli/lib/argv.mjs +37 -0
- package/cli/lib/argv.test.mjs +46 -0
- package/cli/lib/copy-tree.mjs +78 -0
- package/package.json +94 -0
- package/plugins/design/dev-server/annotations-context-toolbar.tsx +397 -0
- package/plugins/design/dev-server/annotations-layer.tsx +1717 -0
- package/plugins/design/dev-server/api.ts +674 -0
- package/plugins/design/dev-server/bin/_screenshot-playwright.mjs +50 -0
- package/plugins/design/dev-server/bin/bootstrap-check.sh +83 -0
- package/plugins/design/dev-server/bin/canvas-edit.sh +48 -0
- package/plugins/design/dev-server/bin/handoff.sh +27 -0
- package/plugins/design/dev-server/bin/screenshot.sh +232 -0
- package/plugins/design/dev-server/bin/server-up.sh +135 -0
- package/plugins/design/dev-server/bin/slug.sh +22 -0
- package/plugins/design/dev-server/bin/smoke.sh +272 -0
- package/plugins/design/dev-server/build.ts +267 -0
- package/plugins/design/dev-server/canvas-build.ts +219 -0
- package/plugins/design/dev-server/canvas-edit.ts +388 -0
- package/plugins/design/dev-server/canvas-header.ts +165 -0
- package/plugins/design/dev-server/canvas-icons.tsx +131 -0
- package/plugins/design/dev-server/canvas-lib-inline.ts +260 -0
- package/plugins/design/dev-server/canvas-lib-resolver.ts +85 -0
- package/plugins/design/dev-server/canvas-lib.tsx +1995 -0
- package/plugins/design/dev-server/canvas-meta.schema.json +181 -0
- package/plugins/design/dev-server/canvas-pipeline.ts +270 -0
- package/plugins/design/dev-server/canvas-shell.tsx +813 -0
- package/plugins/design/dev-server/client/app.jsx +2027 -0
- package/plugins/design/dev-server/client/hmr.mjs +85 -0
- package/plugins/design/dev-server/client/iframe-lazy.mjs +121 -0
- package/plugins/design/dev-server/client/index.html +15 -0
- package/plugins/design/dev-server/client/styles/0-reset.css +18 -0
- package/plugins/design/dev-server/client/styles/1-tokens.css +297 -0
- package/plugins/design/dev-server/client/styles/2-layout.css +35 -0
- package/plugins/design/dev-server/client/styles/3-shell.css +906 -0
- package/plugins/design/dev-server/client/styles/4-components.css +1268 -0
- package/plugins/design/dev-server/client/styles/5-utilities.css +4 -0
- package/plugins/design/dev-server/client/styles/_index.css +24 -0
- package/plugins/design/dev-server/client/styles.css +1419 -0
- package/plugins/design/dev-server/config.schema.json +147 -0
- package/plugins/design/dev-server/context-menu.tsx +343 -0
- package/plugins/design/dev-server/context.ts +173 -0
- package/plugins/design/dev-server/dist/client.bundle.js +20323 -0
- package/plugins/design/dev-server/dist/styles.css +2875 -0
- package/plugins/design/dev-server/examples/README.md +9 -0
- package/plugins/design/dev-server/examples/perf-100-artboards.tsx +113 -0
- package/plugins/design/dev-server/fs-watch.ts +63 -0
- package/plugins/design/dev-server/handoff.ts +721 -0
- package/plugins/design/dev-server/history.ts +125 -0
- package/plugins/design/dev-server/hmr-broadcast.ts +114 -0
- package/plugins/design/dev-server/http.ts +413 -0
- package/plugins/design/dev-server/input-router.tsx +485 -0
- package/plugins/design/dev-server/inspect.ts +365 -0
- package/plugins/design/dev-server/locator.ts +159 -0
- package/plugins/design/dev-server/mem.ts +97 -0
- package/plugins/design/dev-server/runtime-bundle.ts +235 -0
- package/plugins/design/dev-server/server.mjs +1246 -0
- package/plugins/design/dev-server/server.ts +131 -0
- package/plugins/design/dev-server/test/_helpers.ts +81 -0
- package/plugins/design/dev-server/test/active-state.test.ts +145 -0
- package/plugins/design/dev-server/test/annotations-api.test.ts +146 -0
- package/plugins/design/dev-server/test/annotations-layer.test.ts +419 -0
- package/plugins/design/dev-server/test/binary-smoke.test.ts +47 -0
- package/plugins/design/dev-server/test/bundle-smoke.test.ts +29 -0
- package/plugins/design/dev-server/test/canvas-build.test.ts +78 -0
- package/plugins/design/dev-server/test/canvas-edit.test.ts +139 -0
- package/plugins/design/dev-server/test/canvas-header.test.ts +127 -0
- package/plugins/design/dev-server/test/canvas-lib-inline.test.ts +146 -0
- package/plugins/design/dev-server/test/canvas-lib-resolver.test.ts +112 -0
- package/plugins/design/dev-server/test/canvas-meta-api.test.ts +236 -0
- package/plugins/design/dev-server/test/canvas-pipeline.test.ts +180 -0
- package/plugins/design/dev-server/test/canvas-route.test.ts +176 -0
- package/plugins/design/dev-server/test/fs-watch.test.ts +41 -0
- package/plugins/design/dev-server/test/handoff-static-frames.test.ts +215 -0
- package/plugins/design/dev-server/test/handoff.test.ts +281 -0
- package/plugins/design/dev-server/test/history-rollback.test.ts +62 -0
- package/plugins/design/dev-server/test/hmr-broadcast.test.ts +108 -0
- package/plugins/design/dev-server/test/input-router.test.ts +316 -0
- package/plugins/design/dev-server/test/locator.test.ts +214 -0
- package/plugins/design/dev-server/test/perf-harness.ts +193 -0
- package/plugins/design/dev-server/test/phase-3.6-smoke.test.ts +77 -0
- package/plugins/design/dev-server/test/runtime-bundle.test.ts +69 -0
- package/plugins/design/dev-server/test/server-lifecycle.test.ts +28 -0
- package/plugins/design/dev-server/test/tool-palette.test.tsx +55 -0
- package/plugins/design/dev-server/test/use-annotation-selection.test.tsx +77 -0
- package/plugins/design/dev-server/test/use-artboard-drag.test.ts +325 -0
- package/plugins/design/dev-server/test/use-selection-set.test.tsx +166 -0
- package/plugins/design/dev-server/test/use-snap-guides.test.ts +190 -0
- package/plugins/design/dev-server/test/use-tool-mode.test.tsx +93 -0
- package/plugins/design/dev-server/test/ws-handshake.test.ts +33 -0
- package/plugins/design/dev-server/tool-palette.tsx +278 -0
- package/plugins/design/dev-server/tsconfig.json +26 -0
- package/plugins/design/dev-server/use-annotation-selection.tsx +92 -0
- package/plugins/design/dev-server/use-annotations-visibility.tsx +43 -0
- package/plugins/design/dev-server/use-artboard-drag.tsx +445 -0
- package/plugins/design/dev-server/use-selection-set.tsx +224 -0
- package/plugins/design/dev-server/use-snap-guides.tsx +215 -0
- package/plugins/design/dev-server/use-tool-mode.tsx +114 -0
- package/plugins/design/dev-server/ws.ts +90 -0
- package/plugins/design/templates/_shell.html +177 -0
- package/plugins/design/templates/canvas.tsx.template +54 -0
- package/plugins/design/templates/design-system-inspiration/_MAPPING.md +277 -0
- package/plugins/design/templates/design-system-inspiration/_README.md +71 -0
- package/plugins/design/templates/design-system-inspiration/audience-consumer/components-banner.html +68 -0
- package/plugins/design/templates/design-system-inspiration/audience-consumer/components-empty-state-generous.html +39 -0
- package/plugins/design/templates/design-system-inspiration/audience-consumer/components-feature-grid.html +62 -0
- package/plugins/design/templates/design-system-inspiration/audience-consumer/components-marketing-card.html +63 -0
- package/plugins/design/templates/design-system-inspiration/audience-consumer/components-testimonial.html +80 -0
- package/plugins/design/templates/design-system-inspiration/audience-developer/components-code-block.html +71 -0
- package/plugins/design/templates/design-system-inspiration/audience-developer/components-diff-view.html +65 -0
- package/plugins/design/templates/design-system-inspiration/audience-developer/components-log-stream.html +62 -0
- package/plugins/design/templates/design-system-inspiration/audience-developer/components-monospace-table.html +57 -0
- package/plugins/design/templates/design-system-inspiration/audience-developer/components-terminal-pane.html +67 -0
- package/plugins/design/templates/design-system-inspiration/audience-developer/type-mono.html +57 -0
- package/plugins/design/templates/design-system-inspiration/audience-pro/colors-presence.html +74 -0
- package/plugins/design/templates/design-system-inspiration/audience-pro/components-command-palette.html +90 -0
- package/plugins/design/templates/design-system-inspiration/audience-pro/components-keyboard.html +51 -0
- package/plugins/design/templates/design-system-inspiration/audience-pro/components-list.html +89 -0
- package/plugins/design/templates/design-system-inspiration/audience-pro/components-shortcuts-overlay.html +85 -0
- package/plugins/design/templates/design-system-inspiration/audience-pro/components-toast-menu.html +80 -0
- package/plugins/design/templates/design-system-inspiration/core/INDEX.md.tpl +25 -0
- package/plugins/design/templates/design-system-inspiration/core/README.orchestration.md.tpl +71 -0
- package/plugins/design/templates/design-system-inspiration/core/README.philosophy.md.tpl +77 -0
- package/plugins/design/templates/design-system-inspiration/core/SKILL.md.tpl +50 -0
- package/plugins/design/templates/design-system-inspiration/core/colors_and_type.css.tpl +111 -0
- package/plugins/design/templates/design-system-inspiration/core/config.json.tpl +28 -0
- package/plugins/design/templates/design-system-inspiration/core/preview/_layout.css +113 -0
- package/plugins/design/templates/design-system-inspiration/core/preview/colors-accent.html +48 -0
- package/plugins/design/templates/design-system-inspiration/core/preview/colors-surfaces.html +49 -0
- package/plugins/design/templates/design-system-inspiration/core/preview/colors-text.html +52 -0
- package/plugins/design/templates/design-system-inspiration/core/preview/components-buttons.html +83 -0
- package/plugins/design/templates/design-system-inspiration/core/preview/components-cards.html +79 -0
- package/plugins/design/templates/design-system-inspiration/core/preview/components-inputs.html +82 -0
- package/plugins/design/templates/design-system-inspiration/core/preview/motion.html +66 -0
- package/plugins/design/templates/design-system-inspiration/core/preview/spacing-scale.html +53 -0
- package/plugins/design/templates/design-system-inspiration/core/preview/type-scale.html +62 -0
- package/plugins/design/templates/design-system-inspiration/foundations/borders.html +39 -0
- package/plugins/design/templates/design-system-inspiration/foundations/elevation.html +46 -0
- package/plugins/design/templates/design-system-inspiration/foundations/focus.html +48 -0
- package/plugins/design/templates/design-system-inspiration/foundations/grid.html +51 -0
- package/plugins/design/templates/design-system-inspiration/foundations/iconography.html +73 -0
- package/plugins/design/templates/design-system-inspiration/foundations/opacity.html +45 -0
- package/plugins/design/templates/design-system-inspiration/foundations/radii.html +40 -0
- package/plugins/design/templates/design-system-inspiration/foundations/selection.html +45 -0
- package/plugins/design/templates/design-system-inspiration/meta/accessibility.html +62 -0
- package/plugins/design/templates/design-system-inspiration/meta/i18n.html +73 -0
- package/plugins/design/templates/design-system-inspiration/meta/presence-multiplayer.html +71 -0
- package/plugins/design/templates/design-system-inspiration/meta/tokens-index.html +80 -0
- package/plugins/design/templates/design-system-inspiration/patterns/patterns-auth.html +78 -0
- package/plugins/design/templates/design-system-inspiration/patterns/patterns-data-density.html +61 -0
- package/plugins/design/templates/design-system-inspiration/patterns/patterns-error-pages.html +70 -0
- package/plugins/design/templates/design-system-inspiration/patterns/patterns-form-layouts.html +70 -0
- package/plugins/design/templates/design-system-inspiration/patterns/patterns-onboarding.html +71 -0
- package/plugins/design/templates/design-system-inspiration/patterns/patterns-pricing.html +83 -0
- package/plugins/design/templates/design-system-inspiration/platform-desktop/components-resize-panels.html +63 -0
- package/plugins/design/templates/design-system-inspiration/platform-desktop/ui_kits-desktop-index.html +55 -0
- package/plugins/design/templates/design-system-inspiration/platform-desktop/ui_kits-desktop-showcase.html +302 -0
- package/plugins/design/templates/design-system-inspiration/platform-mobile/components-bottom-sheet.html +63 -0
- package/plugins/design/templates/design-system-inspiration/platform-mobile/components-pull-to-refresh.html +74 -0
- package/plugins/design/templates/design-system-inspiration/platform-mobile/components-segmented-control.html +51 -0
- package/plugins/design/templates/design-system-inspiration/platform-mobile/components-tab-bar.html +57 -0
- package/plugins/design/templates/design-system-inspiration/platform-mobile/ui_kits-mobile-index.html +58 -0
- package/plugins/design/templates/design-system-inspiration/platform-mobile/ui_kits-mobile-showcase.html +237 -0
- package/plugins/design/templates/design-system-inspiration/status/colors-status.html +49 -0
- package/plugins/design/templates/design-system-inspiration/status/components-status.html +63 -0
- package/plugins/design/templates/design-system-inspiration/status/skeletons.html +74 -0
- package/plugins/design/templates/design-system-inspiration/theme-both/colors-themes-side-by-side.html +59 -0
- package/plugins/design/templates/design-system-inspiration/universal/components-callout.html +74 -0
- package/plugins/design/templates/design-system-inspiration/universal/components-dialogs.html +81 -0
- package/plugins/design/templates/design-system-inspiration/universal/components-tables.html +101 -0
- package/plugins/design/templates/design-system-inspiration/universal/components-toggles.html +74 -0
- package/plugins/design/templates/design-system-inspiration/universal/components-tooltips.html +74 -0
- package/plugins/design/templates/design-system-inspiration/universal/empty-state.html.tpl +34 -0
- package/plugins/design/templates/design-system-inspiration/universal/logo.html +42 -0
- package/plugins/design/templates/ds-specimen.tsx.template +59 -0
- package/plugins/flow/.claude-plugin/config.schema.json +398 -0
- package/plugins/flow/README.md +45 -0
- package/plugins/flow/templates/ai-skeleton/INDEX.md +50 -0
- package/plugins/flow/templates/ai-skeleton/README.md +46 -0
- package/plugins/flow/templates/ai-skeleton/browser/har/.gitkeep +0 -0
- package/plugins/flow/templates/ai-skeleton/browser/snapshots/.gitkeep +0 -0
- package/plugins/flow/templates/ai-skeleton/business/README.md +12 -0
- package/plugins/flow/templates/ai-skeleton/context/README.md +12 -0
- package/plugins/flow/templates/ai-skeleton/decisions/README.md +20 -0
- package/plugins/flow/templates/ai-skeleton/design-import/.gitkeep +0 -0
- package/plugins/flow/templates/ai-skeleton/dev-logs/.gitkeep +0 -0
- package/plugins/flow/templates/ai-skeleton/device/.gitkeep +0 -0
- package/plugins/flow/templates/ai-skeleton/docs/README.md +5 -0
- package/plugins/flow/templates/ai-skeleton/logs/.gitkeep +0 -0
- package/plugins/flow/templates/ai-skeleton/logs/README.md +13 -0
- package/plugins/flow/templates/ai-skeleton/plans/README.md +16 -0
- package/plugins/flow/templates/ai-skeleton/plans/archive/.gitkeep +0 -0
- package/plugins/flow/templates/ai-skeleton/release-guide.md +35 -0
- package/plugins/flow/templates/ai-skeleton/reviews/README.md +15 -0
- package/plugins/flow/templates/ai-skeleton/scenarios/README.md +26 -0
- package/plugins/flow/templates/ai-skeleton/scenarios/_lib/.gitkeep +0 -0
- package/plugins/flow/templates/ai-skeleton/state/STATE.md +25 -0
- package/plugins/flow/templates/ai-skeleton/templates/HANDOFF.md +32 -0
- package/plugins/flow/templates/ai-skeleton/workflows.config.json +74 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
SPECIMEN: status-components
|
|
3
|
+
DEMONSTRATES: status badges (dot + label, pill, square chip), status row indicators (left-edge bar)
|
|
4
|
+
COMPOSITION: 4 status badges × 2 styles (pill, outline) + status row indicators in a list
|
|
5
|
+
COPY VOICE: status-named real strings ("Recording", "Synced 2m ago", "Couldn't reach server")
|
|
6
|
+
WHEN SCAFFOLDED: status family (almost always)
|
|
7
|
+
NOTES: Pill badges have implicit ARIA — set role="status" on dynamic elements that update. Static badges are decorative — let the surrounding text carry the meaning to screen readers.
|
|
8
|
+
-->
|
|
9
|
+
<!doctype html>
|
|
10
|
+
<html lang="en">
|
|
11
|
+
<head>
|
|
12
|
+
<meta charset="utf-8" />
|
|
13
|
+
<title>Status — components</title>
|
|
14
|
+
<link rel="stylesheet" href="../core/colors_and_type.css" />
|
|
15
|
+
<link rel="stylesheet" href="../core/preview/_layout.css" />
|
|
16
|
+
<style>
|
|
17
|
+
.badge-pill { display: inline-flex; align-items: center; gap: 6px; padding: 2px 10px; border-radius: var(--radius-pill); font-size: var(--type-xs); }
|
|
18
|
+
.badge-pill::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
|
|
19
|
+
.badge-pill.solid::before { background: var(--accent-fg); }
|
|
20
|
+
.row-status { display: grid; grid-template-columns: 4px 1fr auto; gap: 12px; align-items: center; padding: 10px 14px; background: var(--bg-1); border-radius: var(--radius-md); margin-bottom: 6px; }
|
|
21
|
+
.row-status .bar { height: 100%; border-radius: 2px; }
|
|
22
|
+
</style>
|
|
23
|
+
</head>
|
|
24
|
+
<body class="app" data-theme="dark">
|
|
25
|
+
<main class="specimen">
|
|
26
|
+
<h1>Status components</h1>
|
|
27
|
+
<p class="lede">Badges for "what's happening now" and row indicators for "what state is this thing in". Both use the status palette — never reuse accent for these.</p>
|
|
28
|
+
|
|
29
|
+
<h2>Pill badges (solid)</h2>
|
|
30
|
+
<div class="row" style="gap: 8px;">
|
|
31
|
+
<span class="badge-pill solid" style="background: var(--status-success); color: var(--accent-fg);">Recording</span>
|
|
32
|
+
<span class="badge-pill solid" style="background: var(--status-warn); color: var(--accent-fg);">Pending review</span>
|
|
33
|
+
<span class="badge-pill solid" style="background: var(--status-error); color: var(--accent-fg);">Sync failed</span>
|
|
34
|
+
<span class="badge-pill solid" style="background: var(--status-info); color: var(--accent-fg);">New</span>
|
|
35
|
+
</div>
|
|
36
|
+
|
|
37
|
+
<h2>Pill badges (outline — low-density)</h2>
|
|
38
|
+
<div class="row" style="gap: 8px;">
|
|
39
|
+
<span class="badge-pill" style="border: 1px solid var(--status-success); color: var(--status-success);">Passed</span>
|
|
40
|
+
<span class="badge-pill" style="border: 1px solid var(--status-warn); color: var(--status-warn);">Stalled</span>
|
|
41
|
+
<span class="badge-pill" style="border: 1px solid var(--status-error); color: var(--status-error);">Blocked</span>
|
|
42
|
+
<span class="badge-pill" style="border: 1px solid var(--status-info); color: var(--status-info);">Draft</span>
|
|
43
|
+
</div>
|
|
44
|
+
|
|
45
|
+
<h2>Row indicators</h2>
|
|
46
|
+
<div class="row-status">
|
|
47
|
+
<div class="bar" style="background: var(--status-success);"></div>
|
|
48
|
+
<div><strong>Match recap</strong><div style="color: var(--fg-1); font-size: var(--type-sm);">Synced 2m ago to the team channel.</div></div>
|
|
49
|
+
<span class="badge-pill solid" style="background: var(--status-success); color: var(--accent-fg);">Live</span>
|
|
50
|
+
</div>
|
|
51
|
+
<div class="row-status">
|
|
52
|
+
<div class="bar" style="background: var(--status-warn);"></div>
|
|
53
|
+
<div><strong>Player profile update</strong><div style="color: var(--fg-1); font-size: var(--type-sm);">Awaiting captain approval (filed 1h ago).</div></div>
|
|
54
|
+
<span class="badge-pill solid" style="background: var(--status-warn); color: var(--accent-fg);">Pending</span>
|
|
55
|
+
</div>
|
|
56
|
+
<div class="row-status">
|
|
57
|
+
<div class="bar" style="background: var(--status-error);"></div>
|
|
58
|
+
<div><strong>Roster export</strong><div style="color: var(--fg-1); font-size: var(--type-sm);">Couldn't reach the league API. Will retry in 30s.</div></div>
|
|
59
|
+
<span class="badge-pill solid" style="background: var(--status-error); color: var(--accent-fg);">Failed</span>
|
|
60
|
+
</div>
|
|
61
|
+
</main>
|
|
62
|
+
</body>
|
|
63
|
+
</html>
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
SPECIMEN: status-skeletons
|
|
3
|
+
DEMONSTRATES: pulse animation on placeholder shapes, skeleton vs spinner choice, respects prefers-reduced-motion
|
|
4
|
+
COMPOSITION: skeleton for list row, card, paragraph + side-by-side comparison with spinner
|
|
5
|
+
COPY VOICE: N/A (no copy — these are loading placeholders)
|
|
6
|
+
WHEN SCAFFOLDED: status family (almost always — every async UI loads something)
|
|
7
|
+
NOTES: Skeleton wins over spinner for content where the shape is predictable (lists, cards, articles). Spinner is only acceptable when you literally don't know the dimensions yet (file upload, indeterminate work). Pulse uses opacity, not background-color — compositor-only.
|
|
8
|
+
-->
|
|
9
|
+
<!doctype html>
|
|
10
|
+
<html lang="en">
|
|
11
|
+
<head>
|
|
12
|
+
<meta charset="utf-8" />
|
|
13
|
+
<title>Status — skeletons</title>
|
|
14
|
+
<link rel="stylesheet" href="../core/colors_and_type.css" />
|
|
15
|
+
<link rel="stylesheet" href="../core/preview/_layout.css" />
|
|
16
|
+
<style>
|
|
17
|
+
.skel { background: var(--bg-3); border-radius: var(--radius-sm); animation: pulse var(--dur-soft) ease-in-out infinite alternate; }
|
|
18
|
+
@keyframes pulse { from { opacity: 0.5; } to { opacity: 1; } }
|
|
19
|
+
@media (prefers-reduced-motion: reduce) { .skel { animation: none; opacity: 0.7; } }
|
|
20
|
+
.spinner { width: 24px; height: 24px; border: 2px solid var(--bg-3); border-top-color: var(--accent); border-radius: 50%; animation: spin var(--dur-route) linear infinite; }
|
|
21
|
+
@keyframes spin { to { transform: rotate(360deg); } }
|
|
22
|
+
@media (prefers-reduced-motion: reduce) { .spinner { animation: none; } }
|
|
23
|
+
</style>
|
|
24
|
+
</head>
|
|
25
|
+
<body class="app" data-theme="dark">
|
|
26
|
+
<main class="specimen">
|
|
27
|
+
<h1>Skeletons</h1>
|
|
28
|
+
<p class="lede">Use a skeleton when the rendered shape is predictable — list rows, cards, paragraphs. Use a spinner only when dimensions are unknown (file uploads, indeterminate work). Both respect <code>prefers-reduced-motion: reduce</code>.</p>
|
|
29
|
+
|
|
30
|
+
<h2>List skeleton</h2>
|
|
31
|
+
<div style="background: var(--bg-1); border: 1px solid var(--border-default); border-radius: var(--radius-md); padding: 12px; max-width: 480px;">
|
|
32
|
+
<div style="display: flex; gap: 12px; align-items: center; padding: 8px 0;">
|
|
33
|
+
<div class="skel" style="width: 32px; height: 32px; border-radius: 50%;"></div>
|
|
34
|
+
<div style="flex: 1; display: grid; gap: 6px;">
|
|
35
|
+
<div class="skel" style="height: 12px; width: 60%;"></div>
|
|
36
|
+
<div class="skel" style="height: 10px; width: 40%;"></div>
|
|
37
|
+
</div>
|
|
38
|
+
</div>
|
|
39
|
+
<div style="display: flex; gap: 12px; align-items: center; padding: 8px 0;">
|
|
40
|
+
<div class="skel" style="width: 32px; height: 32px; border-radius: 50%;"></div>
|
|
41
|
+
<div style="flex: 1; display: grid; gap: 6px;">
|
|
42
|
+
<div class="skel" style="height: 12px; width: 50%;"></div>
|
|
43
|
+
<div class="skel" style="height: 10px; width: 30%;"></div>
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
<div style="display: flex; gap: 12px; align-items: center; padding: 8px 0;">
|
|
47
|
+
<div class="skel" style="width: 32px; height: 32px; border-radius: 50%;"></div>
|
|
48
|
+
<div style="flex: 1; display: grid; gap: 6px;">
|
|
49
|
+
<div class="skel" style="height: 12px; width: 70%;"></div>
|
|
50
|
+
<div class="skel" style="height: 10px; width: 35%;"></div>
|
|
51
|
+
</div>
|
|
52
|
+
</div>
|
|
53
|
+
</div>
|
|
54
|
+
|
|
55
|
+
<h2>Card skeleton</h2>
|
|
56
|
+
<div style="background: var(--bg-1); border: 1px solid var(--border-default); border-radius: var(--radius-md); padding: 16px; max-width: 320px; display: grid; gap: 12px;">
|
|
57
|
+
<div class="skel" style="height: 18px; width: 60%;"></div>
|
|
58
|
+
<div class="skel" style="height: 12px; width: 100%;"></div>
|
|
59
|
+
<div class="skel" style="height: 12px; width: 85%;"></div>
|
|
60
|
+
<div class="skel" style="height: 32px; width: 96px; border-radius: var(--radius-sm);"></div>
|
|
61
|
+
</div>
|
|
62
|
+
|
|
63
|
+
<h2>Spinner — when dimensions are unknown</h2>
|
|
64
|
+
<div style="background: var(--bg-1); border: 1px solid var(--border-default); border-radius: var(--radius-md); padding: 32px; display: flex; align-items: center; gap: 12px; max-width: 320px;">
|
|
65
|
+
<div class="spinner"></div>
|
|
66
|
+
<span style="color: var(--fg-1);">Uploading match video…</span>
|
|
67
|
+
</div>
|
|
68
|
+
|
|
69
|
+
<footer class="legend">
|
|
70
|
+
<p>Don't animate background-color on the skel — animation: opacity (or transform) is compositor-only and respects reduced-motion cleanly.</p>
|
|
71
|
+
</footer>
|
|
72
|
+
</main>
|
|
73
|
+
</body>
|
|
74
|
+
</html>
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
SPECIMEN: theme-both-side-by-side
|
|
3
|
+
DEMONSTRATES: dark + light themes rendered side-by-side, same UI in both, theme-switch token contract
|
|
4
|
+
COMPOSITION: 2-column side-by-side of a card showing buttons + text + tokens; left = dark, right = light
|
|
5
|
+
COPY VOICE: identical strings in both panes (only theme differs)
|
|
6
|
+
WHEN SCAFFOLDED: theme-both (only when Q4 = both equal)
|
|
7
|
+
NOTES: Both themes use the SAME tokens (--bg-0..4 etc.); only their OKLCH values differ. The HTML structure is shared — only the data-theme attribute switches. Test this specimen by toggling data-theme on the body and verifying nothing else changes.
|
|
8
|
+
-->
|
|
9
|
+
<!doctype html>
|
|
10
|
+
<html lang="en">
|
|
11
|
+
<head>
|
|
12
|
+
<meta charset="utf-8" />
|
|
13
|
+
<title>Theme — both equal</title>
|
|
14
|
+
<link rel="stylesheet" href="../core/colors_and_type.css" />
|
|
15
|
+
<link rel="stylesheet" href="../core/preview/_layout.css" />
|
|
16
|
+
<style>
|
|
17
|
+
.pane { padding: 24px; border-radius: var(--radius-md); border: 1px solid var(--border-default); }
|
|
18
|
+
.card { background: var(--bg-1); border: 1px solid var(--border-default); border-radius: var(--radius-md); padding: 16px; display: grid; gap: 12px; }
|
|
19
|
+
.card h3 { margin: 0; }
|
|
20
|
+
.card .meta { color: var(--fg-2); font-size: var(--type-sm); }
|
|
21
|
+
.btn-primary { background: var(--accent); color: var(--accent-fg); border: 0; padding: 8px 14px; border-radius: var(--radius-sm); font: inherit; }
|
|
22
|
+
.btn-secondary { background: var(--bg-3); color: var(--fg-0); border: 1px solid var(--border-default); padding: 8px 14px; border-radius: var(--radius-sm); font: inherit; }
|
|
23
|
+
</style>
|
|
24
|
+
</head>
|
|
25
|
+
<body class="app" data-theme="dark">
|
|
26
|
+
<main class="specimen">
|
|
27
|
+
<h1>Themes — side by side</h1>
|
|
28
|
+
<p class="lede">The exact same UI rendered in both themes. Tokens carry the difference; the HTML structure is identical. If a component renders differently across themes (beyond color), that's a token-resolution bug, not a per-theme design.</p>
|
|
29
|
+
|
|
30
|
+
<div class="grid" style="grid-template-columns: 1fr 1fr; gap: 16px;">
|
|
31
|
+
<div class="pane app" data-theme="dark" style="background: oklch(16% 0.012 245); color: oklch(96% 0.008 245);">
|
|
32
|
+
<h2 style="margin: 0 0 16px;">Dark</h2>
|
|
33
|
+
<div class="card">
|
|
34
|
+
<h3>Match recap</h3>
|
|
35
|
+
<p class="meta">vs. Sparta U17 · 3-1</p>
|
|
36
|
+
<div class="row" style="gap: 8px;">
|
|
37
|
+
<button class="btn-primary">View</button>
|
|
38
|
+
<button class="btn-secondary">Share</button>
|
|
39
|
+
</div>
|
|
40
|
+
</div>
|
|
41
|
+
</div>
|
|
42
|
+
|
|
43
|
+
<div class="pane app" data-theme="light" style="background: oklch(98% 0.005 245); color: oklch(20% 0.012 245);">
|
|
44
|
+
<h2 style="margin: 0 0 16px;">Light</h2>
|
|
45
|
+
<div class="card" style="background: oklch(95% 0.005 245); border-color: oklch(82% 0.010 245);">
|
|
46
|
+
<h3>Match recap</h3>
|
|
47
|
+
<p class="meta" style="color: oklch(48% 0.012 245);">vs. Sparta U17 · 3-1</p>
|
|
48
|
+
<div class="row" style="gap: 8px;">
|
|
49
|
+
<button class="btn-primary">View</button>
|
|
50
|
+
<button class="btn-secondary" style="background: oklch(91% 0.005 245); color: oklch(20% 0.012 245); border-color: oklch(78% 0.010 245);">Share</button>
|
|
51
|
+
</div>
|
|
52
|
+
</div>
|
|
53
|
+
</div>
|
|
54
|
+
</div>
|
|
55
|
+
|
|
56
|
+
<footer class="legend"><p>Inline OKLCH values here are just for the specimen; real projects swap them via <code>[data-theme="light"]</code> selectors in <code>colors_and_type.css</code>. The cascade carries every component without per-component theme overrides.</p></footer>
|
|
57
|
+
</main>
|
|
58
|
+
</body>
|
|
59
|
+
</html>
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
SPECIMEN: components-callout
|
|
3
|
+
DEMONSTRATES: --bg-1, --bg-2, --border-subtle, --status-info, --status-warn, --status-error, --status-success, --fg-0..1
|
|
4
|
+
COMPOSITION: 4 variants (note / tip / warning / error) — each with icon + title + body inline
|
|
5
|
+
COPY VOICE: title is the takeaway ("Heads up:", "Tip:", "Action required:", "Couldn't save"). Body explains in one short sentence.
|
|
6
|
+
WHEN SCAFFOLDED: universal (default-on)
|
|
7
|
+
NOTES: Callout is INLINE content — not a toast (transient) and not an alert (modal). Used for in-flow context. Border-left in the status color; bg stays neutral so callouts stack without competing.
|
|
8
|
+
-->
|
|
9
|
+
<!doctype html>
|
|
10
|
+
<html lang="en">
|
|
11
|
+
<head>
|
|
12
|
+
<meta charset="utf-8" />
|
|
13
|
+
<title>Components — callout</title>
|
|
14
|
+
<link rel="stylesheet" href="../core/colors_and_type.css" />
|
|
15
|
+
<link rel="stylesheet" href="../core/preview/_layout.css" />
|
|
16
|
+
<style>
|
|
17
|
+
.callout { background: var(--bg-1); border: 1px solid var(--border-subtle); border-left-width: 3px; border-radius: var(--radius-md); padding: 12px 16px; margin: 0 0 12px; display: flex; gap: 12px; align-items: flex-start; }
|
|
18
|
+
.callout .icon { font-size: 16px; line-height: 1; padding-top: 1px; }
|
|
19
|
+
.callout .body { flex: 1; }
|
|
20
|
+
.callout .head { font-weight: 600; margin: 0 0 2px; color: var(--fg-0); }
|
|
21
|
+
.callout .text { margin: 0; color: var(--fg-1); font-size: var(--type-sm); }
|
|
22
|
+
.callout--note { border-left-color: var(--status-info); }
|
|
23
|
+
.callout--tip { border-left-color: var(--status-success); }
|
|
24
|
+
.callout--warning { border-left-color: var(--status-warn); }
|
|
25
|
+
.callout--error { border-left-color: var(--status-error); }
|
|
26
|
+
.callout--note .icon { color: var(--status-info); }
|
|
27
|
+
.callout--tip .icon { color: var(--status-success); }
|
|
28
|
+
.callout--warning .icon { color: var(--status-warn); }
|
|
29
|
+
.callout--error .icon { color: var(--status-error); }
|
|
30
|
+
</style>
|
|
31
|
+
</head>
|
|
32
|
+
<body class="app" data-theme="dark">
|
|
33
|
+
<main class="specimen">
|
|
34
|
+
<h1>Callouts</h1>
|
|
35
|
+
<p class="lede">Inline notes, tips, warnings, and errors. Use callouts to surface context that's relevant where the user is looking — neither a transient toast nor a blocking modal.</p>
|
|
36
|
+
|
|
37
|
+
<div class="callout callout--note">
|
|
38
|
+
<span class="icon" aria-hidden="true">i</span>
|
|
39
|
+
<div class="body">
|
|
40
|
+
<p class="head">Heads up</p>
|
|
41
|
+
<p class="text">Match results sync to the club channel once the captain confirms.</p>
|
|
42
|
+
</div>
|
|
43
|
+
</div>
|
|
44
|
+
|
|
45
|
+
<div class="callout callout--tip">
|
|
46
|
+
<span class="icon" aria-hidden="true">★</span>
|
|
47
|
+
<div class="body">
|
|
48
|
+
<p class="head">Tip</p>
|
|
49
|
+
<p class="text">Drag a player from the bench onto a roster row to swap them in.</p>
|
|
50
|
+
</div>
|
|
51
|
+
</div>
|
|
52
|
+
|
|
53
|
+
<div class="callout callout--warning">
|
|
54
|
+
<span class="icon" aria-hidden="true">!</span>
|
|
55
|
+
<div class="body">
|
|
56
|
+
<p class="head">Action required</p>
|
|
57
|
+
<p class="text">Two players have expired medical clearances. Update before the next match.</p>
|
|
58
|
+
</div>
|
|
59
|
+
</div>
|
|
60
|
+
|
|
61
|
+
<div class="callout callout--error">
|
|
62
|
+
<span class="icon" aria-hidden="true">×</span>
|
|
63
|
+
<div class="body">
|
|
64
|
+
<p class="head">Couldn't save</p>
|
|
65
|
+
<p class="text">Connection dropped. We'll retry in 30s, or you can save manually.</p>
|
|
66
|
+
</div>
|
|
67
|
+
</div>
|
|
68
|
+
|
|
69
|
+
<footer class="legend">
|
|
70
|
+
<p>Title leads with the takeaway ("Action required") so a skimming reader doesn't need the body. Use the body for the one-sentence explanation, not for elaborating the warning.</p>
|
|
71
|
+
</footer>
|
|
72
|
+
</main>
|
|
73
|
+
</body>
|
|
74
|
+
</html>
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
SPECIMEN: components-dialogs
|
|
3
|
+
DEMONSTRATES: --bg-1, --bg-2, --border-default, --shadow-lg, --radius-lg, --space-4/5, --dur-route
|
|
4
|
+
COMPOSITION: modal / sheet / alert — each with title, body, primary + secondary actions
|
|
5
|
+
COPY VOICE: terse and unambiguous in titles ("Remove player?"), neutral body ("This will...", not "Are you sure..."), action-verb confirm ("Remove", not "OK")
|
|
6
|
+
WHEN SCAFFOLDED: universal (default-on)
|
|
7
|
+
NOTES: Modal blocks the page; sheet slides from edge; alert is for irreversible destructive actions. Always pair primary action with a clear cancel.
|
|
8
|
+
-->
|
|
9
|
+
<!doctype html>
|
|
10
|
+
<html lang="en">
|
|
11
|
+
<head>
|
|
12
|
+
<meta charset="utf-8" />
|
|
13
|
+
<title>Components — dialogs</title>
|
|
14
|
+
<link rel="stylesheet" href="../core/colors_and_type.css" />
|
|
15
|
+
<link rel="stylesheet" href="../core/preview/_layout.css" />
|
|
16
|
+
<style>
|
|
17
|
+
.dialog-frame { background: var(--bg-0); border: 1px solid var(--border-subtle); border-radius: var(--radius-lg); padding: var(--space-4); margin-bottom: 24px; position: relative; overflow: hidden; min-height: 220px; }
|
|
18
|
+
.dialog-frame .veil { position: absolute; inset: 0; background: rgba(0,0,0,0.4); }
|
|
19
|
+
.dialog { background: var(--bg-1); border: 1px solid var(--border-default); border-radius: var(--radius-lg); box-shadow: var(--shadow-lg); padding: var(--space-5); width: 360px; position: relative; }
|
|
20
|
+
.dialog .title { font-family: var(--font-display); font-size: var(--type-lg); font-weight: 600; line-height: var(--lh-lg); margin: 0 0 8px; }
|
|
21
|
+
.dialog .body { color: var(--fg-1); margin: 0 0 var(--space-4); }
|
|
22
|
+
.dialog .actions { display: flex; justify-content: flex-end; gap: 8px; }
|
|
23
|
+
.dialog-modal { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); }
|
|
24
|
+
.dialog-sheet { position: absolute; right: var(--space-3); top: var(--space-3); bottom: var(--space-3); width: 320px; border-radius: var(--radius-md); }
|
|
25
|
+
.btn { padding: 6px 12px; border-radius: var(--radius-sm); border: 1px solid transparent; font: inherit; cursor: pointer; }
|
|
26
|
+
.btn--primary { background: var(--accent); color: var(--accent-fg); }
|
|
27
|
+
.btn--secondary { background: transparent; color: var(--fg-1); }
|
|
28
|
+
.btn--destructive { background: var(--status-error); color: var(--accent-fg); }
|
|
29
|
+
</style>
|
|
30
|
+
</head>
|
|
31
|
+
<body class="app" data-theme="dark">
|
|
32
|
+
<main class="specimen">
|
|
33
|
+
<h1>Dialogs</h1>
|
|
34
|
+
<p class="lede">Modals interrupt the flow for confirmation or input. Sheets slide from an edge for related details that don't need full attention. Alerts are reserved for destructive, irreversible actions.</p>
|
|
35
|
+
|
|
36
|
+
<h2>Modal</h2>
|
|
37
|
+
<div class="dialog-frame">
|
|
38
|
+
<div class="veil"></div>
|
|
39
|
+
<div class="dialog dialog-modal" role="dialog" aria-modal="true" aria-labelledby="modal-t">
|
|
40
|
+
<p class="title" id="modal-t">Save match recap</p>
|
|
41
|
+
<p class="body">The current draft will be saved to your team archive and shared with the captain.</p>
|
|
42
|
+
<div class="actions">
|
|
43
|
+
<button class="btn btn--secondary">Cancel</button>
|
|
44
|
+
<button class="btn btn--primary">Save recap</button>
|
|
45
|
+
</div>
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
|
|
49
|
+
<h2>Sheet</h2>
|
|
50
|
+
<div class="dialog-frame">
|
|
51
|
+
<div class="veil" style="background: rgba(0,0,0,0.25);"></div>
|
|
52
|
+
<aside class="dialog dialog-sheet" role="dialog" aria-labelledby="sheet-t">
|
|
53
|
+
<p class="title" id="sheet-t">Player details</p>
|
|
54
|
+
<p class="body">#9 · Forward · Captain</p>
|
|
55
|
+
<p style="color: var(--fg-2); font-size: var(--type-sm); margin: 0 0 12px;">21 matches · 14 goals · 3 assists</p>
|
|
56
|
+
<div class="actions">
|
|
57
|
+
<button class="btn btn--secondary">Close</button>
|
|
58
|
+
<button class="btn btn--primary">Edit profile</button>
|
|
59
|
+
</div>
|
|
60
|
+
</aside>
|
|
61
|
+
</div>
|
|
62
|
+
|
|
63
|
+
<h2>Alert (destructive)</h2>
|
|
64
|
+
<div class="dialog-frame">
|
|
65
|
+
<div class="veil"></div>
|
|
66
|
+
<div class="dialog dialog-modal" role="alertdialog" aria-labelledby="alert-t" aria-describedby="alert-b">
|
|
67
|
+
<p class="title" id="alert-t">Remove "Scout Radar Mobile"?</p>
|
|
68
|
+
<p class="body" id="alert-b">This deletes the canvas and its iteration history. Cannot be undone.</p>
|
|
69
|
+
<div class="actions">
|
|
70
|
+
<button class="btn btn--secondary">Cancel</button>
|
|
71
|
+
<button class="btn btn--destructive">Remove canvas</button>
|
|
72
|
+
</div>
|
|
73
|
+
</div>
|
|
74
|
+
</div>
|
|
75
|
+
|
|
76
|
+
<footer class="legend">
|
|
77
|
+
<p>Title phrasing: ask the consequential question ("Remove player?"), don't restate the action ("Confirm removal"). Body explains the outcome, not the question. Confirm uses the verb ("Remove"), not "OK / Yes".</p>
|
|
78
|
+
</footer>
|
|
79
|
+
</main>
|
|
80
|
+
</body>
|
|
81
|
+
</html>
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
SPECIMEN: components-tables
|
|
3
|
+
DEMONSTRATES: --bg-1, --bg-2, --bg-3, --bg-4, --border-subtle, --border-default, --fg-0..2, --space-2/3, --radius-md
|
|
4
|
+
COMPOSITION: sortable header, sticky first column, row selection, empty / loading / error states
|
|
5
|
+
COPY VOICE: column labels in noun-form ("Player", "Goals", "Synced"); date labels relative when fresh ("2m ago"), absolute when older ("Apr 12")
|
|
6
|
+
WHEN SCAFFOLDED: universal (default-on)
|
|
7
|
+
NOTES: Header is bg-2 with sortable indicator. Row hover is bg-3, selected is bg-4. Sticky header for tall tables; sticky first column only for wide tables.
|
|
8
|
+
-->
|
|
9
|
+
<!doctype html>
|
|
10
|
+
<html lang="en">
|
|
11
|
+
<head>
|
|
12
|
+
<meta charset="utf-8" />
|
|
13
|
+
<title>Components — tables</title>
|
|
14
|
+
<link rel="stylesheet" href="../core/colors_and_type.css" />
|
|
15
|
+
<link rel="stylesheet" href="../core/preview/_layout.css" />
|
|
16
|
+
<style>
|
|
17
|
+
table { width: 100%; border-collapse: collapse; background: var(--bg-1); border-radius: var(--radius-md); overflow: hidden; border: 1px solid var(--border-default); font-size: var(--type-sm); }
|
|
18
|
+
th, td { padding: 8px 12px; text-align: left; border-bottom: 1px solid var(--border-subtle); }
|
|
19
|
+
th { background: var(--bg-2); font-weight: 500; color: var(--fg-1); position: sticky; top: 0; }
|
|
20
|
+
th[aria-sort] { cursor: pointer; }
|
|
21
|
+
th[aria-sort="ascending"]::after { content: ' ↑'; color: var(--accent); }
|
|
22
|
+
th[aria-sort="descending"]::after { content: ' ↓'; color: var(--accent); }
|
|
23
|
+
tr:last-child td { border-bottom: 0; }
|
|
24
|
+
tr:hover td { background: var(--bg-3); }
|
|
25
|
+
tr.is-selected td { background: var(--bg-4); }
|
|
26
|
+
.meta { color: var(--fg-2); font-size: var(--type-xs); }
|
|
27
|
+
.num { font-variant-numeric: tabular-nums; }
|
|
28
|
+
</style>
|
|
29
|
+
</head>
|
|
30
|
+
<body class="app" data-theme="dark">
|
|
31
|
+
<main class="specimen">
|
|
32
|
+
<h1>Tables</h1>
|
|
33
|
+
<p class="lede">Dense rows, sortable headers, row selection. The header uses <code>--bg-2</code> and sticks on tall scrolls. Hover uses <code>--bg-3</code>, selected uses <code>--bg-4</code> — never the accent (rows aren't navigation).</p>
|
|
34
|
+
|
|
35
|
+
<h2>Populated</h2>
|
|
36
|
+
<div style="max-height: 280px; overflow: auto; border-radius: var(--radius-md);">
|
|
37
|
+
<table>
|
|
38
|
+
<thead>
|
|
39
|
+
<tr>
|
|
40
|
+
<th></th>
|
|
41
|
+
<th aria-sort="ascending">Player</th>
|
|
42
|
+
<th>Position</th>
|
|
43
|
+
<th class="num">Matches</th>
|
|
44
|
+
<th class="num">Goals</th>
|
|
45
|
+
<th>Synced</th>
|
|
46
|
+
</tr>
|
|
47
|
+
</thead>
|
|
48
|
+
<tbody>
|
|
49
|
+
<tr class="is-selected">
|
|
50
|
+
<td><input type="checkbox" checked /></td>
|
|
51
|
+
<td>Kim Park</td>
|
|
52
|
+
<td>Forward</td>
|
|
53
|
+
<td class="num">24</td>
|
|
54
|
+
<td class="num">14</td>
|
|
55
|
+
<td class="meta">2m ago</td>
|
|
56
|
+
</tr>
|
|
57
|
+
<tr>
|
|
58
|
+
<td><input type="checkbox" /></td>
|
|
59
|
+
<td>Jonas Weber</td>
|
|
60
|
+
<td>Midfield</td>
|
|
61
|
+
<td class="num">22</td>
|
|
62
|
+
<td class="num">3</td>
|
|
63
|
+
<td class="meta">12m ago</td>
|
|
64
|
+
</tr>
|
|
65
|
+
<tr>
|
|
66
|
+
<td><input type="checkbox" /></td>
|
|
67
|
+
<td>Marta Silva</td>
|
|
68
|
+
<td>Defender</td>
|
|
69
|
+
<td class="num">23</td>
|
|
70
|
+
<td class="num">1</td>
|
|
71
|
+
<td class="meta">Apr 12</td>
|
|
72
|
+
</tr>
|
|
73
|
+
<tr>
|
|
74
|
+
<td><input type="checkbox" /></td>
|
|
75
|
+
<td>Liam Chen</td>
|
|
76
|
+
<td>Goalkeeper</td>
|
|
77
|
+
<td class="num">19</td>
|
|
78
|
+
<td class="num">0</td>
|
|
79
|
+
<td class="meta">Apr 11</td>
|
|
80
|
+
</tr>
|
|
81
|
+
</tbody>
|
|
82
|
+
</table>
|
|
83
|
+
</div>
|
|
84
|
+
|
|
85
|
+
<h2>Empty</h2>
|
|
86
|
+
<div style="background: var(--bg-1); border: 1px solid var(--border-default); border-radius: var(--radius-md); padding: 32px; text-align: center;">
|
|
87
|
+
<p style="margin: 0 0 4px; color: var(--fg-0);">No matches yet</p>
|
|
88
|
+
<p style="margin: 0 0 16px; color: var(--fg-2); font-size: var(--type-sm);">When you log your first match, it'll show up here.</p>
|
|
89
|
+
<button style="background: var(--accent); color: var(--accent-fg); border: 0; padding: 6px 12px; border-radius: var(--radius-sm); font: inherit;">Log a match</button>
|
|
90
|
+
</div>
|
|
91
|
+
|
|
92
|
+
<h2>Loading</h2>
|
|
93
|
+
<table>
|
|
94
|
+
<thead><tr><th>Player</th><th>Position</th><th>Goals</th></tr></thead>
|
|
95
|
+
<tbody>
|
|
96
|
+
<tr><td colspan="3" style="text-align: center; color: var(--fg-2); padding: 24px;">Loading roster…</td></tr>
|
|
97
|
+
</tbody>
|
|
98
|
+
</table>
|
|
99
|
+
</main>
|
|
100
|
+
</body>
|
|
101
|
+
</html>
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
SPECIMEN: components-toggles
|
|
3
|
+
DEMONSTRATES: --accent, --accent-fg, --bg-3, --bg-4, --border-default, --fg-0..2, --radius-sm, --radius-pill, --dur-flip
|
|
4
|
+
COMPOSITION: checkbox / radio / switch / segmented — each in unchecked, checked, focused, disabled states
|
|
5
|
+
COPY VOICE: real labels — "Notify on goals", "Default theme", "Match visibility" — never "Toggle me"
|
|
6
|
+
WHEN SCAFFOLDED: universal (default-on)
|
|
7
|
+
NOTES: Switch is rounded pill; checkbox is squared; radio is round. Each is a real <input> with custom styling — accessibility tree must remain intact.
|
|
8
|
+
-->
|
|
9
|
+
<!doctype html>
|
|
10
|
+
<html lang="en">
|
|
11
|
+
<head>
|
|
12
|
+
<meta charset="utf-8" />
|
|
13
|
+
<title>Components — toggles</title>
|
|
14
|
+
<link rel="stylesheet" href="../core/colors_and_type.css" />
|
|
15
|
+
<link rel="stylesheet" href="../core/preview/_layout.css" />
|
|
16
|
+
<style>
|
|
17
|
+
.toggle-row { display: flex; align-items: center; gap: 12px; padding: 8px 0; }
|
|
18
|
+
.toggle-row label { color: var(--fg-0); font-size: var(--type-sm); }
|
|
19
|
+
|
|
20
|
+
/* Switch */
|
|
21
|
+
.switch { position: relative; width: 36px; height: 20px; background: var(--bg-4); border-radius: var(--radius-pill); transition: background var(--dur-flip) var(--ease-out); cursor: pointer; }
|
|
22
|
+
.switch::after { content: ''; position: absolute; top: 2px; left: 2px; width: 16px; height: 16px; background: var(--fg-0); border-radius: 50%; transition: transform var(--dur-flip) var(--ease-out); }
|
|
23
|
+
.switch.is-on { background: var(--accent); }
|
|
24
|
+
.switch.is-on::after { transform: translateX(16px); background: var(--accent-fg); }
|
|
25
|
+
|
|
26
|
+
/* Checkbox */
|
|
27
|
+
.checkbox { width: 16px; height: 16px; border: 1px solid var(--border-default); background: var(--bg-3); border-radius: var(--radius-sm); display: inline-flex; align-items: center; justify-content: center; cursor: pointer; }
|
|
28
|
+
.checkbox.is-on { background: var(--accent); border-color: var(--accent); }
|
|
29
|
+
.checkbox.is-on::after { content: '✓'; color: var(--accent-fg); font-size: 12px; line-height: 1; }
|
|
30
|
+
|
|
31
|
+
/* Radio */
|
|
32
|
+
.radio { width: 16px; height: 16px; border: 1px solid var(--border-default); background: var(--bg-3); border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; cursor: pointer; }
|
|
33
|
+
.radio.is-on { border-color: var(--accent); }
|
|
34
|
+
.radio.is-on::after { content: ''; width: 8px; height: 8px; border-radius: 50%; background: var(--accent); }
|
|
35
|
+
|
|
36
|
+
/* Segmented */
|
|
37
|
+
.segmented { display: inline-flex; background: var(--bg-3); border: 1px solid var(--border-default); border-radius: var(--radius-md); padding: 2px; }
|
|
38
|
+
.segmented > button { background: transparent; border: 0; color: var(--fg-1); padding: 4px 12px; border-radius: calc(var(--radius-md) - 2px); cursor: pointer; font: inherit; transition: background var(--dur-flip) var(--ease-out); }
|
|
39
|
+
.segmented > button.is-on { background: var(--accent); color: var(--accent-fg); }
|
|
40
|
+
|
|
41
|
+
.disabled { opacity: 0.5; pointer-events: none; }
|
|
42
|
+
</style>
|
|
43
|
+
</head>
|
|
44
|
+
<body class="app" data-theme="dark">
|
|
45
|
+
<main class="specimen">
|
|
46
|
+
<h1>Toggles</h1>
|
|
47
|
+
<p class="lede">Switches for settings (binary, takes effect immediately). Checkboxes for batch select. Radios for exclusive choice within a small set. Segmented controls for view modes.</p>
|
|
48
|
+
|
|
49
|
+
<h2>Switch</h2>
|
|
50
|
+
<div class="toggle-row"><span class="switch is-on" role="switch" aria-checked="true"></span><label>Notify on goals</label></div>
|
|
51
|
+
<div class="toggle-row"><span class="switch" role="switch" aria-checked="false"></span><label>Auto-share to club channel</label></div>
|
|
52
|
+
<div class="toggle-row disabled"><span class="switch" role="switch" aria-checked="false"></span><label>Beta features (org admin only)</label></div>
|
|
53
|
+
|
|
54
|
+
<h2>Checkbox</h2>
|
|
55
|
+
<div class="toggle-row"><span class="checkbox is-on" role="checkbox" aria-checked="true"></span><label>Captain</label></div>
|
|
56
|
+
<div class="toggle-row"><span class="checkbox is-on" role="checkbox" aria-checked="true"></span><label>Available this match</label></div>
|
|
57
|
+
<div class="toggle-row"><span class="checkbox" role="checkbox" aria-checked="false"></span><label>Override squad cap</label></div>
|
|
58
|
+
|
|
59
|
+
<h2>Radio</h2>
|
|
60
|
+
<div class="toggle-row"><span class="radio is-on" role="radio" aria-checked="true"></span><label>Win</label></div>
|
|
61
|
+
<div class="toggle-row"><span class="radio" role="radio" aria-checked="false"></span><label>Draw</label></div>
|
|
62
|
+
<div class="toggle-row"><span class="radio" role="radio" aria-checked="false"></span><label>Loss</label></div>
|
|
63
|
+
|
|
64
|
+
<h2>Segmented</h2>
|
|
65
|
+
<div class="row">
|
|
66
|
+
<div class="segmented">
|
|
67
|
+
<button class="is-on">Roster</button>
|
|
68
|
+
<button>Bench</button>
|
|
69
|
+
<button>Reserves</button>
|
|
70
|
+
</div>
|
|
71
|
+
</div>
|
|
72
|
+
</main>
|
|
73
|
+
</body>
|
|
74
|
+
</html>
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
SPECIMEN: components-tooltips
|
|
3
|
+
DEMONSTRATES: --bg-2, --fg-0, --border-default, --radius-sm, --shadow-md, --dur-soft
|
|
4
|
+
COMPOSITION: 4 placement variants (top / right / bottom / left) + popover (richer content)
|
|
5
|
+
COPY VOICE: tooltip = single short phrase, no period ("Open in editor"). Popover = headline + 1–2 supporting sentences.
|
|
6
|
+
WHEN SCAFFOLDED: universal (default-on)
|
|
7
|
+
NOTES: Tooltips trigger after ~400ms hover. Never required to convey information — they augment, not replace. Popover can be triggered by click and contain interactive content.
|
|
8
|
+
-->
|
|
9
|
+
<!doctype html>
|
|
10
|
+
<html lang="en">
|
|
11
|
+
<head>
|
|
12
|
+
<meta charset="utf-8" />
|
|
13
|
+
<title>Components — tooltips</title>
|
|
14
|
+
<link rel="stylesheet" href="../core/colors_and_type.css" />
|
|
15
|
+
<link rel="stylesheet" href="../core/preview/_layout.css" />
|
|
16
|
+
<style>
|
|
17
|
+
.tooltip-host { position: relative; display: inline-block; margin: 32px 16px; }
|
|
18
|
+
.tooltip { position: absolute; background: var(--bg-2); color: var(--fg-0); padding: 6px 10px; border-radius: var(--radius-sm); font-size: var(--type-xs); white-space: nowrap; box-shadow: var(--shadow-md); border: 1px solid var(--border-default); pointer-events: none; }
|
|
19
|
+
.tooltip--top { bottom: calc(100% + 6px); left: 50%; transform: translateX(-50%); }
|
|
20
|
+
.tooltip--bottom { top: calc(100% + 6px); left: 50%; transform: translateX(-50%); }
|
|
21
|
+
.tooltip--left { right: calc(100% + 6px); top: 50%; transform: translateY(-50%); }
|
|
22
|
+
.tooltip--right { left: calc(100% + 6px); top: 50%; transform: translateY(-50%); }
|
|
23
|
+
.anchor { background: var(--bg-3); border: 1px solid var(--border-default); padding: 8px 12px; border-radius: var(--radius-sm); }
|
|
24
|
+
.popover { background: var(--bg-1); border: 1px solid var(--border-default); border-radius: var(--radius-md); box-shadow: var(--shadow-md); padding: 14px; width: 240px; }
|
|
25
|
+
.popover .head { font-weight: 600; margin: 0 0 4px; }
|
|
26
|
+
.popover .body { color: var(--fg-1); font-size: var(--type-sm); margin: 0 0 10px; }
|
|
27
|
+
</style>
|
|
28
|
+
</head>
|
|
29
|
+
<body class="app" data-theme="dark">
|
|
30
|
+
<main class="specimen">
|
|
31
|
+
<h1>Tooltips & popovers</h1>
|
|
32
|
+
<p class="lede">Tooltips are single-line hints that appear on hover or focus, never required to convey essential info. Popovers carry richer content and can be triggered by click.</p>
|
|
33
|
+
|
|
34
|
+
<h2>Placement</h2>
|
|
35
|
+
<div class="row" style="gap: 48px;">
|
|
36
|
+
<div class="tooltip-host">
|
|
37
|
+
<span class="anchor">top</span>
|
|
38
|
+
<span class="tooltip tooltip--top">Open in editor</span>
|
|
39
|
+
</div>
|
|
40
|
+
<div class="tooltip-host">
|
|
41
|
+
<span class="anchor">right</span>
|
|
42
|
+
<span class="tooltip tooltip--right">Duplicate canvas</span>
|
|
43
|
+
</div>
|
|
44
|
+
<div class="tooltip-host">
|
|
45
|
+
<span class="anchor">bottom</span>
|
|
46
|
+
<span class="tooltip tooltip--bottom">Available offline</span>
|
|
47
|
+
</div>
|
|
48
|
+
<div class="tooltip-host">
|
|
49
|
+
<span class="anchor">left</span>
|
|
50
|
+
<span class="tooltip tooltip--left">Last synced 2h ago</span>
|
|
51
|
+
</div>
|
|
52
|
+
</div>
|
|
53
|
+
|
|
54
|
+
<h2>Popover</h2>
|
|
55
|
+
<div style="margin-top: 80px;">
|
|
56
|
+
<div class="tooltip-host">
|
|
57
|
+
<button class="anchor" style="cursor: pointer;">Match settings</button>
|
|
58
|
+
<div class="popover tooltip--bottom" style="position: absolute; left: 0; transform: none;">
|
|
59
|
+
<p class="head">Visibility</p>
|
|
60
|
+
<p class="body">Who can read this match recap before it's shared with the club.</p>
|
|
61
|
+
<div class="row" style="gap: 8px;">
|
|
62
|
+
<button style="background: var(--accent); color: var(--accent-fg); border: 0; padding: 4px 10px; border-radius: var(--radius-sm); font: inherit;">Squad only</button>
|
|
63
|
+
<button style="background: transparent; color: var(--fg-1); border: 0; padding: 4px 10px; border-radius: var(--radius-sm); font: inherit;">Public</button>
|
|
64
|
+
</div>
|
|
65
|
+
</div>
|
|
66
|
+
</div>
|
|
67
|
+
</div>
|
|
68
|
+
|
|
69
|
+
<footer class="legend" style="margin-top: 120px;">
|
|
70
|
+
<p>Never put essential information in a tooltip — keyboard users hovering over a trigger should not be required to read it. Tooltips augment labeled controls; they don't replace labels.</p>
|
|
71
|
+
</footer>
|
|
72
|
+
</main>
|
|
73
|
+
</body>
|
|
74
|
+
</html>
|