@cosxai/ui 1.0.0-alpha.13 → 1.0.0-alpha.14
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/CHANGELOG.md +4 -0
- package/package.json +1 -1
- package/src/components/ActionBar.tsx +22 -11
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
## 1.0.0-alpha.14
|
|
2
|
+
|
|
3
|
+
- ActionBar: an action can carry `divider` (a rule before it), `iconOnly` (just the icon, label in the tooltip) and `wrap` + `wrapKey` (wrap the button in a menu or popover trigger so it opens something anchored to itself).
|
|
4
|
+
|
|
1
5
|
## 1.0.0-alpha.13 (2026-10-04)
|
|
2
6
|
|
|
3
7
|
- BottomSheet: the scrolling list reaches the sheet's sides (its padding
|
package/package.json
CHANGED
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
useRef,
|
|
12
12
|
useState,
|
|
13
13
|
type KeyboardEvent as ReactKeyboardEvent,
|
|
14
|
+
type ReactElement,
|
|
14
15
|
type ReactNode,
|
|
15
16
|
} from 'react';
|
|
16
17
|
|
|
@@ -35,6 +36,14 @@ export type ActionBarAction = {
|
|
|
35
36
|
disabledReason?: string | undefined;
|
|
36
37
|
/** Actions of a kind: more than two sharing a group fold into one menu. */
|
|
37
38
|
group?: string | undefined;
|
|
39
|
+
/** A thin rule before it, setting it apart from the actions on its left. */
|
|
40
|
+
divider?: boolean | undefined;
|
|
41
|
+
/** Always just the icon (a star, ⋯); the label names it for screen readers and the tooltip. */
|
|
42
|
+
iconOnly?: boolean | undefined;
|
|
43
|
+
/** Wrap the button, e.g. in a menu's or popover's trigger (asChild), so it opens something anchored to itself. */
|
|
44
|
+
wrap?: ((button: ReactElement) => ReactElement) | undefined;
|
|
45
|
+
/** Changes when what `wrap` shows changes (the bar re-renders only when an action's fields change). */
|
|
46
|
+
wrapKey?: string | undefined;
|
|
38
47
|
};
|
|
39
48
|
|
|
40
49
|
export type ActionBarSelection = {
|
|
@@ -126,7 +135,7 @@ function editable(t: EventTarget | null): boolean {
|
|
|
126
135
|
const dialogOpen = () => Boolean(document.querySelector('[role="dialog"][data-state="open"], [role="alertdialog"][data-state="open"]'));
|
|
127
136
|
|
|
128
137
|
const signature = (a: ActionBarAction[] | null | undefined) =>
|
|
129
|
-
a ? a.map((x) => [x.id, x.label, x.shortcut, x.active, x.disabled, x.disabledReason, x.group, x.icon?.displayName].join('\u0001')).join('\u0002') : '';
|
|
138
|
+
a ? a.map((x) => [x.id, x.label, x.shortcut, x.active, x.disabled, x.disabledReason, x.group, x.icon?.displayName, x.divider, x.iconOnly, x.wrapKey].join('\u0001')).join('\u0002') : '';
|
|
130
139
|
|
|
131
140
|
// ─── Provider ─────────────────────────────────────────────────────────
|
|
132
141
|
|
|
@@ -465,8 +474,8 @@ export function ActionBar({ presentation, hidden: hiddenProp, maxActions = 6, la
|
|
|
465
474
|
const renderAction = (a: ActionBarAction) => {
|
|
466
475
|
const keys = a.shortcut ? formatShortcut(a.shortcut) : null;
|
|
467
476
|
const Glyph = a.icon;
|
|
468
|
-
const iconOnly = shown === 'icons' && Glyph;
|
|
469
|
-
const
|
|
477
|
+
const iconOnly = (shown === 'icons' || a.iconOnly) && Glyph;
|
|
478
|
+
const plain = (
|
|
470
479
|
<button
|
|
471
480
|
type="button"
|
|
472
481
|
aria-label={iconOnly ? a.label : undefined}
|
|
@@ -479,16 +488,18 @@ export function ActionBar({ presentation, hidden: hiddenProp, maxActions = 6, la
|
|
|
479
488
|
>
|
|
480
489
|
{Glyph && <Glyph size={16} strokeWidth={1.75} aria-hidden />}
|
|
481
490
|
{!iconOnly && <span>{a.label}</span>}
|
|
482
|
-
{shown === 'full' && keys && <kbd className="font-sans text-meta font-medium opacity-55">{keys}</kbd>}
|
|
491
|
+
{shown === 'full' && keys && !iconOnly && <kbd className="font-sans text-meta font-medium opacity-55">{keys}</kbd>}
|
|
483
492
|
</button>
|
|
484
493
|
);
|
|
485
|
-
const
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
494
|
+
const button = a.wrap ? a.wrap(plain) : plain;
|
|
495
|
+
const rule = a.divider ? <span aria-hidden className="mx-1 h-5 w-px shrink-0 bg-white/20 ink:bg-ink/20" /> : null;
|
|
496
|
+
const hint = a.disabledReason ?? (shown !== 'full' || iconOnly ? [a.label, keys].filter(Boolean).join(' · ') : null);
|
|
497
|
+
const tipped = hint && (iconOnly || a.disabledReason || keys) ? <Tooltip content={hint}>{button}</Tooltip> : button;
|
|
498
|
+
return (
|
|
499
|
+
<Fragment key={a.id}>
|
|
500
|
+
{rule}
|
|
501
|
+
{tipped}
|
|
502
|
+
</Fragment>
|
|
492
503
|
);
|
|
493
504
|
};
|
|
494
505
|
|