@elabs-ai/components-ui 4.0.0 → 4.1.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/README.md +10 -8
- package/dist/chunk-JKPPTL63.js +48 -0
- package/dist/chunk-JKPPTL63.js.map +1 -0
- package/dist/form.d.ts +28 -0
- package/dist/form.js +123 -0
- package/dist/form.js.map +1 -0
- package/dist/index.d.ts +2485 -167
- package/dist/index.js +10716 -2706
- package/dist/index.js.map +1 -1
- package/package.json +21 -7
- package/src/_peer-deps.test.ts +59 -0
- package/src/blocks-comparison-table.stories.tsx +2 -2
- package/src/components/accordion/accordion.tsx +1 -1
- package/src/components/advanced-group/advanced-group.tsx +1 -1
- package/src/components/alert/alert.tsx +4 -1
- package/src/components/app-shell/app-shell.stories.tsx +44 -2
- package/src/components/app-shell/app-shell.tsx +35 -2
- package/src/components/app-sidebar/app-sidebar.stories.tsx +9 -1
- package/src/components/attribution-panel/attribution-panel.tsx +1 -1
- package/src/components/attribution-panel/attributions.generated.ts +81 -77
- package/src/components/badge/badge.stories.tsx +8 -0
- package/src/components/badge/badge.tsx +1 -1
- package/src/components/bento-grid/bento-grid.test.tsx +1 -1
- package/src/components/bento-grid/bento-grid.tsx +1 -1
- package/src/components/breadcrumb/breadcrumb.stories.tsx +38 -0
- package/src/components/breadcrumb/breadcrumb.test.tsx +24 -1
- package/src/components/breadcrumb/breadcrumb.tsx +7 -2
- package/src/components/button/button.stories.tsx +116 -8
- package/src/components/button/button.tsx +1 -1
- package/src/components/card/card.stories.tsx +11 -6
- package/src/components/card/card.tsx +1 -1
- package/src/components/change-review/change-review.stories.tsx +145 -1
- package/src/components/change-review/change-review.test.tsx +143 -0
- package/src/components/change-review/change-review.tsx +185 -4
- package/src/components/checkbox/checkbox.tsx +1 -1
- package/src/components/color-picker/color-picker.tsx +6 -5
- package/src/components/command/command.stories.tsx +16 -6
- package/src/components/command/command.test.tsx +73 -0
- package/src/components/command/command.tsx +30 -7
- package/src/components/command/index.ts +1 -0
- package/src/components/command-trigger/command-trigger.stories.tsx +39 -0
- package/src/components/command-trigger/command-trigger.test.tsx +18 -0
- package/src/components/command-trigger/command-trigger.tsx +70 -0
- package/src/components/command-trigger/index.ts +1 -0
- package/src/components/context-rail/context-rail.stories.tsx +285 -0
- package/src/components/context-rail/context-rail.test.tsx +263 -0
- package/src/components/context-rail/context-rail.tsx +678 -0
- package/src/components/context-rail/index.ts +1 -0
- package/src/components/copyable-value/copyable-value.tsx +1 -1
- package/src/components/dialog/dialog.tsx +2 -2
- package/src/components/dropdown-menu/dropdown-menu.stories.tsx +1 -1
- package/src/components/empty-state/empty-state.test.tsx +26 -0
- package/src/components/empty-state/empty-state.tsx +6 -1
- package/src/components/expand-dialog/expand-dialog.tsx +1 -2
- package/src/components/field/field-context.ts +59 -0
- package/src/components/field/field.stories.tsx +142 -0
- package/src/components/field/field.test.tsx +415 -0
- package/src/components/field/field.tsx +340 -0
- package/src/components/field/index.ts +9 -0
- package/src/components/field-row/field-row.stories.tsx +85 -1
- package/src/components/field-row/field-row.test.tsx +145 -0
- package/src/components/field-row/field-row.tsx +48 -6
- package/src/components/file-upload/file-upload.stories.tsx +16 -0
- package/src/components/file-upload/file-upload.test.tsx +7 -2
- package/src/components/file-upload/file-upload.tsx +15 -4
- package/src/components/form/form.tsx +5 -2
- package/src/components/icon-button/icon-button.test.tsx +1 -1
- package/src/components/icon-button/icon-button.tsx +2 -2
- package/src/components/input/input.stories.tsx +121 -0
- package/src/components/input/input.test.tsx +13 -0
- package/src/components/input/input.tsx +2 -2
- package/src/components/input-group/input-group.stories.tsx +74 -0
- package/src/components/input-group/input-group.tsx +13 -4
- package/src/components/input-otp/input-otp.tsx +5 -1
- package/src/components/keyboard-shortcuts/index.ts +6 -0
- package/src/components/keyboard-shortcuts/keyboard-shortcuts.stories.tsx +177 -0
- package/src/components/keyboard-shortcuts/keyboard-shortcuts.test.tsx +73 -0
- package/src/components/keyboard-shortcuts/keyboard-shortcuts.tsx +203 -0
- package/src/components/link-preview/link-preview.tsx +1 -1
- package/src/components/locale-provider/index.ts +6 -1
- package/src/components/locale-provider/locale-provider.stories.tsx +89 -1
- package/src/components/locale-provider/locale-provider.test.tsx +257 -1
- package/src/components/locale-provider/locale-provider.tsx +63 -8
- package/src/components/locale-provider/messages.ts +501 -2
- package/src/components/match-highlight/match-highlight.stories.tsx +1 -1
- package/src/components/mention-input/mention-input-mirror.stories.tsx +9 -1
- package/src/components/mention-input/mention-input.tsx +8 -38
- package/src/components/mention-input/mention-value.ts +8 -2
- package/src/components/metric-card/metric-card.stories.tsx +5 -3
- package/src/components/metric-card/metric-card.tsx +21 -2
- package/src/components/model-picker/model-picker.stories.tsx +63 -3
- package/src/components/model-picker/model-picker.test.tsx +63 -0
- package/src/components/model-picker/model-picker.tsx +62 -36
- package/src/components/nav-main/nav-main.tsx +1 -1
- package/src/components/nav-notifications/nav-notifications.stories.tsx +110 -0
- package/src/components/nav-notifications/nav-notifications.tsx +57 -5
- package/src/components/navigation-menu/navigation-menu.stories.tsx +22 -0
- package/src/components/navigation-menu/navigation-menu.test.tsx +174 -0
- package/src/components/navigation-menu/navigation-menu.tsx +189 -12
- package/src/components/page-shell/page-shell.stories.tsx +163 -0
- package/src/components/page-shell/page-shell.test.tsx +229 -0
- package/src/components/page-shell/page-shell.tsx +108 -25
- package/src/components/pagination/pagination.test.tsx +90 -0
- package/src/components/pagination/pagination.tsx +9 -5
- package/src/components/radio-group/radio-group.tsx +1 -1
- package/src/components/rating/rating.tsx +1 -1
- package/src/components/resizable/resizable.stories.tsx +114 -2
- package/src/components/resizable/resizable.tsx +1 -1
- package/src/components/revision-timeline/revision-timeline.stories.tsx +8 -1
- package/src/components/revision-timeline/revision-timeline.test.tsx +26 -0
- package/src/components/revision-timeline/revision-timeline.tsx +46 -3
- package/src/components/schema-form/from-json-schema.test.ts +390 -0
- package/src/components/schema-form/from-json-schema.ts +375 -0
- package/src/components/schema-form/index.ts +81 -0
- package/src/components/schema-form/schema-form-spec.ts +698 -0
- package/src/components/schema-form/schema-form.stories.tsx +566 -0
- package/src/components/schema-form/schema-form.test.tsx +900 -0
- package/src/components/schema-form/schema-form.tsx +1545 -0
- package/src/components/section-header/section-header.stories.tsx +37 -0
- package/src/components/section-header/section-header.tsx +12 -1
- package/src/components/select/select.tsx +6 -2
- package/src/components/sheet/sheet.tsx +1 -1
- package/src/components/side-dock/index.ts +1 -0
- package/src/components/side-dock/side-dock.stories.tsx +137 -0
- package/src/components/side-dock/side-dock.test.tsx +273 -0
- package/src/components/side-dock/side-dock.tsx +502 -0
- package/src/components/sidebar/index.ts +1 -0
- package/src/components/sidebar/sidebar-frame.test.tsx +162 -0
- package/src/components/sidebar/sidebar.stories.tsx +421 -1
- package/src/components/sidebar/sidebar.test.tsx +36 -1
- package/src/components/sidebar/sidebar.tsx +245 -33
- package/src/components/skip-link/index.ts +1 -0
- package/src/components/skip-link/skip-link.stories.tsx +106 -0
- package/src/components/skip-link/skip-link.test.tsx +20 -0
- package/src/components/skip-link/skip-link.tsx +34 -0
- package/src/components/slider/slider.tsx +1 -1
- package/src/components/split-panel/index.ts +6 -1
- package/src/components/split-panel/split-panel.stories.tsx +18 -2
- package/src/components/split-panel/split-panel.test.tsx +20 -0
- package/src/components/split-panel/split-panel.tsx +28 -8
- package/src/components/state-panel/state-panel.stories.tsx +52 -0
- package/src/components/state-panel/state-panel.test.tsx +125 -0
- package/src/components/state-panel/state-panel.tsx +96 -17
- package/src/components/status-badge/status-badge.stories.tsx +8 -0
- package/src/components/switch/switch.tsx +1 -1
- package/src/components/table/table.stories.tsx +62 -0
- package/src/components/table/table.test.tsx +142 -1
- package/src/components/table/table.tsx +60 -1
- package/src/components/tabs/tabs.tsx +8 -2
- package/src/components/tag-input/tag-input.tsx +3 -2
- package/src/components/team-switcher/team-switcher.tsx +34 -5
- package/src/components/textarea/textarea.tsx +1 -1
- package/src/components/theme-switcher/theme-switcher.tsx +6 -2
- package/src/components/theme-switcher/use-theme-transition.ts +2 -2
- package/src/components/timeline/timeline.stories.tsx +27 -0
- package/src/components/timeline/timeline.tsx +11 -1
- package/src/components/toggle/toggle.tsx +1 -1
- package/src/components/toolbar/toolbar.stories.tsx +10 -2
- package/src/components/tree/tree.stories.tsx +2 -2
- package/src/components/tree/tree.tsx +14 -9
- package/src/components/typography/prose.tsx +1 -1
- package/src/components/typography/typography.stories.tsx +228 -0
- package/src/components/view-toolbar/view-toolbar.stories.tsx +41 -1
- package/src/components/view-toolbar/view-toolbar.test.tsx +33 -0
- package/src/components/view-toolbar/view-toolbar.tsx +37 -4
- package/src/components/virtual-select/virtual-select.test.tsx +1 -1
- package/src/components/wizard/wizard.tsx +1 -1
- package/src/components/workspace-picker/index.ts +3 -0
- package/src/components/workspace-picker/workspace-picker-state.ts +50 -0
- package/src/components/workspace-picker/workspace-picker.stories.tsx +126 -0
- package/src/components/workspace-picker/workspace-picker.test.tsx +207 -0
- package/src/components/workspace-picker/workspace-picker.tsx +172 -0
- package/src/illustrations/empty-list-illustration.tsx +26 -0
- package/src/illustrations/error-illustration.tsx +60 -0
- package/src/illustrations/first-run-illustration.tsx +27 -0
- package/src/illustrations/illustration-base.tsx +108 -0
- package/src/illustrations/illustrations.stories.tsx +94 -0
- package/src/illustrations/illustrations.test.tsx +98 -0
- package/src/illustrations/index.ts +16 -0
- package/src/illustrations/no-access-illustration.tsx +45 -0
- package/src/illustrations/no-results-illustration.tsx +46 -0
- package/src/illustrations/offline-illustration.tsx +37 -0
- package/src/illustrations/success-illustration.tsx +40 -0
- package/src/index.ts +75 -2
- package/src/lib/agent-event-model.test.ts +12 -0
- package/src/lib/agent-event-model.ts +42 -0
- package/src/lib/approval-option.test.ts +17 -0
- package/src/lib/approval-option.ts +53 -0
- package/src/lib/check-result.ts +33 -0
- package/src/lib/diff-line.test.ts +36 -0
- package/src/lib/diff-line.ts +63 -0
- package/src/lib/diff-rows.test.ts +76 -0
- package/src/lib/diff-rows.ts +92 -0
- package/src/lib/format-duration.test.ts +22 -0
- package/src/lib/format-duration.ts +30 -0
- package/src/lib/has-renderable-content.test.ts +49 -0
- package/src/lib/has-renderable-content.ts +32 -0
- package/src/lib/operating-mode.test.ts +36 -0
- package/src/lib/operating-mode.ts +81 -0
- package/src/lib/optional-peer.ts +59 -0
- package/src/lib/session-launch.ts +37 -0
- package/src/lib/slash-command.test.ts +44 -0
- package/src/lib/slash-command.ts +45 -0
- package/src/lib/trigger-query.test.ts +94 -0
- package/src/lib/trigger-query.ts +88 -0
- package/src/lib/use-mobile.ts +12 -6
- package/src/motion.stories.tsx +6 -0
- package/src/templates-object-detail-hub.stories.tsx +2 -2
- package/src/templates-screen-states.stories.tsx +5 -5
- package/src/templates-settings.stories.tsx +1 -1
- package/src/blocks/sidebar-02/app-sidebar.tsx +0 -160
- package/src/blocks/sidebar-02/logo.tsx +0 -18
- package/src/blocks/sidebar-02/nav-main.tsx +0 -13
- package/src/blocks/sidebar-02/nav-notifications.tsx +0 -7
- package/src/blocks/sidebar-02/sidebar-02.stories.tsx +0 -23
- package/src/blocks/sidebar-02/team-switcher.tsx +0 -7
- package/src/blocks/sidebar-04/app-sidebar.tsx +0 -236
- package/src/blocks/sidebar-04/mail-context.tsx +0 -29
- package/src/blocks/sidebar-04/nav-user.tsx +0 -6
- package/src/blocks/sidebar-04/sidebar-04.stories.tsx +0 -150
- package/src/blocks/sidebar-05/app-sidebar.tsx +0 -375
- package/src/blocks/sidebar-05/sidebar-05.stories.tsx +0 -18
- package/src/blocks/sidebar-05/team-switcher.tsx +0 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elabs-ai/components-ui",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.1.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -21,6 +21,10 @@
|
|
|
21
21
|
"./lib/cn": {
|
|
22
22
|
"types": "./dist/lib/cn.d.ts",
|
|
23
23
|
"default": "./dist/lib/cn.js"
|
|
24
|
+
},
|
|
25
|
+
"./form": {
|
|
26
|
+
"types": "./dist/form.d.ts",
|
|
27
|
+
"default": "./dist/form.js"
|
|
24
28
|
}
|
|
25
29
|
},
|
|
26
30
|
"publishConfig": {
|
|
@@ -28,7 +32,6 @@
|
|
|
28
32
|
"registry": "https://registry.npmjs.org/"
|
|
29
33
|
},
|
|
30
34
|
"dependencies": {
|
|
31
|
-
"@hookform/resolvers": "^3.9.1",
|
|
32
35
|
"@radix-ui/react-accordion": "^1.2.2",
|
|
33
36
|
"@radix-ui/react-alert-dialog": "^1.1.4",
|
|
34
37
|
"@radix-ui/react-aspect-ratio": "^1.1.1",
|
|
@@ -65,19 +68,28 @@
|
|
|
65
68
|
"input-otp": "^1.4.1",
|
|
66
69
|
"lucide-react": "^0.577.0",
|
|
67
70
|
"react-day-picker": "^9.4.4",
|
|
68
|
-
"react-hook-form": "^7.54.2",
|
|
69
71
|
"react-resizable-panels": "^2.1.7",
|
|
70
72
|
"sonner": "^1.7.1",
|
|
71
73
|
"tailwind-merge": "^2.6.0",
|
|
72
|
-
"vaul": "^1.1.2"
|
|
73
|
-
"zod": "^3.24.1"
|
|
74
|
+
"vaul": "^1.1.2"
|
|
74
75
|
},
|
|
75
76
|
"peerDependencies": {
|
|
77
|
+
"@hookform/resolvers": "^3.9.1",
|
|
76
78
|
"react": "^18.2.0 || ^19.0.0",
|
|
77
79
|
"react-dom": "^18.2.0 || ^19.0.0",
|
|
78
|
-
"
|
|
80
|
+
"react-hook-form": "^7.54.2",
|
|
81
|
+
"@elabs-ai/components-tokens": "4.1.0"
|
|
82
|
+
},
|
|
83
|
+
"peerDependenciesMeta": {
|
|
84
|
+
"@hookform/resolvers": {
|
|
85
|
+
"optional": true
|
|
86
|
+
},
|
|
87
|
+
"react-hook-form": {
|
|
88
|
+
"optional": true
|
|
89
|
+
}
|
|
79
90
|
},
|
|
80
91
|
"devDependencies": {
|
|
92
|
+
"@hookform/resolvers": "^3.9.1",
|
|
81
93
|
"@testing-library/jest-dom": "^6.6.3",
|
|
82
94
|
"@testing-library/react": "^16.1.0",
|
|
83
95
|
"@testing-library/user-event": "^14.5.2",
|
|
@@ -88,12 +100,14 @@
|
|
|
88
100
|
"jsdom": "^25.0.1",
|
|
89
101
|
"react": "^19.0.0",
|
|
90
102
|
"react-dom": "^19.0.0",
|
|
103
|
+
"react-hook-form": "^7.54.2",
|
|
91
104
|
"tsup": "^8.3.5",
|
|
92
105
|
"typescript": "^5.7.3",
|
|
93
106
|
"vitest": "^3.0.2",
|
|
107
|
+
"zod": "^3.24.1",
|
|
94
108
|
"@elabs-ai/components-eslint-config": "0.1.0",
|
|
95
109
|
"@elabs-ai/components-typescript-config": "0.1.0",
|
|
96
|
-
"@elabs-ai/components-tokens": "4.
|
|
110
|
+
"@elabs-ai/components-tokens": "4.1.0"
|
|
97
111
|
},
|
|
98
112
|
"scripts": {
|
|
99
113
|
"build": "rm -rf dist && tsup",
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { describe, expect, it } from "vitest";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Regression guard for issue #26 — `react-hook-form` / `@hookform/resolvers`
|
|
8
|
+
* are used ONLY by the RHF-bound `Form` family
|
|
9
|
+
* (`packages/ui/src/components/form/form.tsx`); `FieldRow` and every other
|
|
10
|
+
* component in this package render from plain props and never import either.
|
|
11
|
+
*
|
|
12
|
+
* A consumer who never imports `Form` should not be forced to install (or
|
|
13
|
+
* have their bundler resolve) react-hook-form. Declaring both as
|
|
14
|
+
* `dependencies` defeats that — npm/pnpm install them unconditionally for
|
|
15
|
+
* every consumer of `@elabs-ai/components-ui`, regardless of whether `Form`
|
|
16
|
+
* is ever imported. This test locks the fix: both packages are declared as
|
|
17
|
+
* OPTIONAL peers, and neither reappears as a hard `dependency`.
|
|
18
|
+
*
|
|
19
|
+
* `zod` is used only inside `form.stories.tsx` (the `zodResolver` demo) and
|
|
20
|
+
* never in shipped runtime source — it belongs in `devDependencies`, never as
|
|
21
|
+
* a runtime `dependency` or a peer a consumer must install.
|
|
22
|
+
*/
|
|
23
|
+
const PACKAGE_JSON_PATH = join(dirname(fileURLToPath(import.meta.url)), "..", "package.json");
|
|
24
|
+
|
|
25
|
+
function readPackageJson(): {
|
|
26
|
+
dependencies?: Record<string, string>;
|
|
27
|
+
devDependencies?: Record<string, string>;
|
|
28
|
+
peerDependencies?: Record<string, string>;
|
|
29
|
+
peerDependenciesMeta?: Record<string, { optional?: boolean }>;
|
|
30
|
+
} {
|
|
31
|
+
return JSON.parse(readFileSync(PACKAGE_JSON_PATH, "utf8"));
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
describe("packages/ui/package.json — react-hook-form is an optional peer, not a hard dependency", () => {
|
|
35
|
+
const pkg = readPackageJson();
|
|
36
|
+
|
|
37
|
+
it.each(["react-hook-form", "@hookform/resolvers"])(
|
|
38
|
+
"declares %s as an OPTIONAL peerDependency",
|
|
39
|
+
(name) => {
|
|
40
|
+
expect(pkg.dependencies?.[name]).toBeUndefined();
|
|
41
|
+
expect(pkg.peerDependencies?.[name]).toBeTruthy();
|
|
42
|
+
expect(pkg.peerDependenciesMeta?.[name]?.optional).toBe(true);
|
|
43
|
+
},
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
it("still lists react-hook-form + @hookform/resolvers as devDependencies for the workspace's own build/test", () => {
|
|
47
|
+
// The package's own `Form` tests/stories (and `form.tsx` itself) need the
|
|
48
|
+
// real library to typecheck/run inside this workspace — peer alone does
|
|
49
|
+
// not guarantee resolution here, only for an external consumer.
|
|
50
|
+
expect(pkg.devDependencies?.["react-hook-form"]).toBeTruthy();
|
|
51
|
+
expect(pkg.devDependencies?.["@hookform/resolvers"]).toBeTruthy();
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it("declares zod as a devDependency only — never a runtime dependency or peer", () => {
|
|
55
|
+
expect(pkg.dependencies?.zod).toBeUndefined();
|
|
56
|
+
expect(pkg.peerDependencies?.zod).toBeUndefined();
|
|
57
|
+
expect(pkg.devDependencies?.zod).toBeTruthy();
|
|
58
|
+
});
|
|
59
|
+
});
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* cells, a price row, and a per-plan CTA row. Reuses brand-ui's strongest
|
|
8
8
|
* assets — Table + Badge + Button — and stays token-only.
|
|
9
9
|
*
|
|
10
|
-
* Reads in
|
|
10
|
+
* Reads in every theme. Verify with globals=theme:<slug>.
|
|
11
11
|
*/
|
|
12
12
|
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
13
13
|
import { Check, Minus } from "lucide-react";
|
|
@@ -152,7 +152,7 @@ const meta = {
|
|
|
152
152
|
docs: {
|
|
153
153
|
description: {
|
|
154
154
|
component:
|
|
155
|
-
"The canonical plan/feature comparison matrix (brand-ui's Compare gap): a header with one featured column (badge + recessed wash), feature rows with check / dash / value cells, a price row, and a per-plan CTA row. Composes Table + Badge + Button; semantic tokens only; reads in
|
|
155
|
+
"The canonical plan/feature comparison matrix (brand-ui's Compare gap): a header with one featured column (badge + recessed wash), feature rows with check / dash / value cells, a price row, and a per-plan CTA row. Composes Table + Badge + Button; semantic tokens only; reads in every theme.",
|
|
156
156
|
},
|
|
157
157
|
},
|
|
158
158
|
},
|
|
@@ -21,7 +21,7 @@ export const AccordionTrigger = forwardRef<
|
|
|
21
21
|
<AccordionPrimitive.Trigger
|
|
22
22
|
ref={ref}
|
|
23
23
|
className={cn(
|
|
24
|
-
"flex flex-1 items-center justify-between py-4 text-sm font-medium transition-all hover:underline focus-
|
|
24
|
+
"flex flex-1 items-center justify-between py-4 text-sm font-medium transition-all hover:underline focus-ring [&[data-state=open]>svg]:rotate-180",
|
|
25
25
|
className,
|
|
26
26
|
)}
|
|
27
27
|
{...props}
|
|
@@ -85,7 +85,7 @@ export function AdvancedGroup({
|
|
|
85
85
|
>
|
|
86
86
|
<CollapsibleTrigger
|
|
87
87
|
data-slot="advanced-group-trigger"
|
|
88
|
-
className="group -mx-2 flex items-center gap-2 rounded-md px-2 py-1.5 text-body font-medium hover:bg-accent hover:text-accent-foreground focus-
|
|
88
|
+
className="group -mx-2 flex items-center gap-2 rounded-md px-2 py-1.5 text-body font-medium hover:bg-accent hover:text-accent-foreground focus-ring"
|
|
89
89
|
>
|
|
90
90
|
<ChevronDown
|
|
91
91
|
aria-hidden="true"
|
|
@@ -11,8 +11,11 @@ export const alertVariants = cva(
|
|
|
11
11
|
info: "border-info/40 bg-info/10 text-foreground",
|
|
12
12
|
success: "border-success/40 bg-success/10 text-foreground",
|
|
13
13
|
warning: "border-warning/50 bg-warning/10 text-foreground",
|
|
14
|
+
// #124: the bare `text-destructive` set the ambient colour for the
|
|
15
|
+
// Title/Description running text — ink rung. `[&>svg]:text-destructive`
|
|
16
|
+
// (the icon mark) is unchanged.
|
|
14
17
|
destructive:
|
|
15
|
-
"border-destructive/40 bg-destructive/10 text-destructive [&>svg]:text-destructive",
|
|
18
|
+
"border-destructive/40 bg-destructive/10 text-destructive-text [&>svg]:text-destructive",
|
|
16
19
|
},
|
|
17
20
|
},
|
|
18
21
|
defaultVariants: { variant: "default" },
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
2
|
+
import { expect, within } from "storybook/test";
|
|
2
3
|
import { AppShell } from "./app-shell";
|
|
3
4
|
import { TopNav } from "../top-nav";
|
|
4
5
|
import { PageShell } from "../page-shell";
|
|
@@ -6,7 +7,7 @@ import { SectionHeader } from "../section-header";
|
|
|
6
7
|
import { Button } from "../button";
|
|
7
8
|
|
|
8
9
|
const meta = {
|
|
9
|
-
title: "Layout/App Shell/
|
|
10
|
+
title: "Layout/App Shell/Minimal",
|
|
10
11
|
component: AppShell,
|
|
11
12
|
parameters: { layout: "fullscreen" },
|
|
12
13
|
} satisfies Meta<typeof AppShell>;
|
|
@@ -46,8 +47,10 @@ export const Default: Story = {
|
|
|
46
47
|
<PageShell
|
|
47
48
|
header={
|
|
48
49
|
<SectionHeader
|
|
50
|
+
// The page's own title, so it owns the document outline root.
|
|
51
|
+
as="h1"
|
|
49
52
|
title="Overview"
|
|
50
|
-
description="A
|
|
53
|
+
description="A minimal, unstyled two-region shell — the honest answer for a simple layout. For full sidebar behavior use the Sidebar primitive; for a fully wired enterprise console see Layout/App Shell/Flagship."
|
|
51
54
|
/>
|
|
52
55
|
}
|
|
53
56
|
>
|
|
@@ -58,4 +61,43 @@ export const Default: Story = {
|
|
|
58
61
|
</AppShell>
|
|
59
62
|
</div>
|
|
60
63
|
),
|
|
64
|
+
play: async ({ canvasElement }) => {
|
|
65
|
+
const canvas = within(canvasElement);
|
|
66
|
+
|
|
67
|
+
// The shell ships a skip link, so a keyboard user can pass the nav rail
|
|
68
|
+
// instead of tabbing through it on every route (WCAG 2.4.1). Resolve the
|
|
69
|
+
// TARGET FROM THE LINK, never from a hard-coded `#main-content`: querying
|
|
70
|
+
// the id directly stays green when the link and the target are deleted
|
|
71
|
+
// together.
|
|
72
|
+
const skip = canvas.getByRole("link", { name: "Skip to main content" });
|
|
73
|
+
const targetId = (skip.getAttribute("href") ?? "").replace(/^#/, "");
|
|
74
|
+
await expect(targetId).not.toBe("");
|
|
75
|
+
const target = canvasElement.querySelector(`#${CSS.escape(targetId)}`) as HTMLElement;
|
|
76
|
+
await expect(target).toBeVisible();
|
|
77
|
+
await expect(target.tagName).toBe("MAIN");
|
|
78
|
+
await expect(canvas.getByRole("main")).toBe(target);
|
|
79
|
+
|
|
80
|
+
// …and here <main> IS the scroll port (in the registry blocks the skip
|
|
81
|
+
// target and the port are separate elements), so it takes a REAL tab stop,
|
|
82
|
+
// not the `-1` a pure skip target would carry: a region that scrolls has to
|
|
83
|
+
// be keyboard-operable even when nothing inside it is focusable (WCAG
|
|
84
|
+
// 2.1.1, axe `scrollable-region-focusable`). Read as an ATTRIBUTE — the
|
|
85
|
+
// `tabIndex` IDL getter answers -1 for any non-focusable element whether or
|
|
86
|
+
// not anyone set it, so it cannot tell "-1 was set" from "nothing was set".
|
|
87
|
+
await expect(target).toHaveAttribute("tabindex", "0");
|
|
88
|
+
await expect(getComputedStyle(target).overflowY).toBe("auto");
|
|
89
|
+
// The INSET rung: the shell root above carries `overflow-hidden`, which
|
|
90
|
+
// clips both layers of the plain `focus-ring`. Asserting only that
|
|
91
|
+
// `focus-ring-inset` is present would still pass with both classes on the
|
|
92
|
+
// element — and then the clipped one is what paints.
|
|
93
|
+
await expect(target.classList.contains("focus-ring-inset")).toBe(true);
|
|
94
|
+
await expect(target.classList.contains("focus-ring")).toBe(false);
|
|
95
|
+
|
|
96
|
+
// The outline has a root. axe cannot catch its absence here:
|
|
97
|
+
// `page-has-heading-one` is a best-practice rule outside the wcag2a/wcag2aa
|
|
98
|
+
// tag set, and `heading-order` passes happily on levels that start at 2.
|
|
99
|
+
const h1s = canvasElement.querySelectorAll("h1");
|
|
100
|
+
await expect(h1s.length).toBe(1);
|
|
101
|
+
await expect(canvas.getByRole("heading", { level: 1 })).toHaveTextContent("Overview");
|
|
102
|
+
},
|
|
61
103
|
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type ReactNode } from "react";
|
|
2
2
|
import { cn } from "../../lib/cn";
|
|
3
|
+
import { SkipLink } from "../skip-link";
|
|
3
4
|
|
|
4
5
|
export interface AppShellProps {
|
|
5
6
|
/** Persistent left navigation (often a <Sidebar />). */
|
|
@@ -10,21 +11,53 @@ export interface AppShellProps {
|
|
|
10
11
|
className?: string;
|
|
11
12
|
/** Class for the scrolling main content region. */
|
|
12
13
|
mainClassName?: string;
|
|
14
|
+
/**
|
|
15
|
+
* The `<main>` region's id, and the skip link's target. Override it when a
|
|
16
|
+
* page mounts more than one shell — two elements sharing `main-content`
|
|
17
|
+
* would make the skip link ambiguous. @default "main-content"
|
|
18
|
+
*/
|
|
19
|
+
mainId?: string;
|
|
13
20
|
}
|
|
14
21
|
|
|
15
22
|
/**
|
|
16
23
|
* App-first layout: fixed-height viewport with an optional sidebar, a top bar,
|
|
17
24
|
* and a scrollable main region. Pure layout — bring your own nav components.
|
|
18
25
|
*/
|
|
19
|
-
export function AppShell({
|
|
26
|
+
export function AppShell({
|
|
27
|
+
sidebar,
|
|
28
|
+
topNav,
|
|
29
|
+
children,
|
|
30
|
+
className,
|
|
31
|
+
mainClassName,
|
|
32
|
+
mainId = "main-content",
|
|
33
|
+
}: AppShellProps) {
|
|
20
34
|
return (
|
|
21
35
|
<div
|
|
22
36
|
className={cn("flex h-dvh w-full overflow-hidden bg-background text-foreground", className)}
|
|
23
37
|
>
|
|
38
|
+
{/* The first focusable element of the shell, so a keyboard user can pass
|
|
39
|
+
the nav rail instead of tabbing through it on every route (WCAG 2.4.1).
|
|
40
|
+
All four registry app-shell blocks ship one; the primitive they sit
|
|
41
|
+
beside must not be the exception, and it is the surface with the widest
|
|
42
|
+
reach — it is imported, not copy-owned. */}
|
|
43
|
+
<SkipLink targetId={mainId} />
|
|
24
44
|
{sidebar ? <div className="hidden md:flex">{sidebar}</div> : null}
|
|
25
45
|
<div className="flex min-w-0 flex-1 flex-col">
|
|
26
46
|
{topNav}
|
|
27
|
-
|
|
47
|
+
{/* `<main>` IS the scroll port here (in the blocks the skip target and
|
|
48
|
+
the scroll port are separate elements), so it takes `tabIndex={0}`
|
|
49
|
+
rather than `{-1}`: a region that scrolls has to be keyboard-operable
|
|
50
|
+
even when the content inside it is not focusable (WCAG 2.1.1, axe
|
|
51
|
+
`scrollable-region-focusable`). `focus-ring-inset`, not `focus-ring`
|
|
52
|
+
— the root above carries `overflow-hidden`, which clips both layers
|
|
53
|
+
of the plain rung. */}
|
|
54
|
+
<main
|
|
55
|
+
id={mainId}
|
|
56
|
+
tabIndex={0}
|
|
57
|
+
className={cn("min-h-0 flex-1 overflow-y-auto focus-ring-inset", mainClassName)}
|
|
58
|
+
>
|
|
59
|
+
{children}
|
|
60
|
+
</main>
|
|
28
61
|
</div>
|
|
29
62
|
</div>
|
|
30
63
|
);
|
|
@@ -17,7 +17,15 @@ const meta = {
|
|
|
17
17
|
title: "Layout/AppSidebar",
|
|
18
18
|
component: AppSidebar,
|
|
19
19
|
tags: ["autodocs"],
|
|
20
|
-
parameters: {
|
|
20
|
+
parameters: {
|
|
21
|
+
layout: "fullscreen",
|
|
22
|
+
docs: {
|
|
23
|
+
description: {
|
|
24
|
+
component:
|
|
25
|
+
"The opinionated application sidebar — the raw primitive set it composes is `Layout/Sidebar`; see [Choosing between similar components](?path=/docs/docs-choosing-between-similar-components--docs). `AppSidebar` wraps the `Sidebar` → `SidebarHeader` → `SidebarContent` → `SidebarFooter` skeleton behind typed `header` / `footer` slots with the navigation as `children`, and forwards every `Sidebar` prop. The registry’s sidebar blocks import this rather than rebuilding the skeleton.",
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
},
|
|
21
29
|
decorators: [
|
|
22
30
|
(Story) => (
|
|
23
31
|
<SidebarProvider>
|
|
@@ -74,7 +74,7 @@ function AttributionItem({ item, requiredLabel }: { item: Attribution; requiredL
|
|
|
74
74
|
href={item.url}
|
|
75
75
|
target="_blank"
|
|
76
76
|
rel="noopener noreferrer"
|
|
77
|
-
className="text-body font-medium underline underline-offset-2 focus-
|
|
77
|
+
className="text-body font-medium underline underline-offset-2 focus-ring rounded-xs"
|
|
78
78
|
>
|
|
79
79
|
{item.name}
|
|
80
80
|
</a>
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Run `pnpm gen:attributions` after changing a dependency, a vendored font, or
|
|
3
3
|
// scripts/attributions.sources.json. `pnpm attributions:check` fails on a stale copy.
|
|
4
4
|
//
|
|
5
|
-
// 116 entries (data: 2, source:
|
|
5
|
+
// 116 entries (data: 2, source: 18, font: 2, dependency: 94).
|
|
6
6
|
|
|
7
7
|
import type { Attribution } from "./attribution-types";
|
|
8
8
|
|
|
@@ -93,14 +93,14 @@ export const ATTRIBUTIONS: readonly Attribution[] = [
|
|
|
93
93
|
},
|
|
94
94
|
{
|
|
95
95
|
version: null,
|
|
96
|
-
note: "
|
|
97
|
-
id: "
|
|
96
|
+
note: "Agent-session UI logic re-expressed on our tokens: the line-level diff model and its screen-reader polarity prefixes, the scoped N-option permission anatomy, the slash-palette prefix-filter/clamp behaviour, the turn-status elapsed formatter, the hook/lifecycle event line, and the grouped keyboard-shortcuts sheet. No upstream code, styling or terminal palette is shipped.",
|
|
97
|
+
id: "brainless",
|
|
98
98
|
category: "source",
|
|
99
|
-
name: "
|
|
99
|
+
name: "brainless",
|
|
100
100
|
license: "MIT",
|
|
101
|
-
copyright: "Copyright (c)
|
|
102
|
-
url: "https://github.com/
|
|
103
|
-
usedBy: ["@elabs-ai/components-ui"],
|
|
101
|
+
copyright: "Copyright (c) 2026 Ben Swerdlow",
|
|
102
|
+
url: "https://github.com/theswerd/brainless",
|
|
103
|
+
usedBy: ["@elabs-ai/components-ai", "@elabs-ai/components-ui", "@elabs-ai/components-terminal"],
|
|
104
104
|
required: false,
|
|
105
105
|
},
|
|
106
106
|
{
|
|
@@ -115,6 +115,18 @@ export const ATTRIBUTIONS: readonly Attribution[] = [
|
|
|
115
115
|
usedBy: ["@elabs-ai/components-viewer"],
|
|
116
116
|
required: false,
|
|
117
117
|
},
|
|
118
|
+
{
|
|
119
|
+
version: null,
|
|
120
|
+
note: "The editorial chart gallery behind the 2026-09-04 charts gap analysis: 71 files across the charts and tokens packages cite it as the source of a value, a mark shape or a composition (unit decomposition, hairline furniture, the sequential/diverging ramps, the reveal timing), and three copy-own registry blocks (chart-editorial-hourglass, -patchwork, -almanac) reproduce three of its gallery cards' DATA-SHAPE DESCRIPTIONS from that same analysis' one-line prose. No code was copied verbatim — each was re-expressed onto this repo's tokens and primitives. Its LICENSE is PolyForm Noncommercial 1.0.0, read verbatim from the upstream file; GitHub's own detection reports NOASSERTION, which is why nothing flagged it earlier. The licence's Required Notice slot is left at the template's example value, so upstream states no copyright holder and none is claimed here. Noncommercial-only is unresolved for a repo headed for public release — a licensing decision for the maintainer, not something attribution settles.",
|
|
121
|
+
id: "lieflat-charts",
|
|
122
|
+
category: "source",
|
|
123
|
+
name: "lieflat-charts",
|
|
124
|
+
license: "PolyForm-Noncommercial-1.0.0",
|
|
125
|
+
copyright: null,
|
|
126
|
+
url: "https://github.com/larashero3-dotcom/lieflat-charts",
|
|
127
|
+
usedBy: ["@elabs-ai/components-charts", "@elabs-ai/components-tokens"],
|
|
128
|
+
required: false,
|
|
129
|
+
},
|
|
118
130
|
{
|
|
119
131
|
version: null,
|
|
120
132
|
note: "The live-axis tick-interval picker behind live-y-axis.tsx. Upstream now names that function niceTimeInterval.",
|
|
@@ -151,6 +163,18 @@ export const ATTRIBUTIONS: readonly Attribution[] = [
|
|
|
151
163
|
usedBy: ["@elabs-ai/components-editor"],
|
|
152
164
|
required: false,
|
|
153
165
|
},
|
|
166
|
+
{
|
|
167
|
+
version: null,
|
|
168
|
+
note: "Algorithm shape for the framework-free process-mining core: which aggregates a directly-follows graph carries (discoverGraph) and how traces are grouped into variants (extractVariants), with durationStats as their shared summary. Re-typed in TypeScript from the published algorithms, not copied.",
|
|
169
|
+
id: "pm4js",
|
|
170
|
+
category: "source",
|
|
171
|
+
name: "pm4js",
|
|
172
|
+
license: "BSD-3-Clause",
|
|
173
|
+
copyright: "Copyright 2021 Alessandro Berti",
|
|
174
|
+
url: "https://github.com/pm4js/pm4js-core",
|
|
175
|
+
usedBy: ["@elabs-ai/components-process"],
|
|
176
|
+
required: false,
|
|
177
|
+
},
|
|
154
178
|
{
|
|
155
179
|
version: null,
|
|
156
180
|
note: "Beyond the npm dependency below, the shipped dist of react-scroll-area and react-select is modified in patches/ — disclosed here so the change is not invisible.",
|
|
@@ -261,14 +285,38 @@ export const ATTRIBUTIONS: readonly Attribution[] = [
|
|
|
261
285
|
note: null,
|
|
262
286
|
},
|
|
263
287
|
{
|
|
264
|
-
id: "@
|
|
288
|
+
id: "@dnd-kit/core",
|
|
265
289
|
category: "dependency",
|
|
266
|
-
name: "@
|
|
267
|
-
version: "3.
|
|
290
|
+
name: "@dnd-kit/core",
|
|
291
|
+
version: "6.3.1",
|
|
268
292
|
license: "MIT",
|
|
269
|
-
copyright: "
|
|
270
|
-
url: "https://www.npmjs.com/package/@
|
|
271
|
-
usedBy: ["@elabs-ai/components-
|
|
293
|
+
copyright: "Claudéric Demers",
|
|
294
|
+
url: "https://www.npmjs.com/package/@dnd-kit/core",
|
|
295
|
+
usedBy: ["@elabs-ai/components-data"],
|
|
296
|
+
required: false,
|
|
297
|
+
note: null,
|
|
298
|
+
},
|
|
299
|
+
{
|
|
300
|
+
id: "@dnd-kit/sortable",
|
|
301
|
+
category: "dependency",
|
|
302
|
+
name: "@dnd-kit/sortable",
|
|
303
|
+
version: "10.0.0",
|
|
304
|
+
license: "MIT",
|
|
305
|
+
copyright: "Claudéric Demers",
|
|
306
|
+
url: "https://www.npmjs.com/package/@dnd-kit/sortable",
|
|
307
|
+
usedBy: ["@elabs-ai/components-data"],
|
|
308
|
+
required: false,
|
|
309
|
+
note: null,
|
|
310
|
+
},
|
|
311
|
+
{
|
|
312
|
+
id: "@dnd-kit/utilities",
|
|
313
|
+
category: "dependency",
|
|
314
|
+
name: "@dnd-kit/utilities",
|
|
315
|
+
version: "3.2.2",
|
|
316
|
+
license: "MIT",
|
|
317
|
+
copyright: "Claudéric Demers",
|
|
318
|
+
url: "https://www.npmjs.com/package/@dnd-kit/utilities",
|
|
319
|
+
usedBy: ["@elabs-ai/components-data"],
|
|
272
320
|
required: false,
|
|
273
321
|
note: null,
|
|
274
322
|
},
|
|
@@ -656,18 +704,6 @@ export const ATTRIBUTIONS: readonly Attribution[] = [
|
|
|
656
704
|
required: false,
|
|
657
705
|
note: null,
|
|
658
706
|
},
|
|
659
|
-
{
|
|
660
|
-
id: "@rive-app/react-webgl2",
|
|
661
|
-
category: "dependency",
|
|
662
|
-
name: "@rive-app/react-webgl2",
|
|
663
|
-
version: "4.28.6",
|
|
664
|
-
license: "MIT",
|
|
665
|
-
copyright: null,
|
|
666
|
-
url: "https://www.npmjs.com/package/@rive-app/react-webgl2",
|
|
667
|
-
usedBy: ["@elabs-ai/components-ai"],
|
|
668
|
-
required: false,
|
|
669
|
-
note: null,
|
|
670
|
-
},
|
|
671
707
|
{
|
|
672
708
|
id: "@streamdown/cjk",
|
|
673
709
|
category: "dependency",
|
|
@@ -901,30 +937,6 @@ export const ATTRIBUTIONS: readonly Attribution[] = [
|
|
|
901
937
|
required: false,
|
|
902
938
|
note: null,
|
|
903
939
|
},
|
|
904
|
-
{
|
|
905
|
-
id: "@xterm/addon-fit",
|
|
906
|
-
category: "dependency",
|
|
907
|
-
name: "@xterm/addon-fit",
|
|
908
|
-
version: "0.11.0",
|
|
909
|
-
license: "MIT",
|
|
910
|
-
copyright: "The xterm.js authors",
|
|
911
|
-
url: "https://www.npmjs.com/package/@xterm/addon-fit",
|
|
912
|
-
usedBy: ["@elabs-ai/components-ai"],
|
|
913
|
-
required: false,
|
|
914
|
-
note: null,
|
|
915
|
-
},
|
|
916
|
-
{
|
|
917
|
-
id: "@xterm/xterm",
|
|
918
|
-
category: "dependency",
|
|
919
|
-
name: "@xterm/xterm",
|
|
920
|
-
version: "6.0.0",
|
|
921
|
-
license: "MIT",
|
|
922
|
-
copyright: null,
|
|
923
|
-
url: "https://www.npmjs.com/package/@xterm/xterm",
|
|
924
|
-
usedBy: ["@elabs-ai/components-ai"],
|
|
925
|
-
required: false,
|
|
926
|
-
note: null,
|
|
927
|
-
},
|
|
928
940
|
{
|
|
929
941
|
id: "ansi-to-react",
|
|
930
942
|
category: "dependency",
|
|
@@ -933,7 +945,7 @@ export const ATTRIBUTIONS: readonly Attribution[] = [
|
|
|
933
945
|
license: "BSD-3-Clause",
|
|
934
946
|
copyright: "Kyle Kelley",
|
|
935
947
|
url: "https://www.npmjs.com/package/ansi-to-react",
|
|
936
|
-
usedBy: ["@elabs-ai/components-
|
|
948
|
+
usedBy: ["@elabs-ai/components-terminal"],
|
|
937
949
|
required: false,
|
|
938
950
|
note: null,
|
|
939
951
|
},
|
|
@@ -949,6 +961,8 @@ export const ATTRIBUTIONS: readonly Attribution[] = [
|
|
|
949
961
|
"@elabs-ai/components-ai",
|
|
950
962
|
"@elabs-ai/components-charts",
|
|
951
963
|
"@elabs-ai/components-editor",
|
|
964
|
+
"@elabs-ai/components-process",
|
|
965
|
+
"@elabs-ai/components-terminal",
|
|
952
966
|
"@elabs-ai/components-ui",
|
|
953
967
|
],
|
|
954
968
|
required: false,
|
|
@@ -998,7 +1012,7 @@ export const ATTRIBUTIONS: readonly Attribution[] = [
|
|
|
998
1012
|
license: "ISC",
|
|
999
1013
|
copyright: "Mike Bostock",
|
|
1000
1014
|
url: "https://www.npmjs.com/package/d3-force",
|
|
1001
|
-
usedBy: ["@elabs-ai/components-flow"],
|
|
1015
|
+
usedBy: ["@elabs-ai/components-charts", "@elabs-ai/components-flow"],
|
|
1002
1016
|
required: false,
|
|
1003
1017
|
note: null,
|
|
1004
1018
|
},
|
|
@@ -1014,6 +1028,18 @@ export const ATTRIBUTIONS: readonly Attribution[] = [
|
|
|
1014
1028
|
required: false,
|
|
1015
1029
|
note: null,
|
|
1016
1030
|
},
|
|
1031
|
+
{
|
|
1032
|
+
id: "d3-hierarchy",
|
|
1033
|
+
category: "dependency",
|
|
1034
|
+
name: "d3-hierarchy",
|
|
1035
|
+
version: "3.1.2",
|
|
1036
|
+
license: "ISC",
|
|
1037
|
+
copyright: "Mike Bostock",
|
|
1038
|
+
url: "https://www.npmjs.com/package/d3-hierarchy",
|
|
1039
|
+
usedBy: ["@elabs-ai/components-charts"],
|
|
1040
|
+
required: false,
|
|
1041
|
+
note: null,
|
|
1042
|
+
},
|
|
1017
1043
|
{
|
|
1018
1044
|
id: "d3-sankey",
|
|
1019
1045
|
category: "dependency",
|
|
@@ -1113,24 +1139,14 @@ export const ATTRIBUTIONS: readonly Attribution[] = [
|
|
|
1113
1139
|
"@elabs-ai/components-editor",
|
|
1114
1140
|
"@elabs-ai/components-flow",
|
|
1115
1141
|
"@elabs-ai/components-maps",
|
|
1142
|
+
"@elabs-ai/components-process",
|
|
1143
|
+
"@elabs-ai/components-terminal",
|
|
1116
1144
|
"@elabs-ai/components-ui",
|
|
1117
1145
|
"@elabs-ai/components-viewer",
|
|
1118
1146
|
],
|
|
1119
1147
|
required: false,
|
|
1120
1148
|
note: null,
|
|
1121
1149
|
},
|
|
1122
|
-
{
|
|
1123
|
-
id: "media-chrome",
|
|
1124
|
-
category: "dependency",
|
|
1125
|
-
name: "media-chrome",
|
|
1126
|
-
version: "4.19.1",
|
|
1127
|
-
license: "MIT",
|
|
1128
|
-
copyright: "@muxinc",
|
|
1129
|
-
url: "https://www.npmjs.com/package/media-chrome",
|
|
1130
|
-
usedBy: ["@elabs-ai/components-ai"],
|
|
1131
|
-
required: false,
|
|
1132
|
-
note: null,
|
|
1133
|
-
},
|
|
1134
1150
|
{
|
|
1135
1151
|
id: "mermaid",
|
|
1136
1152
|
category: "dependency",
|
|
@@ -1139,7 +1155,7 @@ export const ATTRIBUTIONS: readonly Attribution[] = [
|
|
|
1139
1155
|
license: "MIT",
|
|
1140
1156
|
copyright: "Knut Sveidqvist",
|
|
1141
1157
|
url: "https://www.npmjs.com/package/mermaid",
|
|
1142
|
-
usedBy: ["@elabs-ai/components-
|
|
1158
|
+
usedBy: ["@elabs-ai/components-editor"],
|
|
1143
1159
|
required: false,
|
|
1144
1160
|
note: null,
|
|
1145
1161
|
},
|
|
@@ -1179,18 +1195,6 @@ export const ATTRIBUTIONS: readonly Attribution[] = [
|
|
|
1179
1195
|
required: false,
|
|
1180
1196
|
note: null,
|
|
1181
1197
|
},
|
|
1182
|
-
{
|
|
1183
|
-
id: "react-hook-form",
|
|
1184
|
-
category: "dependency",
|
|
1185
|
-
name: "react-hook-form",
|
|
1186
|
-
version: "7.77.0",
|
|
1187
|
-
license: "MIT",
|
|
1188
|
-
copyright: "Beier(Bill) Luo",
|
|
1189
|
-
url: "https://www.npmjs.com/package/react-hook-form",
|
|
1190
|
-
usedBy: ["@elabs-ai/components-ui"],
|
|
1191
|
-
required: false,
|
|
1192
|
-
note: null,
|
|
1193
|
-
},
|
|
1194
1198
|
{
|
|
1195
1199
|
id: "react-jsx-parser",
|
|
1196
1200
|
category: "dependency",
|
|
@@ -1415,7 +1419,7 @@ export const ATTRIBUTIONS: readonly Attribution[] = [
|
|
|
1415
1419
|
license: "MIT",
|
|
1416
1420
|
copyright: "Colin McDonnell",
|
|
1417
1421
|
url: "https://www.npmjs.com/package/zod",
|
|
1418
|
-
usedBy: ["@elabs-ai/components-ai"
|
|
1422
|
+
usedBy: ["@elabs-ai/components-ai"],
|
|
1419
1423
|
required: false,
|
|
1420
1424
|
note: null,
|
|
1421
1425
|
},
|
|
@@ -5,6 +5,14 @@ const meta = {
|
|
|
5
5
|
title: "Core/Badge",
|
|
6
6
|
component: Badge,
|
|
7
7
|
tags: ["autodocs"],
|
|
8
|
+
parameters: {
|
|
9
|
+
docs: {
|
|
10
|
+
description: {
|
|
11
|
+
component:
|
|
12
|
+
"A neutral label or count. The closed seven-state execution-status vocabulary — each state carrying its own glyph, so it survives greyscale — is `Core/StatusBadge`; see [Choosing between similar components](?path=/docs/docs-choosing-between-similar-components--docs). Reach for `Badge` when the text IS the meaning and the tone is decoration.",
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
},
|
|
8
16
|
args: { children: "Badge" },
|
|
9
17
|
argTypes: {
|
|
10
18
|
variant: {
|
|
@@ -3,7 +3,7 @@ import { cva, type VariantProps } from "class-variance-authority";
|
|
|
3
3
|
import { cn } from "../../lib/cn";
|
|
4
4
|
|
|
5
5
|
export const badgeVariants = cva(
|
|
6
|
-
"inline-flex items-center gap-1 rounded-full border px-2.5 py-0.5 text-meta font-medium transition-colors focus
|
|
6
|
+
"inline-flex items-center gap-1 rounded-full border px-2.5 py-0.5 text-meta font-medium transition-colors focus-ring focus-visible:ring-offset-2",
|
|
7
7
|
{
|
|
8
8
|
variants: {
|
|
9
9
|
variant: {
|
|
@@ -104,7 +104,7 @@ describe("BentoGridItem", () => {
|
|
|
104
104
|
// The tile stays a div; the inner anchor is the focusable element.
|
|
105
105
|
const item = screen.getByTestId("item");
|
|
106
106
|
expect(item.tagName).toBe("DIV");
|
|
107
|
-
expect(item.className).toMatch(/focus-within
|
|
107
|
+
expect(item.className).toMatch(/focus-ring-within/);
|
|
108
108
|
expect(screen.getByRole("link", { name: "go" })).toBeInTheDocument();
|
|
109
109
|
});
|
|
110
110
|
|
|
@@ -178,7 +178,7 @@ export const bentoGridItemVariants = cva(
|
|
|
178
178
|
* (elevation + edge) is on the base — every tile lifts, clickable or not.
|
|
179
179
|
*/
|
|
180
180
|
interactive: {
|
|
181
|
-
true: "cursor-pointer focus-
|
|
181
|
+
true: "cursor-pointer focus-ring-within",
|
|
182
182
|
false: "",
|
|
183
183
|
},
|
|
184
184
|
},
|