cursedbelt 5.26.0 → 5.28.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/dist/react/charts/IntervalTimeline.d.ts.map +1 -1
- package/dist/react/charts/IntervalTimeline.js +6 -2
- package/dist/react/charts/IntervalTimeline.js.map +1 -1
- package/dist/react/components/Button.d.ts +1 -1
- package/dist/react/components/Button.d.ts.map +1 -1
- package/dist/react/components/Button.js +4 -0
- package/dist/react/components/Button.js.map +1 -1
- package/dist/react/components/CodeArea.d.ts.map +1 -1
- package/dist/react/components/CodeArea.js +3 -1
- package/dist/react/components/CodeArea.js.map +1 -1
- package/dist/react/components/DataTable/DataTable.js +2 -2
- package/dist/react/components/DataTable/DataTable.js.map +1 -1
- package/dist/react/components/DataTable/TableFilterBuilder.d.ts.map +1 -1
- package/dist/react/components/DataTable/TableFilterBuilder.js +2 -1
- package/dist/react/components/DataTable/TableFilterBuilder.js.map +1 -1
- package/dist/react/components/FindingsList.d.ts.map +1 -1
- package/dist/react/components/FindingsList.js +2 -1
- package/dist/react/components/FindingsList.js.map +1 -1
- package/dist/react/components/InfoHint.d.ts.map +1 -1
- package/dist/react/components/InfoHint.js +3 -1
- package/dist/react/components/InfoHint.js.map +1 -1
- package/dist/react/components/Section.d.ts.map +1 -1
- package/dist/react/components/Section.js +3 -1
- package/dist/react/components/Section.js.map +1 -1
- package/dist/react/components/calendar/MonthGrid.d.ts.map +1 -1
- package/dist/react/components/calendar/MonthGrid.js +33 -32
- package/dist/react/components/calendar/MonthGrid.js.map +1 -1
- package/dist/react/components/calendar/WeekView.d.ts.map +1 -1
- package/dist/react/components/calendar/WeekView.js +2 -1
- package/dist/react/components/calendar/WeekView.js.map +1 -1
- package/dist/react/components/sharing/RecipientPicker.d.ts.map +1 -1
- package/dist/react/components/sharing/RecipientPicker.js +3 -1
- package/dist/react/components/sharing/RecipientPicker.js.map +1 -1
- package/dist/react/dashboard-grid/WidgetFrame.d.ts.map +1 -1
- package/dist/react/dashboard-grid/WidgetFrame.js +2 -1
- package/dist/react/dashboard-grid/WidgetFrame.js.map +1 -1
- package/dist/react/diff-viewer/TextComparePane.d.ts.map +1 -1
- package/dist/react/diff-viewer/TextComparePane.js +2 -1
- package/dist/react/diff-viewer/TextComparePane.js.map +1 -1
- package/dist/react/emoji/EmojiAutocomplete.d.ts.map +1 -1
- package/dist/react/emoji/EmojiAutocomplete.js +3 -1
- package/dist/react/emoji/EmojiAutocomplete.js.map +1 -1
- package/dist/react/folder-tree/FolderPicker.d.ts.map +1 -1
- package/dist/react/folder-tree/FolderPicker.js +3 -2
- package/dist/react/folder-tree/FolderPicker.js.map +1 -1
- package/dist/react/layoutEngine/LayoutCanvas.d.ts.map +1 -1
- package/dist/react/layoutEngine/LayoutCanvas.js.map +1 -1
- package/dist/react/layoutEngine/NodeInspector.d.ts.map +1 -1
- package/dist/react/layoutEngine/NodeInspector.js +2 -1
- package/dist/react/layoutEngine/NodeInspector.js.map +1 -1
- package/dist/react/media/TrimRangeSlider.d.ts.map +1 -1
- package/dist/react/media/TrimRangeSlider.js +3 -1
- package/dist/react/media/TrimRangeSlider.js.map +1 -1
- package/dist/react/media-gallery/MediaGallery.d.ts +14 -1
- package/dist/react/media-gallery/MediaGallery.d.ts.map +1 -1
- package/dist/react/media-gallery/MediaGallery.js +11 -7
- package/dist/react/media-gallery/MediaGallery.js.map +1 -1
- package/dist/react/media-gallery/index.d.ts +1 -1
- package/dist/react/media-gallery/index.d.ts.map +1 -1
- package/dist/react/media-gallery/index.js +1 -1
- package/dist/react/media-gallery/index.js.map +1 -1
- package/dist/react/problem-detail/ProblemDetailView.d.ts.map +1 -1
- package/dist/react/problem-detail/ProblemDetailView.js +2 -1
- package/dist/react/problem-detail/ProblemDetailView.js.map +1 -1
- package/dist/scripts/guardrailsEnforce.d.ts.map +1 -1
- package/dist/styles-areas/core.css +29 -28
- package/dist/styles-utilities.css +9 -0
- package/dist/theme.css +11 -0
- package/package.json +8 -2
- package/scripts/guardrails-baseline.json +2 -1
- package/scripts/guardrailsEnforce.spec.ts +36 -0
- package/scripts/guardrailsEnforce.ts +66 -0
- package/src/react/charts/IntervalTimeline.tsx +2 -0
- package/src/react/components/Button.spec.tsx +8 -0
- package/src/react/components/Button.tsx +4 -0
- package/src/react/components/CodeArea.tsx +1 -0
- package/src/react/components/DataTable/DataTable.tsx +4 -4
- package/src/react/components/DataTable/TableFilterBuilder.tsx +3 -2
- package/src/react/components/FindingsList.tsx +9 -5
- package/src/react/components/InfoHint.tsx +1 -0
- package/src/react/components/Section.tsx +1 -0
- package/src/react/components/calendar/MonthGrid.tsx +3 -1
- package/src/react/components/calendar/WeekView.tsx +3 -2
- package/src/react/components/sharing/RecipientPicker.tsx +4 -1
- package/src/react/dashboard-grid/WidgetFrame.tsx +4 -6
- package/src/react/diff-viewer/TextComparePane.tsx +4 -6
- package/src/react/emoji/EmojiAutocomplete.tsx +1 -0
- package/src/react/folder-tree/FolderPicker.tsx +5 -4
- package/src/react/layoutEngine/LayoutCanvas.tsx +1 -0
- package/src/react/layoutEngine/NodeInspector.tsx +3 -2
- package/src/react/media/TrimRangeSlider.tsx +1 -0
- package/src/react/media-gallery/MediaGallery.spec.tsx +22 -0
- package/src/react/media-gallery/MediaGallery.tsx +27 -6
- package/src/react/media-gallery/index.ts +2 -0
- package/src/react/problem-detail/ProblemDetailView.tsx +14 -5
- package/src/styles-areas/core.css +29 -28
- package/src/styles-utilities.css +9 -0
- package/src/theme.css +11 -0
|
@@ -5,6 +5,7 @@ import { Badge } from '../components/Badge.js';
|
|
|
5
5
|
import { CopyButton } from '../components/CopyButton.js';
|
|
6
6
|
import { PathText } from '../components/PathText.js';
|
|
7
7
|
import { cn } from '../lib/cn.js';
|
|
8
|
+
import { Surface } from '../components/Surface.js';
|
|
8
9
|
const EXPLAIN_ROWS = [
|
|
9
10
|
{ key: 'what', label: 'What’s happening', icon: _jsx(AlertTriangle, { className: 'size-4' }) },
|
|
10
11
|
{ key: 'why', label: 'Why', icon: _jsx(HelpCircle, { className: 'size-4' }) },
|
|
@@ -12,6 +13,6 @@ const EXPLAIN_ROWS = [
|
|
|
12
13
|
{ key: 'whatToDo', label: 'What to do', icon: _jsx(Wrench, { className: 'size-4' }) },
|
|
13
14
|
];
|
|
14
15
|
export function ProblemDetailView({ kind, summary, detail, eli5, eli5By, explain, triage, blocking, ready, session, createdAt, actions, className, }) {
|
|
15
|
-
return (_jsxs("div", { className: cn('flex select-text flex-col gap-4 text-sm', className), children: [_jsxs("header", { className: 'flex flex-col gap-1', children: [_jsxs("div", { className: 'flex items-start justify-between gap-2', children: [_jsxs("div", { className: 'flex min-w-0 items-center gap-2', children: [_jsx(Badge, { tone: 'outline', className: 'shrink-0 font-mono text-caption', children: kind }), createdAt !== undefined && (_jsx("span", { className: 'text-xs text-muted-foreground', children: formatTimeAgo(createdAt) }))] }), _jsx(CopyButton, { value: summary, label: 'Copy summary', className: 'shrink-0' })] }), _jsx("p", { className: 'font-medium leading-snug text-foreground', children: summary })] }), eli5 && (_jsxs("section", { className: 'rounded-lg border border-accent/30 bg-accent/5 p-3', children: [_jsxs("div", { className: 'mb-1 flex items-center justify-between gap-2', children: [_jsx("span", { className: 'text-caption font-semibold uppercase tracking-wide text-accent-strong', children: "In plain words" }), _jsx(CopyButton, { value: eli5, label: 'Copy explanation', iconSize: 14, className: 'shrink-0' })] }), _jsx("p", { className: 'leading-relaxed text-foreground', children: eli5 }), eli5By && eli5By !== 'deterministic' && (_jsxs("p", { className: 'mt-1 text-caption text-muted-foreground', children: ["explained by ", eli5By] }))] })), explain && (_jsx("section", { className: 'grid gap-2 sm:grid-cols-2', children: EXPLAIN_ROWS.map(({ key, label, icon }) => explain[key] ? (_jsxs("
|
|
16
|
+
return (_jsxs("div", { className: cn('flex select-text flex-col gap-4 text-sm', className), children: [_jsxs("header", { className: 'flex flex-col gap-1', children: [_jsxs("div", { className: 'flex items-start justify-between gap-2', children: [_jsxs("div", { className: 'flex min-w-0 items-center gap-2', children: [_jsx(Badge, { tone: 'outline', className: 'shrink-0 font-mono text-caption', children: kind }), createdAt !== undefined && (_jsx("span", { className: 'text-xs text-muted-foreground', children: formatTimeAgo(createdAt) }))] }), _jsx(CopyButton, { value: summary, label: 'Copy summary', className: 'shrink-0' })] }), _jsx("p", { className: 'font-medium leading-snug text-foreground', children: summary })] }), eli5 && (_jsxs("section", { className: 'rounded-lg border border-accent/30 bg-accent/5 p-3', children: [_jsxs("div", { className: 'mb-1 flex items-center justify-between gap-2', children: [_jsx("span", { className: 'text-caption font-semibold uppercase tracking-wide text-accent-strong', children: "In plain words" }), _jsx(CopyButton, { value: eli5, label: 'Copy explanation', iconSize: 14, className: 'shrink-0' })] }), _jsx("p", { className: 'leading-relaxed text-foreground', children: eli5 }), eli5By && eli5By !== 'deterministic' && (_jsxs("p", { className: 'mt-1 text-caption text-muted-foreground', children: ["explained by ", eli5By] }))] })), explain && (_jsx("section", { className: 'grid gap-2 sm:grid-cols-2', children: EXPLAIN_ROWS.map(({ key, label, icon }) => explain[key] ? (_jsxs(Surface, { level: "flat", pad: "sm", radius: "lg", className: 'bg-card', children: [_jsxs("div", { className: 'mb-1 flex items-center gap-1.5 text-muted-foreground', children: [_jsx("span", { className: 'shrink-0', children: icon }), _jsx("span", { className: 'text-caption font-semibold uppercase tracking-wide', children: label })] }), _jsx("p", { className: 'leading-snug text-foreground', children: explain[key] })] }, key)) : null) })), blocking && (_jsxs("section", { className: 'rounded-lg border border-border p-3', children: [_jsxs("div", { className: 'mb-2 flex flex-wrap items-center gap-2', children: [_jsx("span", { className: 'text-caption font-semibold uppercase tracking-wide text-muted-foreground', children: "Blocking gate" }), blocking.ownerGated && (_jsxs(Badge, { tone: 'warning', className: 'gap-1', children: [_jsx(Lock, { className: 'size-3' }), " needs you"] })), blocking.gateFlags.map((f) => (_jsx(Badge, { tone: 'outline', className: 'font-mono text-caption', children: f }, f)))] }), _jsxs("div", { className: 'flex items-center gap-2', children: [_jsx(PathText, { path: `blocked/${blocking.head.file}`, className: 'min-w-0 flex-1 text-xs' }), _jsx(CopyButton, { value: blocking.head.file, label: 'Copy filename', iconSize: 14, className: 'shrink-0' })] }), blocking.head.brief && (_jsx("p", { className: 'mt-1 text-xs text-muted-foreground', children: blocking.head.brief })), blocking.chain.length > 1 && (_jsxs("p", { className: 'mt-2 text-caption text-muted-foreground', children: ["+", blocking.chain.length - 1, " more gate", blocking.chain.length - 1 === 1 ? '' : 's', " in the blocked chain."] }))] })), ready && ready.length > 0 && (_jsxs("section", { children: [_jsxs("div", { className: 'mb-1.5 flex items-center gap-1.5 text-muted-foreground', children: [_jsx(ListChecks, { className: 'size-4 shrink-0' }), _jsxs("span", { className: 'text-caption font-semibold uppercase tracking-wide', children: [ready.length, " ready, waiting"] })] }), _jsx("ul", { className: 'flex flex-col gap-1', children: ready.slice(0, 12).map((t) => (_jsx(Surface, { asChild: true, level: 'flat', pad: 'none', radius: 'md', className: 'flex items-center gap-2 rounded border-border/60 bg-card/50 px-2 py-1', children: _jsxs("li", { children: [_jsx("span", { className: 'min-w-0 flex-1 truncate font-mono text-caption text-foreground', children: t.file }), t.unmetNeeds.length > 0 && (_jsxs(Badge, { tone: 'warning', className: 'shrink-0 text-caption', children: ["waits on ", t.unmetNeeds.join(', ')] }))] }) }, t.file))) }), ready.length > 12 && (_jsxs("p", { className: 'mt-1 text-caption text-muted-foreground', children: ["+", ready.length - 12, " more."] }))] })), session && session.events.length > 0 && (_jsxs("section", { children: [_jsxs("div", { className: 'mb-1.5 flex items-center justify-between gap-2', children: [_jsxs("span", { className: 'text-caption font-semibold uppercase tracking-wide text-muted-foreground', children: ["Session activity \u00B7 ", session.events.length, " event", session.events.length === 1 ? '' : 's'] }), _jsx(CopyButton, { value: session.events.map((e) => `[${e.kind}] ${e.message}`).join('\n'), label: 'Copy event log', iconSize: 14, className: 'shrink-0' })] }), _jsx("ol", { className: 'flex flex-col gap-2 border-l border-border pl-3', children: session.events.map((e) => (_jsxs("li", { className: 'relative', children: [_jsx("span", { "aria-hidden": true, className: 'absolute -left-[calc(0.75rem+3px)] top-1.5 size-1.5 rounded-full bg-muted-foreground' }), _jsxs("div", { className: 'flex items-baseline justify-between gap-2', children: [_jsx("span", { className: 'font-mono text-caption uppercase tracking-wide text-muted-foreground', children: e.kind }), _jsx("span", { className: 'shrink-0 text-caption text-muted-foreground', children: formatTimeAgo(e.at) })] }), _jsx("p", { className: 'whitespace-pre-wrap break-words leading-snug text-foreground', children: e.message })] }, e.seq))) })] })), triage && (_jsx(Surface, { asChild: true, level: 'flat', pad: 'sm', radius: 'lg', className: 'bg-muted/30 text-xs', children: _jsxs("section", { children: [_jsxs("span", { className: 'text-caption font-semibold uppercase tracking-wide text-muted-foreground', children: ["System verdict \u00B7 ", triage.status] }), _jsx("p", { className: 'mt-1 text-foreground', children: triage.cause }), _jsx("p", { className: 'mt-0.5 text-muted-foreground', children: triage.action }), triage.decidedBy && (_jsxs("p", { className: 'mt-1 text-caption text-muted-foreground', children: ["decided by ", triage.decidedBy] }))] }) })), detail?.trim() && (_jsxs("details", { className: 'rounded-lg border border-border', children: [_jsx("summary", { className: 'cursor-pointer select-none px-3 py-2 text-caption font-semibold uppercase tracking-wide text-muted-foreground', children: "Raw detail" }), _jsxs("div", { className: 'flex items-start gap-2 border-t border-border p-3', children: [_jsx("pre", { className: 'min-w-0 flex-1 whitespace-pre-wrap break-words font-mono text-caption text-muted-foreground', children: detail }), _jsx(CopyButton, { value: detail, label: 'Copy detail', iconSize: 14, className: 'shrink-0' })] })] })), actions && (_jsx("footer", { className: 'flex flex-wrap items-center gap-2 border-t border-border pt-3', children: actions }))] }));
|
|
16
17
|
}
|
|
17
18
|
//# sourceMappingURL=ProblemDetailView.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProblemDetailView.js","sourceRoot":"","sources":["../../../src/react/problem-detail/ProblemDetailView.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEnF,OAAO,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AACzD,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AACrD,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"ProblemDetailView.js","sourceRoot":"","sources":["../../../src/react/problem-detail/ProblemDetailView.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"guardrailsEnforce.d.ts","sourceRoot":"","sources":["../../scripts/guardrailsEnforce.ts"],"names":[],"mappings":";AA2NA,UAAU,SAAS;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB;;;sEAGkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,IAAI;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,SAAS,EAAE,CAAC;CACzD;AAED,wBAAgB,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,GAAE,MAAM,EAAO,GAAG,MAAM,EAAE,CA6B9D;AAu5BD,iGAAiG;AACjG,wBAAgB,WAAW,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAE3D;AAmHD,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAEpE;AA+vBD,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,SAAS,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,GAAG,IAAI,CAEpF;AAID,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,CAoBhE;
|
|
1
|
+
{"version":3,"file":"guardrailsEnforce.d.ts","sourceRoot":"","sources":["../../scripts/guardrailsEnforce.ts"],"names":[],"mappings":";AA2NA,UAAU,SAAS;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB;;;sEAGkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,IAAI;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,SAAS,EAAE,CAAC;CACzD;AAED,wBAAgB,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,GAAE,MAAM,EAAO,GAAG,MAAM,EAAE,CA6B9D;AAu5BD,iGAAiG;AACjG,wBAAgB,WAAW,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAE3D;AAmHD,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAEpE;AA+vBD,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,SAAS,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,GAAG,IAAI,CAEpF;AAID,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,CAoBhE;AA+GD,eAAO,MAAM,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,CAyBtC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,mBAAmB,EAAE,WAAW,CAAC,MAAM,CAAuC,CAAC;AAE5F,0EAA0E;AAC1E,eAAO,MAAM,SAAS,EAAE,SAAS,MAAM,EAAwE,CAAC;AAShH,eAAO,MAAM,uBAAuB,aAAkD,CAAC;AAGvF,MAAM,WAAW,SAAS;IACzB,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACb;AAED;2FAC2F;AAC3F,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,CA0C3F;AAED,YAAY,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;AAmGhC,wBAAgB,0BAA0B,CAAC,SAAS,GAAE,MAAwB,GAAG,MAAM,EAAE,CAyBxF"}
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* after an app's responsive variant (task 2124). An app that imports every area gets exactly
|
|
16
16
|
* what `cursedbelt/styles-utilities.css` emits — proved rule by rule in
|
|
17
17
|
* src/stylesAreas.spec.ts, which is also what fails when this file is stale.
|
|
18
|
-
*
|
|
18
|
+
* 718 candidate(s).
|
|
19
19
|
*
|
|
20
20
|
* Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
|
|
21
21
|
* `bun run build` runs. The map of what is in which area, and why the areas are
|
|
@@ -43,21 +43,21 @@
|
|
|
43
43
|
@source inline("bg-background bg-background/80 bg-background/90 bg-background/95 bg-black/50 bg-border bg-card");
|
|
44
44
|
@source inline("bg-current bg-destructive bg-destructive-solid bg-destructive/15 bg-destructive/5");
|
|
45
45
|
@source inline("bg-destructive/8 bg-emerald-100 bg-field-bg bg-muted bg-muted-foreground/40");
|
|
46
|
-
@source inline("bg-muted-foreground/50 bg-muted/20 bg-popover bg-success bg-success
|
|
47
|
-
@source inline("bg-surface-sunken bg-tone-amber-bg bg-tone-cyan-bg bg-tone-emerald-bg
|
|
48
|
-
@source inline("bg-tone-
|
|
49
|
-
@source inline("bg-tone-slate-bg bg-tone-teal-bg bg-tone-violet-bg bg-transparent bg-warning
|
|
50
|
-
@source inline("bg-warning/5 bg-warning/8 bg-white block blur border border-accent/40
|
|
51
|
-
@source inline("border-b-2 border-b-[7px] border-b-current border-border
|
|
52
|
-
@source inline("border-
|
|
53
|
-
@source inline("border-
|
|
54
|
-
@source inline("border-tone-sky-fg/30 border-tone-slate-fg/30
|
|
55
|
-
@source inline("border-warning/40 border-warning/50 border-x-4
|
|
56
|
-
@source inline("break-all break-words c ca cap capitalize co com
|
|
57
|
-
@source inline("cursor-col-resize cursor-default cursor-ew-resize
|
|
58
|
-
@source inline("dark:bg-card-overlay dark:bg-card-raised
|
|
59
|
-
@source inline("data-[disabled]:
|
|
60
|
-
@source inline("data-[interactive=true]:duration-[var(--duration-base)]");
|
|
46
|
+
@source inline("bg-muted-foreground/50 bg-muted/20 bg-popover bg-success bg-success-solid bg-success/15");
|
|
47
|
+
@source inline("bg-success/5 bg-surface bg-surface-sunken bg-tone-amber-bg bg-tone-cyan-bg bg-tone-emerald-bg");
|
|
48
|
+
@source inline("bg-tone-fuchsia-bg bg-tone-lime-bg bg-tone-orange-bg bg-tone-purple-bg bg-tone-rose-bg");
|
|
49
|
+
@source inline("bg-tone-sky-bg bg-tone-slate-bg bg-tone-teal-bg bg-tone-violet-bg bg-transparent bg-warning");
|
|
50
|
+
@source inline("bg-warning/15 bg-warning/5 bg-warning/8 bg-white block blur border border-accent/40");
|
|
51
|
+
@source inline("border-accent/50 border-b border-b-2 border-b-[7px] border-b-current border-border");
|
|
52
|
+
@source inline("border-border-strong border-border/60 border-collapse border-current border-destructive/30");
|
|
53
|
+
@source inline("border-destructive/40 border-destructive/50 border-field-border border-success/30");
|
|
54
|
+
@source inline("border-success/40 border-success/50 border-t border-tone-sky-fg/30 border-tone-slate-fg/30");
|
|
55
|
+
@source inline("border-transparent border-warning/30 border-warning/40 border-warning/50 border-x-4");
|
|
56
|
+
@source inline("border-x-transparent bot bottom bottom-0 break break-all break-words c ca cap capitalize co com");
|
|
57
|
+
@source inline("contain container content contents cursor cursor-col-resize cursor-default cursor-ew-resize");
|
|
58
|
+
@source inline("cursor-pointer cursor-row-resize d dark dark:bg-card-overlay dark:bg-card-raised");
|
|
59
|
+
@source inline("dark:bg-gray-800 data data-[disabled]:hover:bg-border data-[disabled]:opacity-50");
|
|
60
|
+
@source inline("data-[disabled]:pointer-events-none data-[interactive=true]:duration-[var(--duration-base)]");
|
|
61
61
|
@source inline("data-[interactive=true]:ease-[var(--ease-out)] data-[interactive=true]:hover:-translate-y-0.5");
|
|
62
62
|
@source inline("data-[interactive=true]:hover:border-border-strong data-[interactive=true]:hover:shadow-overlay");
|
|
63
63
|
@source inline("data-[interactive=true]:transition-all data-[placeholder]:text-muted-foreground");
|
|
@@ -86,11 +86,11 @@
|
|
|
86
86
|
@source inline("focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent");
|
|
87
87
|
@source inline("focus-visible:ring-accent-solid focus-visible:ring-destructive focus-visible:ring-field-ring/30");
|
|
88
88
|
@source inline("focus-visible:ring-offset-1 focus-visible:ring-offset-2 focus-visible:ring-offset-background");
|
|
89
|
-
@source inline("focus-visible:ring-ring focus-visible:text-destructive-foreground
|
|
90
|
-
@source inline("focus:bg-destructive/10 focus:outline-none focus:ring-2 focus:ring-accent
|
|
91
|
-
@source inline("focus:text-destructive font-bold font-medium font-mono font-normal
|
|
92
|
-
@source inline("gap-0.5 gap-1 gap-1.5 gap-12 gap-16 gap-2 gap-3 gap-4 gap-6 gap-8
|
|
93
|
-
@source inline("gap-y-2 gap-y-4 grid grid-cols-2");
|
|
89
|
+
@source inline("focus-visible:ring-ring focus-visible:ring-success focus-visible:text-destructive-foreground");
|
|
90
|
+
@source inline("focus:bg-accent/10 focus:bg-destructive/10 focus:outline-none focus:ring-2 focus:ring-accent");
|
|
91
|
+
@source inline("focus:text-accent focus:text-destructive font-bold font-medium font-mono font-normal");
|
|
92
|
+
@source inline("font-semibold gap gap-0 gap-0.5 gap-1 gap-1.5 gap-12 gap-16 gap-2 gap-3 gap-4 gap-6 gap-8");
|
|
93
|
+
@source inline("gap-x-2.5 gap-x-3 gap-y-1 gap-y-2 gap-y-4 grid grid-cols-2");
|
|
94
94
|
@source inline("grid-cols-[repeat(auto-fit,minmax(min(var(--cb-grid-min),100%),1fr))] group");
|
|
95
95
|
@source inline("group-active/sep:opacity-100 group-data-[state=open]:rotate-180");
|
|
96
96
|
@source inline("group-focus-visible/sep:opacity-100 group-hover group-hover/path:opacity-100");
|
|
@@ -99,13 +99,14 @@
|
|
|
99
99
|
@source inline("h-[var(--control-h-lg)] h-[var(--control-h-md)] h-[var(--control-h-sm)] h-auto h-full h-px hi");
|
|
100
100
|
@source inline("hid hidden hover hover:bg-accent hover:bg-accent-solid-hover hover:bg-accent/10");
|
|
101
101
|
@source inline("hover:bg-accent/20 hover:bg-destructive-solid hover:bg-destructive-solid-hover hover:bg-muted");
|
|
102
|
-
@source inline("hover:bg-
|
|
103
|
-
@source inline("hover:
|
|
104
|
-
@source inline("hover:underline i in inline inline-block
|
|
105
|
-
@source inline("is iso isolate it item items
|
|
106
|
-
@source inline("
|
|
107
|
-
@source inline("left left-1/2 left-2 lg lg:px-8
|
|
108
|
-
@source inline("max-h-[
|
|
102
|
+
@source inline("hover:bg-success-solid-hover hover:bg-transparent hover:border-accent");
|
|
103
|
+
@source inline("hover:border-destructive-solid hover:opacity-70 hover:text-accent hover:text-destructive");
|
|
104
|
+
@source inline("hover:text-destructive-foreground hover:text-foreground hover:underline i in inline inline-block");
|
|
105
|
+
@source inline("inline-flex inset inset-0 inset-x-0 inset-y-0 invisible is iso isolate it item items");
|
|
106
|
+
@source inline("items-baseline items-center items-end items-start just justify-between justify-center");
|
|
107
|
+
@source inline("justify-end l leading leading-none leading-relaxed leading-snug left left-1/2 left-2 lg lg:px-8");
|
|
108
|
+
@source inline("lower lowercase m m-0 max max-h max-h-[80vh] max-h-[calc(100dvh-2rem)]");
|
|
109
|
+
@source inline("max-h-[calc(var(--radix-popper-available-height,100dvh)-1rem)]");
|
|
109
110
|
@source inline("max-h-[min(90dvh,calc(100dvh-2rem))] max-h-[var(--radix-select-content-available-height)]");
|
|
110
111
|
@source inline("max-w-2xl max-w-4xl max-w-5xl max-w-[10rem] max-w-[calc(100vw-2rem)]");
|
|
111
112
|
@source inline("max-w-[var(--reading-width)] max-w-full max-w-lg max-w-sm max-w-xl max-w-xs mb-0.5 mb-1 md");
|
|
@@ -2098,6 +2098,9 @@
|
|
|
2098
2098
|
.bg-success {
|
|
2099
2099
|
background-color: var(--success);
|
|
2100
2100
|
}
|
|
2101
|
+
.bg-success-solid {
|
|
2102
|
+
background-color: var(--success-solid);
|
|
2103
|
+
}
|
|
2101
2104
|
.bg-success\/5 {
|
|
2102
2105
|
background-color: var(--success);
|
|
2103
2106
|
@supports (color: color-mix(in lab, red, red)) {
|
|
@@ -3520,6 +3523,9 @@
|
|
|
3520
3523
|
background-color: color-mix(in oklab, var(--muted) 80%, transparent);
|
|
3521
3524
|
}
|
|
3522
3525
|
}
|
|
3526
|
+
.hover\:bg-success-solid-hover:hover {
|
|
3527
|
+
background-color: var(--success-solid-hover);
|
|
3528
|
+
}
|
|
3523
3529
|
.hover\:bg-transparent:hover {
|
|
3524
3530
|
background-color: transparent;
|
|
3525
3531
|
}
|
|
@@ -3667,6 +3673,9 @@
|
|
|
3667
3673
|
.focus-visible\:ring-ring:focus-visible {
|
|
3668
3674
|
--tw-ring-color: var(--ring);
|
|
3669
3675
|
}
|
|
3676
|
+
.focus-visible\:ring-success:focus-visible {
|
|
3677
|
+
--tw-ring-color: var(--success);
|
|
3678
|
+
}
|
|
3670
3679
|
.focus-visible\:ring-offset-1:focus-visible {
|
|
3671
3680
|
--tw-ring-offset-width: 1px;
|
|
3672
3681
|
--tw-ring-offset-shadow: var(--tw-ring-inset,) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
package/dist/theme.css
CHANGED
|
@@ -169,6 +169,13 @@
|
|
|
169
169
|
--destructive-solid: var(--destructive); /* guardrails-ignore no-hardcoded-colors: this file IS the theme token source of truth — every value here is necessarily a literal color definition */
|
|
170
170
|
--destructive-solid-hover: #991b1b; /* guardrails-ignore no-hardcoded-colors: this file IS the theme token source of truth — every value here is necessarily a literal color definition */
|
|
171
171
|
--success: #16a34a; /* guardrails-ignore no-hardcoded-colors: this file IS the theme token source of truth — every value here is necessarily a literal color definition */
|
|
172
|
+
/* Solid-fill success, for a green button carrying WHITE text — the `destructive-solid`
|
|
173
|
+
split, for the same reason: --success is tuned as a status colour, and white on it
|
|
174
|
+
is 3.3:1. green-700 is 5.02:1 with white and its hover 7.1:1, in both modes, so it
|
|
175
|
+
is mode-stable like --accent-solid. First consumer: station's Resume, the green half
|
|
176
|
+
of a run/pause toggle whose Pause is `destructive-solid` (owner, 2026-09-29). */
|
|
177
|
+
--success-solid: #15803d; /* guardrails-ignore no-hardcoded-colors: this file IS the theme token source of truth — every value here is necessarily a literal color definition */
|
|
178
|
+
--success-solid-hover: #166534; /* guardrails-ignore no-hardcoded-colors: this file IS the theme token source of truth — every value here is necessarily a literal color definition */
|
|
172
179
|
--warning: #d97706; /* guardrails-ignore no-hardcoded-colors: this file IS the theme token source of truth — every value here is necessarily a literal color definition */
|
|
173
180
|
/* The gold a filled star is painted in (StarRating). Light needs a DARKER gold
|
|
174
181
|
than dark mode does, and this is measured, not taste: the neon below scores
|
|
@@ -470,6 +477,8 @@
|
|
|
470
477
|
--destructive-solid: #dc2626; /* guardrails-ignore no-hardcoded-colors: this file IS the theme token source of truth — every value here is necessarily a literal color definition */
|
|
471
478
|
--destructive-solid-hover: #b91c1c; /* guardrails-ignore no-hardcoded-colors: this file IS the theme token source of truth — every value here is necessarily a literal color definition */
|
|
472
479
|
--success: #22c55e; /* guardrails-ignore no-hardcoded-colors: this file IS the theme token source of truth — every value here is necessarily a literal color definition */
|
|
480
|
+
--success-solid: #15803d; /* guardrails-ignore no-hardcoded-colors: this file IS the theme token source of truth — every value here is necessarily a literal color definition */
|
|
481
|
+
--success-solid-hover: #166534; /* guardrails-ignore no-hardcoded-colors: this file IS the theme token source of truth — every value here is necessarily a literal color definition */
|
|
473
482
|
--warning: #f59e0b; /* guardrails-ignore no-hardcoded-colors: this file IS the theme token source of truth — every value here is necessarily a literal color definition */
|
|
474
483
|
/* The neon the star always had — correct against a near-black canvas at 10.76:1,
|
|
475
484
|
and the half of the pair that never needed changing. See the note at :root. */
|
|
@@ -845,6 +854,8 @@ option:disabled {
|
|
|
845
854
|
--color-destructive-solid: var(--destructive-solid);
|
|
846
855
|
--color-destructive-solid-hover: var(--destructive-solid-hover);
|
|
847
856
|
--color-success: var(--success);
|
|
857
|
+
--color-success-solid: var(--success-solid);
|
|
858
|
+
--color-success-solid-hover: var(--success-solid-hover);
|
|
848
859
|
--color-warning: var(--warning);
|
|
849
860
|
--color-star: var(--star);
|
|
850
861
|
/* AA-safe status TEXT over the 15% tinted badge fills */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cursedbelt",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.28.0",
|
|
4
4
|
"license": "ISC",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "The React design system of the cursedbelt split — components, styles, theme. cursedbelt-core below it; server tier in cursedbelt-server.",
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
"typecheck:scripts": "tsc --noEmit --project tsconfig.scripts.json",
|
|
69
69
|
"demo:check": "tsc --noEmit --project demo/tsconfig.json",
|
|
70
70
|
"demo:paths": "bun run demo/generatePaths.ts --write",
|
|
71
|
-
"guardrails:report": "bun run scripts/guardrailsEnforce.ts no-raw-action-button,no-raw-overflow,no-raw-inputs,no-hardcoded-colors,no-raw-modal-footer,no-unguarded-editing-modal,control-height-tokens,no-raw-zindex,no-raw-data-table,no-tailwind-palette,no-raw-title-attr,micro-typography-floor,choice-needs-empty-state,no-select-as-action-menu,no-native-dialog,no-fast-tooltip,no-raw-password,no-raw-lazy,no-raw-popover,no-hand-rolled-scroll-memory --scope cursedbelt src/react src/styles.css",
|
|
71
|
+
"guardrails:report": "bun run scripts/guardrailsEnforce.ts no-raw-action-button,no-raw-overflow,no-raw-inputs,no-hardcoded-colors,no-raw-modal-footer,no-unguarded-editing-modal,control-height-tokens,no-raw-zindex,no-raw-data-table,no-tailwind-palette,no-raw-title-attr,micro-typography-floor,choice-needs-empty-state,no-select-as-action-menu,no-native-dialog,no-fast-tooltip,no-raw-password,no-raw-lazy,no-raw-popover,no-hand-rolled-scroll-memory,no-hand-rolled-surface --scope cursedbelt src/react src/styles.css",
|
|
72
72
|
"lint": "biome lint --error-on-warnings src e2e demo scripts",
|
|
73
73
|
"styles": "bun run styles:static && bun run styles:utilities && bun run styles:areas",
|
|
74
74
|
"styles:static": "bun run scripts/generateStaticStyles.ts",
|
|
@@ -391,6 +391,12 @@
|
|
|
391
391
|
"source": "./src/react/components/MultiSelectField.tsx",
|
|
392
392
|
"import": "./dist/react/components/MultiSelectField.js"
|
|
393
393
|
},
|
|
394
|
+
"./react/segmented-control": {
|
|
395
|
+
"types": "./dist/react/components/SegmentedControl.d.ts",
|
|
396
|
+
"bun": "./src/react/components/SegmentedControl.tsx",
|
|
397
|
+
"source": "./src/react/components/SegmentedControl.tsx",
|
|
398
|
+
"import": "./dist/react/components/SegmentedControl.js"
|
|
399
|
+
},
|
|
394
400
|
"./react/sharing": {
|
|
395
401
|
"types": "./dist/react/sharing/index.d.ts",
|
|
396
402
|
"bun": "./src/react/sharing/index.ts",
|
|
@@ -1628,3 +1628,39 @@ describe('no-raw-popover — a popup its stylesheet positions (the 2026-09-27 su
|
|
|
1628
1628
|
).toHaveLength(0);
|
|
1629
1629
|
});
|
|
1630
1630
|
});
|
|
1631
|
+
|
|
1632
|
+
describe('no-hand-rolled-surface', () => {
|
|
1633
|
+
test('🔴 flags a hand-classed card — the shape family carried 23 of (2026-09-29)', () => {
|
|
1634
|
+
expect(
|
|
1635
|
+
check('no-hand-rolled-surface', `<div className="rounded-xl border border-[var(--border)] bg-[var(--card)] p-3">{body}</div>`),
|
|
1636
|
+
).toHaveLength(1);
|
|
1637
|
+
expect(check('no-hand-rolled-surface', `<li className="rounded-lg border border-border bg-card p-4">`)).toHaveLength(1);
|
|
1638
|
+
expect(
|
|
1639
|
+
check('no-hand-rolled-surface', `<section className={cn("rounded-md border bg-[var(--muted)]/10 p-3", open && "ring")}>`),
|
|
1640
|
+
).toHaveLength(1);
|
|
1641
|
+
});
|
|
1642
|
+
|
|
1643
|
+
test('passes Surface, a control, a hover-only fill, a drop target and a stated reason', () => {
|
|
1644
|
+
expect(check('no-hand-rolled-surface', `<Surface level="raised" pad="sm">{body}</Surface>`)).toHaveLength(0);
|
|
1645
|
+
expect(
|
|
1646
|
+
check('no-hand-rolled-surface', `<button className="rounded-lg border border-[var(--border)] bg-[var(--card)] px-3">Go</button>`),
|
|
1647
|
+
).toHaveLength(0);
|
|
1648
|
+
expect(
|
|
1649
|
+
check('no-hand-rolled-surface', `<div className="rounded-lg border border-transparent px-2 hover:border-[var(--border)] hover:bg-[var(--card)]">`),
|
|
1650
|
+
).toHaveLength(0);
|
|
1651
|
+
expect(
|
|
1652
|
+
check('no-hand-rolled-surface', `<div className="rounded-xl border-2 border-dashed border-[var(--border)] bg-[var(--card)]">`),
|
|
1653
|
+
).toHaveLength(0);
|
|
1654
|
+
expect(
|
|
1655
|
+
check(
|
|
1656
|
+
'no-hand-rolled-surface',
|
|
1657
|
+
`{/* guardrails-ignore no-hand-rolled-surface: the map's HUD is positioned over a canvas */}
|
|
1658
|
+
<div className="absolute rounded-lg border bg-[var(--card)]">`,
|
|
1659
|
+
),
|
|
1660
|
+
).toHaveLength(0);
|
|
1661
|
+
});
|
|
1662
|
+
|
|
1663
|
+
test('a comment that merely quotes the classes is not a violation', () => {
|
|
1664
|
+
expect(check('no-hand-rolled-surface', `// was <div className="rounded-xl border bg-card">`)).toHaveLength(0);
|
|
1665
|
+
});
|
|
1666
|
+
});
|
|
@@ -2141,6 +2141,71 @@ function localComponentRootIsPositioned(source: string, scannable: string, name:
|
|
|
2141
2141
|
return FLOATING_POSITION_RE.test(tag.code) || completesPositioned(classTokens(tag.code));
|
|
2142
2142
|
}
|
|
2143
2143
|
|
|
2144
|
+
// ── no-hand-rolled-surface ──────────────────────────────────────────────────
|
|
2145
|
+
// The owner, 2026-09-29 (`full-move-to-cb-review`): *"apps keep turning up with hand rolled
|
|
2146
|
+
// components that are buggy or bad Ux … containers, sidebars, sections … Most layout related
|
|
2147
|
+
// components are better in cb."* `no-local-reimplementation` catches a component declared under a
|
|
2148
|
+
// cursedbelt NAME; a card is usually not a component at all but a class string —
|
|
2149
|
+
// `<div className="rounded-xl border border-[var(--border)] bg-[var(--card)] p-3">` — which has no
|
|
2150
|
+
// name to match, compiles, and looks nearly right. Music carried a dozen of them past a zero
|
|
2151
|
+
// baseline until the owner found them by eye (task 2276); family carried 24.
|
|
2152
|
+
//
|
|
2153
|
+
// The signal: a CONTAINER element (not a control — a bordered button or input is the control's
|
|
2154
|
+
// own look) whose static className rounds its corners, draws a real border AND fills with a
|
|
2155
|
+
// surface colour. That triple is the whole definition of `Surface` (`level`, `radius`, `pad`,
|
|
2156
|
+
// `interactive`, `asChild` for a `<section>`/`<li>`). A dashed border is a drop target
|
|
2157
|
+
// (`FileDropZone`), and is left to that component's review.
|
|
2158
|
+
const SURFACE_TAG_RE = /<(div|section|li|ul|ol|article|aside|header|footer|form|fieldset)\b/g;
|
|
2159
|
+
const SURFACE_IGNORE_RE = /guardrails-ignore\s+no-hand-rolled-surface\s*:/;
|
|
2160
|
+
const SURFACE_ROUNDED_RE = /^rounded(?:-(?:sm|md|lg|xl|2xl|3xl))?$/;
|
|
2161
|
+
const SURFACE_BORDER_RE = /^border(?:-[a-z0-9-]+|-\[[^\]]+\])?$/;
|
|
2162
|
+
const SURFACE_NO_BORDER_RE = /^border-(?:0|transparent|none|dashed|dotted)$/;
|
|
2163
|
+
const SURFACE_FILL_RE =
|
|
2164
|
+
/^bg-(?:\[var\(--(?:card|surface|muted|popover)[\w-]*\)\](?:\/\d+)?|(?:card|surface|muted|popover)(?:-[\w-]+)?(?:\/\d+)?)$/;
|
|
2165
|
+
|
|
2166
|
+
/** Every whitespace-separated token inside the string literals of a tag's `className` value. */
|
|
2167
|
+
function classLiteralTokens(tagCode: string): string[] {
|
|
2168
|
+
const at = tagCode.search(/\bclassName=/);
|
|
2169
|
+
if (at === -1) return [];
|
|
2170
|
+
let value = tagCode.slice(at + "className=".length);
|
|
2171
|
+
if (value.startsWith("{")) value = balancedBraces(value, 0);
|
|
2172
|
+
else value = value.match(/^(["'])([^"']*)\1/)?.[0] ?? "";
|
|
2173
|
+
const tokens: string[] = [];
|
|
2174
|
+
for (const lit of value.matchAll(/(["'`])((?:(?!\1)[^\\]|\\.)*)\1/g))
|
|
2175
|
+
for (const token of (lit[2] ?? "").replace(/\$\{[^}]*\}/g, " ").split(/\s+/)) if (token) tokens.push(token);
|
|
2176
|
+
return tokens;
|
|
2177
|
+
}
|
|
2178
|
+
|
|
2179
|
+
const noHandRolledSurface: Rule = {
|
|
2180
|
+
name: "no-hand-rolled-surface",
|
|
2181
|
+
description:
|
|
2182
|
+
"Owner, 2026-09-29: containers come from cursedbelt. A container element whose className rounds, borders AND fills with a surface colour is a hand-rolled card — use `Surface` (`level=\"raised\"` for a card, `flat` for a panel, `asChild` to keep a `<section>`/`<li>`), `Section` for a titled group, or `Alert` for a tinted notice. A frame that is genuinely none of those takes the opt-out with its reason.",
|
|
2183
|
+
check(filePath, source) {
|
|
2184
|
+
const normalized = filePath.replace(/\\/g, "/");
|
|
2185
|
+
if (isTestSource(normalized)) return [];
|
|
2186
|
+
const scannable = blankComments(source);
|
|
2187
|
+
const lines = source.split("\n");
|
|
2188
|
+
const out: Violation[] = [];
|
|
2189
|
+
SURFACE_TAG_RE.lastIndex = 0;
|
|
2190
|
+
for (const match of scannable.matchAll(SURFACE_TAG_RE)) {
|
|
2191
|
+
const tag = readOpeningTag(source, match.index ?? 0);
|
|
2192
|
+
const tokens = classLiteralTokens(tag.code);
|
|
2193
|
+
if (tokens.length === 0) continue;
|
|
2194
|
+
const bare = tokens.map((t) => t.replace(/^(?:[a-z0-9-]+:)+/, ""));
|
|
2195
|
+
// Only the UNPREFIXED classes define the resting look: `hover:bg-card` is a row's hover.
|
|
2196
|
+
const resting = tokens.filter((t) => !t.includes(":"));
|
|
2197
|
+
if (bare.some((t) => SURFACE_NO_BORDER_RE.test(t))) continue;
|
|
2198
|
+
if (!resting.some((t) => SURFACE_ROUNDED_RE.test(t))) continue;
|
|
2199
|
+
if (!resting.some((t) => SURFACE_BORDER_RE.test(t) && !SURFACE_NO_BORDER_RE.test(t))) continue;
|
|
2200
|
+
if (!resting.some((t) => SURFACE_FILL_RE.test(t))) continue;
|
|
2201
|
+
const line = lineOf(source, match.index ?? 0);
|
|
2202
|
+
if (SURFACE_IGNORE_RE.test(tag.text) || SURFACE_IGNORE_RE.test(blockAbove(lines, line))) continue;
|
|
2203
|
+
out.push({ file: filePath, line, snippet: lines[line - 1]?.trim().slice(0, 160) ?? "" });
|
|
2204
|
+
}
|
|
2205
|
+
return out;
|
|
2206
|
+
},
|
|
2207
|
+
};
|
|
2208
|
+
|
|
2144
2209
|
export const RULES: Record<string, Rule> = {
|
|
2145
2210
|
[noRawActionButton.name]: noRawActionButton,
|
|
2146
2211
|
[noRawOverflow.name]: noRawOverflow,
|
|
@@ -2165,6 +2230,7 @@ export const RULES: Record<string, Rule> = {
|
|
|
2165
2230
|
[noRawLazy.name]: noRawLazy,
|
|
2166
2231
|
[noRawPopover.name]: noRawPopover,
|
|
2167
2232
|
[noHandRolledScrollMemory.name]: noHandRolledScrollMemory,
|
|
2233
|
+
[noHandRolledSurface.name]: noHandRolledSurface,
|
|
2168
2234
|
};
|
|
2169
2235
|
|
|
2170
2236
|
/**
|
|
@@ -137,6 +137,7 @@ export function IntervalTimeline({
|
|
|
137
137
|
return (
|
|
138
138
|
<div ref={rootRef} className={cn('flex min-w-0 flex-col gap-1.5', className)}>
|
|
139
139
|
<div
|
|
140
|
+
// guardrails-ignore no-hand-rolled-surface: a chart's plot well (sunken, fixed height, drawn into) — an instrument surface, not a card
|
|
140
141
|
role='img'
|
|
141
142
|
aria-label={ariaLabel}
|
|
142
143
|
className='relative w-full overflow-hidden rounded-md border border-border bg-surface-sunken'
|
|
@@ -211,6 +212,7 @@ export function IntervalTimeline({
|
|
|
211
212
|
|
|
212
213
|
{showConcurrency && peak > 0 && (
|
|
213
214
|
<div
|
|
215
|
+
// guardrails-ignore no-hand-rolled-surface: the concurrency strip's plot well — an instrument surface, not a card
|
|
214
216
|
className='relative h-8 w-full overflow-hidden rounded-md border border-border bg-surface-sunken'
|
|
215
217
|
role='img'
|
|
216
218
|
aria-label={`How many ran at once, peaking at ${peak}`}
|
|
@@ -49,6 +49,14 @@ describe('Button', () => {
|
|
|
49
49
|
expect(cls).toMatch(/(^|\s)bg-destructive-solid(\s|$)/);
|
|
50
50
|
});
|
|
51
51
|
|
|
52
|
+
test('success-solid is the green twin of destructive-solid — a solid fill carrying white text', () => {
|
|
53
|
+
const { getByRole } = render(<Button tooltip='R' variant='success-solid'>Resume</Button>);
|
|
54
|
+
const cls = getByRole('button').className;
|
|
55
|
+
expect(cls).toMatch(/(^|\s)bg-success-solid(\s|$)/);
|
|
56
|
+
expect(cls).toContain('text-white');
|
|
57
|
+
expect(cls).toContain('hover:bg-success-solid-hover');
|
|
58
|
+
});
|
|
59
|
+
|
|
52
60
|
test('tertiary is a first-class variant rendering the ghost weight', () => {
|
|
53
61
|
const { getByRole, rerender } = render(<Button tooltip='T' variant='tertiary'>T</Button>);
|
|
54
62
|
const tertiaryCls = getByRole('button').className;
|
|
@@ -47,6 +47,9 @@ export const buttonVariants = cva(
|
|
|
47
47
|
// destructive-solid — always-loud solid red for the rare surface whose
|
|
48
48
|
// hero action IS destruction (a confirm dialog's confirm,
|
|
49
49
|
// an emergency stop). ≤1 per view, like primary.
|
|
50
|
+
// success-solid — its green twin, for the "go" half of a state toggle whose
|
|
51
|
+
// "stop" half is destructive-solid (a runner's Resume beside its
|
|
52
|
+
// Pause): the colour says what the press DOES. Not a second primary.
|
|
50
53
|
variant: {
|
|
51
54
|
primary:
|
|
52
55
|
'bg-accent-solid text-white hover:bg-accent-solid-hover focus-visible:ring-accent-solid',
|
|
@@ -71,6 +74,7 @@ export const buttonVariants = cva(
|
|
|
71
74
|
'border border-destructive/50 bg-card text-destructive shadow-raised hover:border-destructive-solid hover:bg-destructive-solid hover:text-destructive-foreground focus-visible:ring-destructive',
|
|
72
75
|
'destructive-solid':
|
|
73
76
|
'bg-destructive-solid text-destructive-foreground hover:bg-destructive-solid-hover focus-visible:ring-destructive',
|
|
77
|
+
'success-solid': 'bg-success-solid text-white hover:bg-success-solid-hover focus-visible:ring-success',
|
|
74
78
|
},
|
|
75
79
|
// Height is LOCKED to the control-height token scale (theme.css `--control-h-*`,
|
|
76
80
|
// task cbux-41) — padding is horizontal-only, never vertical, so Button/Input/
|
|
@@ -88,6 +88,7 @@ export function CodeArea({
|
|
|
88
88
|
|
|
89
89
|
return (
|
|
90
90
|
<div
|
|
91
|
+
// guardrails-ignore no-hand-rolled-surface: a code INPUT's well — it carries the field focus ring (focus-within), which makes it a control, not a surface
|
|
91
92
|
className={cn(
|
|
92
93
|
'group relative flex min-h-0 flex-col overflow-hidden rounded-md border border-border bg-surface-sunken',
|
|
93
94
|
// The textarea's own outline is suppressed (it would clip inside the scroll
|
|
@@ -1702,9 +1702,9 @@ export function DataTable<TRow extends Record<string, unknown>>({
|
|
|
1702
1702
|
</div>
|
|
1703
1703
|
{isExpanded ? (
|
|
1704
1704
|
<div className='bg-muted/20 px-4 pt-1 pb-3'>
|
|
1705
|
-
<
|
|
1705
|
+
<Surface level="raised" pad="sm" radius="lg">
|
|
1706
1706
|
{renderExpanded(row.original)}
|
|
1707
|
-
</
|
|
1707
|
+
</Surface>
|
|
1708
1708
|
</div>
|
|
1709
1709
|
) : null}
|
|
1710
1710
|
</Fragment>
|
|
@@ -2006,9 +2006,9 @@ export function DataTable<TRow extends Record<string, unknown>>({
|
|
|
2006
2006
|
instead of a full-bleed band that fractures the pane
|
|
2007
2007
|
(owner final judgments part 2, detail §1). */}
|
|
2008
2008
|
<div className='animate-in fade-in slide-in-from-top-1 px-4 pt-1 pb-3 duration-200'>
|
|
2009
|
-
<
|
|
2009
|
+
<Surface level="raised" pad="sm" radius="lg">
|
|
2010
2010
|
{renderExpanded(row.original)}
|
|
2011
|
-
</
|
|
2011
|
+
</Surface>
|
|
2012
2012
|
</div>
|
|
2013
2013
|
</td>
|
|
2014
2014
|
</tr>
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
newGroup,
|
|
18
18
|
VALUELESS_OPS,
|
|
19
19
|
} from './filterQuery.js';
|
|
20
|
+
import { Surface } from '../Surface.js';
|
|
20
21
|
|
|
21
22
|
export interface TableFilterBuilderColumn {
|
|
22
23
|
key: string;
|
|
@@ -163,7 +164,7 @@ export function TableFilterBuilder({
|
|
|
163
164
|
<span className='h-px flex-1 bg-border' />
|
|
164
165
|
</div>
|
|
165
166
|
) : null}
|
|
166
|
-
<
|
|
167
|
+
<Surface level="flat" pad="none" radius="lg" className='bg-muted/30 p-2'>
|
|
167
168
|
<div className='flex flex-col gap-1.5'>
|
|
168
169
|
{group.conditions.map((condition, conditionIndex) => (
|
|
169
170
|
<div key={condition.id} className='flex items-center gap-1.5'>
|
|
@@ -254,7 +255,7 @@ export function TableFilterBuilder({
|
|
|
254
255
|
>
|
|
255
256
|
<Plus className='size-3' /> And
|
|
256
257
|
</button>
|
|
257
|
-
</
|
|
258
|
+
</Surface>
|
|
258
259
|
</div>
|
|
259
260
|
))}
|
|
260
261
|
</div>
|
|
@@ -2,6 +2,7 @@ import type { ReactNode } from 'react';
|
|
|
2
2
|
import { cn } from '../lib/cn.js';
|
|
3
3
|
import { Badge, type BadgeTone } from './Badge.js';
|
|
4
4
|
import { EmptyState } from './EmptyState.js';
|
|
5
|
+
import { Surface } from './Surface.js';
|
|
5
6
|
|
|
6
7
|
/** Ordered worst-first. The order IS the sort key. */
|
|
7
8
|
export const FINDING_SEVERITIES = ['critical', 'warning', 'info'] as const;
|
|
@@ -91,13 +92,15 @@ export function FindingsList({
|
|
|
91
92
|
return (
|
|
92
93
|
<ul className={cn('flex flex-col gap-2', className)}>
|
|
93
94
|
{shown.map((f) => (
|
|
94
|
-
<
|
|
95
|
+
<Surface
|
|
95
96
|
key={f.id}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
97
|
+
asChild
|
|
98
|
+
level='flat'
|
|
99
|
+
pad='none'
|
|
100
|
+
radius='md'
|
|
101
|
+
className={cn('flex min-w-0 flex-col gap-1 border-l-2 bg-card px-3 py-2.5', ACCENT[f.severity])}
|
|
100
102
|
>
|
|
103
|
+
<li>
|
|
101
104
|
<div className='flex min-w-0 flex-wrap items-center gap-2'>
|
|
102
105
|
<Badge tone={TONE[f.severity]}>{f.severity}</Badge>
|
|
103
106
|
{f.scope && <span className='cb-meta-label shrink-0'>{f.scope}</span>}
|
|
@@ -113,6 +116,7 @@ export function FindingsList({
|
|
|
113
116
|
)}
|
|
114
117
|
{f.action && <div className='pt-1'>{f.action}</div>}
|
|
115
118
|
</li>
|
|
119
|
+
</Surface>
|
|
116
120
|
))}
|
|
117
121
|
{hidden > 0 && (
|
|
118
122
|
<li className='px-3 py-1 text-xs text-muted-foreground'>
|
|
@@ -104,6 +104,7 @@ export function InfoHint({
|
|
|
104
104
|
{open ? (
|
|
105
105
|
<FloatingPortal>
|
|
106
106
|
<div
|
|
107
|
+
// guardrails-ignore no-hand-rolled-surface: the hint's floating-ui bubble — a tooltip-class overlay with its own z-index and shadow, not a card
|
|
107
108
|
ref={refs.setFloating}
|
|
108
109
|
style={floatingStyles}
|
|
109
110
|
{...getFloatingProps()}
|
|
@@ -48,6 +48,7 @@ export function Section({
|
|
|
48
48
|
const card = variant === 'card';
|
|
49
49
|
return (
|
|
50
50
|
<section
|
|
51
|
+
// guardrails-ignore no-hand-rolled-surface: this IS the section primitive; its `card` variant is the tinted frame apps are told to use instead of a hand-rolled one
|
|
51
52
|
className={cn(
|
|
52
53
|
'flex flex-col',
|
|
53
54
|
card ? 'gap-3 rounded-lg border border-border bg-muted/20 p-3 sm:p-4' : 'gap-4',
|
|
@@ -3,6 +3,7 @@ import { dayStartMs, monthMatrix, todayKey, WEEKDAY_LABELS } from 'cwip/calendar
|
|
|
3
3
|
import type { ReactNode } from 'react';
|
|
4
4
|
import { cn } from '../../lib/cn.js';
|
|
5
5
|
import { TAP_TARGET_ALWAYS } from '../../lib/tapTarget.js';
|
|
6
|
+
import { Surface } from '../Surface.js';
|
|
6
7
|
|
|
7
8
|
export interface MonthGridDay {
|
|
8
9
|
/** Local day key ("YYYY-MM-DD") this cell represents. */
|
|
@@ -71,8 +72,8 @@ export function MonthGrid({
|
|
|
71
72
|
const clickable = Boolean(onSelectDay);
|
|
72
73
|
|
|
73
74
|
return (
|
|
75
|
+
<Surface asChild level='flat' pad='none' radius='xl' className={cn('overflow-hidden bg-card', className)}>
|
|
74
76
|
<section
|
|
75
|
-
className={cn('overflow-hidden rounded-xl border border-border bg-card', className)}
|
|
76
77
|
aria-label='Month calendar'
|
|
77
78
|
>
|
|
78
79
|
{/* Weekday header — presentational */}
|
|
@@ -164,5 +165,6 @@ export function MonthGrid({
|
|
|
164
165
|
})}
|
|
165
166
|
</div>
|
|
166
167
|
</section>
|
|
168
|
+
</Surface>
|
|
167
169
|
);
|
|
168
170
|
}
|