@adea-ai/ui 0.63.4 → 0.64.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 CHANGED
@@ -153,6 +153,30 @@ The toolbar switches theme, accent, typeface and density live, which is the
153
153
  fastest way to see how a component behaves across the catalogue rather than in
154
154
  one theme.
155
155
 
156
+ ## Busy composer action
157
+
158
+ Square icon controls use the control-height tokens through the Tailwind `--size`
159
+ mapping; `--spacing-control-*` remains the separate inline-padding ladder.
160
+ Text controls, icon buttons and toggles share the same height in both densities.
161
+ Dimensions remain rem-based and follow the consumer's root font size. The browser
162
+ geometry lane checks all six rungs, heights and padding under both themes/densities.
163
+
164
+ `BusySendButton` translates KiroCrew's split fire/mode-picker composition. Pass
165
+ controlled `mode`, `onModeChange` and `onFire`. `disabled` prevents firing while
166
+ leaving mode choice available before typing; `selectionDisabled` gates choosing.
167
+ Inject `unavailable` reasons for unsupported or unauthorized modes: rows remain
168
+ visible, and the selected action cannot fire. Supply `alternateActionHint` only
169
+ when the host implements the described keyboard chord. The component adds no
170
+ keyboard chord, preference storage, runtime command or queue. Persistence and
171
+ same-session preference synchronization remain application-owned.
172
+
173
+ Kobalte owns the menu and focus lifecycle. Its Tab prevention lacks row cycling,
174
+ so a menu-scoped donor translation cycles enabled rows without a document listener.
175
+ Stories cover before-typing, working,
176
+ unavailable and read-only states. `bun run test:components` checks the isolated
177
+ Solid composition headlessly in Chromium and WebKit. Full Chat composition,
178
+ packed distribution and real consumer/native acceptance remain separate gates.
179
+
156
180
  ## Transcript follow
157
181
 
158
182
  `ConversationSurface` follows streamed text, earlier-row growth, turn collapse
package/dist/NOTICE CHANGED
@@ -49,6 +49,29 @@ Origin UI / coss (AGPL-3.0-or-later) was consulted for visual ideas only. No
49
49
  code, class string, or asset from that project is reproduced here, because its
50
50
  licence is incompatible with this distribution.
51
51
 
52
+ Busy composer action translated from KiroCrew
53
+ --------------------------------------------
54
+ Original: website/src/components/BusySendButton.tsx
55
+ Also translated: website/src/hooks/useMenuKeyboard.ts (enabled-row Tab cycle)
56
+ Revision: 283e136c0f902e965a535a7c9548c57c7504fed0
57
+ Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
58
+ This product includes software developed at Amazon.com, Inc.
59
+ Apache License, Version 2.0 (see LICENSE).
60
+ Destination: packages/ui/src/components/conversation/busy-send-button.tsx
61
+
62
+ The split fire/mode-picker structure, descriptions, independent disabled-fire
63
+ state, selected radio treatment and conditional alternate-action hint are
64
+ substantially translated to Solid and the shared design system. Kobalte owns
65
+ portal positioning, arrow navigation, dismissal and focus restoration. Its
66
+ Tab prevention lacks row cycling, so the donor cycle is translated as a scoped
67
+ menu handler over enabled rows; no document listener or manual focus trap.
68
+ Donor per-slot storage/migration/broadcast, i18n/platform lookup, React runtime,
69
+ manual portal and document listeners are not copied. Applications inject mode,
70
+ action and unavailable reasons. No runtime queue or force-reset authority added.
71
+ Nearest tests: BusySendButton.menuKeyboard.test.tsx and
72
+ BusySendButton.slotScope.test.tsx; controlled mode replaces donor storage tests,
73
+ while keyboard/focus expectations are exercised in Chromium and WebKit.
74
+
52
75
  ## Plain transcript follow translated from KiroCrew
53
76
 
54
77
  `packages/ui/src/components/conversation/scroll-follow-core.ts`,
@@ -0,0 +1,28 @@
1
+ export type BusySendMode = 'steer' | 'queue';
2
+ export type BusySendButtonProps = {
3
+ mode: BusySendMode;
4
+ onModeChange: (mode: BusySendMode) => void;
5
+ /** Executes only the selected action. The host owns the draft and command. */
6
+ onFire: () => void;
7
+ /** An empty draft or pending delivery disables fire, but not choosing a mode. */
8
+ disabled?: boolean;
9
+ /** Disable mode selection when the host has no authority to change preferences. */
10
+ selectionDisabled?: boolean;
11
+ /** Host capability/authority failures: unavailable rows remain visible. */
12
+ unavailable?: Partial<Record<BusySendMode, string>>;
13
+ /** Supply only when the host implements this alternate-action keyboard chord. */
14
+ alternateActionHint?: string;
15
+ };
16
+ /**
17
+ * Kiro's split action/menu composition, with app-owned mode and availability.
18
+ * Picking a mode never fires it. Persistence, migration and same-session
19
+ * broadcasts belong to the consumer; this component has no storage or global listeners.
20
+ * Kobalte replaces the donor manual portal/positioning and document listeners:
21
+ * arrows wrap and selection/Escape return focus. Kobalte 0.13.14 prevents Tab
22
+ * without moving focus, so a menu-scoped translation of the donor Tab cycle
23
+ * fills that gap. It discovers enabled radio rows only; no document trap.
24
+ * No force-reset timer or runtime authority is translated from the adjacent
25
+ * donor stop flow.
26
+ */
27
+ export declare function BusySendButton(props: BusySendButtonProps): import("solid-js").JSX.Element;
28
+ //# sourceMappingURL=busy-send-button.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"busy-send-button.d.ts","sourceRoot":"","sources":["../../../src/components/conversation/busy-send-button.tsx"],"names":[],"mappings":"AAmBA,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,OAAO,CAAA;AAC5C,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,EAAE,YAAY,CAAA;IAClB,YAAY,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,IAAI,CAAA;IAC1C,8EAA8E;IAC9E,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB,iFAAiF;IACjF,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,mFAAmF;IACnF,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,2EAA2E;IAC3E,WAAW,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC,CAAA;IACnD,iFAAiF;IACjF,mBAAmB,CAAC,EAAE,MAAM,CAAA;CAC7B,CAAA;AASD;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,kCA2GxD"}
@@ -0,0 +1,184 @@
1
+ import { Button } from "../ui/button/button.js";
2
+ import { ButtonGroup } from "../ui/button-group/button-group.js";
3
+ import { DropdownMenu, DropdownMenuContent, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuTrigger } from "../ui/dropdown-menu/dropdown-menu.js";
4
+ import { createComponent, insert, setAttribute, template } from "solid-js/web";
5
+ import { ArrowUpFromLine, ChevronDown, Target } from "lucide-solid";
6
+ import { For, Show, createUniqueId } from "solid-js";
7
+ //#region src/components/conversation/busy-send-button.tsx
8
+ var _tmpl$ = /*#__PURE__*/ template(`<p class="text-muted-foreground px-2 py-1 text-xs">`);
9
+ var _tmpl$2 = /*#__PURE__*/ template(`<div data-slot=busy-send-button class="flex w-fit flex-col gap-1">`);
10
+ var _tmpl$3 = /*#__PURE__*/ template(`<div class="flex min-w-0 flex-col gap-1"><span></span><span class="text-muted-foreground text-xs">`);
11
+ var _tmpl$4 = /*#__PURE__*/ template(`<span class="text-muted-foreground text-xs">`);
12
+ var _tmpl$5 = /*#__PURE__*/ template(`<p class="text-muted-foreground text-xs">`);
13
+ var modes = ["steer", "queue"];
14
+ var labels = {
15
+ steer: "Steer",
16
+ queue: "Queue"
17
+ };
18
+ var descriptions = {
19
+ steer: "Act on this right away",
20
+ queue: "Run after the current work finishes"
21
+ };
22
+ /**
23
+ * Kiro's split action/menu composition, with app-owned mode and availability.
24
+ * Picking a mode never fires it. Persistence, migration and same-session
25
+ * broadcasts belong to the consumer; this component has no storage or global listeners.
26
+ * Kobalte replaces the donor manual portal/positioning and document listeners:
27
+ * arrows wrap and selection/Escape return focus. Kobalte 0.13.14 prevents Tab
28
+ * without moving focus, so a menu-scoped translation of the donor Tab cycle
29
+ * fills that gap. It discovers enabled radio rows only; no document trap.
30
+ * No force-reset timer or runtime authority is translated from the adjacent
31
+ * donor stop flow.
32
+ */
33
+ function BusySendButton(props) {
34
+ const reasonId = createUniqueId();
35
+ const reason = () => props.unavailable?.[props.mode];
36
+ const variant = () => props.mode === "steer" ? "default" : "secondary";
37
+ return (() => {
38
+ var _el$ = _tmpl$2();
39
+ insert(_el$, createComponent(DropdownMenu, {
40
+ placement: "top-end",
41
+ modal: false,
42
+ get children() {
43
+ return [createComponent(ButtonGroup, {
44
+ label: "Send while busy",
45
+ get children() {
46
+ return [createComponent(Button, {
47
+ type: "button",
48
+ size: "icon-sm",
49
+ get variant() {
50
+ return variant();
51
+ },
52
+ get ["aria-label"]() {
53
+ return props.mode === "steer" ? "Steer" : "Queue message";
54
+ },
55
+ get ["aria-describedby"]() {
56
+ return reason() ? reasonId : void 0;
57
+ },
58
+ get disabled() {
59
+ return props.disabled || !!reason();
60
+ },
61
+ onClick: () => {
62
+ if (!props.disabled && !reason()) props.onFire();
63
+ },
64
+ get children() {
65
+ return createComponent(Show, {
66
+ get when() {
67
+ return props.mode === "steer";
68
+ },
69
+ get fallback() {
70
+ return createComponent(ArrowUpFromLine, {});
71
+ },
72
+ get children() {
73
+ return createComponent(Target, {});
74
+ }
75
+ });
76
+ }
77
+ }), createComponent(DropdownMenuTrigger, {
78
+ as: Button,
79
+ type: "button",
80
+ size: "icon-sm",
81
+ get variant() {
82
+ return variant();
83
+ },
84
+ "aria-label": "Send options",
85
+ get disabled() {
86
+ return props.selectionDisabled;
87
+ },
88
+ get children() {
89
+ return createComponent(ChevronDown, {});
90
+ }
91
+ })];
92
+ }
93
+ }), createComponent(DropdownMenuContent, {
94
+ hideArrow: true,
95
+ get children() {
96
+ return [createComponent(DropdownMenuRadioGroup, {
97
+ "on:keydown": (event) => {
98
+ if (event.key !== "Tab" || event.isComposing || !(event.currentTarget instanceof HTMLElement)) return;
99
+ const rows = Array.from(event.currentTarget.querySelectorAll("[role=\"menuitemradio\"]:not([aria-disabled=\"true\"])"));
100
+ if (!rows.length) return;
101
+ event.preventDefault();
102
+ event.stopPropagation();
103
+ const active = document.activeElement;
104
+ const index = active instanceof HTMLElement ? rows.indexOf(active) : -1;
105
+ rows[index < 0 ? event.shiftKey ? rows.length - 1 : 0 : (index + (event.shiftKey ? -1 : 1) + rows.length) % rows.length]?.focus();
106
+ },
107
+ get value() {
108
+ return props.mode;
109
+ },
110
+ onChange: (value) => {
111
+ if ((value === "steer" || value === "queue") && !props.selectionDisabled && !props.unavailable?.[value]) props.onModeChange(value);
112
+ },
113
+ get children() {
114
+ return createComponent(For, {
115
+ each: modes,
116
+ children: (mode) => createComponent(DropdownMenuRadioItem, {
117
+ value: mode,
118
+ closeOnSelect: true,
119
+ get disabled() {
120
+ return props.selectionDisabled || !!props.unavailable?.[mode];
121
+ },
122
+ get children() {
123
+ return [createComponent(Show, {
124
+ when: mode === "steer",
125
+ get fallback() {
126
+ return createComponent(ArrowUpFromLine, {});
127
+ },
128
+ get children() {
129
+ return createComponent(Target, {});
130
+ }
131
+ }), (() => {
132
+ var _el$3 = _tmpl$3(), _el$4 = _el$3.firstChild, _el$5 = _el$4.nextSibling;
133
+ insert(_el$4, () => labels[mode]);
134
+ insert(_el$5, () => descriptions[mode]);
135
+ insert(_el$3, createComponent(Show, {
136
+ get when() {
137
+ return props.unavailable?.[mode];
138
+ },
139
+ children: (message) => (() => {
140
+ var _el$6 = _tmpl$4();
141
+ insert(_el$6, message);
142
+ return _el$6;
143
+ })()
144
+ }), null);
145
+ return _el$3;
146
+ })()];
147
+ }
148
+ })
149
+ });
150
+ }
151
+ }), createComponent(Show, {
152
+ get when() {
153
+ return props.alternateActionHint;
154
+ },
155
+ get children() {
156
+ return [createComponent(DropdownMenuSeparator, {}), (() => {
157
+ var _el$2 = _tmpl$();
158
+ insert(_el$2, () => props.alternateActionHint);
159
+ return _el$2;
160
+ })()];
161
+ }
162
+ })];
163
+ }
164
+ })];
165
+ }
166
+ }), null);
167
+ insert(_el$, createComponent(Show, {
168
+ get when() {
169
+ return reason();
170
+ },
171
+ children: (message) => (() => {
172
+ var _el$7 = _tmpl$5();
173
+ setAttribute(_el$7, "id", reasonId);
174
+ insert(_el$7, message);
175
+ return _el$7;
176
+ })()
177
+ }), null);
178
+ return _el$;
179
+ })();
180
+ }
181
+ //#endregion
182
+ export { BusySendButton };
183
+
184
+ //# sourceMappingURL=busy-send-button.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"busy-send-button.js","names":["ArrowUpFromLine","ChevronDown","Target","For","Show","createUniqueId","Button","ButtonGroup","DropdownMenu","DropdownMenuContent","DropdownMenuRadioGroup","DropdownMenuRadioItem","DropdownMenuSeparator","DropdownMenuTrigger","BusySendMode","BusySendButtonProps","mode","onModeChange","onFire","disabled","selectionDisabled","unavailable","Partial","Record","alternateActionHint","modes","labels","steer","queue","descriptions","BusySendButton","props","reasonId","reason","variant","const","_el$","_tmpl$2","_$insert","_$createComponent","placement","modal","children","label","type","size","aria-label","aria-describedby","undefined","onClick","when","fallback","as","hideArrow","on:keydown","event","KeyboardEvent","key","isComposing","currentTarget","HTMLElement","rows","Array","from","querySelectorAll","length","preventDefault","stopPropagation","active","document","activeElement","index","indexOf","next","shiftKey","focus","value","onChange","each","closeOnSelect","_el$3","_tmpl$3","_el$4","firstChild","_el$5","nextSibling","message","_el$6","_tmpl$4","_el$2","_tmpl$","_el$7","_tmpl$5","_$setAttribute","_$createComponent"],"sources":["../../../src/components/conversation/busy-send-button.tsx"],"sourcesContent":["/*\n * Substantially translated from KiroCrew website/src/components/BusySendButton.tsx\n * at 283e136c0f902e965a535a7c9548c57c7504fed0.\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * Licensed under Apache-2.0; see LICENSE and NOTICE.\n */\nimport { ArrowUpFromLine, ChevronDown, Target } from 'lucide-solid'\nimport { For, Show, createUniqueId } from 'solid-js'\nimport { Button } from '../ui/button/button'\nimport { ButtonGroup } from '../ui/button-group/button-group'\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from '../ui/dropdown-menu/dropdown-menu'\n\nexport type BusySendMode = 'steer' | 'queue'\nexport type BusySendButtonProps = {\n mode: BusySendMode\n onModeChange: (mode: BusySendMode) => void\n /** Executes only the selected action. The host owns the draft and command. */\n onFire: () => void\n /** An empty draft or pending delivery disables fire, but not choosing a mode. */\n disabled?: boolean\n /** Disable mode selection when the host has no authority to change preferences. */\n selectionDisabled?: boolean\n /** Host capability/authority failures: unavailable rows remain visible. */\n unavailable?: Partial<Record<BusySendMode, string>>\n /** Supply only when the host implements this alternate-action keyboard chord. */\n alternateActionHint?: string\n}\n\nconst modes: BusySendMode[] = ['steer', 'queue']\nconst labels = { steer: 'Steer', queue: 'Queue' }\nconst descriptions = {\n steer: 'Act on this right away',\n queue: 'Run after the current work finishes',\n}\n\n/**\n * Kiro's split action/menu composition, with app-owned mode and availability.\n * Picking a mode never fires it. Persistence, migration and same-session\n * broadcasts belong to the consumer; this component has no storage or global listeners.\n * Kobalte replaces the donor manual portal/positioning and document listeners:\n * arrows wrap and selection/Escape return focus. Kobalte 0.13.14 prevents Tab\n * without moving focus, so a menu-scoped translation of the donor Tab cycle\n * fills that gap. It discovers enabled radio rows only; no document trap.\n * No force-reset timer or runtime authority is translated from the adjacent\n * donor stop flow.\n */\nexport function BusySendButton(props: BusySendButtonProps) {\n const reasonId = createUniqueId()\n const reason = () => props.unavailable?.[props.mode]\n const variant = () => (props.mode === 'steer' ? ('default' as const) : ('secondary' as const))\n return (\n <div data-slot=\"busy-send-button\" class=\"flex w-fit flex-col gap-1\">\n <DropdownMenu placement=\"top-end\" modal={false}>\n <ButtonGroup label=\"Send while busy\">\n <Button\n type=\"button\"\n size=\"icon-sm\"\n variant={variant()}\n aria-label={props.mode === 'steer' ? 'Steer' : 'Queue message'}\n aria-describedby={reason() ? reasonId : undefined}\n disabled={props.disabled || !!reason()}\n onClick={() => {\n if (!props.disabled && !reason()) props.onFire()\n }}\n >\n <Show when={props.mode === 'steer'} fallback={<ArrowUpFromLine />}>\n <Target />\n </Show>\n </Button>\n <DropdownMenuTrigger\n as={Button}\n type=\"button\"\n size=\"icon-sm\"\n variant={variant()}\n aria-label=\"Send options\"\n disabled={props.selectionDisabled}\n >\n <ChevronDown />\n </DropdownMenuTrigger>\n </ButtonGroup>\n <DropdownMenuContent hideArrow>\n <DropdownMenuRadioGroup\n on:keydown={(event: KeyboardEvent) => {\n if (\n event.key !== 'Tab' ||\n event.isComposing ||\n !(event.currentTarget instanceof HTMLElement)\n )\n return\n const rows = Array.from(\n event.currentTarget.querySelectorAll<HTMLElement>(\n '[role=\"menuitemradio\"]:not([aria-disabled=\"true\"])'\n )\n )\n if (!rows.length) return\n event.preventDefault()\n event.stopPropagation()\n const active = document.activeElement\n const index = active instanceof HTMLElement ? rows.indexOf(active) : -1\n const next =\n index < 0\n ? event.shiftKey\n ? rows.length - 1\n : 0\n : (index + (event.shiftKey ? -1 : 1) + rows.length) % rows.length\n rows[next]?.focus()\n }}\n value={props.mode}\n onChange={(value) => {\n if (\n (value === 'steer' || value === 'queue') &&\n !props.selectionDisabled &&\n !props.unavailable?.[value]\n )\n props.onModeChange(value)\n }}\n >\n <For each={modes}>\n {(mode) => (\n <DropdownMenuRadioItem\n value={mode}\n closeOnSelect\n disabled={props.selectionDisabled || !!props.unavailable?.[mode]}\n >\n <Show when={mode === 'steer'} fallback={<ArrowUpFromLine />}>\n <Target />\n </Show>\n <div class=\"flex min-w-0 flex-col gap-1\">\n <span>{labels[mode]}</span>\n <span class=\"text-muted-foreground text-xs\">{descriptions[mode]}</span>\n <Show when={props.unavailable?.[mode]}>\n {(message) => <span class=\"text-muted-foreground text-xs\">{message()}</span>}\n </Show>\n </div>\n </DropdownMenuRadioItem>\n )}\n </For>\n </DropdownMenuRadioGroup>\n <Show when={props.alternateActionHint}>\n <DropdownMenuSeparator />\n <p class=\"text-muted-foreground px-2 py-1 text-xs\">{props.alternateActionHint}</p>\n </Show>\n </DropdownMenuContent>\n </DropdownMenu>\n <Show when={reason()}>\n {(message) => (\n <p id={reasonId} class=\"text-muted-foreground text-xs\">\n {message()}\n </p>\n )}\n </Show>\n </div>\n )\n}\n"],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ export { BusySendButton, type BusySendMode, type BusySendButtonProps } from './busy-send-button';
1
2
  export { ConversationAvatar, type ConversationAvatarKind, type ConversationAvatarProps, } from './conversation-avatar';
2
3
  export { ConversationSurface, type ConversationSurfaceProps } from './conversation-surface';
3
4
  export { ComposerAttachmentButton, ComposerHint, MessageComposer, type MessageComposerProps, } from './message-composer';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/conversation/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,GAC7B,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAE,mBAAmB,EAAE,KAAK,wBAAwB,EAAE,MAAM,wBAAwB,CAAA;AAC3F,OAAO,EACL,wBAAwB,EACxB,YAAY,EACZ,eAAe,EACf,KAAK,oBAAoB,GAC1B,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EACL,WAAW,EACX,iBAAiB,EACjB,YAAY,EACZ,UAAU,EACV,KAAK,eAAe,GACrB,MAAM,eAAe,CAAA;AACtB,OAAO,EACL,cAAc,EACd,WAAW,EACX,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,GACtB,MAAM,gBAAgB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/conversation/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,KAAK,YAAY,EAAE,KAAK,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AAChG,OAAO,EACL,kBAAkB,EAClB,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,GAC7B,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAE,mBAAmB,EAAE,KAAK,wBAAwB,EAAE,MAAM,wBAAwB,CAAA;AAC3F,OAAO,EACL,wBAAwB,EACxB,YAAY,EACZ,eAAe,EACf,KAAK,oBAAoB,GAC1B,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EACL,WAAW,EACX,iBAAiB,EACjB,YAAY,EACZ,UAAU,EACV,KAAK,eAAe,GACrB,MAAM,eAAe,CAAA;AACtB,OAAO,EACL,cAAc,EACd,WAAW,EACX,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,GACtB,MAAM,gBAAgB,CAAA"}
@@ -1,6 +1,7 @@
1
+ import { BusySendButton } from "./busy-send-button.js";
1
2
  import { ConversationAvatar } from "./conversation-avatar.js";
2
3
  import { ConversationSurface } from "./conversation-surface.js";
3
4
  import { ComposerAttachmentButton, ComposerHint, MessageComposer } from "./message-composer.js";
4
5
  import { MessageBody, MessageDayDivider, MessageGroup, MessageRow } from "./message-row.js";
5
6
  import { AttachmentCard, ThreadPanel } from "./thread-panel.js";
6
- export { AttachmentCard, ComposerAttachmentButton, ComposerHint, ConversationAvatar, ConversationSurface, MessageBody, MessageComposer, MessageDayDivider, MessageGroup, MessageRow, ThreadPanel };
7
+ export { AttachmentCard, BusySendButton, ComposerAttachmentButton, ComposerHint, ConversationAvatar, ConversationSurface, MessageBody, MessageComposer, MessageDayDivider, MessageGroup, MessageRow, ThreadPanel };
package/dist/index.js CHANGED
@@ -67,6 +67,7 @@ import { SideRail, SideRailButton, SideRailContent, SideRailFooter, SideRailHead
67
67
  import { SidebarNav, SidebarNavButton, SidebarNavContent, SidebarNavFooter, SidebarNavHeader, SidebarNavItem, SidebarNavSection, SidebarNavTitle, sidebarNavItemClass, sidebarNavItemStateClass } from "./components/layout/sidebar-nav/sidebar-nav.js";
68
68
  import { StatusBar, StatusBarItem, StatusBarSpacer } from "./components/layout/status-bar/status-bar.js";
69
69
  import { TopBar, TopBarBreadcrumb, TopBarPill, TopBarSearch, TopBarSection, TopBarTitle } from "./components/layout/top-bar/top-bar.js";
70
+ import { BusySendButton } from "./components/conversation/busy-send-button.js";
70
71
  import { ConversationAvatar } from "./components/conversation/conversation-avatar.js";
71
72
  import { ConversationSurface } from "./components/conversation/conversation-surface.js";
72
73
  import { ComposerAttachmentButton, ComposerHint, MessageComposer } from "./components/conversation/message-composer.js";
@@ -88,4 +89,4 @@ import { formatBytes, formatReleaseDate, plainTextFromMarkdown } from "./lib/ver
88
89
  import { UpdateDialog } from "./components/composites/update-dialog/update-dialog.js";
89
90
  import { WorkspaceMark } from "./components/composites/workspace-mark/workspace-mark.js";
90
91
  import { keyedRows } from "./lib/keyed-rows.js";
91
- export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, AccountMenu, Alert, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertTitle, AppShell, AppShellBody, AppShellContent, AppShellMain, AppearanceEditor, AppearancePanel, AppearancePopover, AspectRatio, AttachmentCard, Avatar, AvatarFallback, AvatarImage, Badge, Board, BoardCardBody, BoardCardTitle, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbSeparator, Button, ButtonGroup, ButtonGroupSeparator, ButtonGroupText, CalendarSurface, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Checkbox, CheckboxDescription, CheckboxLabel, CodeBlock, Collapsible, CollapsibleContent, CollapsibleTrigger, Combobox, ComboboxClear, ComboboxContent, ComboboxControl, ComboboxInput, ComboboxItem, ComboboxSection, ComboboxTrigger, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandLoading, CommandSeparator, CommandShortcut, ComposerAttachmentButton, ComposerHint, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, ConversationAvatar, ConversationSurface, DatePicker, DetailPanel, DetailPanelBody, DetailPanelField, DetailPanelHeader, DetailPanelSection, Dialog, DialogClose, DialogCloseButton, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DiffBlock, DiffSummary, Drawer, DrawerBody, DrawerCloseButton, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerTitle, DrawerTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle, EntityIcon, Field, FieldDescription, FieldError, FieldInput, FieldLabel, FieldLegend, FieldSeparator, FieldSet, FieldTextArea, HoverCard, HoverCardContent, HoverCardTrigger, InlineCode, Input, InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputOtp, InputOtpCaret, Item, ItemDescription, ItemEmpty, ItemGroup, ItemGroupEntry, ItemTitle, Kbd, KbdGroup, Label, ListGroup, ListRow, Menubar, MenubarCheckboxItem, MenubarContent, MenubarGroup, MenubarItem, MenubarLabel, MenubarMenu, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger, MessageBody, MessageComposer, MessageDayDivider, MessageGroup, MessageRow, ModalDialog, Motion, NavigationMenu, NavigationMenuContent, NavigationMenuGroup, NavigationMenuGroupLabel, NavigationMenuItem, NavigationMenuMenu, NavigationMenuSeparator, NavigationMenuTrigger, NavigationMenuViewport, Page, PageHeader, PageHeaderActions, PageHeaderContent, PageHeaderDescription, PageHeaderTitle, PageSection, Pagination, PaginationEllipsis, PaginationItem, PaginationNext, PaginationPrevious, PalettePreview, Panel, PanelActions, PanelBody, PanelCard, PanelDescription, PanelFooter, PanelHeader, PanelPlaceholder, PanelTitle, PanelToolbar, Popover, PopoverAnchor, PopoverCloseButton, PopoverContent, PopoverDescription, PopoverTitle, PopoverTrigger, Presence, Progress, PropertyList, PropertyRow, PropertyTerm, PropertyValue, RadioGroup, RadioGroupItem, ResizableHandle, ResizablePanel, ResizablePanelGroup, ScrollArea, Select, SelectChevronsUpDown, SelectContent, SelectItem, SelectLabel, SelectSection, SelectTrigger, SelectValue, Separator, SettingsField, SettingsPage, SettingsRow, SettingsSection, Sheet, SheetBody, SheetCloseButton, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, SideRail, SideRailButton, SideRailContent, SideRailFooter, SideRailHeader, SideRailItem, SideRailSection, SidebarNav, SidebarNavButton, SidebarNavContent, SidebarNavFooter, SidebarNavHeader, SidebarNavItem, SidebarNavSection, SidebarNavTitle, Skeleton, Slider, Spinner, Stat, StatGroup, StatusBar, StatusBarItem, StatusBarSpacer, StatusChip, StatusList, Switch, SwitchDescription, SwitchLabel, TALL_CODE_BLOCK_PX, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableNumericCell, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, ThemeMiniature, ThemeMiniatureSplit, ThemePicker, ThemePreview, ThemeProvider, ThemeSwatch, ThemeToggle, ThreadPanel, Toaster, Toggle, ToggleGroup, ToggleGroupItem, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, TopBar, TopBarBreadcrumb, TopBarPill, TopBarSearch, TopBarSection, TopBarTitle, UpdateDialog, WorkspaceMark, accentPresets, alertVariants, allTokens, badgeVariants, boardCardTitleVariants, builtinThemes, buttonVariants, cn, colorTokens, contrastRatio, controlInteractive, controlSize, controlSizeIcon, controlSizes, cva, defaultDarkThemeId, defaultLightThemeId, defaultThemeSelection, densityTokens, designTokens, diffLineVariants, diffStats, diffTargetPath, elevationTokens, entityIconVariants, fontOptions, formatBytes, formatReleaseDate, initialsFrom, inlineScriptLiteral, itemVariants, keyedRows, monogram, motionTokens, parseDiff, plainTextFromMarkdown, radiusTokens, resolvedDensity, sheetVariants, sidebarNavItemClass, sidebarNavItemStateClass, statusDotVariants, surfaceInteractive, themeById, themeCssVariables, themeFamilies, themeScript, themesForAppearance, toast, toaster, toggleVariants, typographyTokens, undocumentedTokenAliases, useSideRail, useTheme, validateTheme, validateThemeRegistry, zIndexTokens };
92
+ export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, AccountMenu, Alert, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertTitle, AppShell, AppShellBody, AppShellContent, AppShellMain, AppearanceEditor, AppearancePanel, AppearancePopover, AspectRatio, AttachmentCard, Avatar, AvatarFallback, AvatarImage, Badge, Board, BoardCardBody, BoardCardTitle, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbSeparator, BusySendButton, Button, ButtonGroup, ButtonGroupSeparator, ButtonGroupText, CalendarSurface, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Checkbox, CheckboxDescription, CheckboxLabel, CodeBlock, Collapsible, CollapsibleContent, CollapsibleTrigger, Combobox, ComboboxClear, ComboboxContent, ComboboxControl, ComboboxInput, ComboboxItem, ComboboxSection, ComboboxTrigger, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandLoading, CommandSeparator, CommandShortcut, ComposerAttachmentButton, ComposerHint, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, ConversationAvatar, ConversationSurface, DatePicker, DetailPanel, DetailPanelBody, DetailPanelField, DetailPanelHeader, DetailPanelSection, Dialog, DialogClose, DialogCloseButton, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DiffBlock, DiffSummary, Drawer, DrawerBody, DrawerCloseButton, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerTitle, DrawerTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle, EntityIcon, Field, FieldDescription, FieldError, FieldInput, FieldLabel, FieldLegend, FieldSeparator, FieldSet, FieldTextArea, HoverCard, HoverCardContent, HoverCardTrigger, InlineCode, Input, InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputOtp, InputOtpCaret, Item, ItemDescription, ItemEmpty, ItemGroup, ItemGroupEntry, ItemTitle, Kbd, KbdGroup, Label, ListGroup, ListRow, Menubar, MenubarCheckboxItem, MenubarContent, MenubarGroup, MenubarItem, MenubarLabel, MenubarMenu, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger, MessageBody, MessageComposer, MessageDayDivider, MessageGroup, MessageRow, ModalDialog, Motion, NavigationMenu, NavigationMenuContent, NavigationMenuGroup, NavigationMenuGroupLabel, NavigationMenuItem, NavigationMenuMenu, NavigationMenuSeparator, NavigationMenuTrigger, NavigationMenuViewport, Page, PageHeader, PageHeaderActions, PageHeaderContent, PageHeaderDescription, PageHeaderTitle, PageSection, Pagination, PaginationEllipsis, PaginationItem, PaginationNext, PaginationPrevious, PalettePreview, Panel, PanelActions, PanelBody, PanelCard, PanelDescription, PanelFooter, PanelHeader, PanelPlaceholder, PanelTitle, PanelToolbar, Popover, PopoverAnchor, PopoverCloseButton, PopoverContent, PopoverDescription, PopoverTitle, PopoverTrigger, Presence, Progress, PropertyList, PropertyRow, PropertyTerm, PropertyValue, RadioGroup, RadioGroupItem, ResizableHandle, ResizablePanel, ResizablePanelGroup, ScrollArea, Select, SelectChevronsUpDown, SelectContent, SelectItem, SelectLabel, SelectSection, SelectTrigger, SelectValue, Separator, SettingsField, SettingsPage, SettingsRow, SettingsSection, Sheet, SheetBody, SheetCloseButton, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, SideRail, SideRailButton, SideRailContent, SideRailFooter, SideRailHeader, SideRailItem, SideRailSection, SidebarNav, SidebarNavButton, SidebarNavContent, SidebarNavFooter, SidebarNavHeader, SidebarNavItem, SidebarNavSection, SidebarNavTitle, Skeleton, Slider, Spinner, Stat, StatGroup, StatusBar, StatusBarItem, StatusBarSpacer, StatusChip, StatusList, Switch, SwitchDescription, SwitchLabel, TALL_CODE_BLOCK_PX, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableNumericCell, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, ThemeMiniature, ThemeMiniatureSplit, ThemePicker, ThemePreview, ThemeProvider, ThemeSwatch, ThemeToggle, ThreadPanel, Toaster, Toggle, ToggleGroup, ToggleGroupItem, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, TopBar, TopBarBreadcrumb, TopBarPill, TopBarSearch, TopBarSection, TopBarTitle, UpdateDialog, WorkspaceMark, accentPresets, alertVariants, allTokens, badgeVariants, boardCardTitleVariants, builtinThemes, buttonVariants, cn, colorTokens, contrastRatio, controlInteractive, controlSize, controlSizeIcon, controlSizes, cva, defaultDarkThemeId, defaultLightThemeId, defaultThemeSelection, densityTokens, designTokens, diffLineVariants, diffStats, diffTargetPath, elevationTokens, entityIconVariants, fontOptions, formatBytes, formatReleaseDate, initialsFrom, inlineScriptLiteral, itemVariants, keyedRows, monogram, motionTokens, parseDiff, plainTextFromMarkdown, radiusTokens, resolvedDensity, sheetVariants, sidebarNavItemClass, sidebarNavItemStateClass, statusDotVariants, surfaceInteractive, themeById, themeCssVariables, themeFamilies, themeScript, themesForAppearance, toast, toaster, toggleVariants, typographyTokens, undocumentedTokenAliases, useSideRail, useTheme, validateTheme, validateThemeRegistry, zIndexTokens };
@@ -34,6 +34,9 @@ export type TokenDefinition = {
34
34
  export declare const colorTokens: TokenDefinition[];
35
35
  export declare const radiusTokens: TokenDefinition[];
36
36
  export declare const typographyTokens: TokenDefinition[];
37
+ /** Height tokens also size both axes of icon controls through Tailwind's --size
38
+ * namespace. Padding has its own --spacing mapping. Nominal pixel descriptions
39
+ * use a 16px rem; rendered dimensions follow the consumer's root font size. */
37
40
  export declare const densityTokens: TokenDefinition[];
38
41
  export declare const elevationTokens: TokenDefinition[];
39
42
  export declare const motionTokens: TokenDefinition[];
@@ -1 +1 @@
1
- {"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../../src/lib/tokens.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAIH,MAAM,MAAM,SAAS,GACjB,OAAO,GACP,WAAW,GACX,aAAa,GACb,QAAQ,GACR,UAAU,GACV,QAAQ,GACR,QAAQ,GACR,MAAM,CAAA;AAEV,MAAM,MAAM,eAAe,GAAG;IAC5B,0DAA0D;IAC1D,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,SAAS,CAAA;IACf,8DAA8D;IAC9D,WAAW,EAAE,MAAM,CAAA;IACnB,oEAAoE;IACpE,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,WAAW,EAAE,eAAe,EAwSxC,CAAA;AAED,eAAO,MAAM,YAAY,EAAE,eAAe,EAezC,CAAA;AAED,eAAO,MAAM,gBAAgB,EAAE,eAAe,EAyE7C,CAAA;AAED,eAAO,MAAM,aAAa,EAAE,eAAe,EAmE1C,CAAA;AAED,eAAO,MAAM,eAAe,EAAE,eAAe,EA2B5C,CAAA;AAED,eAAO,MAAM,YAAY,EAAE,eAAe,EAkBzC,CAAA;AAED,eAAO,MAAM,YAAY,EAAE,eAAe,EAyBzC,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB,qEAAqE;IACrE,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,8DAA8D;IAC9D,WAAW,EAAE,MAAM,CAAA;IACnB,uEAAuE;IACvE,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,sEAAsE;IACtE,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,CAAA;AAED,eAAO,MAAM,aAAa,EAAE,SAAS,YAAY,EAQ/C,CAAA;AAEF;;;;;;;;;GASG;AACH,MAAM,MAAM,UAAU,GAAG;IACvB,oFAAoF;IACpF,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;IACnB,gDAAgD;IAChD,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAA;CAChC,CAAA;AAED,eAAO,MAAM,WAAW,EAAE,SAAS,UAAU,EA+B3C,CAAA;AAEF,qCAAqC;AACrC,eAAO,MAAM,YAAY;;;;;;;;CAQf,CAAA;AAEV,yDAAyD;AACzD,eAAO,MAAM,SAAS,EAAE,eAAe,EAAuC,CAAA;AAE9E;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,EAAE,MAAM,EAAe,CAAA"}
1
+ {"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../../src/lib/tokens.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAIH,MAAM,MAAM,SAAS,GACjB,OAAO,GACP,WAAW,GACX,aAAa,GACb,QAAQ,GACR,UAAU,GACV,QAAQ,GACR,QAAQ,GACR,MAAM,CAAA;AAEV,MAAM,MAAM,eAAe,GAAG;IAC5B,0DAA0D;IAC1D,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,SAAS,CAAA;IACf,8DAA8D;IAC9D,WAAW,EAAE,MAAM,CAAA;IACnB,oEAAoE;IACpE,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,WAAW,EAAE,eAAe,EAwSxC,CAAA;AAED,eAAO,MAAM,YAAY,EAAE,eAAe,EAezC,CAAA;AAED,eAAO,MAAM,gBAAgB,EAAE,eAAe,EAyE7C,CAAA;AAED;;+EAE+E;AAC/E,eAAO,MAAM,aAAa,EAAE,eAAe,EAmE1C,CAAA;AAED,eAAO,MAAM,eAAe,EAAE,eAAe,EA2B5C,CAAA;AAED,eAAO,MAAM,YAAY,EAAE,eAAe,EAkBzC,CAAA;AAED,eAAO,MAAM,YAAY,EAAE,eAAe,EAyBzC,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB,qEAAqE;IACrE,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,8DAA8D;IAC9D,WAAW,EAAE,MAAM,CAAA;IACnB,uEAAuE;IACvE,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,sEAAsE;IACtE,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,CAAA;AAED,eAAO,MAAM,aAAa,EAAE,SAAS,YAAY,EAQ/C,CAAA;AAEF;;;;;;;;;GASG;AACH,MAAM,MAAM,UAAU,GAAG;IACvB,oFAAoF;IACpF,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;IACnB,gDAAgD;IAChD,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAA;CAChC,CAAA;AAED,eAAO,MAAM,WAAW,EAAE,SAAS,UAAU,EA+B3C,CAAA;AAEF,qCAAqC;AACrC,eAAO,MAAM,YAAY;;;;;;;;CAQf,CAAA;AAEV,yDAAyD;AACzD,eAAO,MAAM,SAAS,EAAE,eAAe,EAAuC,CAAA;AAE9E;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,EAAE,MAAM,EAAe,CAAA"}
@@ -525,6 +525,9 @@ var typographyTokens = [
525
525
  description: "30px — the largest size in the system. Reserved for an empty-state headline."
526
526
  }
527
527
  ];
528
+ /** Height tokens also size both axes of icon controls through Tailwind's --size
529
+ * namespace. Padding has its own --spacing mapping. Nominal pixel descriptions
530
+ * use a 16px rem; rendered dimensions follow the consumer's root font size. */
528
531
  var densityTokens = [
529
532
  {
530
533
  name: "control-height-2xs",
@@ -1 +1 @@
1
- {"version":3,"file":"tokens.js","names":[],"sources":["../../src/lib/tokens.ts"],"sourcesContent":["/**\n * The design system's token manifest.\n *\n * `theme.css` is the source of truth for token *values*. This file is the\n * source of truth for token *names and meaning* — what each one is for, and\n * which ones a theme may vary.\n *\n * It exists because a manifest that is only documentation rots. Two things read\n * it instead:\n *\n * - the token galleries in Storybook, so the review surface shows every token\n * rather than the ones an author remembered;\n * - `tests/tokens.test.ts`, which parses `theme.css` and fails when a token\n * is declared in one place and missing from the other.\n *\n * That pairing is what makes \"every token is documented and every documented\n * token exists\" a property the build enforces rather than a promise.\n */\n\nimport { ACCENTS } from '@adea-ai/themes'\n\nexport type TokenKind =\n | 'color'\n | 'dimension'\n | 'font-family'\n | 'number'\n | 'duration'\n | 'easing'\n | 'shadow'\n | 'text'\n\nexport type TokenDefinition = {\n /** The custom property name, without the leading `--`. */\n name: string\n kind: TokenKind\n /** One line: what this token is for. Shown in the gallery. */\n description: string\n /** True when the light and dark themes give it different values. */\n themed?: boolean\n}\n\n/**\n * Colour roles, in the order they appear in a page: surfaces first, then text,\n * then the lines between them, then the semantic fills. The order is the\n * documentation — reading the gallery top to bottom walks the surface ladder.\n */\nexport const colorTokens: TokenDefinition[] = [\n // Surfaces\n {\n name: 'background',\n kind: 'color',\n themed: true,\n description: 'The canvas every panel sits on.',\n },\n {\n name: 'foreground',\n kind: 'color',\n themed: true,\n description: 'Default body text on the canvas.',\n },\n {\n name: 'card',\n kind: 'color',\n themed: true,\n description: 'A panel or card raised one rung above the canvas.',\n },\n { name: 'card-foreground', kind: 'color', themed: true, description: 'Text on `card`.' },\n {\n name: 'popover',\n kind: 'color',\n themed: true,\n description: 'A floating surface: dialog, menu, popover, tooltip-free.',\n },\n { name: 'popover-foreground', kind: 'color', themed: true, description: 'Text on `popover`.' },\n {\n name: 'surface',\n kind: 'color',\n themed: true,\n description: 'Alias of `background`, for code that means \"a surface\" not \"the page\".',\n },\n {\n name: 'surface-sunken',\n kind: 'color',\n themed: true,\n description: 'A well: code blocks, inset lists, empty states.',\n },\n {\n name: 'surface-raised',\n kind: 'color',\n themed: true,\n description: 'Alias of `card`, for panels that sit on the canvas.',\n },\n {\n name: 'surface-overlay',\n kind: 'color',\n themed: true,\n description: 'Alias of `popover`, for floating layers.',\n },\n {\n name: 'surface-hover',\n kind: 'color',\n themed: true,\n description: 'The hover fill shared by rows, menu items and ghost controls.',\n },\n {\n name: 'surface-active',\n kind: 'color',\n themed: true,\n description: 'The pressed/selected fill, one rung past hover.',\n },\n {\n name: 'chrome',\n kind: 'color',\n themed: true,\n description: 'Window chrome: the top bar and its frosted fill.',\n },\n {\n name: 'chrome-alpha',\n kind: 'number',\n themed: true,\n description: 'Opacity of the chrome fill behind a blur.',\n },\n\n // The brand action\n {\n name: 'primary',\n kind: 'color',\n themed: true,\n description: 'The Adea emerald. The one primary action in a view.',\n },\n {\n name: 'primary-foreground',\n kind: 'color',\n themed: true,\n description: 'Label on `primary`. Black in dark, white in light — the accent flips polarity.',\n },\n {\n name: 'primary-hover',\n kind: 'color',\n themed: true,\n description: 'Hover rung for a primary action.',\n },\n {\n name: 'primary-subtle',\n kind: 'color',\n themed: true,\n description: 'Tinted primary fill: selected rows, focus rings, subtle buttons.',\n },\n\n {\n name: 'secondary',\n kind: 'color',\n themed: true,\n description: 'A quieter filled surface for a secondary action.',\n },\n {\n name: 'secondary-foreground',\n kind: 'color',\n themed: true,\n description: 'Label on `secondary`.',\n },\n {\n name: 'muted',\n kind: 'color',\n themed: true,\n description: 'A neutral fill: skeletons, inert chips, table footers.',\n },\n {\n name: 'muted-foreground',\n kind: 'color',\n themed: true,\n description: 'De-emphasised text. Measured to clear 4.5:1 on both `background` and `card`.',\n },\n {\n name: 'accent',\n kind: 'color',\n themed: true,\n description: \"shadcn's hover-surface accent. Not the brand colour — that is `primary`.\",\n },\n { name: 'accent-foreground', kind: 'color', themed: true, description: 'Text on `accent`.' },\n\n // Status\n {\n name: 'destructive',\n kind: 'color',\n themed: true,\n description: 'Irreversible or dangerous actions.',\n },\n {\n name: 'destructive-foreground',\n kind: 'color',\n themed: true,\n description: 'Label on `destructive`.',\n },\n {\n name: 'destructive-subtle',\n kind: 'color',\n themed: true,\n description: 'Tinted destructive fill: alert banners, invalid fields.',\n },\n { name: 'success', kind: 'color', themed: true, description: 'A completed or healthy state.' },\n { name: 'success-foreground', kind: 'color', themed: true, description: 'Label on `success`.' },\n { name: 'success-subtle', kind: 'color', themed: true, description: 'Tinted success fill.' },\n {\n name: 'warning',\n kind: 'color',\n themed: true,\n description: 'Something needs attention but is not broken.',\n },\n { name: 'warning-foreground', kind: 'color', themed: true, description: 'Label on `warning`.' },\n { name: 'warning-subtle', kind: 'color', themed: true, description: 'Tinted warning fill.' },\n { name: 'info', kind: 'color', themed: true, description: 'Neutral information.' },\n { name: 'info-foreground', kind: 'color', themed: true, description: 'Label on `info`.' },\n { name: 'info-subtle', kind: 'color', themed: true, description: 'Tinted info fill.' },\n\n // Lines\n {\n name: 'border',\n kind: 'color',\n themed: true,\n description: 'Every hairline: panel edges, dividers, card outlines.',\n },\n {\n name: 'input',\n kind: 'color',\n themed: true,\n description:\n 'The edge of an editable control. A rung stronger than `border` so a field is findable.',\n },\n {\n name: 'ring',\n kind: 'color',\n themed: true,\n description: 'The focus ring. Always paired with `primary-subtle` as its glow.',\n },\n\n // Theme-invariant glass\n {\n name: 'scrim',\n kind: 'color',\n description: 'Dark glass for overlays and on-screen controls. Same in both themes.',\n },\n { name: 'scrim-foreground', kind: 'color', description: 'Text drawn on `scrim`.' },\n { name: 'scrim-edge', kind: 'color', description: 'The hairline drawn on `scrim`.' },\n\n // Diff and code\n { name: 'diff-add', kind: 'color', themed: true, description: 'Background of an added line.' },\n {\n name: 'diff-add-foreground',\n kind: 'color',\n themed: true,\n description: 'Text of an added line.',\n },\n {\n name: 'diff-delete',\n kind: 'color',\n themed: true,\n description: 'Background of a removed line.',\n },\n {\n name: 'diff-delete-foreground',\n kind: 'color',\n themed: true,\n description: 'Text of a removed line.',\n },\n { name: 'diff-hunk', kind: 'color', themed: true, description: 'Background of a hunk header.' },\n {\n name: 'diff-hunk-foreground',\n kind: 'color',\n themed: true,\n description: 'Text of a hunk header.',\n },\n {\n name: 'diff-meta-foreground',\n kind: 'color',\n themed: true,\n description: 'File headers and line numbers in a diff.',\n },\n\n // Charts\n {\n name: 'chart-1',\n kind: 'color',\n themed: true,\n description: 'Categorical series 1. The set is closed at six.',\n },\n { name: 'chart-2', kind: 'color', themed: true, description: 'Categorical series 2.' },\n { name: 'chart-3', kind: 'color', themed: true, description: 'Categorical series 3.' },\n { name: 'chart-4', kind: 'color', themed: true, description: 'Categorical series 4.' },\n { name: 'chart-5', kind: 'color', themed: true, description: 'Categorical series 5.' },\n { name: 'chart-6', kind: 'color', themed: true, description: 'Categorical series 6.' },\n\n // Sidebar (the shadcn contract, kept whole)\n {\n name: 'sidebar',\n kind: 'color',\n themed: true,\n description: 'The rail and sidebar surface, tinted against the canvas.',\n },\n {\n name: 'sidebar-foreground',\n kind: 'color',\n themed: true,\n description: 'Default text in the rail and sidebar.',\n },\n {\n name: 'sidebar-primary',\n kind: 'color',\n themed: true,\n description: 'The active destination in the rail.',\n },\n {\n name: 'sidebar-primary-foreground',\n kind: 'color',\n themed: true,\n description: 'Text on the active rail destination.',\n },\n {\n name: 'sidebar-accent',\n kind: 'color',\n themed: true,\n description: 'Hover and selected fill for rail and sidebar rows.',\n },\n {\n name: 'sidebar-accent-foreground',\n kind: 'color',\n themed: true,\n description: 'Text on `sidebar-accent`.',\n },\n {\n name: 'sidebar-border',\n kind: 'color',\n themed: true,\n description: 'The rule between the rail and the canvas.',\n },\n { name: 'sidebar-ring', kind: 'color', themed: true, description: 'Focus ring inside the rail.' },\n {\n name: 'sidebar-muted-foreground',\n kind: 'color',\n themed: true,\n description: 'Rail labels that are not the current destination.',\n },\n]\n\nexport const radiusTokens: TokenDefinition[] = [\n {\n name: 'radius-lg',\n kind: 'dimension',\n description:\n '10px — cards and panels. Also the knob: move this one value to re-round the whole system.',\n },\n { name: 'radius-sm', kind: 'dimension', description: '6px — badges, keyboard keys, menu items.' },\n {\n name: 'radius-md',\n kind: 'dimension',\n description: '8px — every control: buttons, inputs, selects.',\n },\n { name: 'radius-xl', kind: 'dimension', description: '14px — dialogs, menus, sheets.' },\n { name: 'radius-2xl', kind: 'dimension', description: '18px — full-window surfaces and media.' },\n]\n\nexport const typographyTokens: TokenDefinition[] = [\n {\n name: 'font-sans',\n kind: 'font-family',\n description: 'The selected interface face. Space Grotesk unless the font axis says otherwise.',\n },\n {\n name: 'font-mono',\n kind: 'font-family',\n description: 'The selected monospace face. Code, terminals, ids, paths.',\n },\n {\n name: 'font-family-space-grotesk',\n kind: 'font-family',\n description: 'The interface default, and the face the visual language was drawn against.',\n },\n {\n name: 'font-family-jetbrains-mono',\n kind: 'font-family',\n description: 'The monospace default. Code, terminals, diffs.',\n },\n {\n name: 'font-family-geist',\n kind: 'font-family',\n description: 'An alternative interface face. cortana already ships it.',\n },\n {\n name: 'font-family-geist-mono',\n kind: 'font-family',\n description: 'The monospace counterpart to Geist.',\n },\n {\n name: 'font-family-system',\n kind: 'font-family',\n description: \"The platform's own interface face. First-class, not a fallback.\",\n },\n {\n name: 'font-family-system-mono',\n kind: 'font-family',\n description: \"The platform's own monospace face.\",\n },\n {\n name: 'ui-tracking',\n kind: 'text',\n description:\n 'Letter spacing for measured chrome. `normal` on a proportional face, tightened when the UI font is monospace — which is roughly 20% wider at the same size.',\n },\n {\n name: 'ui-word-spacing',\n kind: 'text',\n description:\n \"Word spacing for measured chrome. Mono's space is a full advance-width cell, so a two-word label reads as two floating words without this.\",\n },\n {\n name: 'text-2xs',\n kind: 'text',\n description: '11px — the smallest label the system permits: kbd keys, status bar.',\n },\n { name: 'text-xs', kind: 'text', description: '12px — metadata, badges, secondary rows.' },\n {\n name: 'text-sm',\n kind: 'text',\n description: '14px — the interface default. Body copy, labels, controls.',\n },\n { name: 'text-base', kind: 'text', description: '16px — card titles and dialog titles.' },\n { name: 'text-lg', kind: 'text', description: '18px — a section heading inside a page.' },\n { name: 'text-xl', kind: 'text', description: '20px — a page title.' },\n { name: 'text-2xl', kind: 'text', description: '24px — a display figure.' },\n {\n name: 'text-3xl',\n kind: 'text',\n description: '30px — the largest size in the system. Reserved for an empty-state headline.',\n },\n]\n\nexport const densityTokens: TokenDefinition[] = [\n { name: 'control-height-2xs', kind: 'dimension', description: '20px — an inline chip control.' },\n { name: 'control-height-xs', kind: 'dimension', description: '24px — a dense table row action.' },\n { name: 'control-height-sm', kind: 'dimension', description: '28px — the toolbar default.' },\n {\n name: 'control-height-md',\n kind: 'dimension',\n description: '32px — the form default. Button and Input are this size unless told otherwise.',\n },\n { name: 'control-height-lg', kind: 'dimension', description: '36px — a primary form action.' },\n {\n name: 'control-height-xl',\n kind: 'dimension',\n description: '40px — a hero control in an empty state.',\n },\n {\n name: 'control-padding-2xs',\n kind: 'dimension',\n description: 'Inline padding that pairs with the 20px control.',\n },\n {\n name: 'control-padding-xs',\n kind: 'dimension',\n description: 'Inline padding that pairs with the 24px control.',\n },\n {\n name: 'control-padding-sm',\n kind: 'dimension',\n description: 'Inline padding that pairs with the 28px control.',\n },\n {\n name: 'control-padding-md',\n kind: 'dimension',\n description: 'Inline padding that pairs with the 32px control.',\n },\n {\n name: 'control-padding-lg',\n kind: 'dimension',\n description: 'Inline padding that pairs with the 36px control.',\n },\n {\n name: 'control-padding-xl',\n kind: 'dimension',\n description: 'Inline padding that pairs with the 40px control.',\n },\n { name: 'row-height-sm', kind: 'dimension', description: '28px — a dense list row.' },\n { name: 'row-height-md', kind: 'dimension', description: '32px — the default list row.' },\n { name: 'row-height-lg', kind: 'dimension', description: '36px — a two-line list row.' },\n { name: 'rail-width', kind: 'dimension', description: '58px — the icon-only rail.' },\n { name: 'rail-width-expanded', kind: 'dimension', description: '236px — the labelled rail.' },\n {\n name: 'rail-item-height',\n kind: 'dimension',\n description: '36px — a rail or sidebar destination.',\n },\n {\n name: 'sidebar-width',\n kind: 'dimension',\n description: '256px — the secondary navigation column.',\n },\n {\n name: 'sidebar-width-compact',\n kind: 'dimension',\n description: '48px — the collapsed secondary column.',\n },\n { name: 'topbar-height', kind: 'dimension', description: '48px — the window title row.' },\n { name: 'statusbar-height', kind: 'dimension', description: '28px — the bottom readout strip.' },\n]\n\nexport const elevationTokens: TokenDefinition[] = [\n {\n name: 'shadow-2xs',\n kind: 'shadow',\n themed: true,\n description: 'Barely there: a chip resting on a card.',\n },\n {\n name: 'shadow-xs',\n kind: 'shadow',\n themed: true,\n description: 'A card or panel on the canvas.',\n },\n {\n name: 'shadow-sm',\n kind: 'shadow',\n themed: true,\n description: 'A control that lifts: a pressed toggle, a thumb.',\n },\n { name: 'shadow-md', kind: 'shadow', themed: true, description: 'A menu or popover.' },\n { name: 'shadow-lg', kind: 'shadow', themed: true, description: 'A dialog or sheet.' },\n {\n name: 'shadow-xl',\n kind: 'shadow',\n themed: true,\n description: 'The command palette, above everything.',\n },\n]\n\nexport const motionTokens: TokenDefinition[] = [\n {\n name: 'duration-fast',\n kind: 'duration',\n description: '120ms — a state change the user is already watching.',\n },\n { name: 'duration-normal', kind: 'duration', description: '200ms — an entrance.' },\n { name: 'duration-slow', kind: 'duration', description: '320ms — a layout settle.' },\n {\n name: 'ease-out',\n kind: 'easing',\n description: 'A fast start and a long settle. Reads as decisive rather than floaty.',\n },\n {\n name: 'ease-in-out',\n kind: 'easing',\n description: 'For a loop that has no start or end, such as a shimmer.',\n },\n]\n\nexport const zIndexTokens: TokenDefinition[] = [\n { name: 'z-base', kind: 'number', description: 'In flow, at the document order.' },\n {\n name: 'z-docked',\n kind: 'number',\n description: 'A sticky table header standing above its own scroll body.',\n },\n { name: 'z-sticky', kind: 'number', description: 'The top bar and any other pinned chrome.' },\n { name: 'z-drawer', kind: 'number', description: 'A drawer, below a modal dialog.' },\n { name: 'z-dialog', kind: 'number', description: 'A modal dialog and its scrim.' },\n {\n name: 'z-menu',\n kind: 'number',\n description: 'Menus, popovers and comboboxes. Above dialogs, because a dialog can contain one.',\n },\n {\n name: 'z-tooltip',\n kind: 'number',\n description: 'Tooltips. Above menus, because a menu item can carry one.',\n },\n {\n name: 'z-toast',\n kind: 'number',\n description: 'Notifications. Above everything, so they are never hidden by a dialog.',\n },\n]\n\n/**\n * The accent axis.\n *\n * adea's accent presets, as a selection rather than a constant. `theme` is the\n * default and means \"the variant's own primary\" — monochrome in adea's palette —\n * and each named preset overrides the interactive roles through the\n * `[data-accent]` blocks in `theme.css`.\n *\n * These are the same six presets `accentPresets` exports in adea's own\n * `appearance.ts`, and the values match. A consumer's appearance picker and the\n * workshop's theme toolbar read this one list, so the two cannot disagree about\n * what a preset is called or what colour it is.\n */\nexport type AccentPreset = {\n /** The `data-accent` value. `theme` is the variant's own primary. */\n id: string\n label: string\n /** What the preset is for, in the gallery and in a picker. */\n description: string\n /** The accent as it appears in the light theme. Absent for `theme`. */\n light?: string\n /** The accent as it appears in the dark theme. Absent for `theme`. */\n dark?: string\n}\n\nexport const accentPresets: readonly AccentPreset[] = Object.freeze([\n {\n id: 'theme',\n label: 'Theme',\n description:\n \"The variant's own primary. Neutral in adea's palette, so the interface stays monochrome.\",\n },\n ...ACCENTS,\n])\n\n/**\n * The font axis.\n *\n * The family is a selection, like the accent: `data-font` sits on the same element\n * and each option swaps the interface face. `space-grotesk` is the default because\n * it is the face the visual language was drawn against, and `system` is a\n * first-class option rather than a fallback — an application that wants the\n * platform's own face should be able to say so without losing the rest of the\n * system.\n */\nexport type FontOption = {\n /** The `data-font` value. `space-grotesk` is the default and needs no attribute. */\n id: string\n label: string\n description: string\n /** Which of the two stacks this option sets. */\n stack: 'sans' | 'mono' | 'both'\n}\n\nexport const fontOptions: readonly FontOption[] = Object.freeze([\n {\n id: 'space-grotesk',\n label: 'Space Grotesk',\n description: 'The default, and the face the visual language was drawn against.',\n stack: 'both',\n },\n {\n id: 'system',\n label: 'System',\n description: \"The platform's own face. What a terminal or editor usually wants.\",\n stack: 'both',\n },\n {\n id: 'geist',\n label: 'Geist',\n description: 'The face cortana already ships. Neutral and wide.',\n stack: 'both',\n },\n {\n id: 'geist-mono',\n label: 'Geist Mono',\n description: 'Monospace throughout, for someone who wants a uniform texture.',\n stack: 'both',\n },\n {\n id: 'jetbrains-mono',\n label: 'JetBrains Mono',\n description: 'Monospace throughout, with coding ligatures off.',\n stack: 'both',\n },\n])\n\n/** Every token, in gallery order. */\nexport const designTokens = {\n color: colorTokens,\n radius: radiusTokens,\n typography: typographyTokens,\n density: densityTokens,\n elevation: elevationTokens,\n motion: motionTokens,\n zIndex: zIndexTokens,\n} as const\n\n/** Flat list, for completeness checks and for search. */\nexport const allTokens: TokenDefinition[] = Object.values(designTokens).flat()\n\n/**\n * Aliases that exist only to make a call site read better, and which therefore\n * have no gallery row of their own. Kept explicit so the completeness check\n * below can tell \"deliberately absent\" from \"forgotten\".\n */\nexport const undocumentedTokenAliases: string[] = ['radius']\n"],"mappings":"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"}
1
+ {"version":3,"file":"tokens.js","names":[],"sources":["../../src/lib/tokens.ts"],"sourcesContent":["/**\n * The design system's token manifest.\n *\n * `theme.css` is the source of truth for token *values*. This file is the\n * source of truth for token *names and meaning* — what each one is for, and\n * which ones a theme may vary.\n *\n * It exists because a manifest that is only documentation rots. Two things read\n * it instead:\n *\n * - the token galleries in Storybook, so the review surface shows every token\n * rather than the ones an author remembered;\n * - `tests/tokens.test.ts`, which parses `theme.css` and fails when a token\n * is declared in one place and missing from the other.\n *\n * That pairing is what makes \"every token is documented and every documented\n * token exists\" a property the build enforces rather than a promise.\n */\n\nimport { ACCENTS } from '@adea-ai/themes'\n\nexport type TokenKind =\n | 'color'\n | 'dimension'\n | 'font-family'\n | 'number'\n | 'duration'\n | 'easing'\n | 'shadow'\n | 'text'\n\nexport type TokenDefinition = {\n /** The custom property name, without the leading `--`. */\n name: string\n kind: TokenKind\n /** One line: what this token is for. Shown in the gallery. */\n description: string\n /** True when the light and dark themes give it different values. */\n themed?: boolean\n}\n\n/**\n * Colour roles, in the order they appear in a page: surfaces first, then text,\n * then the lines between them, then the semantic fills. The order is the\n * documentation — reading the gallery top to bottom walks the surface ladder.\n */\nexport const colorTokens: TokenDefinition[] = [\n // Surfaces\n {\n name: 'background',\n kind: 'color',\n themed: true,\n description: 'The canvas every panel sits on.',\n },\n {\n name: 'foreground',\n kind: 'color',\n themed: true,\n description: 'Default body text on the canvas.',\n },\n {\n name: 'card',\n kind: 'color',\n themed: true,\n description: 'A panel or card raised one rung above the canvas.',\n },\n { name: 'card-foreground', kind: 'color', themed: true, description: 'Text on `card`.' },\n {\n name: 'popover',\n kind: 'color',\n themed: true,\n description: 'A floating surface: dialog, menu, popover, tooltip-free.',\n },\n { name: 'popover-foreground', kind: 'color', themed: true, description: 'Text on `popover`.' },\n {\n name: 'surface',\n kind: 'color',\n themed: true,\n description: 'Alias of `background`, for code that means \"a surface\" not \"the page\".',\n },\n {\n name: 'surface-sunken',\n kind: 'color',\n themed: true,\n description: 'A well: code blocks, inset lists, empty states.',\n },\n {\n name: 'surface-raised',\n kind: 'color',\n themed: true,\n description: 'Alias of `card`, for panels that sit on the canvas.',\n },\n {\n name: 'surface-overlay',\n kind: 'color',\n themed: true,\n description: 'Alias of `popover`, for floating layers.',\n },\n {\n name: 'surface-hover',\n kind: 'color',\n themed: true,\n description: 'The hover fill shared by rows, menu items and ghost controls.',\n },\n {\n name: 'surface-active',\n kind: 'color',\n themed: true,\n description: 'The pressed/selected fill, one rung past hover.',\n },\n {\n name: 'chrome',\n kind: 'color',\n themed: true,\n description: 'Window chrome: the top bar and its frosted fill.',\n },\n {\n name: 'chrome-alpha',\n kind: 'number',\n themed: true,\n description: 'Opacity of the chrome fill behind a blur.',\n },\n\n // The brand action\n {\n name: 'primary',\n kind: 'color',\n themed: true,\n description: 'The Adea emerald. The one primary action in a view.',\n },\n {\n name: 'primary-foreground',\n kind: 'color',\n themed: true,\n description: 'Label on `primary`. Black in dark, white in light — the accent flips polarity.',\n },\n {\n name: 'primary-hover',\n kind: 'color',\n themed: true,\n description: 'Hover rung for a primary action.',\n },\n {\n name: 'primary-subtle',\n kind: 'color',\n themed: true,\n description: 'Tinted primary fill: selected rows, focus rings, subtle buttons.',\n },\n\n {\n name: 'secondary',\n kind: 'color',\n themed: true,\n description: 'A quieter filled surface for a secondary action.',\n },\n {\n name: 'secondary-foreground',\n kind: 'color',\n themed: true,\n description: 'Label on `secondary`.',\n },\n {\n name: 'muted',\n kind: 'color',\n themed: true,\n description: 'A neutral fill: skeletons, inert chips, table footers.',\n },\n {\n name: 'muted-foreground',\n kind: 'color',\n themed: true,\n description: 'De-emphasised text. Measured to clear 4.5:1 on both `background` and `card`.',\n },\n {\n name: 'accent',\n kind: 'color',\n themed: true,\n description: \"shadcn's hover-surface accent. Not the brand colour — that is `primary`.\",\n },\n { name: 'accent-foreground', kind: 'color', themed: true, description: 'Text on `accent`.' },\n\n // Status\n {\n name: 'destructive',\n kind: 'color',\n themed: true,\n description: 'Irreversible or dangerous actions.',\n },\n {\n name: 'destructive-foreground',\n kind: 'color',\n themed: true,\n description: 'Label on `destructive`.',\n },\n {\n name: 'destructive-subtle',\n kind: 'color',\n themed: true,\n description: 'Tinted destructive fill: alert banners, invalid fields.',\n },\n { name: 'success', kind: 'color', themed: true, description: 'A completed or healthy state.' },\n { name: 'success-foreground', kind: 'color', themed: true, description: 'Label on `success`.' },\n { name: 'success-subtle', kind: 'color', themed: true, description: 'Tinted success fill.' },\n {\n name: 'warning',\n kind: 'color',\n themed: true,\n description: 'Something needs attention but is not broken.',\n },\n { name: 'warning-foreground', kind: 'color', themed: true, description: 'Label on `warning`.' },\n { name: 'warning-subtle', kind: 'color', themed: true, description: 'Tinted warning fill.' },\n { name: 'info', kind: 'color', themed: true, description: 'Neutral information.' },\n { name: 'info-foreground', kind: 'color', themed: true, description: 'Label on `info`.' },\n { name: 'info-subtle', kind: 'color', themed: true, description: 'Tinted info fill.' },\n\n // Lines\n {\n name: 'border',\n kind: 'color',\n themed: true,\n description: 'Every hairline: panel edges, dividers, card outlines.',\n },\n {\n name: 'input',\n kind: 'color',\n themed: true,\n description:\n 'The edge of an editable control. A rung stronger than `border` so a field is findable.',\n },\n {\n name: 'ring',\n kind: 'color',\n themed: true,\n description: 'The focus ring. Always paired with `primary-subtle` as its glow.',\n },\n\n // Theme-invariant glass\n {\n name: 'scrim',\n kind: 'color',\n description: 'Dark glass for overlays and on-screen controls. Same in both themes.',\n },\n { name: 'scrim-foreground', kind: 'color', description: 'Text drawn on `scrim`.' },\n { name: 'scrim-edge', kind: 'color', description: 'The hairline drawn on `scrim`.' },\n\n // Diff and code\n { name: 'diff-add', kind: 'color', themed: true, description: 'Background of an added line.' },\n {\n name: 'diff-add-foreground',\n kind: 'color',\n themed: true,\n description: 'Text of an added line.',\n },\n {\n name: 'diff-delete',\n kind: 'color',\n themed: true,\n description: 'Background of a removed line.',\n },\n {\n name: 'diff-delete-foreground',\n kind: 'color',\n themed: true,\n description: 'Text of a removed line.',\n },\n { name: 'diff-hunk', kind: 'color', themed: true, description: 'Background of a hunk header.' },\n {\n name: 'diff-hunk-foreground',\n kind: 'color',\n themed: true,\n description: 'Text of a hunk header.',\n },\n {\n name: 'diff-meta-foreground',\n kind: 'color',\n themed: true,\n description: 'File headers and line numbers in a diff.',\n },\n\n // Charts\n {\n name: 'chart-1',\n kind: 'color',\n themed: true,\n description: 'Categorical series 1. The set is closed at six.',\n },\n { name: 'chart-2', kind: 'color', themed: true, description: 'Categorical series 2.' },\n { name: 'chart-3', kind: 'color', themed: true, description: 'Categorical series 3.' },\n { name: 'chart-4', kind: 'color', themed: true, description: 'Categorical series 4.' },\n { name: 'chart-5', kind: 'color', themed: true, description: 'Categorical series 5.' },\n { name: 'chart-6', kind: 'color', themed: true, description: 'Categorical series 6.' },\n\n // Sidebar (the shadcn contract, kept whole)\n {\n name: 'sidebar',\n kind: 'color',\n themed: true,\n description: 'The rail and sidebar surface, tinted against the canvas.',\n },\n {\n name: 'sidebar-foreground',\n kind: 'color',\n themed: true,\n description: 'Default text in the rail and sidebar.',\n },\n {\n name: 'sidebar-primary',\n kind: 'color',\n themed: true,\n description: 'The active destination in the rail.',\n },\n {\n name: 'sidebar-primary-foreground',\n kind: 'color',\n themed: true,\n description: 'Text on the active rail destination.',\n },\n {\n name: 'sidebar-accent',\n kind: 'color',\n themed: true,\n description: 'Hover and selected fill for rail and sidebar rows.',\n },\n {\n name: 'sidebar-accent-foreground',\n kind: 'color',\n themed: true,\n description: 'Text on `sidebar-accent`.',\n },\n {\n name: 'sidebar-border',\n kind: 'color',\n themed: true,\n description: 'The rule between the rail and the canvas.',\n },\n { name: 'sidebar-ring', kind: 'color', themed: true, description: 'Focus ring inside the rail.' },\n {\n name: 'sidebar-muted-foreground',\n kind: 'color',\n themed: true,\n description: 'Rail labels that are not the current destination.',\n },\n]\n\nexport const radiusTokens: TokenDefinition[] = [\n {\n name: 'radius-lg',\n kind: 'dimension',\n description:\n '10px — cards and panels. Also the knob: move this one value to re-round the whole system.',\n },\n { name: 'radius-sm', kind: 'dimension', description: '6px — badges, keyboard keys, menu items.' },\n {\n name: 'radius-md',\n kind: 'dimension',\n description: '8px — every control: buttons, inputs, selects.',\n },\n { name: 'radius-xl', kind: 'dimension', description: '14px — dialogs, menus, sheets.' },\n { name: 'radius-2xl', kind: 'dimension', description: '18px — full-window surfaces and media.' },\n]\n\nexport const typographyTokens: TokenDefinition[] = [\n {\n name: 'font-sans',\n kind: 'font-family',\n description: 'The selected interface face. Space Grotesk unless the font axis says otherwise.',\n },\n {\n name: 'font-mono',\n kind: 'font-family',\n description: 'The selected monospace face. Code, terminals, ids, paths.',\n },\n {\n name: 'font-family-space-grotesk',\n kind: 'font-family',\n description: 'The interface default, and the face the visual language was drawn against.',\n },\n {\n name: 'font-family-jetbrains-mono',\n kind: 'font-family',\n description: 'The monospace default. Code, terminals, diffs.',\n },\n {\n name: 'font-family-geist',\n kind: 'font-family',\n description: 'An alternative interface face. cortana already ships it.',\n },\n {\n name: 'font-family-geist-mono',\n kind: 'font-family',\n description: 'The monospace counterpart to Geist.',\n },\n {\n name: 'font-family-system',\n kind: 'font-family',\n description: \"The platform's own interface face. First-class, not a fallback.\",\n },\n {\n name: 'font-family-system-mono',\n kind: 'font-family',\n description: \"The platform's own monospace face.\",\n },\n {\n name: 'ui-tracking',\n kind: 'text',\n description:\n 'Letter spacing for measured chrome. `normal` on a proportional face, tightened when the UI font is monospace — which is roughly 20% wider at the same size.',\n },\n {\n name: 'ui-word-spacing',\n kind: 'text',\n description:\n \"Word spacing for measured chrome. Mono's space is a full advance-width cell, so a two-word label reads as two floating words without this.\",\n },\n {\n name: 'text-2xs',\n kind: 'text',\n description: '11px — the smallest label the system permits: kbd keys, status bar.',\n },\n { name: 'text-xs', kind: 'text', description: '12px — metadata, badges, secondary rows.' },\n {\n name: 'text-sm',\n kind: 'text',\n description: '14px — the interface default. Body copy, labels, controls.',\n },\n { name: 'text-base', kind: 'text', description: '16px — card titles and dialog titles.' },\n { name: 'text-lg', kind: 'text', description: '18px — a section heading inside a page.' },\n { name: 'text-xl', kind: 'text', description: '20px — a page title.' },\n { name: 'text-2xl', kind: 'text', description: '24px — a display figure.' },\n {\n name: 'text-3xl',\n kind: 'text',\n description: '30px — the largest size in the system. Reserved for an empty-state headline.',\n },\n]\n\n/** Height tokens also size both axes of icon controls through Tailwind's --size\n * namespace. Padding has its own --spacing mapping. Nominal pixel descriptions\n * use a 16px rem; rendered dimensions follow the consumer's root font size. */\nexport const densityTokens: TokenDefinition[] = [\n { name: 'control-height-2xs', kind: 'dimension', description: '20px — an inline chip control.' },\n { name: 'control-height-xs', kind: 'dimension', description: '24px — a dense table row action.' },\n { name: 'control-height-sm', kind: 'dimension', description: '28px — the toolbar default.' },\n {\n name: 'control-height-md',\n kind: 'dimension',\n description: '32px — the form default. Button and Input are this size unless told otherwise.',\n },\n { name: 'control-height-lg', kind: 'dimension', description: '36px — a primary form action.' },\n {\n name: 'control-height-xl',\n kind: 'dimension',\n description: '40px — a hero control in an empty state.',\n },\n {\n name: 'control-padding-2xs',\n kind: 'dimension',\n description: 'Inline padding that pairs with the 20px control.',\n },\n {\n name: 'control-padding-xs',\n kind: 'dimension',\n description: 'Inline padding that pairs with the 24px control.',\n },\n {\n name: 'control-padding-sm',\n kind: 'dimension',\n description: 'Inline padding that pairs with the 28px control.',\n },\n {\n name: 'control-padding-md',\n kind: 'dimension',\n description: 'Inline padding that pairs with the 32px control.',\n },\n {\n name: 'control-padding-lg',\n kind: 'dimension',\n description: 'Inline padding that pairs with the 36px control.',\n },\n {\n name: 'control-padding-xl',\n kind: 'dimension',\n description: 'Inline padding that pairs with the 40px control.',\n },\n { name: 'row-height-sm', kind: 'dimension', description: '28px — a dense list row.' },\n { name: 'row-height-md', kind: 'dimension', description: '32px — the default list row.' },\n { name: 'row-height-lg', kind: 'dimension', description: '36px — a two-line list row.' },\n { name: 'rail-width', kind: 'dimension', description: '58px — the icon-only rail.' },\n { name: 'rail-width-expanded', kind: 'dimension', description: '236px — the labelled rail.' },\n {\n name: 'rail-item-height',\n kind: 'dimension',\n description: '36px — a rail or sidebar destination.',\n },\n {\n name: 'sidebar-width',\n kind: 'dimension',\n description: '256px — the secondary navigation column.',\n },\n {\n name: 'sidebar-width-compact',\n kind: 'dimension',\n description: '48px — the collapsed secondary column.',\n },\n { name: 'topbar-height', kind: 'dimension', description: '48px — the window title row.' },\n { name: 'statusbar-height', kind: 'dimension', description: '28px — the bottom readout strip.' },\n]\n\nexport const elevationTokens: TokenDefinition[] = [\n {\n name: 'shadow-2xs',\n kind: 'shadow',\n themed: true,\n description: 'Barely there: a chip resting on a card.',\n },\n {\n name: 'shadow-xs',\n kind: 'shadow',\n themed: true,\n description: 'A card or panel on the canvas.',\n },\n {\n name: 'shadow-sm',\n kind: 'shadow',\n themed: true,\n description: 'A control that lifts: a pressed toggle, a thumb.',\n },\n { name: 'shadow-md', kind: 'shadow', themed: true, description: 'A menu or popover.' },\n { name: 'shadow-lg', kind: 'shadow', themed: true, description: 'A dialog or sheet.' },\n {\n name: 'shadow-xl',\n kind: 'shadow',\n themed: true,\n description: 'The command palette, above everything.',\n },\n]\n\nexport const motionTokens: TokenDefinition[] = [\n {\n name: 'duration-fast',\n kind: 'duration',\n description: '120ms — a state change the user is already watching.',\n },\n { name: 'duration-normal', kind: 'duration', description: '200ms — an entrance.' },\n { name: 'duration-slow', kind: 'duration', description: '320ms — a layout settle.' },\n {\n name: 'ease-out',\n kind: 'easing',\n description: 'A fast start and a long settle. Reads as decisive rather than floaty.',\n },\n {\n name: 'ease-in-out',\n kind: 'easing',\n description: 'For a loop that has no start or end, such as a shimmer.',\n },\n]\n\nexport const zIndexTokens: TokenDefinition[] = [\n { name: 'z-base', kind: 'number', description: 'In flow, at the document order.' },\n {\n name: 'z-docked',\n kind: 'number',\n description: 'A sticky table header standing above its own scroll body.',\n },\n { name: 'z-sticky', kind: 'number', description: 'The top bar and any other pinned chrome.' },\n { name: 'z-drawer', kind: 'number', description: 'A drawer, below a modal dialog.' },\n { name: 'z-dialog', kind: 'number', description: 'A modal dialog and its scrim.' },\n {\n name: 'z-menu',\n kind: 'number',\n description: 'Menus, popovers and comboboxes. Above dialogs, because a dialog can contain one.',\n },\n {\n name: 'z-tooltip',\n kind: 'number',\n description: 'Tooltips. Above menus, because a menu item can carry one.',\n },\n {\n name: 'z-toast',\n kind: 'number',\n description: 'Notifications. Above everything, so they are never hidden by a dialog.',\n },\n]\n\n/**\n * The accent axis.\n *\n * adea's accent presets, as a selection rather than a constant. `theme` is the\n * default and means \"the variant's own primary\" — monochrome in adea's palette —\n * and each named preset overrides the interactive roles through the\n * `[data-accent]` blocks in `theme.css`.\n *\n * These are the same six presets `accentPresets` exports in adea's own\n * `appearance.ts`, and the values match. A consumer's appearance picker and the\n * workshop's theme toolbar read this one list, so the two cannot disagree about\n * what a preset is called or what colour it is.\n */\nexport type AccentPreset = {\n /** The `data-accent` value. `theme` is the variant's own primary. */\n id: string\n label: string\n /** What the preset is for, in the gallery and in a picker. */\n description: string\n /** The accent as it appears in the light theme. Absent for `theme`. */\n light?: string\n /** The accent as it appears in the dark theme. Absent for `theme`. */\n dark?: string\n}\n\nexport const accentPresets: readonly AccentPreset[] = Object.freeze([\n {\n id: 'theme',\n label: 'Theme',\n description:\n \"The variant's own primary. Neutral in adea's palette, so the interface stays monochrome.\",\n },\n ...ACCENTS,\n])\n\n/**\n * The font axis.\n *\n * The family is a selection, like the accent: `data-font` sits on the same element\n * and each option swaps the interface face. `space-grotesk` is the default because\n * it is the face the visual language was drawn against, and `system` is a\n * first-class option rather than a fallback — an application that wants the\n * platform's own face should be able to say so without losing the rest of the\n * system.\n */\nexport type FontOption = {\n /** The `data-font` value. `space-grotesk` is the default and needs no attribute. */\n id: string\n label: string\n description: string\n /** Which of the two stacks this option sets. */\n stack: 'sans' | 'mono' | 'both'\n}\n\nexport const fontOptions: readonly FontOption[] = Object.freeze([\n {\n id: 'space-grotesk',\n label: 'Space Grotesk',\n description: 'The default, and the face the visual language was drawn against.',\n stack: 'both',\n },\n {\n id: 'system',\n label: 'System',\n description: \"The platform's own face. What a terminal or editor usually wants.\",\n stack: 'both',\n },\n {\n id: 'geist',\n label: 'Geist',\n description: 'The face cortana already ships. Neutral and wide.',\n stack: 'both',\n },\n {\n id: 'geist-mono',\n label: 'Geist Mono',\n description: 'Monospace throughout, for someone who wants a uniform texture.',\n stack: 'both',\n },\n {\n id: 'jetbrains-mono',\n label: 'JetBrains Mono',\n description: 'Monospace throughout, with coding ligatures off.',\n stack: 'both',\n },\n])\n\n/** Every token, in gallery order. */\nexport const designTokens = {\n color: colorTokens,\n radius: radiusTokens,\n typography: typographyTokens,\n density: densityTokens,\n elevation: elevationTokens,\n motion: motionTokens,\n zIndex: zIndexTokens,\n} as const\n\n/** Flat list, for completeness checks and for search. */\nexport const allTokens: TokenDefinition[] = Object.values(designTokens).flat()\n\n/**\n * Aliases that exist only to make a call site read better, and which therefore\n * have no gallery row of their own. Kept explicit so the completeness check\n * below can tell \"deliberately absent\" from \"forgotten\".\n */\nexport const undocumentedTokenAliases: string[] = ['radius']\n"],"mappings":"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"}
@@ -8,13 +8,20 @@
8
8
  ],
9
9
  "registryDependencies": [
10
10
  "@adea-ai/ui/button",
11
+ "@adea-ai/ui/button-group",
11
12
  "@adea-ai/ui/code-block",
13
+ "@adea-ai/ui/dropdown-menu",
12
14
  "@adea-ai/ui/kbd",
13
15
  "@adea-ai/ui/spinner",
14
16
  "@adea-ai/ui/textarea",
15
17
  "lib"
16
18
  ],
17
19
  "files": [
20
+ {
21
+ "path": "src/components/conversation/busy-send-button.tsx",
22
+ "type": "registry:ui",
23
+ "target": "components/conversation/busy-send-button.tsx"
24
+ },
18
25
  {
19
26
  "path": "src/components/conversation/conversation-avatar.tsx",
20
27
  "type": "registry:ui",
@@ -1781,13 +1781,20 @@
1781
1781
  ],
1782
1782
  "registryDependencies": [
1783
1783
  "@adea-ai/ui/button",
1784
+ "@adea-ai/ui/button-group",
1784
1785
  "@adea-ai/ui/code-block",
1786
+ "@adea-ai/ui/dropdown-menu",
1785
1787
  "@adea-ai/ui/kbd",
1786
1788
  "@adea-ai/ui/spinner",
1787
1789
  "@adea-ai/ui/textarea",
1788
1790
  "lib"
1789
1791
  ],
1790
1792
  "files": [
1793
+ {
1794
+ "path": "src/components/conversation/busy-send-button.tsx",
1795
+ "type": "registry:ui",
1796
+ "target": "components/conversation/busy-send-button.tsx"
1797
+ },
1791
1798
  {
1792
1799
  "path": "src/components/conversation/conversation-avatar.tsx",
1793
1800
  "type": "registry:ui",
@@ -0,0 +1,161 @@
1
+ /*
2
+ * Substantially translated from KiroCrew website/src/components/BusySendButton.tsx
3
+ * at 283e136c0f902e965a535a7c9548c57c7504fed0.
4
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
5
+ * Licensed under Apache-2.0; see LICENSE and NOTICE.
6
+ */
7
+ import { ArrowUpFromLine, ChevronDown, Target } from 'lucide-solid'
8
+ import { For, Show, createUniqueId } from 'solid-js'
9
+ import { Button } from '../ui/button/button'
10
+ import { ButtonGroup } from '../ui/button-group/button-group'
11
+ import {
12
+ DropdownMenu,
13
+ DropdownMenuContent,
14
+ DropdownMenuRadioGroup,
15
+ DropdownMenuRadioItem,
16
+ DropdownMenuSeparator,
17
+ DropdownMenuTrigger,
18
+ } from '../ui/dropdown-menu/dropdown-menu'
19
+
20
+ export type BusySendMode = 'steer' | 'queue'
21
+ export type BusySendButtonProps = {
22
+ mode: BusySendMode
23
+ onModeChange: (mode: BusySendMode) => void
24
+ /** Executes only the selected action. The host owns the draft and command. */
25
+ onFire: () => void
26
+ /** An empty draft or pending delivery disables fire, but not choosing a mode. */
27
+ disabled?: boolean
28
+ /** Disable mode selection when the host has no authority to change preferences. */
29
+ selectionDisabled?: boolean
30
+ /** Host capability/authority failures: unavailable rows remain visible. */
31
+ unavailable?: Partial<Record<BusySendMode, string>>
32
+ /** Supply only when the host implements this alternate-action keyboard chord. */
33
+ alternateActionHint?: string
34
+ }
35
+
36
+ const modes: BusySendMode[] = ['steer', 'queue']
37
+ const labels = { steer: 'Steer', queue: 'Queue' }
38
+ const descriptions = {
39
+ steer: 'Act on this right away',
40
+ queue: 'Run after the current work finishes',
41
+ }
42
+
43
+ /**
44
+ * Kiro's split action/menu composition, with app-owned mode and availability.
45
+ * Picking a mode never fires it. Persistence, migration and same-session
46
+ * broadcasts belong to the consumer; this component has no storage or global listeners.
47
+ * Kobalte replaces the donor manual portal/positioning and document listeners:
48
+ * arrows wrap and selection/Escape return focus. Kobalte 0.13.14 prevents Tab
49
+ * without moving focus, so a menu-scoped translation of the donor Tab cycle
50
+ * fills that gap. It discovers enabled radio rows only; no document trap.
51
+ * No force-reset timer or runtime authority is translated from the adjacent
52
+ * donor stop flow.
53
+ */
54
+ export function BusySendButton(props: BusySendButtonProps) {
55
+ const reasonId = createUniqueId()
56
+ const reason = () => props.unavailable?.[props.mode]
57
+ const variant = () => (props.mode === 'steer' ? ('default' as const) : ('secondary' as const))
58
+ return (
59
+ <div data-slot="busy-send-button" class="flex w-fit flex-col gap-1">
60
+ <DropdownMenu placement="top-end" modal={false}>
61
+ <ButtonGroup label="Send while busy">
62
+ <Button
63
+ type="button"
64
+ size="icon-sm"
65
+ variant={variant()}
66
+ aria-label={props.mode === 'steer' ? 'Steer' : 'Queue message'}
67
+ aria-describedby={reason() ? reasonId : undefined}
68
+ disabled={props.disabled || !!reason()}
69
+ onClick={() => {
70
+ if (!props.disabled && !reason()) props.onFire()
71
+ }}
72
+ >
73
+ <Show when={props.mode === 'steer'} fallback={<ArrowUpFromLine />}>
74
+ <Target />
75
+ </Show>
76
+ </Button>
77
+ <DropdownMenuTrigger
78
+ as={Button}
79
+ type="button"
80
+ size="icon-sm"
81
+ variant={variant()}
82
+ aria-label="Send options"
83
+ disabled={props.selectionDisabled}
84
+ >
85
+ <ChevronDown />
86
+ </DropdownMenuTrigger>
87
+ </ButtonGroup>
88
+ <DropdownMenuContent hideArrow>
89
+ <DropdownMenuRadioGroup
90
+ on:keydown={(event: KeyboardEvent) => {
91
+ if (
92
+ event.key !== 'Tab' ||
93
+ event.isComposing ||
94
+ !(event.currentTarget instanceof HTMLElement)
95
+ )
96
+ return
97
+ const rows = Array.from(
98
+ event.currentTarget.querySelectorAll<HTMLElement>(
99
+ '[role="menuitemradio"]:not([aria-disabled="true"])'
100
+ )
101
+ )
102
+ if (!rows.length) return
103
+ event.preventDefault()
104
+ event.stopPropagation()
105
+ const active = document.activeElement
106
+ const index = active instanceof HTMLElement ? rows.indexOf(active) : -1
107
+ const next =
108
+ index < 0
109
+ ? event.shiftKey
110
+ ? rows.length - 1
111
+ : 0
112
+ : (index + (event.shiftKey ? -1 : 1) + rows.length) % rows.length
113
+ rows[next]?.focus()
114
+ }}
115
+ value={props.mode}
116
+ onChange={(value) => {
117
+ if (
118
+ (value === 'steer' || value === 'queue') &&
119
+ !props.selectionDisabled &&
120
+ !props.unavailable?.[value]
121
+ )
122
+ props.onModeChange(value)
123
+ }}
124
+ >
125
+ <For each={modes}>
126
+ {(mode) => (
127
+ <DropdownMenuRadioItem
128
+ value={mode}
129
+ closeOnSelect
130
+ disabled={props.selectionDisabled || !!props.unavailable?.[mode]}
131
+ >
132
+ <Show when={mode === 'steer'} fallback={<ArrowUpFromLine />}>
133
+ <Target />
134
+ </Show>
135
+ <div class="flex min-w-0 flex-col gap-1">
136
+ <span>{labels[mode]}</span>
137
+ <span class="text-muted-foreground text-xs">{descriptions[mode]}</span>
138
+ <Show when={props.unavailable?.[mode]}>
139
+ {(message) => <span class="text-muted-foreground text-xs">{message()}</span>}
140
+ </Show>
141
+ </div>
142
+ </DropdownMenuRadioItem>
143
+ )}
144
+ </For>
145
+ </DropdownMenuRadioGroup>
146
+ <Show when={props.alternateActionHint}>
147
+ <DropdownMenuSeparator />
148
+ <p class="text-muted-foreground px-2 py-1 text-xs">{props.alternateActionHint}</p>
149
+ </Show>
150
+ </DropdownMenuContent>
151
+ </DropdownMenu>
152
+ <Show when={reason()}>
153
+ {(message) => (
154
+ <p id={reasonId} class="text-muted-foreground text-xs">
155
+ {message()}
156
+ </p>
157
+ )}
158
+ </Show>
159
+ </div>
160
+ )
161
+ }
@@ -1,3 +1,4 @@
1
+ export { BusySendButton, type BusySendMode, type BusySendButtonProps } from './busy-send-button'
1
2
  export {
2
3
  ConversationAvatar,
3
4
  type ConversationAvatarKind,
@@ -434,6 +434,9 @@ export const typographyTokens: TokenDefinition[] = [
434
434
  },
435
435
  ]
436
436
 
437
+ /** Height tokens also size both axes of icon controls through Tailwind's --size
438
+ * namespace. Padding has its own --spacing mapping. Nominal pixel descriptions
439
+ * use a 16px rem; rendered dimensions follow the consumer's root font size. */
437
440
  export const densityTokens: TokenDefinition[] = [
438
441
  { name: 'control-height-2xs', kind: 'dimension', description: '20px — an inline chip control.' },
439
442
  { name: 'control-height-xs', kind: 'dimension', description: '24px — a dense table row action.' },
@@ -826,6 +826,15 @@
826
826
  --height-control-md: var(--control-height-md);
827
827
  --height-control-lg: var(--control-height-lg);
828
828
  --height-control-xl: var(--control-height-xl);
829
+ /* Tailwind `size-*` prefers --size-* and then --spacing-*. Without this
830
+ bridge, square icon controls use the padding ladder below for both axes.
831
+ Height, square size and inline padding remain distinct semantic contracts. */
832
+ --size-control-2xs: var(--control-height-2xs);
833
+ --size-control-xs: var(--control-height-xs);
834
+ --size-control-sm: var(--control-height-sm);
835
+ --size-control-md: var(--control-height-md);
836
+ --size-control-lg: var(--control-height-lg);
837
+ --size-control-xl: var(--control-height-xl);
829
838
  --height-row-sm: var(--row-height-sm);
830
839
  --height-row-md: var(--row-height-md);
831
840
  --height-row-lg: var(--row-height-lg);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adea-ai/ui",
3
- "version": "0.63.4",
3
+ "version": "0.64.0",
4
4
  "description": "The Adea design system: Kobalte-backed Solid components, semantic OKLCH tokens, and the app-shell layout primitives shared by Adea and Cortana.",
5
5
  "keywords": [
6
6
  "adea",
package/registry.json CHANGED
@@ -1781,13 +1781,20 @@
1781
1781
  ],
1782
1782
  "registryDependencies": [
1783
1783
  "@adea-ai/ui/button",
1784
+ "@adea-ai/ui/button-group",
1784
1785
  "@adea-ai/ui/code-block",
1786
+ "@adea-ai/ui/dropdown-menu",
1785
1787
  "@adea-ai/ui/kbd",
1786
1788
  "@adea-ai/ui/spinner",
1787
1789
  "@adea-ai/ui/textarea",
1788
1790
  "lib"
1789
1791
  ],
1790
1792
  "files": [
1793
+ {
1794
+ "path": "src/components/conversation/busy-send-button.tsx",
1795
+ "type": "registry:ui",
1796
+ "target": "components/conversation/busy-send-button.tsx"
1797
+ },
1791
1798
  {
1792
1799
  "path": "src/components/conversation/conversation-avatar.tsx",
1793
1800
  "type": "registry:ui",
@@ -0,0 +1,161 @@
1
+ /*
2
+ * Substantially translated from KiroCrew website/src/components/BusySendButton.tsx
3
+ * at 283e136c0f902e965a535a7c9548c57c7504fed0.
4
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
5
+ * Licensed under Apache-2.0; see LICENSE and NOTICE.
6
+ */
7
+ import { ArrowUpFromLine, ChevronDown, Target } from 'lucide-solid'
8
+ import { For, Show, createUniqueId } from 'solid-js'
9
+ import { Button } from '../ui/button/button'
10
+ import { ButtonGroup } from '../ui/button-group/button-group'
11
+ import {
12
+ DropdownMenu,
13
+ DropdownMenuContent,
14
+ DropdownMenuRadioGroup,
15
+ DropdownMenuRadioItem,
16
+ DropdownMenuSeparator,
17
+ DropdownMenuTrigger,
18
+ } from '../ui/dropdown-menu/dropdown-menu'
19
+
20
+ export type BusySendMode = 'steer' | 'queue'
21
+ export type BusySendButtonProps = {
22
+ mode: BusySendMode
23
+ onModeChange: (mode: BusySendMode) => void
24
+ /** Executes only the selected action. The host owns the draft and command. */
25
+ onFire: () => void
26
+ /** An empty draft or pending delivery disables fire, but not choosing a mode. */
27
+ disabled?: boolean
28
+ /** Disable mode selection when the host has no authority to change preferences. */
29
+ selectionDisabled?: boolean
30
+ /** Host capability/authority failures: unavailable rows remain visible. */
31
+ unavailable?: Partial<Record<BusySendMode, string>>
32
+ /** Supply only when the host implements this alternate-action keyboard chord. */
33
+ alternateActionHint?: string
34
+ }
35
+
36
+ const modes: BusySendMode[] = ['steer', 'queue']
37
+ const labels = { steer: 'Steer', queue: 'Queue' }
38
+ const descriptions = {
39
+ steer: 'Act on this right away',
40
+ queue: 'Run after the current work finishes',
41
+ }
42
+
43
+ /**
44
+ * Kiro's split action/menu composition, with app-owned mode and availability.
45
+ * Picking a mode never fires it. Persistence, migration and same-session
46
+ * broadcasts belong to the consumer; this component has no storage or global listeners.
47
+ * Kobalte replaces the donor manual portal/positioning and document listeners:
48
+ * arrows wrap and selection/Escape return focus. Kobalte 0.13.14 prevents Tab
49
+ * without moving focus, so a menu-scoped translation of the donor Tab cycle
50
+ * fills that gap. It discovers enabled radio rows only; no document trap.
51
+ * No force-reset timer or runtime authority is translated from the adjacent
52
+ * donor stop flow.
53
+ */
54
+ export function BusySendButton(props: BusySendButtonProps) {
55
+ const reasonId = createUniqueId()
56
+ const reason = () => props.unavailable?.[props.mode]
57
+ const variant = () => (props.mode === 'steer' ? ('default' as const) : ('secondary' as const))
58
+ return (
59
+ <div data-slot="busy-send-button" class="flex w-fit flex-col gap-1">
60
+ <DropdownMenu placement="top-end" modal={false}>
61
+ <ButtonGroup label="Send while busy">
62
+ <Button
63
+ type="button"
64
+ size="icon-sm"
65
+ variant={variant()}
66
+ aria-label={props.mode === 'steer' ? 'Steer' : 'Queue message'}
67
+ aria-describedby={reason() ? reasonId : undefined}
68
+ disabled={props.disabled || !!reason()}
69
+ onClick={() => {
70
+ if (!props.disabled && !reason()) props.onFire()
71
+ }}
72
+ >
73
+ <Show when={props.mode === 'steer'} fallback={<ArrowUpFromLine />}>
74
+ <Target />
75
+ </Show>
76
+ </Button>
77
+ <DropdownMenuTrigger
78
+ as={Button}
79
+ type="button"
80
+ size="icon-sm"
81
+ variant={variant()}
82
+ aria-label="Send options"
83
+ disabled={props.selectionDisabled}
84
+ >
85
+ <ChevronDown />
86
+ </DropdownMenuTrigger>
87
+ </ButtonGroup>
88
+ <DropdownMenuContent hideArrow>
89
+ <DropdownMenuRadioGroup
90
+ on:keydown={(event: KeyboardEvent) => {
91
+ if (
92
+ event.key !== 'Tab' ||
93
+ event.isComposing ||
94
+ !(event.currentTarget instanceof HTMLElement)
95
+ )
96
+ return
97
+ const rows = Array.from(
98
+ event.currentTarget.querySelectorAll<HTMLElement>(
99
+ '[role="menuitemradio"]:not([aria-disabled="true"])'
100
+ )
101
+ )
102
+ if (!rows.length) return
103
+ event.preventDefault()
104
+ event.stopPropagation()
105
+ const active = document.activeElement
106
+ const index = active instanceof HTMLElement ? rows.indexOf(active) : -1
107
+ const next =
108
+ index < 0
109
+ ? event.shiftKey
110
+ ? rows.length - 1
111
+ : 0
112
+ : (index + (event.shiftKey ? -1 : 1) + rows.length) % rows.length
113
+ rows[next]?.focus()
114
+ }}
115
+ value={props.mode}
116
+ onChange={(value) => {
117
+ if (
118
+ (value === 'steer' || value === 'queue') &&
119
+ !props.selectionDisabled &&
120
+ !props.unavailable?.[value]
121
+ )
122
+ props.onModeChange(value)
123
+ }}
124
+ >
125
+ <For each={modes}>
126
+ {(mode) => (
127
+ <DropdownMenuRadioItem
128
+ value={mode}
129
+ closeOnSelect
130
+ disabled={props.selectionDisabled || !!props.unavailable?.[mode]}
131
+ >
132
+ <Show when={mode === 'steer'} fallback={<ArrowUpFromLine />}>
133
+ <Target />
134
+ </Show>
135
+ <div class="flex min-w-0 flex-col gap-1">
136
+ <span>{labels[mode]}</span>
137
+ <span class="text-muted-foreground text-xs">{descriptions[mode]}</span>
138
+ <Show when={props.unavailable?.[mode]}>
139
+ {(message) => <span class="text-muted-foreground text-xs">{message()}</span>}
140
+ </Show>
141
+ </div>
142
+ </DropdownMenuRadioItem>
143
+ )}
144
+ </For>
145
+ </DropdownMenuRadioGroup>
146
+ <Show when={props.alternateActionHint}>
147
+ <DropdownMenuSeparator />
148
+ <p class="text-muted-foreground px-2 py-1 text-xs">{props.alternateActionHint}</p>
149
+ </Show>
150
+ </DropdownMenuContent>
151
+ </DropdownMenu>
152
+ <Show when={reason()}>
153
+ {(message) => (
154
+ <p id={reasonId} class="text-muted-foreground text-xs">
155
+ {message()}
156
+ </p>
157
+ )}
158
+ </Show>
159
+ </div>
160
+ )
161
+ }
@@ -1,3 +1,4 @@
1
+ export { BusySendButton, type BusySendMode, type BusySendButtonProps } from './busy-send-button'
1
2
  export {
2
3
  ConversationAvatar,
3
4
  type ConversationAvatarKind,
package/src/lib/tokens.ts CHANGED
@@ -434,6 +434,9 @@ export const typographyTokens: TokenDefinition[] = [
434
434
  },
435
435
  ]
436
436
 
437
+ /** Height tokens also size both axes of icon controls through Tailwind's --size
438
+ * namespace. Padding has its own --spacing mapping. Nominal pixel descriptions
439
+ * use a 16px rem; rendered dimensions follow the consumer's root font size. */
437
440
  export const densityTokens: TokenDefinition[] = [
438
441
  { name: 'control-height-2xs', kind: 'dimension', description: '20px — an inline chip control.' },
439
442
  { name: 'control-height-xs', kind: 'dimension', description: '24px — a dense table row action.' },
@@ -826,6 +826,15 @@
826
826
  --height-control-md: var(--control-height-md);
827
827
  --height-control-lg: var(--control-height-lg);
828
828
  --height-control-xl: var(--control-height-xl);
829
+ /* Tailwind `size-*` prefers --size-* and then --spacing-*. Without this
830
+ bridge, square icon controls use the padding ladder below for both axes.
831
+ Height, square size and inline padding remain distinct semantic contracts. */
832
+ --size-control-2xs: var(--control-height-2xs);
833
+ --size-control-xs: var(--control-height-xs);
834
+ --size-control-sm: var(--control-height-sm);
835
+ --size-control-md: var(--control-height-md);
836
+ --size-control-lg: var(--control-height-lg);
837
+ --size-control-xl: var(--control-height-xl);
829
838
  --height-row-sm: var(--row-height-sm);
830
839
  --height-row-md: var(--row-height-md);
831
840
  --height-row-lg: var(--row-height-lg);