@godxjp/ui-mcp 0.21.3 → 0.21.5
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/README.md +3 -3
- package/dist/index.js +1025 -6
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -77,7 +77,8 @@ var COMPONENTS = [
|
|
|
77
77
|
"DO: Pass `breadcrumb` as an ordered array of `{ label, to? }` objects from root to current page. The last item is automatically rendered without a link and receives `aria-current='page'`; earlier items with `to` become router `<Link>` elements. Never hand-roll a breadcrumb nav inside a PageContainer.",
|
|
78
78
|
"DON'T: Use `density` to change individual control sizes \u2014 it cascades spacing across the entire page subtree. Set it once per page (e.g. `density='compact'` for data-dense list pages) and let all child components inherit it. Do not apply density classes manually.",
|
|
79
79
|
"DON'T: Confuse PageContainer's prop names with the old PageHeader's prop names \u2014 PageContainer uses `subtitle` (not `description`) and `extra` (not `actions`). If you see those legacy names in old code, migrate them to PageContainer.",
|
|
80
|
-
"DO: Leave `fill` off (the default) for ordinary pages \u2014 the body is content-height and top-packed, so a short page on a tall viewport leaves no stretched empty void below the content (the page background simply spans the shell). Only set `fill` when the body itself should occupy the full remaining height: a full-height DataTable, a SplitPane, or a chat surface whose message list scrolls and whose composer is pinned to the bottom via `footer` + `stickyFooter`. DON'T add a manual `min-h-screen` / `flex-1` wrapper or a spacer div to fight or fake this."
|
|
80
|
+
"DO: Leave `fill` off (the default) for ordinary pages \u2014 the body is content-height and top-packed, so a short page on a tall viewport leaves no stretched empty void below the content (the page background simply spans the shell). Only set `fill` when the body itself should occupy the full remaining height: a full-height DataTable, a SplitPane, or a chat surface whose message list scrolls and whose composer is pinned to the bottom via `footer` + `stickyFooter`. DON'T add a manual `min-h-screen` / `flex-1` wrapper or a spacer div to fight or fake this.",
|
|
81
|
+
"DO: Know the header draws NO bottom divider by default \u2014 it is governed by the semantic token `--page-header-divider` (default `none`). A service theme opts in once, globally, with `--page-header-divider: 1px solid hsl(var(--border));` in its theme CSS. Never re-create the divider with a `border-b` utility on the header or a `<Separator>` under the title; `variant='ghost'` stays divider-less regardless of the token."
|
|
81
82
|
],
|
|
82
83
|
useCases: [
|
|
83
84
|
"A master list page (e.g. invoices, journal entries, customers) where the header holds the page title, a 'New Invoice' button in `extra`, a breadcrumb trail, and a full-bleed DataTable as the body \u2014 use `variant='flush'` + `<PageContainer.Inset>` for the Toolbar above the table.",
|
|
@@ -519,6 +520,12 @@ export default function Shell() {
|
|
|
519
520
|
defaultValue: "undefined",
|
|
520
521
|
description: "Called when the search bar button (\u2318K) is clicked. Wire this to your command-palette or search dialog."
|
|
521
522
|
},
|
|
523
|
+
{
|
|
524
|
+
name: "searchPlaceholder",
|
|
525
|
+
type: "string",
|
|
526
|
+
defaultValue: 'i18n "layout.topbar.searchPlaceholder" ("\u691C\u7D22\u2026")',
|
|
527
|
+
description: "Search-bar placeholder text \u2014 set a domain-specific hint (e.g. \u6848\u4EF6\u30FB\u53D7\u6CE8\u30FB\u9867\u5BA2\u3092\u691C\u7D22\u2026) instead of the generic default."
|
|
528
|
+
},
|
|
522
529
|
{
|
|
523
530
|
name: "onTweaksOpen",
|
|
524
531
|
type: "() => void",
|
|
@@ -1315,7 +1322,7 @@ export function Grid({ rows }: { rows: Row[] }) {
|
|
|
1315
1322
|
{
|
|
1316
1323
|
name: "StatCard",
|
|
1317
1324
|
group: "data-display",
|
|
1318
|
-
tagline: "KPI tile. \u26A0\uFE0F StatCard IS ALREADY a bordered Card \u2014 render it DIRECTLY in ResponsiveGrid. NEVER wrap it in <Card>/<CardContent> (that double-borders it \u2192 looks too thick).
|
|
1325
|
+
tagline: "KPI tile. \u26A0\uFE0F StatCard IS ALREADY a bordered Card \u2014 render it DIRECTLY in ResponsiveGrid. NEVER wrap it in <Card>/<CardContent> (that double-borders it \u2192 looks too thick). Use `accent` for a semantic leading-edge rail on a KPI needing attention.",
|
|
1319
1326
|
props: [
|
|
1320
1327
|
{ name: "label", type: "ReactNode", required: true, description: "Metric name." },
|
|
1321
1328
|
{
|
|
@@ -1336,13 +1343,24 @@ export function Grid({ rows }: { rows: Row[] }) {
|
|
|
1336
1343
|
defaultValue: '"stacked"',
|
|
1337
1344
|
description: "stacked = label over value; inline = label left / value right."
|
|
1338
1345
|
},
|
|
1339
|
-
{ name: "align", type: '"start" | "end"', description: "Align the metric group." }
|
|
1346
|
+
{ name: "align", type: '"start" | "end"', description: "Align the metric group." },
|
|
1347
|
+
{
|
|
1348
|
+
name: "inverse",
|
|
1349
|
+
type: "boolean",
|
|
1350
|
+
defaultValue: "false",
|
|
1351
|
+
description: "Flip delta tone semantics for metrics where lower is better (cost, error rate): '-' renders green, '+' renders red."
|
|
1352
|
+
},
|
|
1353
|
+
{
|
|
1354
|
+
name: "accent",
|
|
1355
|
+
type: '"primary" | "success" | "warning" | "info" | "attention" | "destructive"',
|
|
1356
|
+
description: "Semantic 3px leading-edge rail (forwarded to the underlying Card) \u2014 flags a KPI that needs attention (e.g. attention = backlog with a deadline, destructive = overdue)."
|
|
1357
|
+
}
|
|
1340
1358
|
],
|
|
1341
1359
|
usage: [
|
|
1342
1360
|
"DO place StatCard directly as a child of ResponsiveGrid \u2014 it renders its own bordered Card shell internally, so no wrapping <Card> or <CardContent> is needed or allowed. Wrapping creates a double border.",
|
|
1343
1361
|
"DO pass `delta` as a sign-prefixed string (e.g. '+12%' or '-3%') to get automatic color tone: '+' renders text-success, '-' renders text-destructive. For metrics where a negative delta is good (e.g. cost reduction, error rate), pass `inverse` so the tone is flipped correctly.",
|
|
1344
1362
|
"DO use `hint` for secondary context (e.g. '\u5148\u6708\u6BD4 +3%', 'last 30 days'). In the default `stacked` layout hint renders below the value; in `inline` layout it renders beside the label.",
|
|
1345
|
-
"DO
|
|
1363
|
+
"DO use `accent` (not a className border) for the semantic leading-edge rail \u2014 `attention` for a non-destructive backlog needing action, `destructive` only for overdue/exceeded states. Most tiles in a grid stay rail-less; an all-accented grid says nothing.",
|
|
1346
1364
|
"DO NOT hand-roll a KPI tile using a plain <Card><CardContent>. StatCard is the correct primitive and token-aligns the label/value/hint/delta slots automatically.",
|
|
1347
1365
|
"WHILE data is loading, replace each StatCard with a <SkeletonStat /> at the same grid position \u2014 never render an empty value string or a spinner inside StatCard itself."
|
|
1348
1366
|
],
|
|
@@ -2675,6 +2693,184 @@ export function PrioritySelect({ value, onValueChange }) {
|
|
|
2675
2693
|
storyPath: "data-entry/RadioGroup.stories.tsx",
|
|
2676
2694
|
rules: [23]
|
|
2677
2695
|
},
|
|
2696
|
+
{
|
|
2697
|
+
name: "MonthPicker",
|
|
2698
|
+
group: "data-entry",
|
|
2699
|
+
tagline: "Year/month (yyyy/MM) input with an Ant-Design-style month-grid popover \u2014 a year chevron header over a 3x4 grid of the twelve months. The input stays typeable; the grid is the visual affordance.",
|
|
2700
|
+
props: [
|
|
2701
|
+
{
|
|
2702
|
+
name: "value",
|
|
2703
|
+
type: "Date | undefined",
|
|
2704
|
+
description: "Controlled value \u2014 first day of the selected month. Pass undefined to clear."
|
|
2705
|
+
},
|
|
2706
|
+
{
|
|
2707
|
+
name: "defaultValue",
|
|
2708
|
+
type: "Date | undefined",
|
|
2709
|
+
description: "Uncontrolled initial value."
|
|
2710
|
+
},
|
|
2711
|
+
{
|
|
2712
|
+
name: "onValueChange",
|
|
2713
|
+
type: "(value: Date | undefined) => void",
|
|
2714
|
+
description: "Fires on a grid pick, on a complete typed yyyy/MM, and on clear."
|
|
2715
|
+
},
|
|
2716
|
+
{
|
|
2717
|
+
name: "placeholder",
|
|
2718
|
+
type: "string",
|
|
2719
|
+
defaultValue: '"yyyy/mm"',
|
|
2720
|
+
description: "Placeholder shown while empty."
|
|
2721
|
+
},
|
|
2722
|
+
{
|
|
2723
|
+
name: "disabled",
|
|
2724
|
+
type: "boolean",
|
|
2725
|
+
defaultValue: "false",
|
|
2726
|
+
description: "Disables the input, the clear button and the grid trigger."
|
|
2727
|
+
},
|
|
2728
|
+
{
|
|
2729
|
+
name: "className",
|
|
2730
|
+
type: "string",
|
|
2731
|
+
description: "Extra classes on the control shell (width/margin overrides)."
|
|
2732
|
+
},
|
|
2733
|
+
{
|
|
2734
|
+
name: "id",
|
|
2735
|
+
type: "string",
|
|
2736
|
+
description: "Wired to the inner input; auto-generated when omitted so the field always has an id."
|
|
2737
|
+
},
|
|
2738
|
+
{
|
|
2739
|
+
name: "name",
|
|
2740
|
+
type: "string",
|
|
2741
|
+
description: "Form field name \u2014 submits the display text (yyyy/MM)."
|
|
2742
|
+
},
|
|
2743
|
+
{
|
|
2744
|
+
name: "fromYear",
|
|
2745
|
+
type: "number",
|
|
2746
|
+
description: "Inclusive lower bound for the year navigation."
|
|
2747
|
+
},
|
|
2748
|
+
{
|
|
2749
|
+
name: "toYear",
|
|
2750
|
+
type: "number",
|
|
2751
|
+
description: "Inclusive upper bound for the year navigation."
|
|
2752
|
+
},
|
|
2753
|
+
{
|
|
2754
|
+
name: "allowClear",
|
|
2755
|
+
type: "boolean",
|
|
2756
|
+
defaultValue: "true",
|
|
2757
|
+
description: "Inline clear button while a value is set."
|
|
2758
|
+
}
|
|
2759
|
+
],
|
|
2760
|
+
usage: [
|
|
2761
|
+
"DO use MonthPicker for every yyyy/MM (year-month) field \u2014 never a bare Input with a YYYY/MM helper text.",
|
|
2762
|
+
"DO wrap it in FormField like every other labelled control; FormField injects id/aria wiring.",
|
|
2763
|
+
"DO NOT compose two MonthPickers to fake a from~to range \u2014 that is MonthRangePicker (one control shell, like DateRangePicker)."
|
|
2764
|
+
],
|
|
2765
|
+
related: [
|
|
2766
|
+
"DatePicker \u2014 full date (yyyy-MM-dd); MonthPicker when the day is meaningless (\u7DE0\u3081\u5E74\u6708, \u96C6\u8A08\u5E74\u6708, \u5546\u8AC7\u767A\u751F\u5E74\u6708).",
|
|
2767
|
+
"MonthRangePicker \u2014 use for a yyyy/MM from~to pair; one input-styled control, never two MonthPickers side-by-side."
|
|
2768
|
+
],
|
|
2769
|
+
example: `import { useState } from "react";
|
|
2770
|
+
import { MonthPicker, FormField } from "@godxjp/ui/data-entry";
|
|
2771
|
+
|
|
2772
|
+
export function OrderMonthField() {
|
|
2773
|
+
const [ym, setYm] = useState<Date | undefined>(undefined);
|
|
2774
|
+
|
|
2775
|
+
return (
|
|
2776
|
+
<FormField label="\u53D7\u6CE8\u65E5\u5E74\u6708">
|
|
2777
|
+
<MonthPicker name="search_order_date_ym" value={ym} onValueChange={setYm} />
|
|
2778
|
+
</FormField>
|
|
2779
|
+
);
|
|
2780
|
+
}`,
|
|
2781
|
+
storyPath: "data-entry/MonthPicker.stories.tsx",
|
|
2782
|
+
rules: [3, 6, 13, 31, 43]
|
|
2783
|
+
},
|
|
2784
|
+
{
|
|
2785
|
+
name: "MonthRangePicker",
|
|
2786
|
+
group: "data-entry",
|
|
2787
|
+
tagline: "Year/month (yyyy/MM) RANGE rendered as ONE input-styled control `[ from \u2192 to \u2715 \u{1F4C5} ]` (Ant RangePicker convention, same shell as DateRangePicker) with an Ant-style month-grid popover. Both inputs stay typeable; picks are two-step with from \u2264 to always enforced.",
|
|
2788
|
+
props: [
|
|
2789
|
+
{
|
|
2790
|
+
name: "value",
|
|
2791
|
+
type: "DateRange | undefined",
|
|
2792
|
+
description: "Controlled range \u2014 both edges normalized to the first day of their month. Pass undefined to clear."
|
|
2793
|
+
},
|
|
2794
|
+
{
|
|
2795
|
+
name: "defaultValue",
|
|
2796
|
+
type: "DateRange | undefined",
|
|
2797
|
+
description: "Uncontrolled initial range."
|
|
2798
|
+
},
|
|
2799
|
+
{
|
|
2800
|
+
name: "onValueChange",
|
|
2801
|
+
type: "(value: DateRange | undefined) => void",
|
|
2802
|
+
description: "Fires on each grid step ({from, to: undefined} then the complete pair), on a complete typed yyyy/MM at either edge, and on clear. Never emits an inverted range \u2014 a backwards pick/typing is swapped so from \u2264 to."
|
|
2803
|
+
},
|
|
2804
|
+
{
|
|
2805
|
+
name: "placeholder",
|
|
2806
|
+
type: "string",
|
|
2807
|
+
defaultValue: '"yyyy/mm"',
|
|
2808
|
+
description: "Placeholder shown in both inputs while empty."
|
|
2809
|
+
},
|
|
2810
|
+
{
|
|
2811
|
+
name: "disabled",
|
|
2812
|
+
type: "boolean",
|
|
2813
|
+
defaultValue: "false",
|
|
2814
|
+
description: "Disables both inputs, the clear button and the grid trigger."
|
|
2815
|
+
},
|
|
2816
|
+
{
|
|
2817
|
+
name: "className",
|
|
2818
|
+
type: "string",
|
|
2819
|
+
description: "Extra classes on the control shell (width/margin overrides)."
|
|
2820
|
+
},
|
|
2821
|
+
{
|
|
2822
|
+
name: "id",
|
|
2823
|
+
type: "string",
|
|
2824
|
+
description: "Wired to the from input; the to input gets `${id}-to`. Auto-generated when omitted."
|
|
2825
|
+
},
|
|
2826
|
+
{
|
|
2827
|
+
name: "name",
|
|
2828
|
+
type: "string",
|
|
2829
|
+
description: "Form field name \u2014 emits the range as `${name}_from` / `${name}_to` yyyy/MM fields."
|
|
2830
|
+
},
|
|
2831
|
+
{
|
|
2832
|
+
name: "fromYear",
|
|
2833
|
+
type: "number",
|
|
2834
|
+
description: "Inclusive lower bound for the year navigation."
|
|
2835
|
+
},
|
|
2836
|
+
{
|
|
2837
|
+
name: "toYear",
|
|
2838
|
+
type: "number",
|
|
2839
|
+
description: "Inclusive upper bound for the year navigation."
|
|
2840
|
+
},
|
|
2841
|
+
{
|
|
2842
|
+
name: "allowClear",
|
|
2843
|
+
type: "boolean",
|
|
2844
|
+
defaultValue: "true",
|
|
2845
|
+
description: "Inline clear button (clears the WHOLE range) while a value is set."
|
|
2846
|
+
}
|
|
2847
|
+
],
|
|
2848
|
+
usage: [
|
|
2849
|
+
"DO use MonthRangePicker for every yyyy/MM from~to pair \u2014 never two MonthPickers (or bare Inputs) separated by ~; a range is ONE control, exactly like DateRangePicker.",
|
|
2850
|
+
"DO rely on its built-in range validation: a backwards grid pick or typed pair is swap-normalized so the emitted range always satisfies from \u2264 to \u2014 do not re-validate order in the app.",
|
|
2851
|
+
"DO wrap it in FormField like every other labelled control; FormField injects id/aria wiring.",
|
|
2852
|
+
"Grid picks are two-step (from, then to) and reset-on-complete: picking while a complete range is held STARTS a new range, so the start month is never stuck."
|
|
2853
|
+
],
|
|
2854
|
+
related: [
|
|
2855
|
+
"MonthPicker \u2014 single yyyy/MM value; MonthRangePicker when the field is a from~to pair (\u5546\u8AC7\u767A\u751F\u5E74\u6708\u306E\u7BC4\u56F2\u691C\u7D22, \u96C6\u8A08\u671F\u9593).",
|
|
2856
|
+
"DateRangePicker \u2014 full-date (yyyy-MM-dd) range with the same one-control shell; MonthRangePicker when the day is meaningless."
|
|
2857
|
+
],
|
|
2858
|
+
example: `import { useState } from "react";
|
|
2859
|
+
import type { DateRange } from "react-day-picker";
|
|
2860
|
+
import { MonthRangePicker, FormField } from "@godxjp/ui/data-entry";
|
|
2861
|
+
|
|
2862
|
+
export function NegotiationYmField() {
|
|
2863
|
+
const [range, setRange] = useState<DateRange | undefined>(undefined);
|
|
2864
|
+
|
|
2865
|
+
return (
|
|
2866
|
+
<FormField label="\u5546\u8AC7\u767A\u751F\u5E74\u6708">
|
|
2867
|
+
<MonthRangePicker name="search_negotiation_ym" value={range} onValueChange={setRange} />
|
|
2868
|
+
</FormField>
|
|
2869
|
+
);
|
|
2870
|
+
}`,
|
|
2871
|
+
storyPath: "data-entry/MonthRangePicker.stories.tsx",
|
|
2872
|
+
rules: [3, 6, 13, 31, 43]
|
|
2873
|
+
},
|
|
2678
2874
|
{
|
|
2679
2875
|
name: "DatePicker",
|
|
2680
2876
|
group: "data-entry",
|
|
@@ -7027,6 +7223,18 @@ var TOKENS = [
|
|
|
7027
7223
|
},
|
|
7028
7224
|
{ name: "--info", category: "semantic", tier: "semantic", role: "Information status role." },
|
|
7029
7225
|
{ name: "--attention", category: "semantic", tier: "semantic", role: "Attention status role." },
|
|
7226
|
+
{
|
|
7227
|
+
name: "--page-header-divider",
|
|
7228
|
+
category: "semantic",
|
|
7229
|
+
tier: "semantic",
|
|
7230
|
+
role: "PageContainer header bottom divider. Default none; a service theme opts in with `1px solid hsl(var(--border))`."
|
|
7231
|
+
},
|
|
7232
|
+
{
|
|
7233
|
+
name: "--page-header-pad-bottom",
|
|
7234
|
+
category: "semantic",
|
|
7235
|
+
tier: "semantic",
|
|
7236
|
+
role: "PageContainer header bottom inset. Defaults to page top padding minus the section gap so the title band is vertically balanced."
|
|
7237
|
+
},
|
|
7030
7238
|
{ name: "--badge-space-*", category: "component", tier: "component", role: "Badge spacing." },
|
|
7031
7239
|
{
|
|
7032
7240
|
name: "--card-*",
|
|
@@ -7041,6 +7249,18 @@ var TOKENS = [
|
|
|
7041
7249
|
role: "Shared form control heights, padding, icons, and focus chrome."
|
|
7042
7250
|
},
|
|
7043
7251
|
{ name: "--table-*", category: "component", tier: "component", role: "Table row/cell sizing." },
|
|
7252
|
+
{
|
|
7253
|
+
name: "--form-label-width",
|
|
7254
|
+
category: "component",
|
|
7255
|
+
tier: "component",
|
|
7256
|
+
role: "Label column width in horizontal Form layout. Default max-content; a service theme sets it once (e.g. 110px) \u2014 the labelWidth prop overrides per form/field."
|
|
7257
|
+
},
|
|
7258
|
+
{
|
|
7259
|
+
name: "--form-label-gap",
|
|
7260
|
+
category: "component",
|
|
7261
|
+
tier: "component",
|
|
7262
|
+
role: "Label\u2194control column gap in horizontal Form layout. Default 16px (--space-4)."
|
|
7263
|
+
},
|
|
7044
7264
|
{
|
|
7045
7265
|
name: "--dialog-* / --alert-* / --skeleton-*",
|
|
7046
7266
|
category: "component",
|
|
@@ -7052,6 +7272,715 @@ function tokensByCategory(category) {
|
|
|
7052
7272
|
return TOKENS.filter((t) => t.category === category);
|
|
7053
7273
|
}
|
|
7054
7274
|
|
|
7275
|
+
// src/data/component-tokens.generated.ts
|
|
7276
|
+
var COMPONENT_TOKENS = [
|
|
7277
|
+
{
|
|
7278
|
+
"name": "--badge-space-gap",
|
|
7279
|
+
"value": "var(--space-inline-xs)",
|
|
7280
|
+
"description": "Badge component tokens."
|
|
7281
|
+
},
|
|
7282
|
+
{
|
|
7283
|
+
"name": "--badge-space-x",
|
|
7284
|
+
"value": "var(--space-2)",
|
|
7285
|
+
"description": "Badge component tokens."
|
|
7286
|
+
},
|
|
7287
|
+
{
|
|
7288
|
+
"name": "--badge-space-y",
|
|
7289
|
+
"value": "var(--space-1)",
|
|
7290
|
+
"description": "Badge component tokens."
|
|
7291
|
+
},
|
|
7292
|
+
{
|
|
7293
|
+
"name": "--badge-font-size",
|
|
7294
|
+
"value": "var(--font-size-xs)",
|
|
7295
|
+
"description": "Small-by-design (badge/pill/counter). A knob (rule #45) so a service can * re-tune badge text without touching the global --font-size-xs step."
|
|
7296
|
+
},
|
|
7297
|
+
{
|
|
7298
|
+
"name": "--card-space-inset",
|
|
7299
|
+
"value": "var(--space-section-active)",
|
|
7300
|
+
"description": "Card component tokens: card chrome derives from semantic layout tokens."
|
|
7301
|
+
},
|
|
7302
|
+
{
|
|
7303
|
+
"name": "--card-space-header-y",
|
|
7304
|
+
"value": "var(--space-stack-sm)",
|
|
7305
|
+
"description": "Card component tokens: card chrome derives from semantic layout tokens."
|
|
7306
|
+
},
|
|
7307
|
+
{
|
|
7308
|
+
"name": "--card-space-body-y",
|
|
7309
|
+
"value": "var(--space-section-active)",
|
|
7310
|
+
"description": "Card component tokens: card chrome derives from semantic layout tokens."
|
|
7311
|
+
},
|
|
7312
|
+
{
|
|
7313
|
+
"name": "--card-space-footer-y",
|
|
7314
|
+
"value": "var(--space-stack-sm)",
|
|
7315
|
+
"description": "Card component tokens: card chrome derives from semantic layout tokens."
|
|
7316
|
+
},
|
|
7317
|
+
{
|
|
7318
|
+
"name": "--card-space-gap",
|
|
7319
|
+
"value": "var(--space-stack-xs)",
|
|
7320
|
+
"description": "Card component tokens: card chrome derives from semantic layout tokens."
|
|
7321
|
+
},
|
|
7322
|
+
{
|
|
7323
|
+
"name": "--card-title-font-size",
|
|
7324
|
+
"value": "var(--font-size-base)",
|
|
7325
|
+
"description": "Card component tokens: card chrome derives from semantic layout tokens."
|
|
7326
|
+
},
|
|
7327
|
+
{
|
|
7328
|
+
"name": "--card-title-line-height",
|
|
7329
|
+
"value": "var(--line-height-tight)",
|
|
7330
|
+
"description": "Card component tokens: card chrome derives from semantic layout tokens."
|
|
7331
|
+
},
|
|
7332
|
+
{
|
|
7333
|
+
"name": "--card-title-font-weight",
|
|
7334
|
+
"value": "var(--font-weight-semibold)",
|
|
7335
|
+
"description": "Card component tokens: card chrome derives from semantic layout tokens."
|
|
7336
|
+
},
|
|
7337
|
+
{
|
|
7338
|
+
"name": "--card-description-font-size",
|
|
7339
|
+
"value": "var(--font-size-sm)",
|
|
7340
|
+
"description": "Card component tokens: card chrome derives from semantic layout tokens."
|
|
7341
|
+
},
|
|
7342
|
+
{
|
|
7343
|
+
"name": "--card-description-line-height",
|
|
7344
|
+
"value": "var(--line-height-normal)",
|
|
7345
|
+
"description": "Card component tokens: card chrome derives from semantic layout tokens."
|
|
7346
|
+
},
|
|
7347
|
+
{
|
|
7348
|
+
"name": "--card-background",
|
|
7349
|
+
"value": "var(--card)",
|
|
7350
|
+
"description": "Card component tokens: card chrome derives from semantic layout tokens."
|
|
7351
|
+
},
|
|
7352
|
+
{
|
|
7353
|
+
"name": "--card-border",
|
|
7354
|
+
"value": "var(--border)",
|
|
7355
|
+
"description": "Card component tokens: card chrome derives from semantic layout tokens."
|
|
7356
|
+
},
|
|
7357
|
+
{
|
|
7358
|
+
"name": "--card-header-background",
|
|
7359
|
+
"value": "var(--muted)",
|
|
7360
|
+
"description": "Card component tokens: card chrome derives from semantic layout tokens."
|
|
7361
|
+
},
|
|
7362
|
+
{
|
|
7363
|
+
"name": "--card-header-background-alpha",
|
|
7364
|
+
"value": "0.55",
|
|
7365
|
+
"description": "Card component tokens: card chrome derives from semantic layout tokens."
|
|
7366
|
+
},
|
|
7367
|
+
{
|
|
7368
|
+
"name": "--card-header-border-bottom",
|
|
7369
|
+
"value": "1px solid hsl(var(--card-border))",
|
|
7370
|
+
"description": "Banded-header divider \u2014 tokenised (rule #44) so a service theme can make it * dashed / heavier / none without forking CSS. Pair with * --card-header-background-alpha: 0 for a quiet borderless-band header."
|
|
7371
|
+
},
|
|
7372
|
+
{
|
|
7373
|
+
"name": "--card-radius",
|
|
7374
|
+
"value": "var(--radius)",
|
|
7375
|
+
"description": "Banded-header divider \u2014 tokenised (rule #44) so a service theme can make it * dashed / heavier / none without forking CSS. Pair with * --card-header-background-alpha: 0 for a quiet borderless-band header."
|
|
7376
|
+
},
|
|
7377
|
+
{
|
|
7378
|
+
"name": "--stat-card-label-font-size",
|
|
7379
|
+
"value": "var(--font-size-xs)",
|
|
7380
|
+
"description": "Banded-header divider \u2014 tokenised (rule #44) so a service theme can make it * dashed / heavier / none without forking CSS. Pair with * --card-header-background-alpha: 0 for a quiet borderless-band header."
|
|
7381
|
+
},
|
|
7382
|
+
{
|
|
7383
|
+
"name": "--stat-card-label-font-weight",
|
|
7384
|
+
"value": "var(--font-weight-medium)",
|
|
7385
|
+
"description": "Banded-header divider \u2014 tokenised (rule #44) so a service theme can make it * dashed / heavier / none without forking CSS. Pair with * --card-header-background-alpha: 0 for a quiet borderless-band header."
|
|
7386
|
+
},
|
|
7387
|
+
{
|
|
7388
|
+
"name": "--stat-card-label-letter-spacing",
|
|
7389
|
+
"value": "0.04em",
|
|
7390
|
+
"description": "Banded-header divider \u2014 tokenised (rule #44) so a service theme can make it * dashed / heavier / none without forking CSS. Pair with * --card-header-background-alpha: 0 for a quiet borderless-band header."
|
|
7391
|
+
},
|
|
7392
|
+
{
|
|
7393
|
+
"name": "--stat-card-value-font-size",
|
|
7394
|
+
"value": "var(--font-size-2xl)",
|
|
7395
|
+
"description": "Banded-header divider \u2014 tokenised (rule #44) so a service theme can make it * dashed / heavier / none without forking CSS. Pair with * --card-header-background-alpha: 0 for a quiet borderless-band header."
|
|
7396
|
+
},
|
|
7397
|
+
{
|
|
7398
|
+
"name": "--stat-card-value-line-height",
|
|
7399
|
+
"value": "1.1",
|
|
7400
|
+
"description": "Banded-header divider \u2014 tokenised (rule #44) so a service theme can make it * dashed / heavier / none without forking CSS. Pair with * --card-header-background-alpha: 0 for a quiet borderless-band header."
|
|
7401
|
+
},
|
|
7402
|
+
{
|
|
7403
|
+
"name": "--stat-card-value-font-weight",
|
|
7404
|
+
"value": "var(--font-weight-semibold)",
|
|
7405
|
+
"description": "Banded-header divider \u2014 tokenised (rule #44) so a service theme can make it * dashed / heavier / none without forking CSS. Pair with * --card-header-background-alpha: 0 for a quiet borderless-band header."
|
|
7406
|
+
},
|
|
7407
|
+
{
|
|
7408
|
+
"name": "--stat-card-hint-font-size",
|
|
7409
|
+
"value": "var(--font-size-xs)",
|
|
7410
|
+
"description": "Banded-header divider \u2014 tokenised (rule #44) so a service theme can make it * dashed / heavier / none without forking CSS. Pair with * --card-header-background-alpha: 0 for a quiet borderless-band header."
|
|
7411
|
+
},
|
|
7412
|
+
{
|
|
7413
|
+
"name": "--stat-card-gap",
|
|
7414
|
+
"value": "var(--space-stack-xs)",
|
|
7415
|
+
"description": "Banded-header divider \u2014 tokenised (rule #44) so a service theme can make it * dashed / heavier / none without forking CSS. Pair with * --card-header-background-alpha: 0 for a quiet borderless-band header."
|
|
7416
|
+
},
|
|
7417
|
+
{
|
|
7418
|
+
"name": "--stat-card-icon-size",
|
|
7419
|
+
"value": "2.25rem",
|
|
7420
|
+
"description": "Banded-header divider \u2014 tokenised (rule #44) so a service theme can make it * dashed / heavier / none without forking CSS. Pair with * --card-header-background-alpha: 0 for a quiet borderless-band header."
|
|
7421
|
+
},
|
|
7422
|
+
{
|
|
7423
|
+
"name": "--stat-card-delta-font-size",
|
|
7424
|
+
"value": "var(--font-size-xs)",
|
|
7425
|
+
"description": "Banded-header divider \u2014 tokenised (rule #44) so a service theme can make it * dashed / heavier / none without forking CSS. Pair with * --card-header-background-alpha: 0 for a quiet borderless-band header."
|
|
7426
|
+
},
|
|
7427
|
+
{
|
|
7428
|
+
"name": "--control-height-compact",
|
|
7429
|
+
"value": "1.75rem",
|
|
7430
|
+
"description": "Control primitive tokens: heights, horizontal padding, adjacent control sizes."
|
|
7431
|
+
},
|
|
7432
|
+
{
|
|
7433
|
+
"name": "--control-height-default",
|
|
7434
|
+
"value": "2rem",
|
|
7435
|
+
"description": "Control primitive tokens: heights, horizontal padding, adjacent control sizes."
|
|
7436
|
+
},
|
|
7437
|
+
{
|
|
7438
|
+
"name": "--control-height-comfortable",
|
|
7439
|
+
"value": "2.75rem",
|
|
7440
|
+
"description": "Control primitive tokens: heights, horizontal padding, adjacent control sizes."
|
|
7441
|
+
},
|
|
7442
|
+
{
|
|
7443
|
+
"name": "--control-padding-x-compact",
|
|
7444
|
+
"value": "var(--space-2)",
|
|
7445
|
+
"description": "Control primitive tokens: heights, horizontal padding, adjacent control sizes."
|
|
7446
|
+
},
|
|
7447
|
+
{
|
|
7448
|
+
"name": "--control-padding-x-default",
|
|
7449
|
+
"value": "var(--space-3)",
|
|
7450
|
+
"description": "Control primitive tokens: heights, horizontal padding, adjacent control sizes."
|
|
7451
|
+
},
|
|
7452
|
+
{
|
|
7453
|
+
"name": "--control-padding-x-comfortable",
|
|
7454
|
+
"value": "var(--space-4)",
|
|
7455
|
+
"description": "Control primitive tokens: heights, horizontal padding, adjacent control sizes."
|
|
7456
|
+
},
|
|
7457
|
+
{
|
|
7458
|
+
"name": "--control-height",
|
|
7459
|
+
"value": "var(--control-height-default)",
|
|
7460
|
+
"description": "Control primitive tokens: heights, horizontal padding, adjacent control sizes."
|
|
7461
|
+
},
|
|
7462
|
+
{
|
|
7463
|
+
"name": "--control-height-sm",
|
|
7464
|
+
"value": "calc(var(--control-height) - 0.25rem)",
|
|
7465
|
+
"description": "Adjacent control sizes, derived from the active --control-height. * Default/compact use a 4px/8px step; density overrides comfortable * (which steps 44\u219236\u219232 per the design's spacing-density spec)."
|
|
7466
|
+
},
|
|
7467
|
+
{
|
|
7468
|
+
"name": "--control-height-lg",
|
|
7469
|
+
"value": "calc(var(--control-height) + 0.25rem)",
|
|
7470
|
+
"description": "Adjacent control sizes, derived from the active --control-height. * Default/compact use a 4px/8px step; density overrides comfortable * (which steps 44\u219236\u219232 per the design's spacing-density spec)."
|
|
7471
|
+
},
|
|
7472
|
+
{
|
|
7473
|
+
"name": "--control-height-xs",
|
|
7474
|
+
"value": "calc(var(--control-height) - 0.5rem)",
|
|
7475
|
+
"description": "Adjacent control sizes, derived from the active --control-height. * Default/compact use a 4px/8px step; density overrides comfortable * (which steps 44\u219236\u219232 per the design's spacing-density spec)."
|
|
7476
|
+
},
|
|
7477
|
+
{
|
|
7478
|
+
"name": "--control-padding-x",
|
|
7479
|
+
"value": "var(--control-padding-x-default)",
|
|
7480
|
+
"description": "Adjacent control sizes, derived from the active --control-height. * Default/compact use a 4px/8px step; density overrides comfortable * (which steps 44\u219236\u219232 per the design's spacing-density spec)."
|
|
7481
|
+
},
|
|
7482
|
+
{
|
|
7483
|
+
"name": "--control-gap",
|
|
7484
|
+
"value": "var(--space-inline-sm)",
|
|
7485
|
+
"description": "Adjacent control sizes, derived from the active --control-height. * Default/compact use a 4px/8px step; density overrides comfortable * (which steps 44\u219236\u219232 per the design's spacing-density spec)."
|
|
7486
|
+
},
|
|
7487
|
+
{
|
|
7488
|
+
"name": "--control-gap-sm",
|
|
7489
|
+
"value": "var(--space-inline-xs)",
|
|
7490
|
+
"description": "Adjacent control sizes, derived from the active --control-height. * Default/compact use a 4px/8px step; density overrides comfortable * (which steps 44\u219236\u219232 per the design's spacing-density spec)."
|
|
7491
|
+
},
|
|
7492
|
+
{
|
|
7493
|
+
"name": "--control-radius",
|
|
7494
|
+
"value": "var(--radius)",
|
|
7495
|
+
"description": "Adjacent control sizes, derived from the active --control-height. * Default/compact use a 4px/8px step; density overrides comfortable * (which steps 44\u219236\u219232 per the design's spacing-density spec)."
|
|
7496
|
+
},
|
|
7497
|
+
{
|
|
7498
|
+
"name": "--control-icon-size",
|
|
7499
|
+
"value": "1rem",
|
|
7500
|
+
"description": "Adjacent control sizes, derived from the active --control-height. * Default/compact use a 4px/8px step; density overrides comfortable * (which steps 44\u219236\u219232 per the design's spacing-density spec)."
|
|
7501
|
+
},
|
|
7502
|
+
{
|
|
7503
|
+
"name": "--control-icon-size-sm",
|
|
7504
|
+
"value": "0.875rem",
|
|
7505
|
+
"description": "Adjacent control sizes, derived from the active --control-height. * Default/compact use a 4px/8px step; density overrides comfortable * (which steps 44\u219236\u219232 per the design's spacing-density spec)."
|
|
7506
|
+
},
|
|
7507
|
+
{
|
|
7508
|
+
"name": "--control-focus-ring-width",
|
|
7509
|
+
"value": "2px",
|
|
7510
|
+
"description": "Adjacent control sizes, derived from the active --control-height. * Default/compact use a 4px/8px step; density overrides comfortable * (which steps 44\u219236\u219232 per the design's spacing-density spec)."
|
|
7511
|
+
},
|
|
7512
|
+
{
|
|
7513
|
+
"name": "--checkbox-size",
|
|
7514
|
+
"value": "1rem",
|
|
7515
|
+
"description": "Adjacent control sizes, derived from the active --control-height. * Default/compact use a 4px/8px step; density overrides comfortable * (which steps 44\u219236\u219232 per the design's spacing-density spec)."
|
|
7516
|
+
},
|
|
7517
|
+
{
|
|
7518
|
+
"name": "--checkbox-size-compact",
|
|
7519
|
+
"value": "0.875rem",
|
|
7520
|
+
"description": "Adjacent control sizes, derived from the active --control-height. * Default/compact use a 4px/8px step; density overrides comfortable * (which steps 44\u219236\u219232 per the design's spacing-density spec)."
|
|
7521
|
+
},
|
|
7522
|
+
{
|
|
7523
|
+
"name": "--checkbox-size-comfortable",
|
|
7524
|
+
"value": "1.125rem",
|
|
7525
|
+
"description": "Adjacent control sizes, derived from the active --control-height. * Default/compact use a 4px/8px step; density overrides comfortable * (which steps 44\u219236\u219232 per the design's spacing-density spec)."
|
|
7526
|
+
},
|
|
7527
|
+
{
|
|
7528
|
+
"name": "--choice-gap",
|
|
7529
|
+
"value": "var(--space-inline-sm)",
|
|
7530
|
+
"description": "Adjacent control sizes, derived from the active --control-height. * Default/compact use a 4px/8px step; density overrides comfortable * (which steps 44\u219236\u219232 per the design's spacing-density spec)."
|
|
7531
|
+
},
|
|
7532
|
+
{
|
|
7533
|
+
"name": "--choice-group-gap-x",
|
|
7534
|
+
"value": "var(--space-6)",
|
|
7535
|
+
"description": "Adjacent control sizes, derived from the active --control-height. * Default/compact use a 4px/8px step; density overrides comfortable * (which steps 44\u219236\u219232 per the design's spacing-density spec)."
|
|
7536
|
+
},
|
|
7537
|
+
{
|
|
7538
|
+
"name": "--choice-group-gap-y",
|
|
7539
|
+
"value": "var(--space-3)",
|
|
7540
|
+
"description": "Adjacent control sizes, derived from the active --control-height. * Default/compact use a 4px/8px step; density overrides comfortable * (which steps 44\u219236\u219232 per the design's spacing-density spec)."
|
|
7541
|
+
},
|
|
7542
|
+
{
|
|
7543
|
+
"name": "--choice-description-gap",
|
|
7544
|
+
"value": "0.125rem",
|
|
7545
|
+
"description": "Adjacent control sizes, derived from the active --control-height. * Default/compact use a 4px/8px step; density overrides comfortable * (which steps 44\u219236\u219232 per the design's spacing-density spec)."
|
|
7546
|
+
},
|
|
7547
|
+
{
|
|
7548
|
+
"name": "--choice-control-offset",
|
|
7549
|
+
"value": "0.125rem",
|
|
7550
|
+
"description": "Adjacent control sizes, derived from the active --control-height. * Default/compact use a 4px/8px step; density overrides comfortable * (which steps 44\u219236\u219232 per the design's spacing-density spec)."
|
|
7551
|
+
},
|
|
7552
|
+
{
|
|
7553
|
+
"name": "--switch-width",
|
|
7554
|
+
"value": "2.25rem",
|
|
7555
|
+
"description": "Adjacent control sizes, derived from the active --control-height. * Default/compact use a 4px/8px step; density overrides comfortable * (which steps 44\u219236\u219232 per the design's spacing-density spec)."
|
|
7556
|
+
},
|
|
7557
|
+
{
|
|
7558
|
+
"name": "--switch-width-compact",
|
|
7559
|
+
"value": "2rem",
|
|
7560
|
+
"description": "Adjacent control sizes, derived from the active --control-height. * Default/compact use a 4px/8px step; density overrides comfortable * (which steps 44\u219236\u219232 per the design's spacing-density spec)."
|
|
7561
|
+
},
|
|
7562
|
+
{
|
|
7563
|
+
"name": "--switch-width-comfortable",
|
|
7564
|
+
"value": "2.5rem",
|
|
7565
|
+
"description": "Adjacent control sizes, derived from the active --control-height. * Default/compact use a 4px/8px step; density overrides comfortable * (which steps 44\u219236\u219232 per the design's spacing-density spec)."
|
|
7566
|
+
},
|
|
7567
|
+
{
|
|
7568
|
+
"name": "--switch-height",
|
|
7569
|
+
"value": "1.25rem",
|
|
7570
|
+
"description": "Adjacent control sizes, derived from the active --control-height. * Default/compact use a 4px/8px step; density overrides comfortable * (which steps 44\u219236\u219232 per the design's spacing-density spec)."
|
|
7571
|
+
},
|
|
7572
|
+
{
|
|
7573
|
+
"name": "--switch-height-compact",
|
|
7574
|
+
"value": "1.125rem",
|
|
7575
|
+
"description": "Adjacent control sizes, derived from the active --control-height. * Default/compact use a 4px/8px step; density overrides comfortable * (which steps 44\u219236\u219232 per the design's spacing-density spec)."
|
|
7576
|
+
},
|
|
7577
|
+
{
|
|
7578
|
+
"name": "--switch-height-comfortable",
|
|
7579
|
+
"value": "1.375rem",
|
|
7580
|
+
"description": "Adjacent control sizes, derived from the active --control-height. * Default/compact use a 4px/8px step; density overrides comfortable * (which steps 44\u219236\u219232 per the design's spacing-density spec)."
|
|
7581
|
+
},
|
|
7582
|
+
{
|
|
7583
|
+
"name": "--switch-thumb-size",
|
|
7584
|
+
"value": "1rem",
|
|
7585
|
+
"description": "Adjacent control sizes, derived from the active --control-height. * Default/compact use a 4px/8px step; density overrides comfortable * (which steps 44\u219236\u219232 per the design's spacing-density spec)."
|
|
7586
|
+
},
|
|
7587
|
+
{
|
|
7588
|
+
"name": "--switch-thumb-size-compact",
|
|
7589
|
+
"value": "0.875rem",
|
|
7590
|
+
"description": "Adjacent control sizes, derived from the active --control-height. * Default/compact use a 4px/8px step; density overrides comfortable * (which steps 44\u219236\u219232 per the design's spacing-density spec)."
|
|
7591
|
+
},
|
|
7592
|
+
{
|
|
7593
|
+
"name": "--switch-thumb-size-comfortable",
|
|
7594
|
+
"value": "1.125rem",
|
|
7595
|
+
"description": "Adjacent control sizes, derived from the active --control-height. * Default/compact use a 4px/8px step; density overrides comfortable * (which steps 44\u219236\u219232 per the design's spacing-density spec)."
|
|
7596
|
+
},
|
|
7597
|
+
{
|
|
7598
|
+
"name": "--switch-thumb-translate",
|
|
7599
|
+
"value": "1rem",
|
|
7600
|
+
"description": "Adjacent control sizes, derived from the active --control-height. * Default/compact use a 4px/8px step; density overrides comfortable * (which steps 44\u219236\u219232 per the design's spacing-density spec)."
|
|
7601
|
+
},
|
|
7602
|
+
{
|
|
7603
|
+
"name": "--switch-thumb-translate-compact",
|
|
7604
|
+
"value": "0.875rem",
|
|
7605
|
+
"description": "Adjacent control sizes, derived from the active --control-height. * Default/compact use a 4px/8px step; density overrides comfortable * (which steps 44\u219236\u219232 per the design's spacing-density spec)."
|
|
7606
|
+
},
|
|
7607
|
+
{
|
|
7608
|
+
"name": "--switch-thumb-translate-comfortable",
|
|
7609
|
+
"value": "1.125rem",
|
|
7610
|
+
"description": "Adjacent control sizes, derived from the active --control-height. * Default/compact use a 4px/8px step; density overrides comfortable * (which steps 44\u219236\u219232 per the design's spacing-density spec)."
|
|
7611
|
+
},
|
|
7612
|
+
{
|
|
7613
|
+
"name": "--slider-track-height",
|
|
7614
|
+
"value": "0.375rem",
|
|
7615
|
+
"description": "Adjacent control sizes, derived from the active --control-height. * Default/compact use a 4px/8px step; density overrides comfortable * (which steps 44\u219236\u219232 per the design's spacing-density spec)."
|
|
7616
|
+
},
|
|
7617
|
+
{
|
|
7618
|
+
"name": "--slider-thumb-size",
|
|
7619
|
+
"value": "1rem",
|
|
7620
|
+
"description": "Adjacent control sizes, derived from the active --control-height. * Default/compact use a 4px/8px step; density overrides comfortable * (which steps 44\u219236\u219232 per the design's spacing-density spec)."
|
|
7621
|
+
},
|
|
7622
|
+
{
|
|
7623
|
+
"name": "--color-picker-input-width",
|
|
7624
|
+
"value": "6.5rem",
|
|
7625
|
+
"description": "Adjacent control sizes, derived from the active --control-height. * Default/compact use a 4px/8px step; density overrides comfortable * (which steps 44\u219236\u219232 per the design's spacing-density spec)."
|
|
7626
|
+
},
|
|
7627
|
+
{
|
|
7628
|
+
"name": "--command-list-max-height",
|
|
7629
|
+
"value": "min(300px, 50vh)",
|
|
7630
|
+
"description": "Adjacent control sizes, derived from the active --control-height. * Default/compact use a 4px/8px step; density overrides comfortable * (which steps 44\u219236\u219232 per the design's spacing-density spec)."
|
|
7631
|
+
},
|
|
7632
|
+
{
|
|
7633
|
+
"name": "--command-input-padding-x",
|
|
7634
|
+
"value": "var(--space-3)",
|
|
7635
|
+
"description": "Adjacent control sizes, derived from the active --control-height. * Default/compact use a 4px/8px step; density overrides comfortable * (which steps 44\u219236\u219232 per the design's spacing-density spec)."
|
|
7636
|
+
},
|
|
7637
|
+
{
|
|
7638
|
+
"name": "--command-group-padding",
|
|
7639
|
+
"value": "var(--space-1)",
|
|
7640
|
+
"description": "Adjacent control sizes, derived from the active --control-height. * Default/compact use a 4px/8px step; density overrides comfortable * (which steps 44\u219236\u219232 per the design's spacing-density spec)."
|
|
7641
|
+
},
|
|
7642
|
+
{
|
|
7643
|
+
"name": "--command-item-padding-y",
|
|
7644
|
+
"value": "var(--space-2)",
|
|
7645
|
+
"description": "Adjacent control sizes, derived from the active --control-height. * Default/compact use a 4px/8px step; density overrides comfortable * (which steps 44\u219236\u219232 per the design's spacing-density spec)."
|
|
7646
|
+
},
|
|
7647
|
+
{
|
|
7648
|
+
"name": "--command-item-padding-x",
|
|
7649
|
+
"value": "var(--space-2)",
|
|
7650
|
+
"description": "Adjacent control sizes, derived from the active --control-height. * Default/compact use a 4px/8px step; density overrides comfortable * (which steps 44\u219236\u219232 per the design's spacing-density spec)."
|
|
7651
|
+
},
|
|
7652
|
+
{
|
|
7653
|
+
"name": "--search-input-edge-inset",
|
|
7654
|
+
"value": "var(--space-3)",
|
|
7655
|
+
"description": "Adjacent control sizes, derived from the active --control-height. * Default/compact use a 4px/8px step; density overrides comfortable * (which steps 44\u219236\u219232 per the design's spacing-density spec)."
|
|
7656
|
+
},
|
|
7657
|
+
{
|
|
7658
|
+
"name": "--search-input-start-padding",
|
|
7659
|
+
"value": "calc( var(--search-input-edge-inset) + var(--control-icon-size) + var(--control-gap) )",
|
|
7660
|
+
"description": "Adjacent control sizes, derived from the active --control-height. * Default/compact use a 4px/8px step; density overrides comfortable * (which steps 44\u219236\u219232 per the design's spacing-density spec)."
|
|
7661
|
+
},
|
|
7662
|
+
{
|
|
7663
|
+
"name": "--search-input-end-padding",
|
|
7664
|
+
"value": "calc( var(--search-input-edge-inset) + var(--control-icon-size) + var(--control-gap) )",
|
|
7665
|
+
"description": "Adjacent control sizes, derived from the active --control-height. * Default/compact use a 4px/8px step; density overrides comfortable * (which steps 44\u219236\u219232 per the design's spacing-density spec)."
|
|
7666
|
+
},
|
|
7667
|
+
{
|
|
7668
|
+
"name": "--control-height-compact",
|
|
7669
|
+
"value": "2.75rem",
|
|
7670
|
+
"description": "Rule #24 \u2014 on touch devices (coarse pointer) interactive controls keep a \u226544px tap target * regardless of density; desktop (fine pointer) keeps the compact heights above. --control-height * resolves through these via var(), so inputs/buttons/selects/table rows all bump together."
|
|
7671
|
+
},
|
|
7672
|
+
{
|
|
7673
|
+
"name": "--control-height-default",
|
|
7674
|
+
"value": "2.75rem",
|
|
7675
|
+
"description": "Rule #24 \u2014 on touch devices (coarse pointer) interactive controls keep a \u226544px tap target * regardless of density; desktop (fine pointer) keeps the compact heights above. --control-height * resolves through these via var(), so inputs/buttons/selects/table rows all bump together."
|
|
7676
|
+
},
|
|
7677
|
+
{
|
|
7678
|
+
"name": "--choice-description-font-size",
|
|
7679
|
+
"value": "var(--font-size-xs)",
|
|
7680
|
+
"description": "Rule #24 \u2014 on touch devices (coarse pointer) interactive controls keep a \u226544px tap target * regardless of density; desktop (fine pointer) keeps the compact heights above. --control-height * resolves through these via var(), so inputs/buttons/selects/table rows all bump together."
|
|
7681
|
+
},
|
|
7682
|
+
{
|
|
7683
|
+
"name": "--color-picker-hex-font-size",
|
|
7684
|
+
"value": "var(--font-size-xs)",
|
|
7685
|
+
"description": "Rule #24 \u2014 on touch devices (coarse pointer) interactive controls keep a \u226544px tap target * regardless of density; desktop (fine pointer) keeps the compact heights above. --control-height * resolves through these via var(), so inputs/buttons/selects/table rows all bump together."
|
|
7686
|
+
},
|
|
7687
|
+
{
|
|
7688
|
+
"name": "--command-group-heading-font-size",
|
|
7689
|
+
"value": "var(--font-size-xs)",
|
|
7690
|
+
"description": "Rule #24 \u2014 on touch devices (coarse pointer) interactive controls keep a \u226544px tap target * regardless of density; desktop (fine pointer) keeps the compact heights above. --control-height * resolves through these via var(), so inputs/buttons/selects/table rows all bump together."
|
|
7691
|
+
},
|
|
7692
|
+
{
|
|
7693
|
+
"name": "--search-input-label-font-size",
|
|
7694
|
+
"value": "var(--font-size-xs)",
|
|
7695
|
+
"description": "Rule #24 \u2014 on touch devices (coarse pointer) interactive controls keep a \u226544px tap target * regardless of density; desktop (fine pointer) keeps the compact heights above. --control-height * resolves through these via var(), so inputs/buttons/selects/table rows all bump together."
|
|
7696
|
+
},
|
|
7697
|
+
{
|
|
7698
|
+
"name": "--tag-input-chip-font-size",
|
|
7699
|
+
"value": "var(--font-size-xs)",
|
|
7700
|
+
"description": "Rule #24 \u2014 on touch devices (coarse pointer) interactive controls keep a \u226544px tap target * regardless of density; desktop (fine pointer) keeps the compact heights above. --control-height * resolves through these via var(), so inputs/buttons/selects/table rows all bump together."
|
|
7701
|
+
},
|
|
7702
|
+
{
|
|
7703
|
+
"name": "--toggle-sm-font-size",
|
|
7704
|
+
"value": "var(--font-size-xs)",
|
|
7705
|
+
"description": "Rule #24 \u2014 on touch devices (coarse pointer) interactive controls keep a \u226544px tap target * regardless of density; desktop (fine pointer) keeps the compact heights above. --control-height * resolves through these via var(), so inputs/buttons/selects/table rows all bump together."
|
|
7706
|
+
},
|
|
7707
|
+
{
|
|
7708
|
+
"name": "--button-sm-font-size",
|
|
7709
|
+
"value": "var(--font-size-xs)",
|
|
7710
|
+
"description": "Rule #24 \u2014 on touch devices (coarse pointer) interactive controls keep a \u226544px tap target * regardless of density; desktop (fine pointer) keeps the compact heights above. --control-height * resolves through these via var(), so inputs/buttons/selects/table rows all bump together."
|
|
7711
|
+
},
|
|
7712
|
+
{
|
|
7713
|
+
"name": "--progress-label-font-size",
|
|
7714
|
+
"value": "var(--font-size-xs)",
|
|
7715
|
+
"description": "Data-display component tokens \u2014 small-by-design text knobs (rule #45/#46)."
|
|
7716
|
+
},
|
|
7717
|
+
{
|
|
7718
|
+
"name": "--tree-item-title-font-size",
|
|
7719
|
+
"value": "var(--font-size-xs)",
|
|
7720
|
+
"description": "Data-display component tokens \u2014 small-by-design text knobs (rule #45/#46)."
|
|
7721
|
+
},
|
|
7722
|
+
{
|
|
7723
|
+
"name": "--tree-item-description-font-size",
|
|
7724
|
+
"value": "var(--font-size-xs)",
|
|
7725
|
+
"description": "Data-display component tokens \u2014 small-by-design text knobs (rule #45/#46)."
|
|
7726
|
+
},
|
|
7727
|
+
{
|
|
7728
|
+
"name": "--timeline-note-font-size",
|
|
7729
|
+
"value": "var(--font-size-xs)",
|
|
7730
|
+
"description": "Data-display component tokens \u2014 small-by-design text knobs (rule #45/#46)."
|
|
7731
|
+
},
|
|
7732
|
+
{
|
|
7733
|
+
"name": "--password-strength-score-font-size",
|
|
7734
|
+
"value": "var(--font-size-xs)",
|
|
7735
|
+
"description": "Data-entry component tokens \u2014 small-by-design text knobs (rule #45/#46)."
|
|
7736
|
+
},
|
|
7737
|
+
{
|
|
7738
|
+
"name": "--password-strength-checklist-font-size",
|
|
7739
|
+
"value": "var(--font-size-xs)",
|
|
7740
|
+
"description": "Data-entry component tokens \u2014 small-by-design text knobs (rule #45/#46)."
|
|
7741
|
+
},
|
|
7742
|
+
{
|
|
7743
|
+
"name": "--dialog-space-x",
|
|
7744
|
+
"value": "var(--space-chrome-x)",
|
|
7745
|
+
"description": "Dialog inset defaults to the shared global chrome tokens (override --space-chrome-* once for the * whole system, or --dialog-space-x/-y for dialogs only)."
|
|
7746
|
+
},
|
|
7747
|
+
{
|
|
7748
|
+
"name": "--dialog-space-y",
|
|
7749
|
+
"value": "var(--space-chrome-y)",
|
|
7750
|
+
"description": "Dialog inset defaults to the shared global chrome tokens (override --space-chrome-* once for the * whole system, or --dialog-space-x/-y for dialogs only)."
|
|
7751
|
+
},
|
|
7752
|
+
{
|
|
7753
|
+
"name": "--dialog-space-inset",
|
|
7754
|
+
"value": "var(--dialog-space-y) var(--dialog-space-x)",
|
|
7755
|
+
"description": "Dialog inset defaults to the shared global chrome tokens (override --space-chrome-* once for the * whole system, or --dialog-space-x/-y for dialogs only)."
|
|
7756
|
+
},
|
|
7757
|
+
{
|
|
7758
|
+
"name": "--dialog-space-gap",
|
|
7759
|
+
"value": "var(--space-stack-md)",
|
|
7760
|
+
"description": "Dialog inset defaults to the shared global chrome tokens (override --space-chrome-* once for the * whole system, or --dialog-space-x/-y for dialogs only)."
|
|
7761
|
+
},
|
|
7762
|
+
{
|
|
7763
|
+
"name": "--dialog-close-space-offset",
|
|
7764
|
+
"value": "var(--space-4)",
|
|
7765
|
+
"description": "Dialog inset defaults to the shared global chrome tokens (override --space-chrome-* once for the * whole system, or --dialog-space-x/-y for dialogs only)."
|
|
7766
|
+
},
|
|
7767
|
+
{
|
|
7768
|
+
"name": "--alert-space-inset",
|
|
7769
|
+
"value": "var(--space-section-active)",
|
|
7770
|
+
"description": "Dialog inset defaults to the shared global chrome tokens (override --space-chrome-* once for the * whole system, or --dialog-space-x/-y for dialogs only)."
|
|
7771
|
+
},
|
|
7772
|
+
{
|
|
7773
|
+
"name": "--alert-space-gap",
|
|
7774
|
+
"value": "var(--space-inline-md)",
|
|
7775
|
+
"description": "Dialog inset defaults to the shared global chrome tokens (override --space-chrome-* once for the * whole system, or --dialog-space-x/-y for dialogs only)."
|
|
7776
|
+
},
|
|
7777
|
+
{
|
|
7778
|
+
"name": "--alert-inner-space-gap",
|
|
7779
|
+
"value": "var(--space-stack-sm)",
|
|
7780
|
+
"description": "Dialog inset defaults to the shared global chrome tokens (override --space-chrome-* once for the * whole system, or --dialog-space-x/-y for dialogs only)."
|
|
7781
|
+
},
|
|
7782
|
+
{
|
|
7783
|
+
"name": "--alert-dismiss-space-offset",
|
|
7784
|
+
"value": "var(--space-3)",
|
|
7785
|
+
"description": "Dialog inset defaults to the shared global chrome tokens (override --space-chrome-* once for the * whole system, or --dialog-space-x/-y for dialogs only)."
|
|
7786
|
+
},
|
|
7787
|
+
{
|
|
7788
|
+
"name": "--alert-bg-alpha",
|
|
7789
|
+
"value": "0.05",
|
|
7790
|
+
"description": "Soft (subtle) semantic tint ratios \u2014 themeable so a service can hit its exact spec * (a brand's success-bg/-border are often more present than the faint 5%/30% default)."
|
|
7791
|
+
},
|
|
7792
|
+
{
|
|
7793
|
+
"name": "--alert-border-alpha",
|
|
7794
|
+
"value": "0.3",
|
|
7795
|
+
"description": "Soft (subtle) semantic tint ratios \u2014 themeable so a service can hit its exact spec * (a brand's success-bg/-border are often more present than the faint 5%/30% default)."
|
|
7796
|
+
},
|
|
7797
|
+
{
|
|
7798
|
+
"name": "--empty-state-space-y",
|
|
7799
|
+
"value": "var(--space-10)",
|
|
7800
|
+
"description": "Soft (subtle) semantic tint ratios \u2014 themeable so a service can hit its exact spec * (a brand's success-bg/-border are often more present than the faint 5%/30% default)."
|
|
7801
|
+
},
|
|
7802
|
+
{
|
|
7803
|
+
"name": "--empty-state-space-x",
|
|
7804
|
+
"value": "var(--space-6)",
|
|
7805
|
+
"description": "Soft (subtle) semantic tint ratios \u2014 themeable so a service can hit its exact spec * (a brand's success-bg/-border are often more present than the faint 5%/30% default)."
|
|
7806
|
+
},
|
|
7807
|
+
{
|
|
7808
|
+
"name": "--skeleton-row-gap",
|
|
7809
|
+
"value": "var(--space-stack-sm)",
|
|
7810
|
+
"description": "Soft (subtle) semantic tint ratios \u2014 themeable so a service can hit its exact spec * (a brand's success-bg/-border are often more present than the faint 5%/30% default)."
|
|
7811
|
+
},
|
|
7812
|
+
{
|
|
7813
|
+
"name": "--skeleton-cell-gap",
|
|
7814
|
+
"value": "var(--space-inline-lg)",
|
|
7815
|
+
"description": "Soft (subtle) semantic tint ratios \u2014 themeable so a service can hit its exact spec * (a brand's success-bg/-border are often more present than the faint 5%/30% default)."
|
|
7816
|
+
},
|
|
7817
|
+
{
|
|
7818
|
+
"name": "--skeleton-card-inset",
|
|
7819
|
+
"value": "var(--space-section-active)",
|
|
7820
|
+
"description": "Soft (subtle) semantic tint ratios \u2014 themeable so a service can hit its exact spec * (a brand's success-bg/-border are often more present than the faint 5%/30% default)."
|
|
7821
|
+
},
|
|
7822
|
+
{
|
|
7823
|
+
"name": "--skeleton-radius",
|
|
7824
|
+
"value": "var(--radius)",
|
|
7825
|
+
"description": "Soft (subtle) semantic tint ratios \u2014 themeable so a service can hit its exact spec * (a brand's success-bg/-border are often more present than the faint 5%/30% default)."
|
|
7826
|
+
},
|
|
7827
|
+
{
|
|
7828
|
+
"name": "--form-label-width",
|
|
7829
|
+
"value": "max-content",
|
|
7830
|
+
"description": "Width of the label column in horizontal/inline layout. A service theme sets * this once (e.g. 110px) to align every form to its design grid; the Form/ * FormField `labelWidth` prop overrides per form/field."
|
|
7831
|
+
},
|
|
7832
|
+
{
|
|
7833
|
+
"name": "--form-label-gap",
|
|
7834
|
+
"value": "var(--space-4)",
|
|
7835
|
+
"description": "Column gap between the label and its control in horizontal/inline layout."
|
|
7836
|
+
},
|
|
7837
|
+
{
|
|
7838
|
+
"name": "--pagination-gap",
|
|
7839
|
+
"value": "var(--space-inline-sm)",
|
|
7840
|
+
"description": "Navigation primitive tokens: pagination, filters, compact pickers."
|
|
7841
|
+
},
|
|
7842
|
+
{
|
|
7843
|
+
"name": "--pagination-item-gap",
|
|
7844
|
+
"value": "var(--space-inline-xs)",
|
|
7845
|
+
"description": "Navigation primitive tokens: pagination, filters, compact pickers."
|
|
7846
|
+
},
|
|
7847
|
+
{
|
|
7848
|
+
"name": "--pagination-size-width",
|
|
7849
|
+
"value": "5.5rem",
|
|
7850
|
+
"description": "Navigation primitive tokens: pagination, filters, compact pickers."
|
|
7851
|
+
},
|
|
7852
|
+
{
|
|
7853
|
+
"name": "--pagination-total-font-size",
|
|
7854
|
+
"value": "var(--font-size-sm)",
|
|
7855
|
+
"description": "Navigation primitive tokens: pagination, filters, compact pickers."
|
|
7856
|
+
},
|
|
7857
|
+
{
|
|
7858
|
+
"name": "--filter-bar-gap",
|
|
7859
|
+
"value": "var(--space-3)",
|
|
7860
|
+
"description": "Navigation primitive tokens: pagination, filters, compact pickers."
|
|
7861
|
+
},
|
|
7862
|
+
{
|
|
7863
|
+
"name": "--filter-bar-padding-y",
|
|
7864
|
+
"value": "var(--space-2)",
|
|
7865
|
+
"description": "Navigation primitive tokens: pagination, filters, compact pickers."
|
|
7866
|
+
},
|
|
7867
|
+
{
|
|
7868
|
+
"name": "--filter-label-font-size",
|
|
7869
|
+
"value": "var(--font-size-xs)",
|
|
7870
|
+
"description": "Navigation primitive tokens: pagination, filters, compact pickers."
|
|
7871
|
+
},
|
|
7872
|
+
{
|
|
7873
|
+
"name": "--filter-picker-width-sm",
|
|
7874
|
+
"value": "11rem",
|
|
7875
|
+
"description": "Navigation primitive tokens: pagination, filters, compact pickers."
|
|
7876
|
+
},
|
|
7877
|
+
{
|
|
7878
|
+
"name": "--filter-picker-width-md",
|
|
7879
|
+
"value": "14rem",
|
|
7880
|
+
"description": "Navigation primitive tokens: pagination, filters, compact pickers."
|
|
7881
|
+
},
|
|
7882
|
+
{
|
|
7883
|
+
"name": "--breadcrumb-font-size",
|
|
7884
|
+
"value": "var(--font-size-xs)",
|
|
7885
|
+
"description": "Navigation primitive tokens: pagination, filters, compact pickers."
|
|
7886
|
+
},
|
|
7887
|
+
{
|
|
7888
|
+
"name": "--menubar-shortcut-font-size",
|
|
7889
|
+
"value": "var(--font-size-xs)",
|
|
7890
|
+
"description": "Navigation primitive tokens: pagination, filters, compact pickers."
|
|
7891
|
+
},
|
|
7892
|
+
{
|
|
7893
|
+
"name": "--sidebar-section-label-font-size",
|
|
7894
|
+
"value": "var(--font-size-2xs)",
|
|
7895
|
+
"description": "Shell (sidebar / topbar / kbd) component tokens \u2014 small-by-design text * knobs (rule #45/#46). A service re-tunes chrome text without moving the * global scale."
|
|
7896
|
+
},
|
|
7897
|
+
{
|
|
7898
|
+
"name": "--sidebar-product-tenant-font-size",
|
|
7899
|
+
"value": "var(--font-size-2xs)",
|
|
7900
|
+
"description": "Shell (sidebar / topbar / kbd) component tokens \u2014 small-by-design text * knobs (rule #45/#46). A service re-tunes chrome text without moving the * global scale."
|
|
7901
|
+
},
|
|
7902
|
+
{
|
|
7903
|
+
"name": "--sidebar-badge-font-size",
|
|
7904
|
+
"value": "var(--font-size-2xs)",
|
|
7905
|
+
"description": "Shell (sidebar / topbar / kbd) component tokens \u2014 small-by-design text * knobs (rule #45/#46). A service re-tunes chrome text without moving the * global scale."
|
|
7906
|
+
},
|
|
7907
|
+
{
|
|
7908
|
+
"name": "--sidebar-user-role-font-size",
|
|
7909
|
+
"value": "var(--font-size-2xs)",
|
|
7910
|
+
"description": "Shell (sidebar / topbar / kbd) component tokens \u2014 small-by-design text * knobs (rule #45/#46). A service re-tunes chrome text without moving the * global scale."
|
|
7911
|
+
},
|
|
7912
|
+
{
|
|
7913
|
+
"name": "--sidebar-nav-sub-font-size",
|
|
7914
|
+
"value": "var(--font-size-xs)",
|
|
7915
|
+
"description": "Shell (sidebar / topbar / kbd) component tokens \u2014 small-by-design text * knobs (rule #45/#46). A service re-tunes chrome text without moving the * global scale."
|
|
7916
|
+
},
|
|
7917
|
+
{
|
|
7918
|
+
"name": "--sidebar-flyout-title-font-size",
|
|
7919
|
+
"value": "var(--font-size-xs)",
|
|
7920
|
+
"description": "Shell (sidebar / topbar / kbd) component tokens \u2014 small-by-design text * knobs (rule #45/#46). A service re-tunes chrome text without moving the * global scale."
|
|
7921
|
+
},
|
|
7922
|
+
{
|
|
7923
|
+
"name": "--topbar-chip-icon-font-size",
|
|
7924
|
+
"value": "var(--font-size-2xs)",
|
|
7925
|
+
"description": "Shell (sidebar / topbar / kbd) component tokens \u2014 small-by-design text * knobs (rule #45/#46). A service re-tunes chrome text without moving the * global scale."
|
|
7926
|
+
},
|
|
7927
|
+
{
|
|
7928
|
+
"name": "--kbd-font-size",
|
|
7929
|
+
"value": "var(--font-size-2xs)",
|
|
7930
|
+
"description": "Shell (sidebar / topbar / kbd) component tokens \u2014 small-by-design text * knobs (rule #45/#46). A service re-tunes chrome text without moving the * global scale."
|
|
7931
|
+
},
|
|
7932
|
+
{
|
|
7933
|
+
"name": "--sidebar-logo-mark-font-size",
|
|
7934
|
+
"value": "var(--font-size-xs)",
|
|
7935
|
+
"description": "Shell (sidebar / topbar / kbd) component tokens \u2014 small-by-design text * knobs (rule #45/#46). A service re-tunes chrome text without moving the * global scale."
|
|
7936
|
+
},
|
|
7937
|
+
{
|
|
7938
|
+
"name": "--sidebar-avatar-font-size",
|
|
7939
|
+
"value": "var(--font-size-2xs)",
|
|
7940
|
+
"description": "Shell (sidebar / topbar / kbd) component tokens \u2014 small-by-design text * knobs (rule #45/#46). A service re-tunes chrome text without moving the * global scale."
|
|
7941
|
+
},
|
|
7942
|
+
{
|
|
7943
|
+
"name": "--sidebar-user-name-font-size",
|
|
7944
|
+
"value": "var(--font-size-xs)",
|
|
7945
|
+
"description": "Shell (sidebar / topbar / kbd) component tokens \u2014 small-by-design text * knobs (rule #45/#46). A service re-tunes chrome text without moving the * global scale."
|
|
7946
|
+
},
|
|
7947
|
+
{
|
|
7948
|
+
"name": "--table-row-height-compact",
|
|
7949
|
+
"value": "1.75rem",
|
|
7950
|
+
"description": "Table component tokens: row height, cell padding."
|
|
7951
|
+
},
|
|
7952
|
+
{
|
|
7953
|
+
"name": "--table-row-height-default",
|
|
7954
|
+
"value": "2rem",
|
|
7955
|
+
"description": "Table component tokens: row height, cell padding."
|
|
7956
|
+
},
|
|
7957
|
+
{
|
|
7958
|
+
"name": "--table-row-height-comfortable",
|
|
7959
|
+
"value": "2.75rem",
|
|
7960
|
+
"description": "Table component tokens: row height, cell padding."
|
|
7961
|
+
},
|
|
7962
|
+
{
|
|
7963
|
+
"name": "--table-row-height",
|
|
7964
|
+
"value": "var(--table-row-height-default)",
|
|
7965
|
+
"description": "Table component tokens: row height, cell padding."
|
|
7966
|
+
},
|
|
7967
|
+
{
|
|
7968
|
+
"name": "--table-cell-padding-y",
|
|
7969
|
+
"value": "var(--space-2)",
|
|
7970
|
+
"description": "Table component tokens: row height, cell padding."
|
|
7971
|
+
},
|
|
7972
|
+
{
|
|
7973
|
+
"name": "--table-cell-space-x",
|
|
7974
|
+
"value": "var(--control-padding-x)",
|
|
7975
|
+
"description": "Table component tokens: row height, cell padding."
|
|
7976
|
+
},
|
|
7977
|
+
{
|
|
7978
|
+
"name": "--table-head-font-size",
|
|
7979
|
+
"value": "var(--font-size-xs)",
|
|
7980
|
+
"description": "Table component tokens: row height, cell padding."
|
|
7981
|
+
}
|
|
7982
|
+
];
|
|
7983
|
+
|
|
7055
7984
|
// src/data/rules.ts
|
|
7056
7985
|
var CARDINAL_RULES = [
|
|
7057
7986
|
{
|
|
@@ -7263,6 +8192,26 @@ var CARDINAL_RULES = [
|
|
|
7263
8192
|
number: 42,
|
|
7264
8193
|
title: "Props & Tokens Before Customization",
|
|
7265
8194
|
body: "Before reaching for a Tailwind class, inline `style`, or extra CSS, you MUST first check whether the component already supports the need via a PROP, a design TOKEN, or a layout/typography PRIMITIVE. godx-ui is meant to be enough on its own (Ant-Design-style): `className` is for genuine one-offs only \u2014 never to redo what an API already does. Specifically: (1) NEVER hand-roll typography \u2014 no `text-[13px]`/`text-[11px]` arbitrary px (bypasses the golden type scale), no `font-medium`/`font-semibold`/`text-muted-foreground` on a raw `<span>`; use `<Text size tone weight tabular mono>` / `<Heading level>`. (2) NEVER hand-roll a trivial flex/grid wrapper; use `<Flex>` / `<ResponsiveGrid>` / `<PageContainer>`. (3) NEVER set a control's radius/height/colour with a utility when a `shape`/`size`/`tone`/token exists. If a real need has NO prop/token/primitive, that is a library GAP \u2014 file it (draft_bug_report), don't paper over it with ad-hoc Tailwind."
|
|
8195
|
+
},
|
|
8196
|
+
{
|
|
8197
|
+
number: 43,
|
|
8198
|
+
title: "Every form control goes through FormField",
|
|
8199
|
+
body: "Consumers MUST wrap every labelled form control (Input, Select, DatePicker, DateRangePicker, NumberInput, Radio.Group, Checkbox groups, range pairs, ...) in FormField \u2014 it owns the label (aria-labelledby, never a dangling <label for>), auto-generates/injects the control id, and wires aria-describedby/aria-errormessage/aria-invalid. Bare controls are the rare exception (e.g. a toolbar quick-filter with its own aria-label) and must carry id/name + aria-label themselves. Never hand-roll a label+control stack with Text/Label."
|
|
8200
|
+
},
|
|
8201
|
+
{
|
|
8202
|
+
number: 44,
|
|
8203
|
+
title: "Chrome is a token, default quiet",
|
|
8204
|
+
body: "Any decorative chrome a component draws \u2014 dividers, separator borders, and the padding that exists only to space that chrome \u2014 MUST read a token; never hard-code it in `src/styles/*.css` (a hard-coded `border-bottom: 1px solid hsl(var(--border))` leaves consumers no off-switch short of a variant fork). The DEFAULT is the quietest state (`none` / balanced rhythm); a service theme opts IN, e.g. `--page-header-divider: 1px solid hsl(var(--border))`. Born from real consumption: PageContainer's header divider was undisableable until tokenised."
|
|
8205
|
+
},
|
|
8206
|
+
{
|
|
8207
|
+
number: 45,
|
|
8208
|
+
title: "Every service-tunable constant gets a knob",
|
|
8209
|
+
body: 'When component CSS encodes a geometry choice that a service plausibly re-tunes to match its design handoff \u2014 form label column width, label\u2194control gap, header insets \u2014 it MUST be a documented component token (current value as the default). The theme sets it ONCE globally; props (`labelWidth`) override per instance; Form\u2192FormField priority stays intact. The test: "would a service theme.css want to change this to match its design grid?" If yes and the only route is forking CSS, that is a library gap \u2014 fix the library, don\'t patch the app. Born from real consumption: `--form-label-width` / `--form-label-gap` (design spec said 110px/8px; the values were prop-only and hard-coded `--space-4`).'
|
|
8210
|
+
},
|
|
8211
|
+
{
|
|
8212
|
+
number: 46,
|
|
8213
|
+
title: "Typography is tokens, default is base",
|
|
8214
|
+
body: "A UI framework gives consumers knobs: every font-size in `src/styles/*.css` MUST reference a token \u2014 the global modular scale `var(--font-size-{2xs|xs|sm|base|lg|xl|2xl})` or a per-component `var(--{component}-\u2026-font-size)` knob (rule #45) \u2014 never a hard-coded literal (`font-size: 12px` can't be re-themed). The DEFAULT body size is `--font-size-base`; components render body/UI text at `base`, not at the `sm` alias. Smaller-by-design text (badge, section label, caption) is a component token defaulting to a small step (`--badge-font-size: var(--font-size-xs)`), so a service re-tunes that part without moving the global scale. The `sm`/`xs` tokens stay for the explicit `<Text size>` API. Every component token is surfaced in the MCP `get_component` output (check:mcp-token-sync). Enforced by `check:typography`."
|
|
7266
8215
|
}
|
|
7267
8216
|
];
|
|
7268
8217
|
function findRule(num) {
|
|
@@ -9952,6 +10901,62 @@ ${section.body}
|
|
|
9952
10901
|
|
|
9953
10902
|
_Source: ${skill.source}_`;
|
|
9954
10903
|
}
|
|
10904
|
+
var TOKEN_PREFIXES = {
|
|
10905
|
+
Badge: ["badge"],
|
|
10906
|
+
Button: ["button"],
|
|
10907
|
+
Toggle: ["toggle"],
|
|
10908
|
+
TagInput: ["tag-input"],
|
|
10909
|
+
Card: ["card"],
|
|
10910
|
+
StatCard: ["stat-card"],
|
|
10911
|
+
Table: ["table"],
|
|
10912
|
+
DataTable: ["table"],
|
|
10913
|
+
Dialog: ["dialog"],
|
|
10914
|
+
AlertDialog: ["dialog"],
|
|
10915
|
+
Sheet: ["dialog"],
|
|
10916
|
+
Drawer: ["dialog"],
|
|
10917
|
+
Alert: ["alert"],
|
|
10918
|
+
EmptyState: ["empty-state"],
|
|
10919
|
+
Skeleton: ["skeleton"],
|
|
10920
|
+
Pagination: ["pagination"],
|
|
10921
|
+
Toolbar: ["filter"],
|
|
10922
|
+
Breadcrumb: ["breadcrumb"],
|
|
10923
|
+
Menubar: ["menubar"],
|
|
10924
|
+
Progress: ["progress"],
|
|
10925
|
+
TreeSelect: ["tree"],
|
|
10926
|
+
Timeline: ["timeline"],
|
|
10927
|
+
PasswordStrength: ["password-strength"],
|
|
10928
|
+
PasswordInput: ["password-strength"],
|
|
10929
|
+
Checkbox: ["checkbox"],
|
|
10930
|
+
Switch: ["switch"],
|
|
10931
|
+
Slider: ["slider"],
|
|
10932
|
+
ColorPicker: ["color-picker"],
|
|
10933
|
+
Command: ["command"],
|
|
10934
|
+
Radio: ["choice"],
|
|
10935
|
+
RadioGroup: ["choice"],
|
|
10936
|
+
Field: ["choice"],
|
|
10937
|
+
AppShell: ["sidebar", "topbar"],
|
|
10938
|
+
Sidebar: ["sidebar"],
|
|
10939
|
+
Topbar: ["topbar"],
|
|
10940
|
+
Form: ["form"],
|
|
10941
|
+
FormField: ["form"],
|
|
10942
|
+
// Shared control sizing/typography — every plain control reads these.
|
|
10943
|
+
Input: ["control"],
|
|
10944
|
+
Textarea: ["control"],
|
|
10945
|
+
NumberInput: ["control"],
|
|
10946
|
+
Select: ["control", "search-input"],
|
|
10947
|
+
Cascader: ["control"],
|
|
10948
|
+
DatePicker: ["control"],
|
|
10949
|
+
TimePicker: ["control"],
|
|
10950
|
+
InputOTP: ["control"]
|
|
10951
|
+
};
|
|
10952
|
+
function componentTokensFor(name) {
|
|
10953
|
+
const prefixes = TOKEN_PREFIXES[name] ?? [
|
|
10954
|
+
name.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase()
|
|
10955
|
+
];
|
|
10956
|
+
return COMPONENT_TOKENS.filter(
|
|
10957
|
+
(t) => prefixes.some((p) => t.name.startsWith(`--${p}-`))
|
|
10958
|
+
);
|
|
10959
|
+
}
|
|
9955
10960
|
function getComponent(name) {
|
|
9956
10961
|
const c = findComponent(name);
|
|
9957
10962
|
if (!c) return `Component "${name}" not found. Use \`list_primitives\` to discover.`;
|
|
@@ -9977,6 +10982,20 @@ function getComponent(name) {
|
|
|
9977
10982
|
`;
|
|
9978
10983
|
for (const p of c.props) {
|
|
9979
10984
|
out += `| \`${p.name}\` | \`${p.type}\` | ${p.required ? "\u2713" : ""} | ${p.defaultValue ? `\`${p.defaultValue}\`` : ""} | ${p.description} |
|
|
10985
|
+
`;
|
|
10986
|
+
}
|
|
10987
|
+
const tokens = componentTokensFor(c.name);
|
|
10988
|
+
if (tokens.length) {
|
|
10989
|
+
out += `
|
|
10990
|
+
## Design tokens (theme knobs)
|
|
10991
|
+
|
|
10992
|
+
Override these in a service \`theme.css\` to re-tune ONLY this component (never hard-code or fork CSS \u2014 rules #44/#45/#46):
|
|
10993
|
+
|
|
10994
|
+
`;
|
|
10995
|
+
out += `| Token | Default | What it controls |
|
|
10996
|
+
|---|---|---|
|
|
10997
|
+
`;
|
|
10998
|
+
for (const t of tokens) out += `| \`${t.name}\` | \`${t.value}\` | ${t.description} |
|
|
9980
10999
|
`;
|
|
9981
11000
|
}
|
|
9982
11001
|
if (c.usage && c.usage.length) {
|
|
@@ -10448,8 +11467,8 @@ ${c.example}
|
|
|
10448
11467
|
// package.json
|
|
10449
11468
|
var package_default = {
|
|
10450
11469
|
name: "@godxjp/ui-mcp",
|
|
10451
|
-
version: "0.21.
|
|
10452
|
-
description: "Model Context Protocol server for @godxjp/ui \u2014 gives Claude Code / Codex CLI / Cursor / any MCP-aware agent live access to the component catalog, prop vocabulary, design tokens,
|
|
11470
|
+
version: "0.21.5",
|
|
11471
|
+
description: "Model Context Protocol server for @godxjp/ui \u2014 gives Claude Code / Codex CLI / Cursor / any MCP-aware agent live access to the component catalog, prop vocabulary, design tokens, 45 cardinal rules, copy-paste-ready patterns, 12 design / taste skills synthesised from Leonxlnx/taste-skill, 20+ anti-AI-tell patterns, and a 50-check redesign audit \u2014 token-efficient (list \u2192 drill-down).",
|
|
10453
11472
|
type: "module",
|
|
10454
11473
|
main: "./dist/index.js",
|
|
10455
11474
|
module: "./dist/index.js",
|