@keyfunc/keybricks-ds 2.6.0 → 2.7.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/DEPLOY.md +3 -3
- package/DESIGN.md +13 -4
- package/INTEGRATION.md +18 -3
- package/_adherence.oxlintrc.json +57 -11
- package/_ds_bundle.js +2137 -186
- package/_scripts/build-index.mjs +1 -1
- package/_src/icon-index.js +1 -1
- package/assets/icons/icon-index.json +1 -1
- package/changelog.js +11 -1
- package/components/_cards/accordion.card.html +1 -1
- package/components/_cards/action-chip.card.html +1 -1
- package/components/_cards/activity.card.html +1 -1
- package/components/_cards/alert.card.html +1 -1
- package/components/_cards/app-chrome.card.html +1 -1
- package/components/_cards/banner.card.html +1 -1
- package/components/_cards/breadcrumb.card.html +1 -1
- package/components/_cards/button-1-base.card.html +5 -2
- package/components/_cards/button-2-states.card.html +5 -5
- package/components/_cards/button-3-sizes-icons.card.html +2 -2
- package/components/_cards/button-4-group.card.html +2 -2
- package/components/_cards/button-5-ai.card.html +34 -0
- package/components/_cards/canvas-zoom-controls.card.html +1 -1
- package/components/_cards/cards-indicators.card.html +1 -1
- package/components/_cards/charts-1-sparkline.card.html +1 -1
- package/components/_cards/charts-10-gauge.card.html +1 -1
- package/components/_cards/charts-11-funnel.card.html +1 -1
- package/components/_cards/charts-12-treemap.card.html +1 -1
- package/components/_cards/charts-14-radar.card.html +1 -1
- package/components/_cards/charts-15-distribution.card.html +1 -1
- package/components/_cards/charts-16-pareto.card.html +1 -1
- package/components/_cards/charts-17-candlestick.card.html +1 -1
- package/components/_cards/charts-18-sankey.card.html +1 -1
- package/components/_cards/charts-19-chord.card.html +1 -1
- package/components/_cards/charts-2-line.card.html +1 -1
- package/components/_cards/charts-20-sunburst.card.html +1 -1
- package/components/_cards/charts-21-worldmap.card.html +1 -1
- package/components/_cards/charts-22-gantt.card.html +1 -1
- package/components/_cards/charts-23-bar3d.card.html +1 -1
- package/components/_cards/charts-24-pie3d.card.html +1 -1
- package/components/_cards/charts-25-surface3d.card.html +1 -1
- package/components/_cards/charts-26-scatter3d.card.html +1 -1
- package/components/_cards/charts-27-ribbon3d.card.html +1 -1
- package/components/_cards/charts-3-bar.card.html +1 -1
- package/components/_cards/charts-4-barlist.card.html +1 -1
- package/components/_cards/charts-5-donut.card.html +1 -1
- package/components/_cards/charts-6-scatter.card.html +1 -1
- package/components/_cards/charts-7-heatmap.card.html +1 -1
- package/components/_cards/charts-8-waterfall.card.html +1 -1
- package/components/_cards/charts-9-bullet.card.html +1 -1
- package/components/_cards/charts-99-fullpage.card.html +1 -1
- package/components/_cards/checkbox.card.html +1 -1
- package/components/_cards/codeblock.card.html +1 -1
- package/components/_cards/combobox.card.html +1 -1
- package/components/_cards/context-menu.card.html +1 -1
- package/components/_cards/date-picker.card.html +1 -1
- package/components/_cards/diffvalue.card.html +1 -1
- package/components/_cards/divider.card.html +1 -1
- package/components/_cards/drawer.card.html +1 -1
- package/components/_cards/dropdown-menu.card.html +1 -1
- package/components/_cards/dropzone.card.html +1 -1
- package/components/_cards/empty-state.card.html +1 -1
- package/components/_cards/filter-bar.card.html +1 -1
- package/components/_cards/icon-button.card.html +1 -1
- package/components/_cards/icons-0-usage.card.html +2 -2
- package/components/_cards/icons-1-core.card.html +1 -1
- package/components/_cards/icons-2-feather.card.html +1 -1
- package/components/_cards/icons-2b-lucide.card.html +1 -1
- package/components/_cards/icons-3-unicons.card.html +1 -1
- package/components/_cards/icons-4-datasource.card.html +1 -1
- package/components/_cards/input.card.html +1 -1
- package/components/_cards/kbd.card.html +5 -7
- package/components/_cards/keyvalue.card.html +1 -1
- package/components/_cards/listrow.card.html +1 -1
- package/components/_cards/loading.card.html +1 -1
- package/components/_cards/log-viewer.card.html +1 -1
- package/components/_cards/multi-select.card.html +1 -1
- package/components/_cards/number-stepper.card.html +1 -1
- package/components/_cards/pagination.card.html +1 -1
- package/components/_cards/people.card.html +1 -1
- package/components/_cards/pipeline-node.card.html +1 -1
- package/components/_cards/pipeline-palette.card.html +1 -1
- package/components/_cards/radio.card.html +1 -1
- package/components/_cards/relative-time-picker.card.html +1 -1
- package/components/_cards/search-global.card.html +72 -0
- package/components/_cards/search.card.html +1 -1
- package/components/_cards/segmented-control.card.html +1 -1
- package/components/_cards/select.card.html +1 -1
- package/components/_cards/slider.card.html +1 -1
- package/components/_cards/smart-table.card.html +1 -1
- package/components/_cards/spreadsheet.card.html +1 -1
- package/components/_cards/stepper.card.html +1 -1
- package/components/_cards/table.card.html +1 -1
- package/components/_cards/tabs.card.html +1 -1
- package/components/_cards/tag.card.html +1 -1
- package/components/_cards/textarea.card.html +1 -1
- package/components/_cards/timeline.card.html +1 -1
- package/components/_cards/toast.card.html +1 -1
- package/components/_cards/toggles.card.html +1 -1
- package/components/_cards/tooltip.card.html +1 -1
- package/components/_cards/tree.card.html +1 -1
- package/components/_vue/index.mjs +2 -0
- package/components/buttons/Button.d.ts +14 -5
- package/components/buttons/Button.jsx +45 -8
- package/components/buttons/Button.vue +40 -38
- package/components/buttons/Button.vue.d.ts +4 -1
- package/components/buttons/ai-button.js +54 -0
- package/components/buttons/buttons.prompt.md +7 -2
- package/components/display/Kbd.d.ts +3 -1
- package/components/display/Kbd.jsx +8 -3
- package/components/display/Kbd.vue +7 -3
- package/components/display/display.prompt.md +3 -1
- package/components/feedback/Modal.d.ts +7 -0
- package/components/feedback/Modal.jsx +9 -9
- package/components/feedback/Toast.vue +6 -6
- package/components/feedback/feedback.prompt.md +2 -0
- package/components/forms/GlobalSearch.d.ts +83 -0
- package/components/forms/GlobalSearch.jsx +172 -0
- package/components/forms/GlobalSearch.vue +161 -0
- package/components/forms/forms.prompt.md +7 -0
- package/components/forms/global-search.js +161 -0
- package/components/icons/Icon.d.ts +2 -0
- package/components/icons/Icon.jsx +14 -6
- package/components/icons/Icon.vue +11 -4
- package/components/icons/icon-paths.js +4 -2
- package/components/index.d.ts +1 -0
- package/components/index.js +1 -0
- package/components/navigation/TopBar.d.ts +9 -3
- package/components/navigation/TopBar.jsx +5 -7
- package/components/navigation/TopBar.vue +5 -6
- package/covers.js +4 -2
- package/gallery.html +1 -1
- package/guidelines/brand-logo.html +1 -1
- package/guidelines/colors-schemes.html +1 -1
- package/guidelines/colors-transparency.html +1 -1
- package/guidelines/foundations-borders.html +1 -1
- package/guidelines/foundations-chrome.html +1 -1
- package/guidelines/foundations-motion.html +1 -1
- package/guidelines/foundations-size-tiers.html +1 -1
- package/guidelines/foundations-spacing.html +1 -1
- package/guidelines/interaction-states.html +1 -1
- package/guidelines/type-extended.html +1 -1
- package/guidelines/type-mono.html +1 -1
- package/guidelines/type-scale.html +1 -1
- package/guidelines/type-weights.html +1 -1
- package/index.html +8 -8
- package/package.json +2 -2
- package/readme.md +4 -4
- package/readme.zh-CN.md +4 -4
- package/site-nav.js +1 -1
- package/styles.css +1 -0
- package/tokens/ai.css +17 -0
- package/tokens/colors.css +1 -1
- package/tokens/tokens.d.ts +28 -0
- package/tokens/tokens.js +47 -5
- package/tokens/tokens.json +123 -5
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/* GlobalSearch — shared by GlobalSearch.jsx and GlobalSearch.vue: copy, matching, grouping, row model and styles.
|
|
2
|
+
Lengths are strings so the same style objects work in React and Vue. */
|
|
3
|
+
import "../buttons/ai-button.js"; // registers --kb-ai-angle + kb-ai-spin for the Prophet AI tile
|
|
4
|
+
|
|
5
|
+
export const GLOBAL_SEARCH_LABELS = {
|
|
6
|
+
en: {
|
|
7
|
+
field: "Search features, documents, or ask Prophet AI", input: "Search features, documents, data, or ask a question", ask: "Ask Prophet AI", clear: "Clear",
|
|
8
|
+
scopes: ["All", "Features", "Documents", "Data", "Actions"],
|
|
9
|
+
groups: { feature: "Features", document: "Documents", member: "Dimension Members", action: "Actions" },
|
|
10
|
+
recentSearches: "Recent Searches", recent: "Recent", prompts: "Try Asking Prophet AI", viewAll: "View all {n}",
|
|
11
|
+
results: "{n} results", searching: "Searching…", noResults: "No matches. Ask Prophet AI or try Deep Search.",
|
|
12
|
+
askRow: "Ask Prophet AI: “{q}”", askSub: "Answers from documents, models and data you can access",
|
|
13
|
+
deepRow: "Deep Search “{q}”", deepSub: "Multi-step search across document text, model data and logs you can access · about 1 min",
|
|
14
|
+
deepTitle: "Deep Search: {q}", running: "Running · about 1 min", doneStatus: "Done · {t} · {n} citations",
|
|
15
|
+
stepsDone: "Completed {n} steps", stepOf: "Step {i} of {n}", conclusion: "Conclusion", openReport: "Open Full Report", followUp: "Ask Follow-up",
|
|
16
|
+
select: "Select", close: "Close / Back", privacy: "Reads only content you can access",
|
|
17
|
+
},
|
|
18
|
+
zh: {
|
|
19
|
+
field: "搜索功能、文档,或问方知", input: "搜索功能、文档、数据,或直接提问", ask: "问方知", clear: "清除",
|
|
20
|
+
scopes: ["全部", "功能", "文档", "数据", "操作"],
|
|
21
|
+
groups: { feature: "功能", document: "文档", member: "维度成员", action: "操作" },
|
|
22
|
+
recentSearches: "最近搜索", recent: "最近访问", prompts: "试试问方知", viewAll: "查看全部 {n}",
|
|
23
|
+
results: "{n} 个结果", searching: "正在搜索…", noResults: "没有匹配的结果,可以问方知或使用深度搜索。",
|
|
24
|
+
askRow: "问方知:“{q}”", askSub: "基于你有权限的文档、模型和数据作答",
|
|
25
|
+
deepRow: "深度搜索“{q}”", deepSub: "在你有权限的文档正文、模型数据和日志中多步检索 · 约 1 分钟",
|
|
26
|
+
deepTitle: "深度搜索:{q}", running: "进行中 · 约 1 分钟", doneStatus: "已完成 · {t} · {n} 条引用",
|
|
27
|
+
stepsDone: "已完成 {n} 个步骤", stepOf: "第 {i} / {n} 步", conclusion: "结论", openReport: "打开完整报告", followUp: "就此追问",
|
|
28
|
+
select: "选择", close: "关闭 / 返回", privacy: "仅读取你有权限的内容",
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const GS_KINDS = ["feature", "document", "member", "action"];
|
|
33
|
+
const LIMITS = { feature: 4, document: 5, member: 3, action: 2 };
|
|
34
|
+
export const GS_ICONS = { feature: "layout-grid", document: "file-text", member: "database", action: "zap" };
|
|
35
|
+
|
|
36
|
+
export const gsLabels = (labels) => ({ ...GLOBAL_SEARCH_LABELS.en, ...labels, groups: { ...GLOBAL_SEARCH_LABELS.en.groups, ...(labels && labels.groups) } });
|
|
37
|
+
export const gsFill = (s, vars) => String(s).replace(/\{(\w+)\}/g, (_, k) => (vars[k] != null ? vars[k] : ""));
|
|
38
|
+
export const gsIsMac = () => typeof navigator !== "undefined" && /mac|iphone|ipad|ipod/i.test((navigator.userAgentData && navigator.userAgentData.platform) || navigator.platform || navigator.userAgent || "");
|
|
39
|
+
/** The OS's command modifier: ⌘ on macOS, Ctrl elsewhere. */
|
|
40
|
+
export const gsMod = (e, mac) => (mac ? e.metaKey : e.ctrlKey) && !e.altKey;
|
|
41
|
+
|
|
42
|
+
/** Case-insensitive substring on the title, falling back to keywords (path, kind, owner …). */
|
|
43
|
+
export function gsFilter(items, term) {
|
|
44
|
+
const n = term.trim().toLowerCase();
|
|
45
|
+
if (!n) return [];
|
|
46
|
+
return items.filter((it) => String(it.title).toLowerCase().includes(n) || (it.keywords || []).some((k) => String(k).toLowerCase().includes(n)));
|
|
47
|
+
}
|
|
48
|
+
/** [before, match, after] for highlighting the matched substring of a title. */
|
|
49
|
+
export function gsSplit(title, term) {
|
|
50
|
+
const t = String(title), n = (term || "").trim().toLowerCase(), i = n ? t.toLowerCase().indexOf(n) : -1;
|
|
51
|
+
return i < 0 ? [t, "", ""] : [t.slice(0, i), t.slice(i, i + n.length), t.slice(i + n.length)];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Every selectable row in visual order (↑↓ walks this list), with group headers attached to the first row of each group. */
|
|
55
|
+
export function gsRows({ term, found, loading, scope, recent, prompts, deep, hasDeep, L }) {
|
|
56
|
+
const rows = [];
|
|
57
|
+
let total = 0;
|
|
58
|
+
if (deep) return { rows, total };
|
|
59
|
+
if (!term) {
|
|
60
|
+
recent.forEach((item, j) => rows.push({ kind: "recent", item, head: j === 0 ? { label: L.recent } : null }));
|
|
61
|
+
prompts.forEach((text, j) => rows.push({ kind: "prompt", text, head: j === 0 ? { label: L.prompts } : null }));
|
|
62
|
+
} else {
|
|
63
|
+
if (found && !loading) {
|
|
64
|
+
const kinds = scope ? [GS_KINDS[scope - 1]] : GS_KINDS;
|
|
65
|
+
kinds.forEach((k) => {
|
|
66
|
+
const all = found.filter((it) => (it.kind || "feature") === k);
|
|
67
|
+
total += all.length;
|
|
68
|
+
const shown = scope ? all : all.slice(0, LIMITS[k]);
|
|
69
|
+
shown.forEach((item, j) => rows.push({ kind: "result", item, head: j === 0 ? { label: L.groups[k], more: !scope && all.length > shown.length ? { n: all.length, scope: GS_KINDS.indexOf(k) + 1 } : null } : null }));
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
rows.push({ kind: "ask" });
|
|
73
|
+
if (hasDeep) rows.push({ kind: "deep" });
|
|
74
|
+
}
|
|
75
|
+
rows.forEach((r, i) => { r.i = i; });
|
|
76
|
+
return { rows, total };
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** Where the open card goes: 8px left of the collapsed field, 8px from the top, over the TopBar. */
|
|
80
|
+
export function gsPos(el) {
|
|
81
|
+
const vw = window.innerWidth, vh = window.innerHeight, r = el ? el.getBoundingClientRect() : { left: 16 };
|
|
82
|
+
const width = Math.min(720, vw - 16);
|
|
83
|
+
return { left: Math.max(8, Math.min(r.left - 8, vw - width - 8)), width, maxH: vh - 16 };
|
|
84
|
+
}
|
|
85
|
+
/** Keep the selected row visible inside the scrolling body (no scrollIntoView). */
|
|
86
|
+
export function gsReveal(body, i) {
|
|
87
|
+
if (!body) return;
|
|
88
|
+
const el = body.querySelector('[data-gs-row="' + i + '"]');
|
|
89
|
+
if (!el) return;
|
|
90
|
+
const top = el.offsetTop - body.offsetTop, bottom = top + el.offsetHeight;
|
|
91
|
+
if (top < body.scrollTop) body.scrollTop = top - 6;
|
|
92
|
+
else if (bottom > body.scrollTop + body.clientHeight) body.scrollTop = bottom - body.clientHeight + 6;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const T = (s) => ({ fontFamily: "var(--font-sans)", fontSize: "var(--text-" + s + ")", lineHeight: "var(--leading-" + s + ")", letterSpacing: "var(--tracking-" + s + ")" });
|
|
96
|
+
const ONE = { whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" };
|
|
97
|
+
const FADE = "opacity 300ms var(--ease-out)";
|
|
98
|
+
const tileBase = { width: "32px", height: "32px", flexShrink: "0", display: "flex", alignItems: "center", justifyContent: "center", borderRadius: "var(--radius-md)", border: "1px solid var(--border-card)", background: "var(--bg-surface)", color: "var(--text-secondary)", boxSizing: "border-box" };
|
|
99
|
+
|
|
100
|
+
export const gsStyles = {
|
|
101
|
+
/* Collapsed field: SearchInput's box (surface fill, --border-control hairline, r8). GlobalSearch exception: the placeholder is
|
|
102
|
+
--text-secondary (≥4.5:1, it is the platform's main entry prompt) and hover also fills --bg-inset; border darkens via [data-field]. */
|
|
103
|
+
field: (hover) => ({ display: "inline-flex", alignItems: "center", gap: "8px", minWidth: "400px", width: "max-content", maxWidth: "100%", height: "32px", padding: "0 6px 0 10px", boxSizing: "border-box", borderRadius: "var(--radius-md)", background: hover ? "var(--bg-inset)" : "var(--bg-surface)", border: "1px solid var(--field-border, var(--border-control))", cursor: "pointer", transition: "var(--t-hover)", ...T("base"), color: "var(--text-secondary)", textAlign: "left", flexShrink: "1" }),
|
|
104
|
+
fieldIcon: { display: "inline-flex", color: "var(--text-muted)", flexShrink: "0" },
|
|
105
|
+
fieldLabel: { flex: "1 0 auto", paddingRight: "8px", whiteSpace: "nowrap" },
|
|
106
|
+
scrim: { position: "fixed", inset: "0", background: "var(--bg-scrim)", zIndex: "var(--z-modal)", animation: "kb-fade-in var(--dur) var(--ease-out)" },
|
|
107
|
+
card: { display: "flex", flexDirection: "column", width: "720px", maxWidth: "100%", background: "var(--bg-raised)", border: "1px solid var(--border-card)", borderRadius: "var(--radius-lg)", boxShadow: "var(--shadow-modal)", overflow: "hidden", boxSizing: "border-box", color: "var(--text-body)", textAlign: "left" },
|
|
108
|
+
cardFixed: (p) => ({ position: "fixed", top: "8px", left: p.left + "px", width: p.width + "px", maxHeight: p.maxH + "px", zIndex: "var(--z-modal)", animation: "kb-rise var(--dur-slow) var(--ease-out)" }),
|
|
109
|
+
inputRow: { display: "flex", alignItems: "center", gap: "10px", height: "56px", padding: "0 16px", borderBottom: "1px solid var(--border-subtle)", flexShrink: "0", boxSizing: "border-box" },
|
|
110
|
+
lead: { display: "inline-flex", width: "16px", height: "16px", alignItems: "center", justifyContent: "center", color: "var(--text-secondary)", flexShrink: "0" },
|
|
111
|
+
input: { flex: "1 1 auto", minWidth: "0", border: "none", outline: "none", background: "transparent", padding: "0", ...T("md"), color: "var(--text-heading)" },
|
|
112
|
+
trail: { display: "flex", alignItems: "center", gap: "8px", flexShrink: "0" },
|
|
113
|
+
scope: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: "12px", padding: "10px 16px", borderBottom: "1px solid var(--border-subtle)", flexShrink: "0" },
|
|
114
|
+
count: { ...T("xs"), color: "var(--text-muted)", whiteSpace: "nowrap" },
|
|
115
|
+
body: { flex: "1 1 auto", minHeight: "0", overflowY: "auto", padding: "6px", position: "relative" },
|
|
116
|
+
head: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: "8px", padding: "8px 10px 4px", ...T("xs"), fontWeight: "var(--weight-medium)", color: "var(--text-muted)" },
|
|
117
|
+
more: { border: "none", background: "transparent", padding: "0", cursor: "pointer", ...T("xs"), color: "var(--link)" },
|
|
118
|
+
row: (on) => ({ display: "flex", alignItems: "center", gap: "10px", minHeight: "44px", padding: "6px 10px", boxSizing: "border-box", borderRadius: "var(--radius-md)", background: on ? "var(--bg-hover)" : "transparent", cursor: "pointer" }),
|
|
119
|
+
tile: (tone) => ({ ...tileBase, ...(tone ? { background: "var(--cat-" + tone + "-bg)", color: "var(--cat-" + tone + ")" } : null) }),
|
|
120
|
+
text: { display: "flex", flexDirection: "column", minWidth: "0", flex: "1 1 auto" },
|
|
121
|
+
title: { ...T("base"), ...ONE, color: "var(--text-heading)" },
|
|
122
|
+
mark: { color: "var(--action-primary)", fontWeight: "var(--weight-medium)" },
|
|
123
|
+
sub: { ...T("xs"), ...ONE, color: "var(--text-secondary)" },
|
|
124
|
+
meta: { ...T("xs"), color: "var(--text-muted)", whiteSpace: "nowrap", flexShrink: "0" },
|
|
125
|
+
chips: { display: "flex", flexWrap: "wrap", gap: "8px", padding: "4px 10px 8px" },
|
|
126
|
+
chip: { display: "inline-flex", alignItems: "center", gap: "6px", height: "28px", padding: "0 10px", borderRadius: "var(--radius-md)", border: "1px solid var(--border-control)", background: "var(--bg-surface)", cursor: "pointer", ...T("xs"), color: "var(--text-body)", boxSizing: "border-box" },
|
|
127
|
+
chipIcon: { display: "inline-flex", color: "var(--text-muted)" },
|
|
128
|
+
empty: { padding: "12px 10px", ...T("base"), color: "var(--text-secondary)" },
|
|
129
|
+
skelRow: { display: "flex", alignItems: "center", gap: "10px", minHeight: "44px", padding: "6px 10px", boxSizing: "border-box" },
|
|
130
|
+
skelText: { display: "flex", flexDirection: "column", gap: "6px", flex: "1 1 auto" },
|
|
131
|
+
pinned: { borderTop: "1px solid var(--border-subtle)", padding: "6px", flexShrink: "0" },
|
|
132
|
+
footer: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: "16px", height: "36px", padding: "0 16px", borderTop: "1px solid var(--border-subtle)", background: "var(--bg-surface)", flexShrink: "0", boxSizing: "border-box", ...T("xs"), color: "var(--text-secondary)", whiteSpace: "nowrap" },
|
|
133
|
+
hints: { display: "flex", alignItems: "center", gap: "16px" },
|
|
134
|
+
hint: { display: "inline-flex", alignItems: "center", gap: "6px" },
|
|
135
|
+
deep: { display: "flex", flexDirection: "column", gap: "12px", padding: "12px 16px" },
|
|
136
|
+
deepHead: { display: "flex", alignItems: "center", gap: "10px" },
|
|
137
|
+
deepTitle: { ...T("base"), ...ONE, fontWeight: "var(--weight-medium)", color: "var(--text-heading)" },
|
|
138
|
+
steps: { display: "flex", flexDirection: "column", gap: "2px" },
|
|
139
|
+
toggle: { display: "flex", alignItems: "center", gap: "8px", width: "100%", minHeight: "28px", padding: "0 6px", borderRadius: "var(--radius-md)", border: "none", background: "var(--wash, transparent)", cursor: "pointer", ...T("xs"), color: "var(--text-body)", textAlign: "left", boxSizing: "border-box" },
|
|
140
|
+
stepLine: { display: "flex", alignItems: "center", gap: "8px", minHeight: "24px", padding: "0 6px", ...T("xs") },
|
|
141
|
+
stepIcon: { width: "14px", height: "14px", display: "inline-flex", alignItems: "center", justifyContent: "center", flexShrink: "0" },
|
|
142
|
+
pending: { width: "8px", height: "8px", borderRadius: "var(--radius-full)", border: "1.5px solid var(--border-strong)", boxSizing: "border-box" },
|
|
143
|
+
muted: { color: "var(--text-muted)" },
|
|
144
|
+
grow: { flex: "1 1 auto" },
|
|
145
|
+
conclusion: { display: "flex", flexDirection: "column", gap: "6px", padding: "12px 14px", borderRadius: "var(--radius-lg)", background: "var(--bg-inset)", border: "1px solid var(--border-card)" },
|
|
146
|
+
concLabel: { ...T("xs"), fontWeight: "var(--weight-medium)", color: "var(--text-secondary)" },
|
|
147
|
+
concText: { display: "flex", flexDirection: "column", gap: "4px", ...T("base"), color: "var(--text-body)", textWrap: "pretty" },
|
|
148
|
+
sources: { display: "flex", flexWrap: "wrap", gap: "6px" },
|
|
149
|
+
source: { display: "inline-flex", alignItems: "center", gap: "4px", height: "24px", padding: "0 8px", borderRadius: "var(--radius-sm)", border: "1px solid var(--border-control)", background: "var(--bg-surface)", ...T("xs"), color: "var(--text-body)", boxSizing: "border-box", whiteSpace: "nowrap" },
|
|
150
|
+
actions: { display: "flex", gap: "8px", marginTop: "6px" },
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
/** The 32px Prophet AI tile: hairline tile at rest; selected, it takes the AI hover language (tint, gradient ring at hover speed, gradient glyph), never a glow. */
|
|
154
|
+
export function gsAiTile(on) {
|
|
155
|
+
return {
|
|
156
|
+
outer: { width: "32px", height: "32px", flexShrink: "0", display: "flex", padding: "1px", boxSizing: "border-box", borderRadius: "var(--radius-md)", background: on ? "conic-gradient(from var(--kb-ai-angle), var(--ai-gradient-stops))" : "var(--border-card)", animation: on ? "kb-ai-spin var(--ai-spin-hover) linear infinite" : "none" },
|
|
157
|
+
inner: { position: "relative", flex: "1 1 auto", display: "flex", alignItems: "center", justifyContent: "center", borderRadius: "calc(var(--radius-md) - 1px)", background: "var(--bg-surface)", overflow: "hidden", color: "var(--text-secondary)" },
|
|
158
|
+
tint: { position: "absolute", inset: "0", pointerEvents: "none", background: "linear-gradient(90deg, color-mix(in srgb, var(--ai-gradient-start) var(--ai-tint), transparent), color-mix(in srgb, var(--ai-gradient-end) var(--ai-tint), transparent))", opacity: on ? "1" : "0", transition: FADE },
|
|
159
|
+
icon: { position: "relative" },
|
|
160
|
+
};
|
|
161
|
+
}
|
|
@@ -11,6 +11,8 @@ export interface IconProps {
|
|
|
11
11
|
strokeWidth?: number;
|
|
12
12
|
/** Overrides currentColor */
|
|
13
13
|
color?: string;
|
|
14
|
+
/** Strokes the glyph with the AI gradient (--ai-gradient-start → --ai-gradient-end). Prophet AI entry points only; pass [from, to] to override. */
|
|
15
|
+
gradient?: boolean | [string, string];
|
|
14
16
|
style?: React.CSSProperties;
|
|
15
17
|
className?: string;
|
|
16
18
|
}
|
|
@@ -88,8 +88,8 @@ export const ICON_PATHS = {
|
|
|
88
88
|
"time-future": '<path d="M20 6A10 10 0 1 0 22 12"/><path d="M12 7v5h5"/><path d="M21 2v5h-5"/>',
|
|
89
89
|
"time-restatement": '<path d="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"/><path d="M3 3v5h5"/><path d="M12 7v5l4 2"/>',
|
|
90
90
|
// AI glyphs (2.3.0) — traced from the two reference glyphs, redrawn to core rules (stroke 2, no fill, integer endpoints, >=4 between separate elements)
|
|
91
|
-
ai: '<path d="M9
|
|
92
|
-
"ai-sparkles": '<path d="M9
|
|
91
|
+
ai: '<path d="M9 3H7a4 4 0 0 0-4 4v10a4 4 0 0 0 4 4h10a4 4 0 0 0 4-4v-2"/><path d="M16 2c.72 3.6 2.4 5.28 6 6c-3.6.72-5.28 2.4-6 6c-.72-3.6-2.4-5.28-6-6c3.6-.72 5.28-2.4 6-6Z"/><path d="M9 12c.6 1.5 1.5 2.4 3 3c-1.5.6-2.4 1.5-3 3c-.6-1.5-1.5-2.4-3-3c1.5-.6 2.4-1.5 3-3Z"/>',
|
|
92
|
+
"ai-sparkles": '<path d="M9 2c.84 4.2 2.8 6.16 7 7c-4.2.84-6.16 2.8-7 7c-.84-4.2-2.8-6.16-7-7c4.2-.84 6.16-2.8 7-7Z"/><path d="M17 13c.8 2 2 3.2 4 4c-2 .8-3.2 2-4 4c-.8-2-2-3.2-4-4c2-.8 3.2-2 4-4Z"/>',
|
|
93
93
|
// Keybricks business glyphs (2.4.6) — dimensions, modules, rules-*, task-*; drawn to core rules or taken from Lucide
|
|
94
94
|
"dimension-account": '<path d="M12 7v14"/><path d="M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z"/><path d="M5 8h3"/><path d="M5 11h3"/><path d="M5 14h3"/><path d="M17 6.5v1"/><path d="M17 12.5v1"/><path d="M18.5 7.5h-2a1.25 1.25 0 0 0 0 2.5h1a1.25 1.25 0 0 1 0 2.5h-2"/>',
|
|
95
95
|
"dimension-audit": '<path d="M11.1 22H6a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.706.706l3.589 3.588A2.4 2.4 0 0 1 20 8v3.25"/><path d="M14 2v5a1 1 0 0 0 1 1h5"/><path d="m21 22-2.88-2.88"/><circle cx="16" cy="17" r="3"/>',
|
|
@@ -167,16 +167,24 @@ export const ICON_PATHS = {
|
|
|
167
167
|
"task-shared": '<rect width="8" height="4" x="8" y="2" rx="1"/><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"/><g transform="translate(-.5 4)"><circle cx="15.3" cy="6.8" r=".75"/><circle cx="9.7" cy="10" r=".75"/><circle cx="15.3" cy="13.2" r=".75"/><path d="m11.35 9.06 2.3-1.32"/><path d="m11.35 10.94 2.3 1.32"/></g>',
|
|
168
168
|
"task-intercompany": '<rect width="8" height="4" x="8" y="2" rx="1"/><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"/><g transform="translate(-.5 4)"><path d="M8.5 14V6.5a1 1 0 0 1 1-1h3a1 1 0 0 1 1 1V14"/><path d="M13.5 9.5H16a1 1 0 0 1 1 1V14"/><path d="M7.5 14h10"/><path d="M11 8.5h.01"/><path d="M11 11h.01"/></g>',
|
|
169
169
|
ownership: '<path d="M11 15h2a2 2 0 1 0 0-4h-3c-.6 0-1.1.2-1.4.6L3 17"/><path d="m7 21 1.6-1.4c.3-.4.8-.6 1.4-.6h4c1.1 0 2.1-.4 2.8-1.2l4.6-4.4a2 2 0 0 0-2.75-2.91l-4.2 3.9"/><path d="m2 16 6 6"/><circle cx="9" cy="5" r="3"/><path d="M12 5h9"/><path d="M18 5v2.5"/><path d="M21 5v2"/>',
|
|
170
|
+
prophet: '<path d="M5.66 13.5A7.5 7.5 0 1 1 18.34 13.5"/><path d="M8.5 10a3.5 3.5 0 0 1 7 0v1.5c0 3.2-1.5 5.6-3.5 7.5c-2-1.9-3.5-4.3-3.5-7.5Z"/><path d="M8.71 13.5c1.05.95 2.15 1.4 3.29 1.4s2.24-.45 3.29-1.4"/><path d="M3.5 22a5.5 5.5 0 0 1 4-5.3"/><path d="M20.5 22a5.5 5.5 0 0 0-4-5.3"/>',
|
|
171
|
+
"prophet-sparkle": '<path d="M5.66 13.5A7.5 7.5 0 0 1 13.24 2.1"/><path d="M19 2c.36 1.8 1.2 2.64 3 3c-1.8.36-2.64 1.2-3 3c-.36-1.8-1.2-2.64-3-3c1.8-.36 2.64-1.2 3-3Z"/><path d="M8.5 10a3.5 3.5 0 0 1 7 0v1.5c0 3.2-1.5 5.6-3.5 7.5c-2-1.9-3.5-4.3-3.5-7.5Z"/><path d="M8.71 13.5c1.05.95 2.15 1.4 3.29 1.4s2.24-.45 3.29-1.4"/><path d="M3.5 22a5.5 5.5 0 0 1 4-5.3"/><path d="M20.5 22a5.5 5.5 0 0 0-4-5.3"/>',
|
|
170
172
|
};
|
|
171
173
|
|
|
172
174
|
import { FEATHER_PATHS } from "./feather-paths.js";
|
|
173
175
|
|
|
174
|
-
/**
|
|
175
|
-
export
|
|
176
|
-
|
|
176
|
+
/** Stroke gradient for the AI glyph treatment — bottom-left start to top-right end, in glyph space so every path shares it. */
|
|
177
|
+
export const iconGradientDefs = (id, from = "var(--ai-gradient-start)", to = "var(--ai-gradient-end)") =>
|
|
178
|
+
'<defs><linearGradient id="' + id + '" gradientUnits="userSpaceOnUse" x1="2" y1="22" x2="22" y2="2"><stop offset="0" style="stop-color:' + from + '"/><stop offset="1" style="stop-color:' + to + '"/></linearGradient></defs>';
|
|
179
|
+
|
|
180
|
+
/** Lucide-style stroke icon. name: key of ICON_PATHS (core set) or any Feather icon name (feather-paths.js fallback); size in px; strokeWidth defaults to 2 (24-grid). gradient: true strokes it with the AI gradient (Prophet AI entry points only), or pass [from, to]. Browse both sets with keywords in the Icon Gallery card. */
|
|
181
|
+
export function Icon({ name, size = 16, strokeWidth = 2, color, gradient, style, className }) {
|
|
182
|
+
const gid = "kb-ig" + React.useId().replace(/[^a-zA-Z0-9]/g, "");
|
|
183
|
+
let body = ICON_PATHS[name] || FEATHER_PATHS[name] || "";
|
|
184
|
+
if (gradient) body = (Array.isArray(gradient) ? iconGradientDefs(gid, gradient[0], gradient[1]) : iconGradientDefs(gid)) + body;
|
|
177
185
|
return (
|
|
178
186
|
<svg
|
|
179
|
-
width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
|
187
|
+
width={size} height={size} viewBox="0 0 24 24" fill="none" stroke={gradient ? "url(#" + gid + ")" : "currentColor"}
|
|
180
188
|
strokeWidth={strokeWidth} strokeLinecap="round" strokeLinejoin="round"
|
|
181
189
|
className={className}
|
|
182
190
|
style={{ display: "block", flexShrink: 0, color, ...style }}
|
|
@@ -1,12 +1,19 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
let kbIconSeq = 0
|
|
3
|
+
</script>
|
|
1
4
|
<script setup>
|
|
2
5
|
// Keybricks icon set — Lucide stroke glyphs (24-grid, stroke 2, round caps/joins, currentColor), rendered at 14/16px.
|
|
3
6
|
// Full path dictionary mirrors icons/Icon.jsx's ICON_PATHS (81 entries) — see that file for the complete list.
|
|
7
|
+
// gradient: true strokes the glyph with the AI gradient (Prophet AI entry points only), or pass [from, to].
|
|
8
|
+
import { computed } from 'vue'
|
|
4
9
|
import { VUE_ICON_PATHS } from './icon-paths.js'
|
|
5
10
|
import { FEATHER_PATHS } from './feather-paths.js'
|
|
6
|
-
const props = defineProps({ name: String, size: { type: Number, default: 16 }, strokeWidth: { type: Number, default: 2 }, color: String, style: Object })
|
|
7
|
-
const
|
|
11
|
+
const props = defineProps({ name: String, size: { type: Number, default: 16 }, strokeWidth: { type: Number, default: 2 }, color: String, gradient: [Boolean, Array], style: Object })
|
|
12
|
+
const gid = 'kb-ig-v' + (++kbIconSeq)
|
|
13
|
+
const defs = (from = 'var(--ai-gradient-start)', to = 'var(--ai-gradient-end)') => '<defs><linearGradient id="' + gid + '" gradientUnits="userSpaceOnUse" x1="2" y1="22" x2="22" y2="2"><stop offset="0" style="stop-color:' + from + '"/><stop offset="1" style="stop-color:' + to + '"/></linearGradient></defs>'
|
|
14
|
+
const body = computed(() => { const b = VUE_ICON_PATHS[props.name] || FEATHER_PATHS[props.name] || ''; return props.gradient ? (Array.isArray(props.gradient) ? defs(props.gradient[0], props.gradient[1]) : defs()) + b : b })
|
|
8
15
|
</script>
|
|
9
16
|
<template>
|
|
10
|
-
<svg :width="size" :height="size" viewBox="0 0 24 24" fill="none" stroke="currentColor" :stroke-width="strokeWidth" stroke-linecap="round" stroke-linejoin="round"
|
|
11
|
-
:style="{ display: 'block', flexShrink: 0, color, ...style }" v-html="body
|
|
17
|
+
<svg :width="size" :height="size" viewBox="0 0 24 24" fill="none" :stroke="gradient ? 'url(#' + gid + ')' : 'currentColor'" :stroke-width="strokeWidth" stroke-linecap="round" stroke-linejoin="round"
|
|
18
|
+
:style="{ display: 'block', flexShrink: 0, color, ...style }" v-html="body" />
|
|
12
19
|
</template>
|
|
@@ -83,8 +83,8 @@ export const VUE_ICON_PATHS = {
|
|
|
83
83
|
"time-future": '<path d="M20 6A10 10 0 1 0 22 12"/><path d="M12 7v5h5"/><path d="M21 2v5h-5"/>',
|
|
84
84
|
"time-restatement": '<path d="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"/><path d="M3 3v5h5"/><path d="M12 7v5l4 2"/>',
|
|
85
85
|
// AI glyphs (2.3.0) — traced from the two reference glyphs, redrawn to core rules (stroke 2, no fill, integer endpoints, >=4 between separate elements)
|
|
86
|
-
ai: '<path d="M9
|
|
87
|
-
"ai-sparkles": '<path d="M9
|
|
86
|
+
ai: '<path d="M9 3H7a4 4 0 0 0-4 4v10a4 4 0 0 0 4 4h10a4 4 0 0 0 4-4v-2"/><path d="M16 2c.72 3.6 2.4 5.28 6 6c-3.6.72-5.28 2.4-6 6c-.72-3.6-2.4-5.28-6-6c3.6-.72 5.28-2.4 6-6Z"/><path d="M9 12c.6 1.5 1.5 2.4 3 3c-1.5.6-2.4 1.5-3 3c-.6-1.5-1.5-2.4-3-3c1.5-.6 2.4-1.5 3-3Z"/>',
|
|
87
|
+
"ai-sparkles": '<path d="M9 2c.84 4.2 2.8 6.16 7 7c-4.2.84-6.16 2.8-7 7c-.84-4.2-2.8-6.16-7-7c4.2-.84 6.16-2.8 7-7Z"/><path d="M17 13c.8 2 2 3.2 4 4c-2 .8-3.2 2-4 4c-.8-2-2-3.2-4-4c2-.8 3.2-2 4-4Z"/>',
|
|
88
88
|
// Keybricks business glyphs (2.4.6) — dimensions, modules, rules-*, task-*; drawn to core rules or taken from Lucide
|
|
89
89
|
"dimension-account": '<path d="M12 7v14"/><path d="M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z"/><path d="M5 8h3"/><path d="M5 11h3"/><path d="M5 14h3"/><path d="M17 6.5v1"/><path d="M17 12.5v1"/><path d="M18.5 7.5h-2a1.25 1.25 0 0 0 0 2.5h1a1.25 1.25 0 0 1 0 2.5h-2"/>',
|
|
90
90
|
"dimension-audit": '<path d="M11.1 22H6a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.706.706l3.589 3.588A2.4 2.4 0 0 1 20 8v3.25"/><path d="M14 2v5a1 1 0 0 0 1 1h5"/><path d="m21 22-2.88-2.88"/><circle cx="16" cy="17" r="3"/>',
|
|
@@ -162,4 +162,6 @@ export const VUE_ICON_PATHS = {
|
|
|
162
162
|
"task-shared": '<rect width="8" height="4" x="8" y="2" rx="1"/><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"/><g transform="translate(-.5 4)"><circle cx="15.3" cy="6.8" r=".75"/><circle cx="9.7" cy="10" r=".75"/><circle cx="15.3" cy="13.2" r=".75"/><path d="m11.35 9.06 2.3-1.32"/><path d="m11.35 10.94 2.3 1.32"/></g>',
|
|
163
163
|
"task-intercompany": '<rect width="8" height="4" x="8" y="2" rx="1"/><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"/><g transform="translate(-.5 4)"><path d="M8.5 14V6.5a1 1 0 0 1 1-1h3a1 1 0 0 1 1 1V14"/><path d="M13.5 9.5H16a1 1 0 0 1 1 1V14"/><path d="M7.5 14h10"/><path d="M11 8.5h.01"/><path d="M11 11h.01"/></g>',
|
|
164
164
|
ownership: '<path d="M11 15h2a2 2 0 1 0 0-4h-3c-.6 0-1.1.2-1.4.6L3 17"/><path d="m7 21 1.6-1.4c.3-.4.8-.6 1.4-.6h4c1.1 0 2.1-.4 2.8-1.2l4.6-4.4a2 2 0 0 0-2.75-2.91l-4.2 3.9"/><path d="m2 16 6 6"/><circle cx="9" cy="5" r="3"/><path d="M12 5h9"/><path d="M18 5v2.5"/><path d="M21 5v2"/>',
|
|
165
|
+
prophet: '<path d="M5.66 13.5A7.5 7.5 0 1 1 18.34 13.5"/><path d="M8.5 10a3.5 3.5 0 0 1 7 0v1.5c0 3.2-1.5 5.6-3.5 7.5c-2-1.9-3.5-4.3-3.5-7.5Z"/><path d="M8.71 13.5c1.05.95 2.15 1.4 3.29 1.4s2.24-.45 3.29-1.4"/><path d="M3.5 22a5.5 5.5 0 0 1 4-5.3"/><path d="M20.5 22a5.5 5.5 0 0 0-4-5.3"/>',
|
|
166
|
+
"prophet-sparkle": '<path d="M5.66 13.5A7.5 7.5 0 0 1 13.24 2.1"/><path d="M19 2c.36 1.8 1.2 2.64 3 3c-1.8.36-2.64 1.2-3 3c-.36-1.8-1.2-2.64-3-3c1.8-.36 2.64-1.2 3-3Z"/><path d="M8.5 10a3.5 3.5 0 0 1 7 0v1.5c0 3.2-1.5 5.6-3.5 7.5c-2-1.9-3.5-4.3-3.5-7.5Z"/><path d="M8.71 13.5c1.05.95 2.15 1.4 3.29 1.4s2.24-.45 3.29-1.4"/><path d="M3.5 22a5.5 5.5 0 0 1 4-5.3"/><path d="M20.5 22a5.5 5.5 0 0 0-4-5.3"/>',
|
|
165
167
|
};
|
package/components/index.d.ts
CHANGED
|
@@ -61,6 +61,7 @@ export * from "./forms/Combobox";
|
|
|
61
61
|
export * from "./forms/DatePicker";
|
|
62
62
|
export * from "./forms/Dropzone";
|
|
63
63
|
export * from "./forms/Field";
|
|
64
|
+
export * from "./forms/GlobalSearch";
|
|
64
65
|
export * from "./forms/Input";
|
|
65
66
|
export * from "./forms/MultiSelect";
|
|
66
67
|
export * from "./forms/NumberStepper";
|
package/components/index.js
CHANGED
|
@@ -76,6 +76,7 @@ export { Combobox } from "./forms/Combobox.jsx";
|
|
|
76
76
|
export { DatePicker } from "./forms/DatePicker.jsx";
|
|
77
77
|
export { Dropzone } from "./forms/Dropzone.jsx";
|
|
78
78
|
export { Field } from "./forms/Field.jsx";
|
|
79
|
+
export { GLOBAL_SEARCH_LABELS, GlobalSearch } from "./forms/GlobalSearch.jsx";
|
|
79
80
|
export { Input, Textarea } from "./forms/Input.jsx";
|
|
80
81
|
export { MultiSelect } from "./forms/MultiSelect.jsx";
|
|
81
82
|
export { NumberStepper } from "./forms/NumberStepper.jsx";
|
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
|
|
2
|
+
import type { GlobalSearchProps } from "../forms/GlobalSearch";
|
|
3
|
+
/** 56px top bar: GlobalSearch left (⌘K / Ctrl K); notifications, help and the user trigger right. The trigger opens a UserMenu. Prophet AI is reached through the search card (Button variant="ai"), not a separate pill. */
|
|
3
4
|
export interface TopBarProps {
|
|
5
|
+
/** Collapsed search field text (default GlobalSearch labels.field) */
|
|
4
6
|
placeholder?: string;
|
|
5
|
-
/** Receives the
|
|
7
|
+
/** Receives the query as the user types */
|
|
6
8
|
onSearch?: (value: string) => void;
|
|
9
|
+
/** Props for the GlobalSearch (items / onQuery, recent, prompts, onSelect, onDeepSearch, labels …) */
|
|
10
|
+
search?: GlobalSearchProps;
|
|
7
11
|
/** Replaces the whole right-hand group */
|
|
8
12
|
actions?: React.ReactNode;
|
|
13
|
+
/** Overrides the "Ask Prophet AI" label (same as search.labels.ask) */
|
|
9
14
|
aiLabel?: string;
|
|
10
|
-
|
|
15
|
+
/** Prophet AI hand-off: called with the question when any AI entry in the search card is used */
|
|
16
|
+
onAi?: (question: string) => void;
|
|
11
17
|
onNotifications?: () => void;
|
|
12
18
|
onHelp?: () => void;
|
|
13
19
|
notificationsLabel?: string;
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { Icon } from "../icons/Icon.jsx";
|
|
3
3
|
import { IconButton } from "../buttons/IconButton.jsx";
|
|
4
|
-
import {
|
|
5
|
-
import { SearchInput } from "../forms/SearchInput.jsx";
|
|
4
|
+
import { GlobalSearch } from "../forms/GlobalSearch.jsx";
|
|
6
5
|
import { Avatar } from "../display/Avatar.jsx";
|
|
7
6
|
import { SegmentedControl } from "../tabs/SegmentedControl.jsx";
|
|
8
7
|
import { ContextMenu } from "../feedback/ContextMenu.jsx";
|
|
@@ -33,9 +32,9 @@ export function UserMenu({ name, email, theme, onThemeChange, themeOptions = THE
|
|
|
33
32
|
);
|
|
34
33
|
}
|
|
35
34
|
|
|
36
|
-
/** 56px top bar:
|
|
37
|
-
* The user trigger opens a UserMenu below it (closes on outside click). actions replaces the right-hand group entirely. */
|
|
38
|
-
export function TopBar({ placeholder
|
|
35
|
+
/** 56px top bar: GlobalSearch on the left (⌘K / Ctrl K, Prophet AI hand-off via onAi); notifications, help and the user trigger on the right.
|
|
36
|
+
* The user trigger opens a UserMenu below it (closes on outside click). actions replaces the right-hand group entirely. search passes props to GlobalSearch. */
|
|
37
|
+
export function TopBar({ placeholder, onSearch, search, actions, aiLabel, onAi, onNotifications, onHelp, notificationsLabel = "Notifications", helpLabel = "Help", user, userMenu, style }) {
|
|
39
38
|
const [open, setOpen] = React.useState(false);
|
|
40
39
|
const ref = React.useRef(null);
|
|
41
40
|
React.useEffect(() => {
|
|
@@ -48,10 +47,9 @@ export function TopBar({ placeholder = "Search documents, workflows, data...", o
|
|
|
48
47
|
const [hover, setHover] = React.useState(false);
|
|
49
48
|
return (
|
|
50
49
|
<header style={{ height: "var(--topbar-h)", background: "var(--bg-surface)", borderBottom: "1px solid var(--border-card)", display: "flex", alignItems: "center", justifyContent: "space-between", gap: 16, padding: "0 24px", boxSizing: "border-box", flexShrink: 0, minWidth: 0, position: "relative", ...style }}>
|
|
51
|
-
<
|
|
50
|
+
<GlobalSearch placeholder={placeholder} onInput={onSearch} onAsk={onAi} {...search} labels={aiLabel ? { ...(search && search.labels), ask: aiLabel } : search && search.labels} />
|
|
52
51
|
<div ref={ref} style={{ display: "flex", alignItems: "center", gap: 8, flexShrink: 0 }}>
|
|
53
52
|
{actions || (<>
|
|
54
|
-
<Button variant="dark" icon="ai" onClick={onAi}>{aiLabel}</Button>
|
|
55
53
|
<IconButton icon="bell" label={notificationsLabel} title={notificationsLabel} onClick={onNotifications} />
|
|
56
54
|
<IconButton icon="circle-help" label={helpLabel} title={helpLabel} onClick={onHelp} />
|
|
57
55
|
{user ? <div role="button" tabIndex={0} aria-haspopup="menu" aria-expanded={open} onClick={() => setOpen(!open)} onKeyDown={(e) => { if (e.key === "Enter" || e.key === " ") { e.preventDefault(); setOpen(!open); } }} onMouseEnter={() => setHover(true)} onMouseLeave={() => setHover(false)}
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
import { ref, onMounted, onUnmounted } from 'vue'
|
|
3
3
|
import Icon from '../icons/Icon.vue'
|
|
4
4
|
import IconButton from '../buttons/IconButton.vue'
|
|
5
|
-
import
|
|
6
|
-
import SearchInput from '../forms/SearchInput.vue'
|
|
5
|
+
import GlobalSearch from '../forms/GlobalSearch.vue'
|
|
7
6
|
import UserMenu from './UserMenu.vue'
|
|
8
|
-
// 56px top bar:
|
|
7
|
+
// 56px top bar: GlobalSearch on the left (⌘K / Ctrl K; its ask event is re-emitted as ai(question)); notifications, help and the user trigger on the right.
|
|
8
|
+
// search passes props to GlobalSearch (items, query, recent, prompts, deepSearch, labels …).
|
|
9
9
|
// The user trigger opens a UserMenu below it (closes on outside click / Escape); #user-menu slot replaces its content.
|
|
10
10
|
// #actions slot replaces the whole right-hand group.
|
|
11
|
-
const props = defineProps({ placeholder:
|
|
11
|
+
const props = defineProps({ placeholder: String, search: Object, aiLabel: String, notificationsLabel: { type: String, default: 'Notifications' }, helpLabel: { type: String, default: 'Help' }, user: Object, style: Object })
|
|
12
12
|
const emit = defineEmits(['search', 'ai', 'notifications', 'help'])
|
|
13
13
|
const open = ref(false), hover = ref(false), root = ref(null)
|
|
14
14
|
const off = (e) => { if (open.value && root.value && !root.value.contains(e.target)) open.value = false }
|
|
@@ -19,10 +19,9 @@ function key(e) { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault();
|
|
|
19
19
|
</script>
|
|
20
20
|
<template>
|
|
21
21
|
<header :style="{ height: 'var(--topbar-h)', background: 'var(--bg-surface)', borderBottom: '1px solid var(--border-card)', display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: '16px', padding: '0 24px', boxSizing: 'border-box', flexShrink: 0, minWidth: 0, position: 'relative', ...style }">
|
|
22
|
-
<
|
|
22
|
+
<GlobalSearch :placeholder="placeholder" v-bind="search" :labels="aiLabel ? { ...(search && search.labels), ask: aiLabel } : search && search.labels" @input="v => emit('search', v)" @ask="q => emit('ai', q)" />
|
|
23
23
|
<div ref="root" style="display:flex;align-items:center;gap:8px;flex-shrink:0">
|
|
24
24
|
<slot name="actions">
|
|
25
|
-
<Button variant="dark" icon="ai" @click="emit('ai')">{{ aiLabel }}</Button>
|
|
26
25
|
<IconButton icon="bell" :label="notificationsLabel" :title="notificationsLabel" @click="emit('notifications')" />
|
|
27
26
|
<IconButton icon="circle-help" :label="helpLabel" :title="helpLabel" @click="emit('help')" />
|
|
28
27
|
<div v-if="user" role="button" tabindex="0" aria-haspopup="menu" :aria-expanded="open" @click="open = !open" @keydown="key" @mouseenter="hover = true" @mouseleave="hover = false"
|
package/covers.js
CHANGED
|
@@ -12,10 +12,11 @@ window.KB_COVERS = (function () {
|
|
|
12
12
|
"action-chip": [1, (h, K) => row(h, 8, [h(K.ActionChip, { tone: "info" }, "Mark as New"), h(K.ActionChip, null, "Skip")])],
|
|
13
13
|
"activity": [.85, (h, K) => h("div", { style: { width: 250 } }, h(K.ActivityItem, { icon: "upload", title: "Import finished", meta: "2 min ago" }), h(K.ActivityItem, { icon: "check", title: "Run completed", meta: "1 h ago" }))],
|
|
14
14
|
"alert": [.8, (h, K) => h("div", { style: { width: 280 } }, h(K.Alert, { tone: "info", title: "Mapping saved" }, "3 fields were updated."))],
|
|
15
|
-
"app-chrome": [.5, (h, K) => h("div", { style: { display: "flex", height: 260, width: 480, border: "1px solid var(--border-card)", borderRadius: "var(--radius-md)", overflow: "hidden" } }, h(K.Sidebar, { logo: "assets/keybricks-logo.png", active: "Home", items: [{ icon: "house", label: "Home" }, { icon: "file-text", label: "Documents", trailing: true }, { icon: "database", label: "Data Integration" }], footerItems: [{ icon: "settings", label: "Management", trailing: true }], style: { width: 180 } }), h("div", { style: { flex: 1, minWidth: 0, display: "flex", flexDirection: "column", background: "var(--bg-app)" } }, h("div", { style: { height: 56, background: "var(--bg-surface)", borderBottom: "1px solid var(--border-card)", display: "flex", alignItems: "center",
|
|
15
|
+
"app-chrome": [.5, (h, K) => h("div", { style: { display: "flex", height: 260, width: 480, border: "1px solid var(--border-card)", borderRadius: "var(--radius-md)", overflow: "hidden" } }, h(K.Sidebar, { logo: "assets/keybricks-logo.png", active: "Home", items: [{ icon: "house", label: "Home" }, { icon: "file-text", label: "Documents", trailing: true }, { icon: "database", label: "Data Integration" }], footerItems: [{ icon: "settings", label: "Management", trailing: true }], style: { width: 180 } }), h("div", { style: { flex: 1, minWidth: 0, display: "flex", flexDirection: "column", background: "var(--bg-app)" } }, h("div", { style: { height: 56, background: "var(--bg-surface)", borderBottom: "1px solid var(--border-card)", display: "flex", alignItems: "center", padding: "0 16px" } }, h("div", { style: { display: "flex", alignItems: "center", gap: 8, height: 32, padding: "0 6px 0 10px", borderRadius: "var(--radius-md)", background: "var(--bg-inset)", color: "var(--text-muted)", fontFamily: "var(--font-sans)", fontSize: "var(--text-base)" } }, h(K.Icon, { name: "search", size: 16 }), h("span", { style: { paddingRight: 24 } }, "Search"), h(K.Kbd, { keys: ["mod", "K"] })))))],
|
|
16
16
|
"banner": [.7, (h, K) => h("div", { style: { width: 340 } }, h(K.Banner, { tone: "warning", title: "Scheduled maintenance tonight", action: "Details" }))],
|
|
17
17
|
"breadcrumb": [1, (h, K) => h(K.Breadcrumb, { items: ["Home", "Pipelines", "Import"] })],
|
|
18
18
|
"button-1-base": [1, (h, K) => row(h, 8, [h(K.Button, { variant: "primary" }, "Save"), h(K.Button, { variant: "outline" }, "Cancel")])],
|
|
19
|
+
"button-5-ai": [1, (h, K) => h(K.Button, { variant: "ai" }, "Ask Prophet AI")],
|
|
19
20
|
"button-4-group": [1, (h, K) => h(K.ButtonGroup, null, h(K.Button, { variant: "outline" }, "Day"), h(K.Button, { variant: "outline" }, "Week"), h(K.Button, { variant: "outline" }, "Month"))],
|
|
20
21
|
"button-2-states": [1, (h, K) => row(h, 8, [h(K.Button, { variant: "primary", pressed: true }, "Pressed"), h(K.Button, { variant: "primary", disabled: true }, "Disabled")])],
|
|
21
22
|
"button-3-sizes-icons": [1, (h, K) => row(h, 8, [h("div", { "data-size": "sm" }, h(K.Button, { variant: "outline", icon: "plus" }, "Add")), h(K.Button, { variant: "outline", icon: "plus" }, "Add"), h("div", { "data-size": "lg" }, h(K.Button, { variant: "outline", icon: "plus" }, "Add"))])],
|
|
@@ -36,7 +37,7 @@ window.KB_COVERS = (function () {
|
|
|
36
37
|
"icon-button": [1.2, (h, K) => row(h, 4, [h(K.IconButton, { icon: "pencil-line", label: "Edit" }), h(K.IconButton, { icon: "copy", label: "Copy" }), h(K.IconButton, { icon: "ellipsis", label: "More" })])],
|
|
37
38
|
"input": [1, (h, K) => h("div", { style: { width: 220 } }, h(K.Input, { value: "FIN_CURRENCY_DEFAULT", onChange: () => {} }))],
|
|
38
39
|
"keyvalue": [.9, (h, K) => h("div", { style: { width: 240 } }, h(K.KeyValueList, { rows: [{ label: "Source", value: "Oracle EBS" }, { label: "Rows", value: "12,480" }, { label: "Status", value: "Ready" }] }))],
|
|
39
|
-
"kbd": [1.3, (h, K) => h(K.Kbd, { keys: ["
|
|
40
|
+
"kbd": [1.3, (h, K) => h(K.Kbd, { keys: ["mod", "K"] })],
|
|
40
41
|
"listrow": [.8, (h, K) => h("div", { style: { width: 280 } }, h(K.ListRow, { icon: "database", title: "Oracle EBS", meta: "Last sync 2 min ago" }))],
|
|
41
42
|
"loading": [1, (h, K) => row(h, 16, [h(K.Spinner), h("div", { style: { display: "flex", flexDirection: "column", gap: 8 } }, h(K.Skeleton, { width: 140, height: 12 }), h(K.Skeleton, { width: 100, height: 12 }))])],
|
|
42
43
|
"log-viewer": [.7, (h, K) => h("div", { style: { width: 320 } }, h(K.LogViewer, { lines: ["[14:30] Task started: Import", "[14:30] Reading ledger.csv", "[14:31] 12,480 rows written"], height: 90 }))],
|
|
@@ -49,6 +50,7 @@ window.KB_COVERS = (function () {
|
|
|
49
50
|
"pipeline-palette": [.5, (h, K) => h(K.IconTile, { icon: "database", hue: "source" })],
|
|
50
51
|
"radio": [1, (h, K) => col(h, 10, [h(K.Radio, { checked: true, label: "Overwrite" }), h(K.Radio, { checked: false, label: "Append" })])],
|
|
51
52
|
"search": [1, (h, K) => h("div", { style: { width: 220 } }, h(K.SearchInput, { placeholder: "Search pipelines" }))],
|
|
53
|
+
"search-global": [.42, (h, K) => h(K.GlobalSearch, { inline: true, prompts: ["Which entity had the largest YoY revenue change in Q3?", "Explain how the FX model translates currencies"], recentSearches: ["revenue bridge", "FX rates"] })],
|
|
52
54
|
"segmented-control": [1, (h, K) => h(K.SegmentedControl, { options: ["Grid", "List", "Board"], value: "Grid" })],
|
|
53
55
|
"relative-time-picker": [1, (h, K) => h("div", { style: { width: 220 } }, h(K.RelativeTimePicker, { value: { amount: 24, unit: "Hour" } }))],
|
|
54
56
|
"select": [1, (h, K) => h("div", { style: { width: 200 } }, h(K.Select, { options: ["Monthly", "Quarterly"], value: "Monthly" }))],
|
package/gallery.html
CHANGED
|
@@ -32,7 +32,7 @@ h2:first-child{margin-top:0}
|
|
|
32
32
|
<body>
|
|
33
33
|
<header>
|
|
34
34
|
<h1>Keybricks Design System</h1>
|
|
35
|
-
<p class="sub">
|
|
35
|
+
<p class="sub">122 components in React and Vue 3, on one token layer. Every card below is the real component, not a screenshot.</p>
|
|
36
36
|
<div class="bar">
|
|
37
37
|
<input type="search" id="q" placeholder="Filter components…" autocomplete="off">
|
|
38
38
|
<span class="count" id="count"></span>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!-- @dsCard group="Brand" viewport="
|
|
1
|
+
<!-- @dsCard group="Brand" viewport="700x162" name="Logo & Wordmark" subtitle="Blue cube bitmap + Inter 600 wordmark, −0.609px tracking" -->
|
|
2
2
|
<!DOCTYPE html>
|
|
3
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
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>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!-- @dsCard group="Colors" viewport="
|
|
1
|
+
<!-- @dsCard group="Colors" viewport="700x783" name="Schemes" subtitle="Sets that work together — surface, text, border, accent" -->
|
|
2
2
|
<!DOCTYPE html>
|
|
3
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
4
|
<script src="_color-lab.js"></script>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!-- @dsCard group="Colors" viewport="
|
|
1
|
+
<!-- @dsCard group="Colors" viewport="700x478" name="Transparency" subtitle="Alpha scale — the number is the opacity" -->
|
|
2
2
|
<!DOCTYPE html>
|
|
3
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
4
|
<script src="_color-lab.js"></script>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!-- @dsCard group="Foundations" viewport="
|
|
1
|
+
<!-- @dsCard group="Foundations" viewport="700x176" name="Borders & Shadows" subtitle="Hairlines carry the UI; shadows only on canvas nodes" -->
|
|
2
2
|
<!DOCTYPE html>
|
|
3
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
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>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!-- @dsCard group="Foundations" viewport="
|
|
1
|
+
<!-- @dsCard group="Foundations" viewport="700x164" name="App Chrome Dimensions" subtitle="Fixed panel widths & bar heights" -->
|
|
2
2
|
<!DOCTYPE html>
|
|
3
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
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>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!-- @dsCard group="Foundations" viewport="
|
|
1
|
+
<!-- @dsCard group="Foundations" viewport="700x152" name="Motion" subtitle="120/160/240ms · ease-out — hover, rise, pulse, spin" -->
|
|
2
2
|
<!DOCTYPE html>
|
|
3
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
4
|
<style>body{margin:0;padding:16px;font-family:var(--font-sans);background:var(--bg-surface);display:grid;grid-template-columns:repeat(4,1fr);gap:10px;box-sizing:border-box}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!-- @dsCard group="Foundations" viewport="
|
|
1
|
+
<!-- @dsCard group="Foundations" viewport="700x1335" 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" -->
|
|
2
2
|
<!DOCTYPE html>
|
|
3
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
4
|
<script src="https://unpkg.com/react@18.3.1/umd/react.development.js" integrity="sha384-hD6/rw4ppMLGNu3tX5cjIb+uRZ7UkRJ6BPkLpg4hAu/6onKUg4lLsHAs9EBPT82L" crossorigin="anonymous"></script>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!-- @dsCard group="Foundations" viewport="
|
|
1
|
+
<!-- @dsCard group="Foundations" viewport="700x138" name="Spacing" subtitle="4px family · page 24×32 · card 21 · section gap 24 · gaps 8 inside a group, 12/16/24 between groups" -->
|
|
2
2
|
<!DOCTYPE html>
|
|
3
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
4
|
<style>body{margin:0;padding:16px;font-family:var(--font-sans);background:var(--bg-app);box-sizing:border-box}.bars{display:flex;gap:14px;align-items:flex-end}.b{display:flex;flex-direction:column;gap:5px;align-items:center}.b i{display:block;background:var(--soft-bg);border:1px solid var(--soft-border);border-radius:3px}.b span{font-size:var(--text-xs);font-family:var(--font-sans);font-variant-numeric:tabular-nums;color:var(--text-muted)}.note{margin-top:12px;font-size:var(--text-xs);line-height:var(--leading-xs);color:var(--text-muted)}.note b{color:var(--text-heading);font-weight:500}</style></head>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!-- @dsCard group="Foundations" viewport="
|
|
1
|
+
<!-- @dsCard group="Foundations" viewport="700x552" name="Interaction States" subtitle="The five states every control carries — and where each one is defined" -->
|
|
2
2
|
<!DOCTYPE html>
|
|
3
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
4
|
<style>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!-- @dsCard group="Type" viewport="
|
|
1
|
+
<!-- @dsCard group="Type" viewport="700x388" name="Display Scale" subtitle="Display sizes 24–60 — tracking follows the same size→tracking curve" -->
|
|
2
2
|
<!DOCTYPE html>
|
|
3
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
4
|
<style>body{margin:0;padding:14px 16px;font-family:var(--font-sans);background:var(--bg-surface);box-sizing:border-box}.r{display:grid;grid-template-columns:150px 1fr 200px;gap:12px;align-items:baseline;padding:7px 0;border-bottom:1px solid var(--border-subtle)}.m{font-size:var(--text-xs);font-family:var(--font-sans);font-variant-numeric:tabular-nums;color:var(--text-muted)}.u{font-size:var(--text-xs);color:var(--text-secondary);text-align:right}</style></head>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!-- @dsCard group="Type" viewport="
|
|
1
|
+
<!-- @dsCard group="Type" viewport="700x187" 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" -->
|
|
2
2
|
<!DOCTYPE html>
|
|
3
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
4
|
<style>body{margin:0;padding:16px;font-family:var(--font-sans);background:var(--bg-app);display:flex;gap:12px;box-sizing:border-box}.p{flex:1;min-width:0;border:1px solid var(--border-card);border-radius:10px;padding:12px;display:flex;flex-direction:column;gap:8px}.cap{font-size:var(--text-xs);line-height:var(--leading-xs);color:var(--text-muted)}.codeblk{background:var(--bg-inset);border-radius:8px;padding:8px 10px;font-family:var(--font-mono);font-size:var(--text-xs);line-height:var(--leading-xs);color:var(--text-primary);white-space:pre}.log{background:var(--bg-inset);border-radius:8px;padding:8px 10px;font-family:var(--font-mono);font-size:var(--text-xs);line-height:var(--leading-xs);color:var(--text-secondary);display:flex;flex-direction:column}.ui{font-size:var(--text-base);line-height:var(--leading-base);letter-spacing:var(--tracking-base);color:var(--text-primary);font-variant-numeric:tabular-nums;display:flex;flex-direction:column}</style></head>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!-- @dsCard group="Type" viewport="
|
|
1
|
+
<!-- @dsCard group="Type" viewport="700x408" 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" -->
|
|
2
2
|
<!DOCTYPE html>
|
|
3
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
4
|
<style>body{margin:0;padding:14px 16px;font-family:var(--font-sans);background:var(--bg-surface);box-sizing:border-box}.r{display:grid;grid-template-columns:150px 1fr 190px;gap:12px;align-items:baseline;padding:5px 0;border-bottom:1px solid var(--border-subtle)}.m{font-size:var(--text-xs);font-family:var(--font-sans);font-variant-numeric:tabular-nums;color:var(--text-muted)}.u{font-size:var(--text-xs);color:var(--text-secondary);text-align:right}</style></head>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!-- @dsCard group="Type" viewport="
|
|
1
|
+
<!-- @dsCard group="Type" viewport="700x264" name="Inter Weights" subtitle="300 numerals · 400 body · 500 UI-medium · 600 titles — 500 becomes 600 in Chinese, Japanese and Korean" -->
|
|
2
2
|
<!DOCTYPE html>
|
|
3
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
4
|
<style>body{margin:0;padding:16px;font-family:var(--font-sans);background:var(--bg-surface);display:grid;grid-template-columns:repeat(4,1fr);gap:10px;align-content:start;box-sizing:border-box}.w{border:1px solid var(--border-card);border-radius:10px;padding:12px;display:flex;flex-direction:column;gap:2px}.w b{font-size:var(--text-xl);line-height:var(--leading-xl);letter-spacing:var(--tracking-xl);color:var(--text-primary)}.w span{font-size:var(--text-xs);line-height:var(--leading-xs);color:var(--text-secondary)}</style></head>
|