@keyfunc/keybricks-ds 2.4.8 → 2.4.10
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/DEPLOY.md +9 -6
- package/INTEGRATION.md +11 -1
- package/assets/fonts/inter/InterVariable-Italic.woff2 +0 -0
- package/assets/fonts/inter/InterVariable.woff2 +0 -0
- package/assets/fonts/inter/LICENSE.txt +92 -0
- package/assets/fonts/inter/README.md +13 -0
- package/changelog.js +91 -0
- package/covers.js +104 -0
- package/gallery.html +133 -0
- package/guidelines/_color-lab.js +46 -0
- package/guidelines/brand-logo.html +9 -0
- package/guidelines/colors-list.html +86 -0
- package/guidelines/colors-palette.html +85 -0
- package/guidelines/colors-schemes.html +68 -0
- package/guidelines/colors-transparency.html +59 -0
- package/guidelines/foundations-borders.html +10 -0
- package/guidelines/foundations-chrome.html +17 -0
- package/guidelines/foundations-motion.html +17 -0
- package/guidelines/foundations-radii.html +14 -0
- package/guidelines/foundations-size-tiers.html +88 -0
- package/guidelines/foundations-spacing.html +19 -0
- package/guidelines/interaction-states.html +25 -0
- package/guidelines/type-extended.html +11 -0
- package/guidelines/type-mono.html +10 -0
- package/guidelines/type-scale.html +15 -0
- package/guidelines/type-weights.html +12 -0
- package/index.html +597 -0
- package/package.json +8 -2
- package/readme.md +1 -1
- package/readme.zh-CN.md +1 -1
- package/site-nav.js +1 -0
- package/tokens/fonts.css +19 -4
package/gallery.html
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
|
3
|
+
<title>Keybricks Design System</title>
|
|
4
|
+
<script src="tokens/theme.js"></script>
|
|
5
|
+
<link rel="stylesheet" href="styles.css"><link rel="stylesheet" href="tokens/hover.css">
|
|
6
|
+
<style>
|
|
7
|
+
*{box-sizing:border-box}
|
|
8
|
+
body{margin:0;font-family:var(--font-sans);background:var(--bg-app);color:var(--text-body)}
|
|
9
|
+
header{background:var(--bg-surface);border-bottom:1px solid var(--border-card);padding:22px 32px 18px}
|
|
10
|
+
h1{margin:0;font-size:var(--text-2xl);font-weight:var(--weight-semibold);letter-spacing:var(--tracking-2xl);color:var(--text-heading)}
|
|
11
|
+
.sub{margin:4px 0 0;font-size:var(--text-base);color:var(--text-secondary)}
|
|
12
|
+
.bar{display:flex;align-items:center;gap:10px;padding-top:16px;flex-wrap:wrap}
|
|
13
|
+
input[type=search]{height:var(--h-input);flex:1;min-width:200px;max-width:340px;border:1px solid var(--border-control);border-radius:var(--radius-md);background:var(--bg-surface);color:var(--text-primary);font-family:var(--font-sans);font-size:var(--text-xs);padding:0 10px;letter-spacing:var(--tracking-xs)}
|
|
14
|
+
input[type=search]:focus{outline:none;border-color:var(--focus-border);box-shadow:0 0 0 2px var(--focus-ring)}
|
|
15
|
+
.count{font-family:var(--font-sans);font-variant-numeric:tabular-nums;font-size:var(--text-xs);color:var(--text-muted);letter-spacing:var(--tracking-xs)}
|
|
16
|
+
a.doc{margin-left:auto;font-size:var(--text-xs);color:var(--action-primary);text-decoration:none;font-weight:var(--weight-medium);letter-spacing:var(--tracking-xs)}
|
|
17
|
+
a.doc:hover{color:var(--action-primary-hover);text-decoration:underline}
|
|
18
|
+
main{padding:24px 32px 56px}
|
|
19
|
+
h2{margin:28px 0 12px;font-size:var(--text-xs);line-height:var(--leading-xs);font-weight:var(--weight-semibold);color:var(--text-secondary);letter-spacing:var(--tracking-xs)}
|
|
20
|
+
h2:first-child{margin-top:0}
|
|
21
|
+
.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(320px,1fr));gap:16px}
|
|
22
|
+
.card{background:var(--bg-surface);border:1px solid var(--border-card);border-radius:var(--radius-lg);overflow:hidden;display:flex;flex-direction:column}
|
|
23
|
+
.card figure{margin:0;height:210px;overflow:hidden;background:var(--bg-surface);border-bottom:1px solid var(--border-subtle);position:relative}
|
|
24
|
+
.card iframe{border:0;position:absolute;top:0;left:0;transform-origin:top left;background:var(--bg-surface)}
|
|
25
|
+
.meta{padding:11px 13px 13px}
|
|
26
|
+
.meta b{display:block;font-size:var(--text-base);font-weight:var(--weight-medium);color:var(--text-heading)}
|
|
27
|
+
.meta span{display:block;font-size:var(--text-xs);color:var(--text-secondary);padding-top:2px;line-height:1.45;letter-spacing:var(--tracking-xs)}
|
|
28
|
+
.meta a{display:inline-block;margin-top:8px;font-size:var(--text-xs);font-family:var(--font-sans);font-variant-numeric:tabular-nums;color:var(--action-primary);text-decoration:none;letter-spacing:var(--tracking-xs)}
|
|
29
|
+
.meta a:hover{text-decoration:underline}
|
|
30
|
+
.empty{padding:40px;text-align:center;color:var(--text-muted);font-size:var(--text-xs);letter-spacing:var(--tracking-xs)}
|
|
31
|
+
</style></head>
|
|
32
|
+
<body>
|
|
33
|
+
<header>
|
|
34
|
+
<h1>Keybricks Design System</h1>
|
|
35
|
+
<p class="sub">121 components in React and Vue 3, on one token layer. Every card below is the real component, not a screenshot.</p>
|
|
36
|
+
<div class="bar">
|
|
37
|
+
<input type="search" id="q" placeholder="Filter components…" autocomplete="off">
|
|
38
|
+
<span class="count" id="count"></span>
|
|
39
|
+
<a class="doc" href="INTEGRATION.md">Integration guide →</a>
|
|
40
|
+
</div>
|
|
41
|
+
</header>
|
|
42
|
+
<main id="out"><div class="empty">Loading…</div></main>
|
|
43
|
+
<script type="application/json" id="cards">
|
|
44
|
+
[{"path":"components/_cards/accordion.card.html","group":"Components","viewport":"700x320","name":"Accordion","subtitle":"Generic collapsible section — settings/FAQ style"},{"path":"components/_cards/action-chip.card.html","group":"Components","viewport":"700x370","name":"Action Chip","subtitle":"Tinted bulk-action chips · five tones · size tiers, Latin and CJK"},{"path":"components/_cards/activity.card.html","group":"Components","viewport":"700x300","name":"Activity","subtitle":"ActivityItem rows · DotActivity feed"},{"path":"components/_cards/alert.card.html","group":"Components","viewport":"700x350","name":"Alert","subtitle":"In-card message — 4 tones, with and without body"},{"path":"components/_cards/app-chrome.card.html","group":"Components","viewport":"700x1490","name":"App Chrome","subtitle":"Sidebar tones · SidePanel · TopBar · UserMenu · PageToolbar"},{"path":"components/_cards/banner.card.html","group":"Components","viewport":"700x300","name":"Banner","subtitle":"Page-level notification — 4 tones · action link · dismissible"},{"path":"components/_cards/breadcrumb.card.html","group":"Components","viewport":"700x468","name":"Breadcrumb","subtitle":"Path trail — hover darkens · long trails collapse to an ellipsis dropdown"},{"path":"components/_cards/button-1-base.card.html","group":"Components","viewport":"700x690","name":"Button","subtitle":"Solid · soft/outline · ghost · text-only · disabled · loading"},{"path":"components/_cards/button-4-group.card.html","group":"Components","viewport":"700x490","name":"Button Group","subtitle":"Segmented group · split button · shortcut hint · badge"},{"path":"components/_cards/button-2-states.card.html","group":"Components","viewport":"1000x810","name":"Button Interaction States","subtitle":"Rest · hover · press · focus · loading · disabled — every variant, live and forced"},{"path":"components/_cards/button-3-sizes-icons.card.html","group":"Components","viewport":"700x720","name":"Button Sizes & Icons","subtitle":"sm 28 · md 32 · lg 40, Latin and CJK · icon placement · full width"},{"path":"components/_cards/canvas-zoom-controls.card.html","group":"Components","viewport":"700x180","name":"Canvas Zoom Controls","subtitle":"Pipeline canvas − / % / + / fit-to-view"},{"path":"components/_cards/cards-indicators.card.html","group":"Components","viewport":"700x450","name":"Cards & Indicators","subtitle":"Work in progress · Card · StatCard · Badge · IconTile · charts"},{"path":"components/_cards/checkbox.card.html","group":"Components","viewport":"700x370","name":"Checkbox","subtitle":"Checked · unchecked · indeterminate · disabled · sizes"},{"path":"components/_cards/codeblock.card.html","group":"Components","viewport":"700x260","name":"Code Block","subtitle":"SQL Preview / JSON export — mono with copy button"},{"path":"components/_cards/combobox.card.html","group":"Components","viewport":"700x430","name":"Combobox","subtitle":"Typeahead single-select — type to filter · keyboard nav · no-results"},{"path":"components/_cards/context-menu.card.html","group":"Components","viewport":"700x920","name":"Context Menu","subtitle":"Icons · plain text · danger item · long list"},{"path":"components/_cards/date-picker.card.html","group":"Components","viewport":"700x520","name":"Date Picker","subtitle":"Input + month-grid popover — today outlined · selected filled"},{"path":"components/_cards/diffvalue.card.html","group":"Components","viewport":"700x220","name":"Diff Value","subtitle":"Before → after change display (config migration)"},{"path":"components/_cards/divider.card.html","group":"Components","viewport":"700x220","name":"Divider","subtitle":"Plain · labeled · vertical"},{"path":"components/_cards/drawer.card.html","group":"Components","viewport":"700x540","name":"Drawer","subtitle":"Slide-out detail panel — header · scrollable body · footer actions"},{"path":"components/_cards/dropdown-menu.card.html","group":"Components","viewport":"700x420","name":"Dropdown Menu","subtitle":"Button · icon-only · ghost text · avatar triggers — icon items & plain-text items"},{"path":"components/_cards/dropzone.card.html","group":"Components","viewport":"924x588","name":"Dropzone","subtitle":"Empty · drag-over · uploaded · error · disabled"},{"path":"components/_cards/empty-state.card.html","group":"Components","viewport":"924x580","name":"Empty State","subtitle":"First-run · no results · error — with and without action"},{"path":"components/_cards/filter-bar.card.html","group":"Components","viewport":"1000x620","name":"Filter Bar (List Report)","subtitle":"Fiori-style filter bar composed with a table — Adapt Filters · Go"},{"path":"components/_cards/icon-button.card.html","group":"Components","viewport":"700x400","name":"Icon Button","subtitle":"Square ghost icon button · sm 28 · md 32 · lg 40 · active / muted / danger / loading / disabled"},{"path":"components/_cards/input.card.html","group":"Components","viewport":"700x720","name":"Input","subtitle":"Default · filled · required · readOnly · disabled · error · hint · focus"},{"path":"components/_cards/keyvalue.card.html","group":"Components","viewport":"700x250","name":"Key/Value Rows","subtitle":"Config summary and confirmation-step rows"},{"path":"components/_cards/kbd.card.html","group":"Components","viewport":"700x180","name":"Keyboard Shortcuts","subtitle":"Kbd — keycap hints for a power-user tool"},{"path":"components/_cards/listrow.card.html","group":"Components","viewport":"700x420","name":"List Row","subtitle":"Expandable workflow rows — collapsed, expanded, with trailing count"},{"path":"components/_cards/loading.card.html","group":"Components","viewport":"700x310","name":"Loading","subtitle":"Spinner sizes · Skeleton text, blocks and table rows"},{"path":"components/_cards/log-viewer.card.html","group":"Components","viewport":"700x370","name":"Log Viewer","subtitle":"Mono run log — info · warn · error lines"},{"path":"components/_cards/modal.card.html","group":"Components","viewport":"700x520","name":"Modal","subtitle":"Default · destructive footer · with form content · no subtitle"},{"path":"components/_cards/multi-select.card.html","group":"Components","viewport":"700x400","name":"Multi Select","subtitle":"Checkbox dropdown — removable tags · +n overflow · clear all"},{"path":"components/_cards/number-stepper.card.html","group":"Components","viewport":"700x240","name":"Number Stepper","subtitle":"Default · at min · at max · disabled"},{"path":"components/_cards/pagination.card.html","group":"Components","viewport":"700x520","name":"Pagination","subtitle":"Row-range label · small set · first/last page states"},{"path":"components/_cards/people.card.html","group":"Components","viewport":"700x300","name":"People","subtitle":"Avatar · AvatarGroup — initials, sizes, real images"},{"path":"components/_cards/pipeline-node.card.html","group":"Components","viewport":"700x1620","name":"Pipeline Node Card","subtitle":"220×90 node — category hues · status badges · ports with hover, drag-to-connect and drop states"},{"path":"components/_cards/pipeline-palette.card.html","group":"Components","viewport":"700x690","name":"Pipeline Palette","subtitle":"240px component drawer — grid/list toggle · collapsible hued categories"},{"path":"components/_cards/radio.card.html","group":"Components","viewport":"700x1120","name":"Radio Button","subtitle":"Single choice from a small set — md/sm · description · disabled · row · card variant · arrow-key navigation"},{"path":"components/_cards/search.card.html","group":"Components","viewport":"700x520","name":"Search Input","subtitle":"Bordered · bare top-bar · with value/clear · disabled"},{"path":"components/_cards/segmented-control.card.html","group":"Components","viewport":"700x1260","name":"Segmented Control","subtitle":"Mutually exclusive views in one inset track — md/sm · counts · icons · icon-only · disabled option · full width · ViewToggle"},{"path":"components/_cards/select.card.html","group":"Components","viewport":"700x430","name":"Select","subtitle":"md / sm · placeholder · disabled · error"},{"path":"components/_cards/relative-time-picker.card.html","group":"Components","viewport":"700x720","name":"Relative Time Picker","subtitle":"Filter by how long ago · md / sm / lg · unlimited · disabled · localised labels","zh":"相对时间选择器","ja":"相対時間ピッカー","subtitleZh":"按\"多久以前\"筛选 · md / sm / lg · 不限时间 · 禁用 · 本地化文案","subtitleJa":"「どれくらい前」で絞り込み · md / sm / lg · 無制限 · 無効 · ローカライズ"},{"path":"components/_cards/slider.card.html","group":"Components","viewport":"700x300","name":"Slider","subtitle":"Filled track · ring knob · value bubble · min/max labels"},{"path":"components/_cards/smart-table.card.html","group":"Components","viewport":"700x1040","name":"Smart Table (Database Grid)","subtitle":"Frozen header and row numbers · default and compact density · typed fields · hue pills · aggregates · + New"},{"path":"components/_cards/spreadsheet.card.html","group":"Components","viewport":"924x560","name":"Spreadsheet","subtitle":"Formula bar · frozen headers · range selection · =SUM() · sheet tabs · status bar"},{"path":"components/_cards/stepper.card.html","group":"Components","viewport":"700x450","name":"Stepper","subtitle":"Multi-step flow header — done · current · upcoming"},{"path":"components/_cards/table.card.html","group":"Components","viewport":"700x6150","name":"Table","subtitle":"Anatomy · densities · column types · two-line name · sorting · selection · frames · column resize · states · composition"},{"path":"components/_cards/tabs.card.html","group":"Components","viewport":"700x810","name":"Tabs","subtitle":"Underline tabs · panel tabs · pill filter tabs · counts"},{"path":"components/_cards/tag.card.html","group":"Components","viewport":"700x300","name":"Tag","subtitle":"Removable filter tags — distinct from Badge/ActionChip"},{"path":"components/_cards/textarea.card.html","group":"Components","viewport":"924x520","name":"Textarea","subtitle":"Default · character count · over the limit · disabled"},{"path":"components/_cards/timeline.card.html","group":"Components","viewport":"700x350","name":"Timeline","subtitle":"Vertical activity timeline — toned icon nodes on a hairline spine"},{"path":"components/_cards/toast.card.html","group":"Components","viewport":"700x450","name":"Toast","subtitle":"Tones · with/without meta · live ToastStack demo"},{"path":"components/_cards/toggles.card.html","group":"Components","viewport":"700x1670","name":"Toggle Switch","subtitle":"Binary settings pill — sizes · semantic red→green · glyph knobs · inline text · captions · async loading"},{"path":"components/_cards/tooltip.card.html","group":"Components","viewport":"700x360","name":"Tooltip","subtitle":"Placements — top · bottom · left · right, on icon and text triggers"},{"path":"components/_cards/tree.card.html","group":"Components","viewport":"700x2820","name":"Tree","subtitle":"Cascading checkboxes · disabled nodes · lines · async load · search · drag · reorder · keyboard"},{"path":"components/_cards/icons-0-usage.card.html","group":"Icons","viewport":"700x2250","name":"Icon Usage","subtitle":"Monochrome glyphs · category tiles · document hues · status · marks · icons inside components — when an icon gets colour","zh":"图标用法","ja":"アイコンの使い方","subtitleZh":"单色图标 · 分类色块 · 文档色 · 状态 · 标记 · 组件内图标——图标什么时候用颜色","subtitleJa":"単色グリフ · カテゴリタイル · ドキュメント色 · ステータス · マーク · コンポーネント内のアイコン — いつ色を付けるか"},{"path":"components/_cards/icons-1-core.card.html","group":"Icons","viewport":"700x1900","name":"Core Set","subtitle":"The 157 stroke glyphs the product itself uses — keyword search · click to download the SVG"},{"path":"components/_cards/icons-2-feather.card.html","group":"Icons","viewport":"700x4400","name":"Feather Library","subtitle":"404 stroke icons (core + all of Feather) · keyword search · click to download the SVG"},{"path":"components/_cards/icons-2b-lucide.card.html","group":"Icons","name":"Lucide Library","viewport":"700x1370","subtitle":"Full Lucide set (1,700+ stroke glyphs, core style) via pinned CDN · keyword search · click to download the SVG","zh":"Lucide 图标库","ja":"Lucideライブラリ","subtitleZh":"完整 Lucide 图标集(1,700+ 线性图标,与核心风格一致,固定版本 CDN)· 关键词搜索 · 点击下载 SVG","subtitleJa":"Lucide 全セット(1,700+ のストロークアイコン、コアと同一スタイル、固定版 CDN)· キーワード検索 · クリックで SVG をダウンロード"},{"path":"components/_cards/icons-3-unicons.card.html","group":"Icons","viewport":"700x1370","name":"Unicons Library","subtitle":"1,206 Unicons line glyphs via CDN webfont · keyword search · click to download the SVG"},{"path":"components/_cards/icons-4-datasource.card.html","group":"Icons","viewport":"700x660","name":"Data Source Logos","subtitle":"17 data-source logo images in assets/logos/datasource/","zh":"数据源图标","ja":"データソースロゴ","subtitleZh":"17 张数据源图标图片,位于 assets/logos/datasource/","subtitleJa":"assets/logos/datasource/ の 17 枚のデータソースロゴ画像"},{"path":"guidelines/brand-logo.html","group":"Brand","viewport":"700x170","name":"Logo & Wordmark","subtitle":"Blue cube bitmap + Inter 600 wordmark, −0.609px tracking"},{"path":"guidelines/colors-list.html","group":"Colors","viewport":"700x2740","name":"Color List","subtitle":"Every color in the system, with name and hex"},{"path":"guidelines/colors-palette.html","group":"Colors","viewport":"700x880","name":"Palette","subtitle":"Grouped by role — hover a dot for its token and hex"},{"path":"guidelines/colors-schemes.html","group":"Colors","viewport":"700x800","name":"Schemes","subtitle":"Sets that work together — surface, text, border, accent"},{"path":"guidelines/colors-transparency.html","group":"Colors","viewport":"700x490","name":"Transparency","subtitle":"Alpha scale — the number is the opacity"},{"path":"guidelines/foundations-borders.html","group":"Foundations","viewport":"700x190","name":"Borders & Shadows","subtitle":"Hairlines carry the UI; shadows only on canvas nodes"},{"path":"guidelines/foundations-chrome.html","group":"Foundations","viewport":"700x180","name":"App Chrome Dimensions","subtitle":"Fixed panel widths & bar heights"},{"path":"guidelines/foundations-motion.html","group":"Foundations","viewport":"700x170","name":"Motion","subtitle":"120/160/240ms · ease-out — hover, rise, pulse, spin"},{"path":"guidelines/foundations-radii.html","group":"Foundations","viewport":"700x200","name":"Corner Radii","subtitle":"4 controls · 8 buttons · 10 cards · 14/16 tiles & nodes · full circles"},{"path":"guidelines/foundations-size-tiers.html","group":"Foundations","viewport":"700x1340","name":"Size Tiers","subtitle":"sm 28 · md 32 · lg 40 — one tier per region, never mixed in a row; CJK one step larger at sm"},{"path":"guidelines/foundations-spacing.html","group":"Foundations","viewport":"700x170","name":"Spacing","subtitle":"4px family · page 24×32 · card 21 · section gap 24 · gaps 8 inside a group, 12/16/24 between groups"},{"path":"guidelines/interaction-states.html","group":"Foundations","viewport":"700x570","name":"Interaction States","subtitle":"The five states every control carries — and where each one is defined"},{"path":"guidelines/type-extended.html","group":"Type","viewport":"700x440","name":"Display Scale","subtitle":"Display sizes 24–60 — tracking follows the same size→tracking curve"},{"path":"guidelines/type-mono.html","group":"Type","viewport":"700x170","name":"Mono / Code Only","subtitle":"Menlo for code blocks, logs, inline code and config-code chips — IDs and amounts stay in Inter with tabular figures"},{"path":"guidelines/type-scale.html","group":"Type","viewport":"700x450","name":"Type Scale","subtitle":"Inter — the 14px scale: 12 captions · 14 body and controls · 16 section titles · 20 page titles; CJK one step larger below 14"},{"path":"guidelines/type-weights.html","group":"Type","viewport":"700x280","name":"Inter Weights","subtitle":"300 numerals · 400 body · 500 UI-medium · 600 titles — 500 becomes 600 in Chinese, Japanese and Korean"},{"path":"components/_cards/charts-1-sparkline.card.html","group":"Charts","viewport":"700x830","name":"Sparkline","subtitle":"Micro trends for stat tiles, table cells, list rows — line · area · bars · curve"},{"path":"components/_cards/charts-2-line.card.html","group":"Charts","viewport":"700x1370","name":"Line & Area","subtitle":"Trends over time — straight, smooth or stepped · stacked area · hover + legend mute"},{"path":"components/_cards/charts-3-bar.card.html","group":"Charts","viewport":"700x2040","name":"Bar Chart","subtitle":"Vertical & horizontal — grouped · stacked · 100% stacked · diverging · combo line"},{"path":"components/_cards/charts-4-barlist.card.html","group":"Charts","viewport":"700x540","name":"Bar List","subtitle":"Horizontal labeled bars — top-N rankings, budget consumption"},{"path":"components/_cards/charts-5-donut.card.html","group":"Charts","viewport":"700x570","name":"Donut & Pie","subtitle":"Composition with a KPI center — hover lifts a segment"},{"path":"components/_cards/charts-6-scatter.card.html","group":"Charts","viewport":"700x480","name":"Scatter & Bubble","subtitle":"x/y correlation, bubble = third dimension — nearest-point tooltip"},{"path":"components/_cards/charts-7-heatmap.card.html","group":"Charts","viewport":"700x480","name":"Heatmap","subtitle":"Matrix density — sequential blue ramp · diverging red/green variance"},{"path":"components/_cards/charts-8-waterfall.card.html","group":"Charts","viewport":"700x470","name":"Waterfall","subtitle":"Finance bridge — signed deltas, re-baselining totals, running-sum connectors"},{"path":"components/_cards/charts-9-bullet.card.html","group":"Charts","viewport":"700x470","name":"Bullet","subtitle":"Actual vs. target rows with a target tick — misses in red"},{"path":"components/_cards/charts-10-gauge.card.html","group":"Charts","viewport":"700x310","name":"Gauge","subtitle":"Semi-circular KPI — flat arc, threshold bands, no needle"},{"path":"components/_cards/charts-11-funnel.card.html","group":"Charts","viewport":"700x620","name":"Funnel","subtitle":"Stage counts with step-to-step conversion — sub-50% steps flagged"},{"path":"components/_cards/charts-12-treemap.card.html","group":"Charts","viewport":"700x450","name":"Treemap","subtitle":"Squarified composition — readable at 15+ items, hover for share"},{"path":"components/_cards/charts-14-radar.card.html","group":"Charts","viewport":"700x490","name":"Radar","subtitle":"Spider chart — a few entities across the same 3–10 measures"},{"path":"components/_cards/charts-15-distribution.card.html","group":"Charts","viewport":"700x760","name":"Histogram & Box Plot","subtitle":"Distribution of one measure · spread and outliers per group"},{"path":"components/_cards/charts-16-pareto.card.html","group":"Charts","viewport":"700x460","name":"Pareto","subtitle":"Sorted bars + cumulative % line — the vital few vs. the trivial many"},{"path":"components/_cards/charts-17-candlestick.card.html","group":"Charts","viewport":"700x730","name":"Candlestick","subtitle":"OHLC K-line — volume band, moving average, hollow-body convention"},{"path":"components/_cards/charts-18-sankey.card.html","group":"Charts","viewport":"700x550","name":"Sankey","subtitle":"Flow diagram — columns derived from the graph, never positioned by hand"},{"path":"components/_cards/charts-19-chord.card.html","group":"Charts","viewport":"700x910","name":"Chord","subtitle":"Circular Sankey — many-to-many, cyclical flows on one ring"},{"path":"components/_cards/charts-20-sunburst.card.html","group":"Charts","viewport":"700x540","name":"Sunburst","subtitle":"Hierarchy as concentric rings — click a ring to zoom, center to go back"},{"path":"components/_cards/charts-21-worldmap.card.html","group":"Charts","viewport":"700x870","name":"World Map","subtitle":"Choropleth on real Natural Earth geometry — hover, select, diverging scale"},{"path":"components/_cards/charts-22-gantt.card.html","group":"Charts","viewport":"700x590","name":"Gantt","subtitle":"Timeline of tasks — weekend tinting, progress fill, today marker, milestones"},{"path":"components/_cards/charts-23-bar3d.card.html","group":"Charts","viewport":"700x790","name":"3D Bars","subtitle":"Cuboid bars, grouped depth rows or stacked — drag to orbit, hover to read"},{"path":"components/_cards/charts-24-pie3d.card.html","group":"Charts","viewport":"700x1270","name":"3D Pie & Donut","subtitle":"Extruded and stepped-stairs slices — drag spins in place, hover lifts a slice"},{"path":"components/_cards/charts-25-surface3d.card.html","group":"Charts","viewport":"700x480","name":"3D Surface","subtitle":"z = f(x,y) heat-shaded grid — drag to orbit, hover reads a cell"},{"path":"components/_cards/charts-26-scatter3d.card.html","group":"Charts","viewport":"700x520","name":"3D Scatter","subtitle":"Points in an orientation cube — drag to orbit, hover pins x·y·z"},{"path":"components/_cards/charts-27-ribbon3d.card.html","group":"Charts","viewport":"700x510","name":"3D Ribbon","subtitle":"Series as extruded depth bands — the classic 3D area · drag to orbit"},{"path":"components/_cards/charts-99-fullpage.card.html","group":"Charts","viewport":"1512x2210","name":"Full-Page Analytics","subtitle":"Reference layout only — every chart type composed into one screen"}]
|
|
45
|
+
</script>
|
|
46
|
+
<script>
|
|
47
|
+
// The card list is inlined above so this page works when opened straight from disk
|
|
48
|
+
// (file:// blocks fetch). When served over http it re-reads _ds_manifest.json instead,
|
|
49
|
+
// so a rebuilt design system shows up without regenerating this file.
|
|
50
|
+
function render(m) {
|
|
51
|
+
var cards = (m.cards || []).filter(function (c) { return !/\/_dir\.card\.html$/.test(c.path || ''); }); // per-directory thumbnail stubs are tooling, not site content
|
|
52
|
+
var scalers = [];
|
|
53
|
+
var groups = {};
|
|
54
|
+
cards.forEach(function (c) {
|
|
55
|
+
var g = c.group || 'Other';
|
|
56
|
+
(groups[g] = groups[g] || []).push(c);
|
|
57
|
+
});
|
|
58
|
+
var order = ['Components', 'Icons', 'Colors', 'Type', 'Spacing', 'Foundations', 'Brand'];
|
|
59
|
+
var names = Object.keys(groups).sort(function (a, b) {
|
|
60
|
+
var ia = order.indexOf(a), ib = order.indexOf(b);
|
|
61
|
+
return (ia < 0 ? 99 : ia) - (ib < 0 ? 99 : ib) || a.localeCompare(b);
|
|
62
|
+
});
|
|
63
|
+
var out = document.getElementById('out');
|
|
64
|
+
out.innerHTML = '';
|
|
65
|
+
names.forEach(function (g) {
|
|
66
|
+
var h = document.createElement('h2');
|
|
67
|
+
h.textContent = g + ' · ' + groups[g].length;
|
|
68
|
+
out.appendChild(h);
|
|
69
|
+
var grid = document.createElement('div');
|
|
70
|
+
grid.className = 'grid';
|
|
71
|
+
grid.dataset.group = g;
|
|
72
|
+
groups[g].sort(function (a, b) { return (a.path || '').localeCompare(b.path || ''); }).forEach(function (c) {
|
|
73
|
+
var vp = (c.viewport || '700x400').split('x');
|
|
74
|
+
var w = +vp[0] || 700, hgt = +vp[1] || 400;
|
|
75
|
+
var el = document.createElement('div');
|
|
76
|
+
el.className = 'card';
|
|
77
|
+
el.dataset.name = ((c.name || '') + ' ' + (c.subtitle || '') + ' ' + g).toLowerCase();
|
|
78
|
+
el.innerHTML = '<figure></figure><div class="meta"><b>' + (c.name || c.path) + '</b>' +
|
|
79
|
+
(c.subtitle ? '<span>' + c.subtitle + '</span>' : '') +
|
|
80
|
+
'<a href="' + c.path + '" target="_blank">open full size ↗</a></div>';
|
|
81
|
+
var fig = el.querySelector('figure');
|
|
82
|
+
var f = document.createElement('iframe');
|
|
83
|
+
f.loading = 'lazy';
|
|
84
|
+
f.src = c.path;
|
|
85
|
+
f.width = w;
|
|
86
|
+
f.height = hgt;
|
|
87
|
+
fig.appendChild(f);
|
|
88
|
+
// Thumbnails scale to fit the fixed 210px tile; "open full size" shows them at 1:1.
|
|
89
|
+
// The figure height never changes, so every meta block starts at the same y in a row.
|
|
90
|
+
scalers.push(function () {
|
|
91
|
+
var s = fig.clientWidth / w;
|
|
92
|
+
f.style.transform = 'scale(' + s + ')';
|
|
93
|
+
});
|
|
94
|
+
grid.appendChild(el);
|
|
95
|
+
});
|
|
96
|
+
out.appendChild(grid);
|
|
97
|
+
});
|
|
98
|
+
document.getElementById('count').textContent = cards.length + ' cards';
|
|
99
|
+
|
|
100
|
+
function rescale() { scalers.forEach(function (fn) { fn(); }); }
|
|
101
|
+
requestAnimationFrame(rescale);
|
|
102
|
+
if (window.ResizeObserver) new ResizeObserver(rescale).observe(out);
|
|
103
|
+
else addEventListener('resize', rescale);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
var snapshot = { cards: JSON.parse(document.getElementById('cards').textContent) };
|
|
107
|
+
if (location.protocol === 'file:') {
|
|
108
|
+
render(snapshot);
|
|
109
|
+
} else {
|
|
110
|
+
fetch('_ds_manifest.json')
|
|
111
|
+
.then(function (r) { return r.ok ? r.json() : Promise.reject(); })
|
|
112
|
+
.then(render)
|
|
113
|
+
.catch(function () { render(snapshot); });
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
var q = document.getElementById('q');
|
|
117
|
+
q.addEventListener('input', function () {
|
|
118
|
+
var t = q.value.trim().toLowerCase();
|
|
119
|
+
var shown = 0;
|
|
120
|
+
document.querySelectorAll('.card').forEach(function (el) {
|
|
121
|
+
var hit = !t || el.dataset.name.indexOf(t) > -1;
|
|
122
|
+
el.style.display = hit ? '' : 'none';
|
|
123
|
+
if (hit) shown++;
|
|
124
|
+
});
|
|
125
|
+
document.querySelectorAll('.grid').forEach(function (grid) {
|
|
126
|
+
var any = Array.prototype.some.call(grid.children, function (c) { return c.style.display !== 'none'; });
|
|
127
|
+
grid.style.display = any ? '' : 'none';
|
|
128
|
+
if (grid.previousElementSibling) grid.previousElementSibling.style.display = any ? '' : 'none';
|
|
129
|
+
});
|
|
130
|
+
document.getElementById('count').textContent = shown + (t ? ' of ' + document.querySelectorAll('.card').length : '') + ' cards';
|
|
131
|
+
});
|
|
132
|
+
</script>
|
|
133
|
+
</body></html>
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/* Shared helpers for the colour specimen cards — resolves live token values from the
|
|
2
|
+
loaded stylesheet and computes WCAG contrast, so every label is measured, not typed. */
|
|
3
|
+
window.KBColor = (function () {
|
|
4
|
+
function parse(str) {
|
|
5
|
+
var m = String(str).match(/rgba?\(([^)]+)\)/);
|
|
6
|
+
if (!m) return null;
|
|
7
|
+
var p = m[1].split(/[,\s/]+/).filter(Boolean).map(Number);
|
|
8
|
+
return { r: p[0], g: p[1], b: p[2], a: p.length > 3 ? p[3] : 1 };
|
|
9
|
+
}
|
|
10
|
+
function hex(str) {
|
|
11
|
+
var c = parse(str);
|
|
12
|
+
if (!c) return String(str);
|
|
13
|
+
function h(n) { return ('0' + Math.round(n).toString(16)).slice(-2); }
|
|
14
|
+
return '#' + h(c.r) + h(c.g) + h(c.b);
|
|
15
|
+
}
|
|
16
|
+
function lum(c) {
|
|
17
|
+
var v = [c.r, c.g, c.b].map(function (x) { x /= 255; return x <= .03928 ? x / 12.92 : Math.pow((x + .055) / 1.055, 2.4); });
|
|
18
|
+
return .2126 * v[0] + .7152 * v[1] + .0722 * v[2];
|
|
19
|
+
}
|
|
20
|
+
/** Contrast ratio between two CSS colour strings (alpha is flattened onto `over`). */
|
|
21
|
+
function ratio(fg, bg, over) {
|
|
22
|
+
var a = parse(fg), b = parse(bg);
|
|
23
|
+
if (!a || !b) return 0;
|
|
24
|
+
if (b.a < 1 && over) { var o = parse(over); b = { r: b.r * b.a + o.r * (1 - b.a), g: b.g * b.a + o.g * (1 - b.a), b: b.b * b.a + o.b * (1 - b.a), a: 1 }; }
|
|
25
|
+
if (a.a < 1) { a = { r: a.r * a.a + b.r * (1 - a.a), g: a.g * a.a + b.g * (1 - a.a), b: a.b * a.a + b.b * (1 - a.a), a: 1 }; }
|
|
26
|
+
var l1 = lum(a), l2 = lum(b);
|
|
27
|
+
return (Math.max(l1, l2) + .05) / (Math.min(l1, l2) + .05);
|
|
28
|
+
}
|
|
29
|
+
/** Resolved computed value of a custom property, e.g. token('--blue-600') → "rgb(21, 93, 252)". */
|
|
30
|
+
function token(name, el) {
|
|
31
|
+
var probe = document.createElement('span');
|
|
32
|
+
probe.style.color = 'var(' + name + ')';
|
|
33
|
+
probe.style.display = 'none';
|
|
34
|
+
(el || document.body).appendChild(probe);
|
|
35
|
+
var v = getComputedStyle(probe).color;
|
|
36
|
+
probe.remove();
|
|
37
|
+
return v;
|
|
38
|
+
}
|
|
39
|
+
/** "4.7" plus a grade for normal-size text: AAA ≥7, AA ≥4.5, AA18 ≥3, else Fail. */
|
|
40
|
+
function grade(r) { return r >= 7 ? 'AAA' : r >= 4.5 ? 'AA' : r >= 3 ? 'AA 18px+' : 'Fail'; }
|
|
41
|
+
function best(bg) {
|
|
42
|
+
var w = ratio('rgb(255,255,255)', bg), b = ratio('rgb(10,10,10)', bg);
|
|
43
|
+
return w >= b ? { color: '#ffffff', ratio: w } : { color: '#0a0a0a', ratio: b };
|
|
44
|
+
}
|
|
45
|
+
return { parse: parse, hex: hex, ratio: ratio, token: token, grade: grade, best: best, fix: function (n) { return (Math.round(n * 10) / 10).toFixed(1); } };
|
|
46
|
+
})();
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<!-- @dsCard group="Brand" viewport="700x170" name="Logo & Wordmark" subtitle="Blue cube bitmap + Inter 600 wordmark, −0.609px tracking" -->
|
|
2
|
+
<!DOCTYPE html>
|
|
3
|
+
<html><head><meta charset="utf-8"><script src="../components/_shared/frame-theme.js"></script><link rel="stylesheet" href="../styles.css"><link rel="stylesheet" href="../tokens/hover.css">
|
|
4
|
+
<style>body{margin:0;padding:16px;font-family:var(--font-sans);background:var(--bg-surface);display:flex;gap:12px;box-sizing:border-box}.p{flex:1;border:1px solid var(--border-card);border-radius:10px;display:flex;align-items:center;justify-content:center;gap:10px;height:128px}.p.dark{background:var(--neutral-950)}.wm{font-weight:600;font-size:15px;letter-spacing:-.609px;color:var(--text-primary)}.dark .wm{color:#fff}.cap{position:absolute;font-size:var(--text-xs)}</style></head>
|
|
5
|
+
<body>
|
|
6
|
+
<div class="p"><img src="../assets/keybricks-logo.png" width="24" height="24" alt=""><span class="wm">Keybricks</span></div>
|
|
7
|
+
<div class="p"><img src="../assets/keybricks-logo.png" width="48" height="48" alt=""></div>
|
|
8
|
+
<div class="p dark"><img src="../assets/keybricks-logo.png" width="24" height="24" alt=""><span class="wm">Keybricks</span></div>
|
|
9
|
+
</body></html>
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
<!-- @dsCard group="Colors" viewport="700x2740" name="Color List" subtitle="Every color in the system, with name and hex" -->
|
|
2
|
+
<!DOCTYPE html>
|
|
3
|
+
<html><head><meta charset="utf-8"><script src="../components/_shared/frame-theme.js"></script><link rel="stylesheet" href="../styles.css"><link rel="stylesheet" href="../tokens/hover.css">
|
|
4
|
+
<script src="_color-lab.js"></script>
|
|
5
|
+
<style>
|
|
6
|
+
html,body{height:100%}body{margin:0;padding:18px;box-sizing:border-box;font-family:var(--font-sans);background:var(--bg-surface);overflow-y:auto}
|
|
7
|
+
.sec{display:flex;align-items:center;gap:10px;padding:0 0 12px}
|
|
8
|
+
.sec:not(:first-child){padding-top:20px}
|
|
9
|
+
.sec b{font-size:var(--text-xs);font-weight:600;color:var(--text-muted);white-space:nowrap}
|
|
10
|
+
.sec i{flex:1;height:1px;background:var(--border-subtle)}
|
|
11
|
+
.cols{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:16px 24px}
|
|
12
|
+
.blk h3{margin:0 0 6px;font-size:var(--text-xs);font-weight:600;color:var(--text-heading)}
|
|
13
|
+
.item{display:flex;align-items:center;gap:8px;height:20px}
|
|
14
|
+
.dot{width:13px;height:13px;border-radius:3px;border:1px solid var(--border-card);box-sizing:border-box;flex-shrink:0}
|
|
15
|
+
.nm{flex:1;font-size:var(--text-xs);color:var(--text-body);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
|
16
|
+
.hx{font-family:var(--font-sans);font-variant-numeric:tabular-nums;font-size:var(--text-xs);color:var(--text-secondary);white-space:nowrap}
|
|
17
|
+
</style></head>
|
|
18
|
+
<body>
|
|
19
|
+
<div id="out"></div>
|
|
20
|
+
<script>
|
|
21
|
+
var C = window.KBColor;
|
|
22
|
+
var probe = document.createElement('div');
|
|
23
|
+
probe.setAttribute('data-theme', 'dark');
|
|
24
|
+
probe.style.cssText = 'position:absolute;left:-9999px';
|
|
25
|
+
document.body.appendChild(probe);
|
|
26
|
+
function dk(n){ var s=document.createElement('span'); s.style.color='var('+n+')'; probe.appendChild(s); var v=getComputedStyle(s).color; s.remove(); return v; }
|
|
27
|
+
function show(v){ var p=C.parse(v); return p && p.a<1 ? Math.round(p.a*100)+'% α' : C.hex(v).toUpperCase(); }
|
|
28
|
+
|
|
29
|
+
var TEN = [50,100,200,300,400,500,600,700,800,900,950];
|
|
30
|
+
function ramp(hue, label, steps){
|
|
31
|
+
return [label, (steps||TEN).map(function(s){ return ['--'+hue+'-'+s, hue+'-'+s]; })];
|
|
32
|
+
}
|
|
33
|
+
var sections = [
|
|
34
|
+
['Base ramps', [
|
|
35
|
+
ramp('neutral','Neutral',[0,50,100,200,300,400,500,600,700,800,900,950]),
|
|
36
|
+
ramp('blue','Blue'), ramp('red','Red'), ramp('orange','Orange'),
|
|
37
|
+
ramp('amber','Amber'), ramp('emerald','Emerald'), ramp('teal','Teal'),
|
|
38
|
+
ramp('cyan','Cyan'), ramp('purple','Purple'), ramp('pink','Pink')
|
|
39
|
+
]],
|
|
40
|
+
['Semantic — light theme', [
|
|
41
|
+
['Surface', [['--bg-app','bg-app'],['--bg-surface','bg-surface'],['--bg-raised','bg-raised'],['--bg-inset','bg-inset'],['--bg-hover','bg-hover'],['--bg-active','bg-active'],['--bg-press','bg-press'],['--bg-scrim','bg-scrim']]],
|
|
42
|
+
['Text', [['--text-primary','text-primary'],['--text-heading','text-heading'],['--text-strong','text-strong'],['--text-body','text-body'],['--text-secondary','text-secondary'],['--text-muted','text-muted'],['--text-inverse','text-inverse'],['--on-accent','on-accent']]],
|
|
43
|
+
['Border', [['--border-card','border-card'],['--border-control','border-control'],['--border-subtle','border-subtle'],['--border-strong','border-strong'],['--focus-border','focus-border'],['--focus-ring','focus-ring'],['--selected-border','selected-border'],['--checkbox-border','checkbox-border']]],
|
|
44
|
+
['Action', [['--action-primary','action-primary'],['--action-primary-hover','action-primary-hover'],['--action-primary-active','action-primary-active'],['--action-dark','action-dark'],['--action-dark-hover','action-dark-hover'],['--action-dark-active','action-dark-active'],['--link','link'],['--link-hover','link-hover']]],
|
|
45
|
+
['Tint (soft)', [['--soft-bg','soft-bg'],['--soft-hover','soft-hover'],['--soft-active','soft-active'],['--soft-border','soft-border'],['--info-bg','info-bg'],['--info-fg','info-fg']]],
|
|
46
|
+
['Feedback', [['--success','success'],['--success-strong','success-strong'],['--success-bg','success-bg'],['--success-text','success-text'],['--warning','warning'],['--warning-bg','warning-bg'],['--warning-text','warning-text'],['--danger','danger'],['--danger-bg','danger-bg'],['--danger-text','danger-text'],['--danger-active','danger-active'],['--danger-soft-active','danger-soft-active']]],
|
|
47
|
+
['Node families', [['--cat-source','cat-source'],['--cat-source-bg','cat-source-bg'],['--cat-join','cat-join'],['--cat-join-bg','cat-join-bg'],['--cat-transform','cat-transform'],['--cat-transform-bg','cat-transform-bg'],['--cat-merge','cat-merge'],['--cat-merge-bg','cat-merge-bg'],['--cat-output','cat-output'],['--cat-output-bg','cat-output-bg']]],
|
|
48
|
+
['Inert & data-viz', [['--track','track'],['--skeleton','skeleton'],['--dot-neutral','dot-neutral'],['--edge','edge'],['--chart-blue','chart-blue'],['--port-border','port-border'],['--dropzone-border','dropzone-border'],['--dropzone-border-hover','dropzone-border-hover'],['--tooltip-bg','tooltip-bg'],['--tooltip-fg','tooltip-fg']]]
|
|
49
|
+
]],
|
|
50
|
+
['Semantic — label pills', [
|
|
51
|
+
['Fill', [['--hue-gray-bg','gray-bg'],['--hue-blue-bg','blue-bg'],['--hue-green-bg','green-bg'],['--hue-teal-bg','teal-bg'],['--hue-cyan-bg','cyan-bg'],['--hue-purple-bg','purple-bg'],['--hue-pink-bg','pink-bg'],['--hue-red-bg','red-bg'],['--hue-orange-bg','orange-bg'],['--hue-amber-bg','amber-bg']]],
|
|
52
|
+
['Text', [['--hue-gray-fg','gray-fg'],['--hue-blue-fg','blue-fg'],['--hue-green-fg','green-fg'],['--hue-teal-fg','teal-fg'],['--hue-cyan-fg','cyan-fg'],['--hue-purple-fg','purple-fg'],['--hue-pink-fg','pink-fg'],['--hue-red-fg','red-fg'],['--hue-orange-fg','orange-fg'],['--hue-amber-fg','amber-fg']]],
|
|
53
|
+
['Neutral alpha', [['--neutral-alpha-2','alpha-2'],['--neutral-alpha-4','alpha-4'],['--neutral-alpha-8','alpha-8'],['--neutral-alpha-12','alpha-12'],['--neutral-alpha-16','alpha-16'],['--neutral-alpha-24','alpha-24'],['--neutral-alpha-32','alpha-32'],['--neutral-alpha-48','alpha-48'],['--neutral-alpha-64','alpha-64'],['--neutral-alpha-80','alpha-80']]],
|
|
54
|
+
['Brand alpha & overlays', [['--brand-alpha-8','brand-alpha-8'],['--brand-alpha-12','brand-alpha-12'],['--brand-alpha-16','brand-alpha-16'],['--brand-alpha-24','brand-alpha-24'],['--brand-alpha-32','brand-alpha-32'],['--overlay-hover','overlay-hover'],['--overlay-press','overlay-press'],['--overlay-selected','overlay-selected'],['--overlay-drag','overlay-drag']]]
|
|
55
|
+
]],
|
|
56
|
+
['Semantic — dark theme', [
|
|
57
|
+
['Surface', [['--bg-app','bg-app'],['--bg-surface','bg-surface'],['--bg-raised','bg-raised'],['--bg-inset','bg-inset'],['--bg-hover','bg-hover'],['--bg-active','bg-active'],['--bg-press','bg-press']], true],
|
|
58
|
+
['Text', [['--text-primary','text-primary'],['--text-heading','text-heading'],['--text-strong','text-strong'],['--text-body','text-body'],['--text-secondary','text-secondary'],['--text-muted','text-muted'],['--text-inverse','text-inverse']], true],
|
|
59
|
+
['Border & action', [['--border-card','border-card'],['--border-control','border-control'],['--border-subtle','border-subtle'],['--border-strong','border-strong'],['--action-primary','action-primary'],['--action-primary-hover','action-primary-hover'],['--action-dark','action-dark'],['--focus-border','focus-border']], true],
|
|
60
|
+
['Feedback', [['--success','success'],['--success-text','success-text'],['--warning','warning'],['--warning-text','warning-text'],['--danger','danger'],['--danger-text','danger-text'],['--info-fg','info-fg'],['--tooltip-bg','tooltip-bg']], true]
|
|
61
|
+
]]
|
|
62
|
+
];
|
|
63
|
+
|
|
64
|
+
var out = document.getElementById('out');
|
|
65
|
+
sections.forEach(function (sec) {
|
|
66
|
+
var h = document.createElement('div');
|
|
67
|
+
h.className = 'sec';
|
|
68
|
+
h.innerHTML = '<b>' + sec[0] + '</b><i></i>';
|
|
69
|
+
out.appendChild(h);
|
|
70
|
+
var cols = document.createElement('div');
|
|
71
|
+
cols.className = 'cols';
|
|
72
|
+
sec[1].forEach(function (blk) {
|
|
73
|
+
var isDark = blk[2] === true;
|
|
74
|
+
var el = document.createElement('div');
|
|
75
|
+
el.className = 'blk';
|
|
76
|
+
var items = blk[1].map(function (t) {
|
|
77
|
+
var v = isDark ? dk(t[0]) : C.token(t[0]);
|
|
78
|
+
return '<div class="item" title="' + t[0] + ' · ' + v + '"><span class="dot" style="background:' + v + '"></span><span class="nm">' + t[1] + '</span><span class="hx">' + show(v) + '</span></div>';
|
|
79
|
+
}).join('');
|
|
80
|
+
el.innerHTML = '<h3>' + blk[0] + '</h3>' + items;
|
|
81
|
+
cols.appendChild(el);
|
|
82
|
+
});
|
|
83
|
+
out.appendChild(cols);
|
|
84
|
+
});
|
|
85
|
+
</script>
|
|
86
|
+
</body></html>
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
<!-- @dsCard group="Colors" viewport="700x880" name="Palette" subtitle="Grouped by role — hover a dot for its token and hex" -->
|
|
2
|
+
<!DOCTYPE html>
|
|
3
|
+
<html><head><meta charset="utf-8"><script src="../components/_shared/frame-theme.js"></script><link rel="stylesheet" href="../styles.css"><link rel="stylesheet" href="../tokens/hover.css">
|
|
4
|
+
<script src="_color-lab.js"></script>
|
|
5
|
+
<style>
|
|
6
|
+
html,body{height:100%}body{margin:0;padding:18px;box-sizing:border-box;font-family:var(--font-sans);background:var(--bg-surface);overflow-y:auto}
|
|
7
|
+
.wrap{display:grid;grid-template-columns:repeat(4,1fr);gap:22px 18px}
|
|
8
|
+
.grp{min-width:0}
|
|
9
|
+
.grp h3{margin:0 0 9px;font-size:var(--text-xs);font-weight:500;color:var(--text-heading);letter-spacing:-.1px}
|
|
10
|
+
.dots{display:flex;flex-wrap:wrap;gap:6px}
|
|
11
|
+
.dot{width:22px;height:22px;border-radius:var(--radius-full);border:1px solid var(--border-card);box-sizing:border-box;cursor:default}
|
|
12
|
+
.sec{grid-column:1/-1;display:flex;align-items:center;gap:10px;padding-top:4px}
|
|
13
|
+
.sec b{font-size:var(--text-xs);font-weight:600;color:var(--text-muted)}
|
|
14
|
+
.sec i{flex:1;height:1px;background:var(--border-subtle)}
|
|
15
|
+
.foot{font-size:var(--text-xs);color:var(--text-secondary);padding-top:16px;margin-top:14px;border-top:1px solid var(--border-subtle);line-height:1.6}
|
|
16
|
+
.foot b{font-weight:600;color:var(--text-heading)}
|
|
17
|
+
</style></head>
|
|
18
|
+
<body>
|
|
19
|
+
<div class="wrap" id="w"></div>
|
|
20
|
+
<div class="foot"><b>Base groups</b> are the raw ramps — light to dark, ten steps each. <b>Semantic groups</b> are the sets components actually reference: a fill, its tint, and the text that sits on it. Neutral and blue come from the source file; the rest are generated in OKLCH on one shared curve, with every step that another token depends on pinned to its exact source value.</div>
|
|
21
|
+
<script>
|
|
22
|
+
var C = window.KBColor;
|
|
23
|
+
function dark(n){ var s=document.createElement('span'); s.style.color='var('+n+')'; probe.appendChild(s); var v=getComputedStyle(s).color; s.remove(); return v; }
|
|
24
|
+
var probe = document.createElement('div');
|
|
25
|
+
probe.setAttribute('data-theme','dark');
|
|
26
|
+
probe.style.cssText = 'position:absolute;left:-9999px';
|
|
27
|
+
document.body.appendChild(probe);
|
|
28
|
+
|
|
29
|
+
var ramp = function (hue, steps) { return steps.map(function (s) { return ['--' + hue + '-' + s, null]; }); };
|
|
30
|
+
var TEN = [50,100,200,300,400,500,600,700,800,900];
|
|
31
|
+
|
|
32
|
+
var sections = [
|
|
33
|
+
['Base ramps', [
|
|
34
|
+
['Neutral', ramp('neutral', [50,100,200,300,400,500,600,700,800,900])],
|
|
35
|
+
['Brand blue', ramp('blue', [50,100,200,300,400,500,600,700,800,900])],
|
|
36
|
+
['Error red', ramp('red', TEN)],
|
|
37
|
+
['Warning amber', ramp('amber', TEN)],
|
|
38
|
+
['Success emerald', ramp('emerald', TEN)],
|
|
39
|
+
['Transform orange', ramp('orange', TEN)],
|
|
40
|
+
['Output teal', ramp('teal', TEN)],
|
|
41
|
+
['Merge purple', ramp('purple', TEN)],
|
|
42
|
+
['Cyan', ramp('cyan', TEN)],
|
|
43
|
+
['Pink', ramp('pink', TEN)]
|
|
44
|
+
]],
|
|
45
|
+
['Semantic — feedback', [
|
|
46
|
+
['Feedback / error', [['--danger',null],['--danger-bg',null],['--danger-text',null],['--danger-active',null]]],
|
|
47
|
+
['Feedback / success', [['--success',null],['--success-strong',null],['--success-bg',null],['--success-text',null]]],
|
|
48
|
+
['Feedback / warning', [['--warning',null],['--warning-bg',null],['--warning-text',null]]],
|
|
49
|
+
['Feedback / info', [['--info-bg',null],['--info-fg',null],['--soft-border',null]]]
|
|
50
|
+
]],
|
|
51
|
+
['Semantic — action & surface', [
|
|
52
|
+
['Action', [['--action-primary',null],['--action-primary-hover',null],['--action-primary-active',null],['--soft-bg',null],['--soft-hover',null],['--soft-active',null]]],
|
|
53
|
+
['Surface', [['--bg-app',null],['--bg-surface',null],['--bg-inset',null],['--bg-hover',null],['--bg-active',null],['--bg-press',null]]],
|
|
54
|
+
['On surface (text)', [['--text-primary',null],['--text-heading',null],['--text-body',null],['--text-secondary',null],['--text-muted',null],['--on-accent',null]]],
|
|
55
|
+
['Border', [['--border-subtle',null],['--border-card',null],['--border-control',null],['--border-strong',null],['--focus-border',null],['--selected-border',null]]],
|
|
56
|
+
['Node families', [['--cat-source',null],['--cat-join',null],['--cat-transform',null],['--cat-merge',null],['--cat-output',null]]],
|
|
57
|
+
['Disabled & inert', [['--track',null],['--skeleton',null],['--dot-neutral',null],['--text-muted',null],['--edge',null]]]
|
|
58
|
+
]],
|
|
59
|
+
['Semantic — dark theme', [
|
|
60
|
+
['Dark surface', [['--bg-app',dark('--bg-app')],['--bg-surface',dark('--bg-surface')],['--bg-raised',dark('--bg-raised')],['--bg-inset',dark('--bg-inset')],['--bg-hover',dark('--bg-hover')],['--bg-active',dark('--bg-active')]]],
|
|
61
|
+
['Dark on-surface', [['--text-primary',dark('--text-primary')],['--text-heading',dark('--text-heading')],['--text-body',dark('--text-body')],['--text-secondary',dark('--text-secondary')],['--text-muted',dark('--text-muted')]]],
|
|
62
|
+
['Dark action', [['--action-primary',dark('--action-primary')],['--action-primary-hover',dark('--action-primary-hover')],['--action-dark',dark('--action-dark')],['--focus-border',dark('--focus-border')]]],
|
|
63
|
+
['Dark border', [['--border-subtle',dark('--border-subtle')],['--border-card',dark('--border-card')],['--border-control',dark('--border-control')],['--border-strong',dark('--border-strong')]]]
|
|
64
|
+
]]
|
|
65
|
+
];
|
|
66
|
+
|
|
67
|
+
var w = document.getElementById('w');
|
|
68
|
+
sections.forEach(function (sec) {
|
|
69
|
+
var h = document.createElement('div');
|
|
70
|
+
h.className = 'sec';
|
|
71
|
+
h.innerHTML = '<b>' + sec[0] + '</b><i></i>';
|
|
72
|
+
w.appendChild(h);
|
|
73
|
+
sec[1].forEach(function (grp) {
|
|
74
|
+
var el = document.createElement('div');
|
|
75
|
+
el.className = 'grp';
|
|
76
|
+
var dots = grp[1].map(function (t) {
|
|
77
|
+
var v = t[1] || C.token(t[0]);
|
|
78
|
+
return '<span class="dot" style="background:' + v + '" title="' + t[0] + ' · ' + (C.parse(v) && C.parse(v).a < 1 ? v : C.hex(v).toUpperCase()) + '"></span>';
|
|
79
|
+
}).join('');
|
|
80
|
+
el.innerHTML = '<h3>' + grp[0] + '</h3><div class="dots">' + dots + '</div>';
|
|
81
|
+
w.appendChild(el);
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
</script>
|
|
85
|
+
</body></html>
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
<!-- @dsCard group="Colors" viewport="700x800" name="Schemes" subtitle="Sets that work together — surface, text, border, accent" -->
|
|
2
|
+
<!DOCTYPE html>
|
|
3
|
+
<html><head><meta charset="utf-8"><script src="../components/_shared/frame-theme.js"></script><link rel="stylesheet" href="../styles.css"><link rel="stylesheet" href="../tokens/hover.css">
|
|
4
|
+
<script src="_color-lab.js"></script>
|
|
5
|
+
<style>
|
|
6
|
+
body{margin:0;padding:16px 18px;font-family:var(--font-sans);background:var(--bg-surface);box-sizing:border-box}
|
|
7
|
+
.grid{display:grid;grid-template-columns:1fr 1fr;gap:11px}
|
|
8
|
+
.sc{border:1px solid var(--border-card);border-radius:var(--radius-lg);overflow:hidden}
|
|
9
|
+
.hd{padding:8px 11px 7px}
|
|
10
|
+
.hd b{display:block;font-size:var(--text-xs);font-weight:600;color:var(--text-heading)}
|
|
11
|
+
.hd i{display:block;font-size:var(--text-xs);font-style:normal;color:var(--text-secondary);padding-top:1px}
|
|
12
|
+
.bars{display:flex;height:26px}
|
|
13
|
+
.bars div{flex:1;display:flex;align-items:center;justify-content:center;font-family:var(--font-sans);font-variant-numeric:tabular-nums;font-size:var(--text-xs)}
|
|
14
|
+
.rows{padding:5px 11px 9px}
|
|
15
|
+
.r{display:flex;align-items:center;gap:7px;height:18px;font-size:var(--text-xs);color:var(--text-secondary)}
|
|
16
|
+
.r .h{font-family:var(--font-sans);font-variant-numeric:tabular-nums;font-size:var(--text-xs);color:var(--text-heading);width:62px}
|
|
17
|
+
.foot{font-size:var(--text-xs);color:var(--text-secondary);padding-top:12px;margin-top:11px;border-top:1px solid var(--border-subtle);line-height:1.6}
|
|
18
|
+
.foot b{font-weight:600;color:var(--text-heading)}
|
|
19
|
+
</style></head>
|
|
20
|
+
<body>
|
|
21
|
+
<div class="grid" id="g"></div>
|
|
22
|
+
<div class="foot">Build the UI from <b>Base UI</b>. Blue means “you can click this”. Emerald / amber / red report an outcome — never decoration. Orange, purple, teal, cyan and pink only classify content (node families, labels). White is the only text color on a saturated fill, in both themes.</div>
|
|
23
|
+
<script>
|
|
24
|
+
var C = window.KBColor;
|
|
25
|
+
var schemes = [
|
|
26
|
+
["Base UI", "default surfaces and text", [
|
|
27
|
+
["--bg-app", "app canvas"], ["--bg-surface", "card surface"], ["--border-control", "control border"], ["--text-body", "body text"], ["--text-secondary", "secondary text"]]],
|
|
28
|
+
["Primary action", "rest → hover → press → tint", [
|
|
29
|
+
["--action-primary", "rest"], ["--action-primary-hover", "hover"], ["--action-primary-active", "press"], ["--soft-bg", "tint surface"], ["--focus-border", "focus"]]],
|
|
30
|
+
["Success", "validation passed, run complete", [
|
|
31
|
+
["--success", "solid"], ["--success-bg", "tint"], ["--success-text", "text on tint"]]],
|
|
32
|
+
["Warning", "needs attention, not failed", [
|
|
33
|
+
["--warning", "solid"], ["--warning-bg", "tint"], ["--warning-text", "text on tint"]]],
|
|
34
|
+
["Danger", "failure, destructive action", [
|
|
35
|
+
["--danger", "solid"], ["--danger-bg", "tint"], ["--danger-text", "text on tint"]]],
|
|
36
|
+
["Info", "neutral notice, shares the action hue", [
|
|
37
|
+
["--info-bg", "tint"], ["--info-fg", "text and icon"], ["--soft-border", "border"]]],
|
|
38
|
+
["Node families", "five pipeline categories", [
|
|
39
|
+
["--cat-source", "source"], ["--cat-join", "join"], ["--cat-transform", "transform"], ["--cat-merge", "merge"], ["--cat-output", "output"]]],
|
|
40
|
+
["Dark mode", "surfaces brighten as they nest", [
|
|
41
|
+
["--bg-app", "app canvas"], ["--bg-surface", "card surface"], ["--bg-raised", "raised panel"], ["--text-body", "body text"], ["--action-primary", "action"]]]
|
|
42
|
+
];
|
|
43
|
+
var probe = document.createElement("div");
|
|
44
|
+
probe.setAttribute("data-theme", "dark");
|
|
45
|
+
probe.style.cssText = "position:absolute;left:-9999px";
|
|
46
|
+
document.body.appendChild(probe);
|
|
47
|
+
function dk(n) { var s = document.createElement("span"); s.style.color = "var(" + n + ")"; probe.appendChild(s); var v = getComputedStyle(s).color; s.remove(); return v; }
|
|
48
|
+
var g = document.getElementById("g");
|
|
49
|
+
schemes.forEach(function (sc) {
|
|
50
|
+
var isDark = sc[0] === "Dark mode";
|
|
51
|
+
var read = isDark ? dk : function (n) { return C.token(n); };
|
|
52
|
+
var el = document.createElement("div");
|
|
53
|
+
el.className = "sc";
|
|
54
|
+
var hdBg = isDark ? read("--bg-surface") : "transparent";
|
|
55
|
+
var hdFg = isDark ? read("--text-heading") : "";
|
|
56
|
+
var bars = '<div class="bars">' + sc[2].map(function (r) {
|
|
57
|
+
var v = read(r[0]), b = C.best(v);
|
|
58
|
+
return '<div style="background:' + v + ';color:' + b.color + '" title="' + r[0] + '">' + C.hex(v).toUpperCase().replace("#", "") + '</div>';
|
|
59
|
+
}).join("") + '</div>';
|
|
60
|
+
var rows = '<div class="rows">' + sc[2].map(function (r) {
|
|
61
|
+
var v = read(r[0]);
|
|
62
|
+
return '<div class="r"><span class="h">' + C.hex(v).toUpperCase() + '</span><span>' + r[1] + '</span></div>';
|
|
63
|
+
}).join("") + '</div>';
|
|
64
|
+
el.innerHTML = '<div class="hd"' + (isDark ? ' style="background:' + hdBg + '"' : '') + '><b' + (isDark ? ' style="color:' + hdFg + '"' : '') + '>' + sc[0] + '</b><i>' + sc[1] + '</i></div>' + bars + rows;
|
|
65
|
+
g.appendChild(el);
|
|
66
|
+
});
|
|
67
|
+
</script>
|
|
68
|
+
</body></html>
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
<!-- @dsCard group="Colors" viewport="700x490" name="Transparency" subtitle="Alpha scale — the number is the opacity" -->
|
|
2
|
+
<!DOCTYPE html>
|
|
3
|
+
<html><head><meta charset="utf-8"><script src="../components/_shared/frame-theme.js"></script><link rel="stylesheet" href="../styles.css"><link rel="stylesheet" href="../tokens/hover.css">
|
|
4
|
+
<script src="_color-lab.js"></script>
|
|
5
|
+
<style>
|
|
6
|
+
body{margin:0;padding:16px 18px;font-family:var(--font-sans);background:var(--bg-surface);box-sizing:border-box}
|
|
7
|
+
.lab{font-size:var(--text-xs);font-weight:600;color:var(--text-muted);padding-bottom:7px}
|
|
8
|
+
.lab span{font-weight:400;text-transform:none;letter-spacing:0;color:var(--text-secondary)}
|
|
9
|
+
.row{display:grid;gap:4px;padding-bottom:14px}
|
|
10
|
+
.sw{height:40px;border-radius:5px;border:1px solid var(--border-card);box-sizing:border-box}
|
|
11
|
+
.cap{text-align:center;padding-top:4px;font-family:var(--font-sans);font-variant-numeric:tabular-nums;font-size:var(--text-xs);color:var(--text-secondary)}
|
|
12
|
+
table{border-collapse:collapse;width:100%}
|
|
13
|
+
th{text-align:left;font-size:var(--text-xs);font-weight:600;color:var(--text-muted);padding:0 10px 5px 0;border-bottom:1px solid var(--border-control)}
|
|
14
|
+
td{padding:0 10px 0 0;border-bottom:1px solid var(--border-subtle);font-size:var(--text-xs);color:var(--text-body);height:25px;white-space:nowrap}
|
|
15
|
+
.dot{display:inline-block;width:24px;height:14px;border-radius:3px;vertical-align:-3px;border:1px solid var(--border-card)}
|
|
16
|
+
.mono{font-family:var(--font-sans);font-variant-numeric:tabular-nums;font-size:var(--text-xs);color:var(--text-secondary)}
|
|
17
|
+
.foot{font-size:var(--text-xs);color:var(--text-secondary);padding-top:12px;margin-top:10px;border-top:1px solid var(--border-subtle);line-height:1.6}
|
|
18
|
+
.foot b{font-weight:600;color:var(--text-heading)}
|
|
19
|
+
</style></head>
|
|
20
|
+
<body>
|
|
21
|
+
<div class="lab">Neutral alpha <span>— black in light mode, white in dark</span></div>
|
|
22
|
+
<div class="row" id="n" style="grid-template-columns:repeat(10,1fr)"></div>
|
|
23
|
+
<div class="lab">Brand alpha <span>— selection, drop targets, focus halo</span></div>
|
|
24
|
+
<div class="row" id="b" style="grid-template-columns:repeat(5,1fr);max-width:336px"></div>
|
|
25
|
+
<table id="t">
|
|
26
|
+
<tr><th style="width:34px"></th><th style="width:250px">Used for</th><th style="width:96px">From</th><th>Value</th></tr>
|
|
27
|
+
</table>
|
|
28
|
+
<div class="foot"><b>Alpha or solid?</b> Use alpha when the layer underneath must stay visible — scrims, chips on colored cards, hover over striped rows. Use a solid step when the surface is known and opaque: alpha stacks, and two overlapping washes go muddy. Text on an alpha fill needs 64% or more, and only over a light surface.</div>
|
|
29
|
+
<script>
|
|
30
|
+
var C = window.KBColor;
|
|
31
|
+
function fill(id, prefix, steps) {
|
|
32
|
+
var r = document.getElementById(id);
|
|
33
|
+
steps.forEach(function (s) {
|
|
34
|
+
var v = C.token("--" + prefix + "-alpha-" + s);
|
|
35
|
+
var w = document.createElement("div");
|
|
36
|
+
w.innerHTML = '<div class="sw" style="background:' + v + '"></div><div class="cap">' + s + '%</div>';
|
|
37
|
+
w.title = v;
|
|
38
|
+
r.appendChild(w);
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
fill("n", "neutral", [2, 4, 8, 12, 16, 24, 32, 48, 64, 80]);
|
|
42
|
+
fill("b", "brand", [8, 12, 16, 24, 32]);
|
|
43
|
+
var overlays = [
|
|
44
|
+
["--overlay-hover", "Row or tile hover on an unknown surface", "neutral 4%"],
|
|
45
|
+
["--overlay-press", "Press wash on transparent controls", "neutral 8%"],
|
|
46
|
+
["--overlay-selected", "Selected row, selected canvas node", "brand 8%"],
|
|
47
|
+
["--overlay-drag", "Drop target while a file is dragged over", "brand 12%"],
|
|
48
|
+
["--bg-scrim", "Scrim behind modals and drawers", "neutral 32%"],
|
|
49
|
+
["--border-card", "Card hairline", "grey 60%"]
|
|
50
|
+
];
|
|
51
|
+
var t = document.getElementById("t");
|
|
52
|
+
overlays.forEach(function (o) {
|
|
53
|
+
var v = C.token(o[0]);
|
|
54
|
+
var tr = document.createElement("tr");
|
|
55
|
+
tr.innerHTML = '<td><span class="dot" style="background:' + v + '"></span></td><td>' + o[1] + '</td><td class="mono">' + o[2] + '</td><td class="mono">' + v.replace(/,\s*/g, ", ") + '</td>';
|
|
56
|
+
t.appendChild(tr);
|
|
57
|
+
});
|
|
58
|
+
</script>
|
|
59
|
+
</body></html>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<!-- @dsCard group="Foundations" viewport="700x190" name="Borders & Shadows" subtitle="Hairlines carry the UI; shadows only on canvas nodes" -->
|
|
2
|
+
<!DOCTYPE html>
|
|
3
|
+
<html><head><meta charset="utf-8"><script src="../components/_shared/frame-theme.js"></script><link rel="stylesheet" href="../styles.css"><link rel="stylesheet" href="../tokens/hover.css">
|
|
4
|
+
<style>body{margin:0;padding:16px;font-family:var(--font-sans);background:var(--bg-app);display:grid;grid-template-columns:repeat(4,1fr);gap:10px;box-sizing:border-box}.c{background:var(--bg-surface);border-radius:10px;padding:12px;display:flex;flex-direction:column;gap:8px;justify-content:space-between}.n{font-size:var(--text-xs);font-weight:500;color:var(--text-heading)}.u{font-size:var(--text-xs);font-family:var(--font-sans);font-variant-numeric:tabular-nums;color:var(--text-muted)}.sw{height:56px;border-radius:10px;background:var(--bg-inset)}</style></head>
|
|
5
|
+
<body>
|
|
6
|
+
<div class="c" style="border:1px solid var(--border-card)"><div class="sw" style="border:1px solid var(--border-card)"></div><span class="n">Card hairline</span><span class="u">rgba(229,229,229,.6)</span></div>
|
|
7
|
+
<div class="c" style="border:1px solid var(--border-card)"><div class="sw" style="border:1px solid var(--border-control)"></div><span class="n">Control border</span><span class="u">#e5e5e5 · rows #f5f5f5</span></div>
|
|
8
|
+
<div class="c" style="border:1px solid var(--border-card)"><div class="sw" style="border:1px solid var(--border-control);box-shadow:var(--shadow-node);border-radius:16px"></div><span class="n">Node shadow</span><span class="u">0 1px 3px .1 / 0 1px 2px -1px .1</span></div>
|
|
9
|
+
<div class="c" style="border:1px solid var(--border-card)"><div class="sw" style="border:1px solid var(--selected-border);box-shadow:0 0 0 2px var(--focus-ring);border-radius:16px"></div><span class="n">Selected ring</span><span class="u">#51a2ff + 2px #dbeafe</span></div>
|
|
10
|
+
</body></html>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<!-- @dsCard group="Foundations" viewport="700x180" name="App Chrome Dimensions" subtitle="Fixed panel widths & bar heights" -->
|
|
2
|
+
<!DOCTYPE html>
|
|
3
|
+
<html><head><meta charset="utf-8"><script src="../components/_shared/frame-theme.js"></script><link rel="stylesheet" href="../styles.css"><link rel="stylesheet" href="../tokens/hover.css">
|
|
4
|
+
<style>body{margin:0;padding:16px;font-family:var(--font-sans);background:var(--bg-app);box-sizing:border-box}.wrap{border:1px solid var(--border-card);border-radius:10px;overflow:hidden;display:flex;height:130px;font-size:var(--text-xs);font-family:var(--font-sans);font-variant-numeric:tabular-nums;color:var(--text-muted)}.cell{display:flex;align-items:center;justify-content:center;box-sizing:border-box}.col{display:flex;flex-direction:column;flex:1}</style></head>
|
|
5
|
+
<body>
|
|
6
|
+
<div class="wrap">
|
|
7
|
+
<div class="cell" style="width:38px;background:var(--bg-surface);border-right:1px solid var(--border-card)">64</div>
|
|
8
|
+
<div class="cell" style="width:90px;background:var(--bg-surface);border-right:1px solid var(--border-card)">sidebar 240</div>
|
|
9
|
+
<div class="cell" style="width:90px;background:var(--bg-surface);border-right:1px solid var(--border-card)">palette/tree 240</div>
|
|
10
|
+
<div class="col">
|
|
11
|
+
<div class="cell" style="height:24px;background:var(--bg-surface);border-bottom:1px solid var(--border-card)">top bar 56</div>
|
|
12
|
+
<div class="cell" style="flex:1;background:var(--bg-inset)">canvas / page #fafafa</div>
|
|
13
|
+
<div class="cell" style="height:34px;background:var(--bg-surface);border-top:1px solid var(--border-card)">preview drawer 250</div>
|
|
14
|
+
</div>
|
|
15
|
+
<div class="cell" style="width:120px;background:var(--bg-surface);border-left:1px solid var(--border-card)">config panel 400</div>
|
|
16
|
+
</div>
|
|
17
|
+
</body></html>
|