@flamingo-stack/openframe-frontend-core 0.0.781 → 0.0.782
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/case-study-card-WYZPBDDM.cjs +23 -0
- package/dist/{chunk-D46WFWWI.cjs → chunk-2EXD2RSC.cjs} +41 -39
- package/dist/{chunk-RJX33Y4Q.cjs → chunk-3INHO6GP.cjs} +22 -22
- package/dist/{chunk-JHDPEYZH.cjs → chunk-4DKPNN2A.cjs} +17 -17
- package/dist/{chunk-L4XOCV7S.cjs → chunk-4DQ4CNAG.cjs} +10 -10
- package/dist/{chunk-HTSRCFXP.cjs → chunk-4MQASMIU.cjs} +7 -7
- package/dist/{chunk-3VINTJPE.cjs → chunk-5WMRVMXH.cjs} +5 -5
- package/dist/{chunk-OHXB6HUX.cjs → chunk-5XAWVXNI.cjs} +320 -320
- package/dist/{chunk-VDTLVFCV.cjs → chunk-7DKDVJMR.cjs} +13 -13
- package/dist/{chunk-FWJ5YECN.cjs → chunk-7OJMOG34.cjs} +546 -544
- package/dist/{chunk-63OCO2G5.cjs → chunk-A3UZFFR3.cjs} +4 -4
- package/dist/{chunk-ODZ5XGWA.cjs → chunk-A4YUTS6Q.cjs} +2076 -2052
- package/dist/{chunk-T7SDYBST.cjs → chunk-BE4OUWTA.cjs} +54 -54
- package/dist/{chunk-YKJ4JN6T.cjs → chunk-C42BXIY7.cjs} +42 -42
- package/dist/{chunk-HPGCUYAZ.cjs → chunk-C5UUWXHE.cjs} +110 -110
- package/dist/{chunk-ZV6RQNXE.cjs → chunk-CBKXU77H.cjs} +46 -46
- package/dist/{chunk-IYU2ZH2J.cjs → chunk-CS5SZJFV.cjs} +2 -2
- package/dist/{chunk-Q7HXTF2C.cjs → chunk-DYF6XB27.cjs} +4 -4
- package/dist/{chunk-AKCBLZAO.cjs → chunk-E2ZZOYSM.cjs} +74 -62
- package/dist/{chunk-57NE7SHG.cjs → chunk-EFCWHAYC.cjs} +8 -8
- package/dist/{chunk-KWV23THO.cjs → chunk-EHQ2UGT4.cjs} +14 -14
- package/dist/{chunk-DJTPDK3W.cjs → chunk-F2FFJWOQ.cjs} +4 -4
- package/dist/{chunk-CDBFQVPA.cjs → chunk-FLS6DZEN.cjs} +46 -43
- package/dist/{chunk-VZKAAXU3.cjs → chunk-FS7CBRF4.cjs} +23 -23
- package/dist/{chunk-B6EQVH7D.cjs → chunk-GFRKNUJZ.cjs} +51 -51
- package/dist/{chunk-PID7LUDP.cjs → chunk-I7LRZR4Q.cjs} +31 -31
- package/dist/{chunk-A7FSNBNV.cjs → chunk-ISB7LW3D.cjs} +173 -172
- package/dist/{chunk-LDGR5VCK.cjs → chunk-IZKEWQJN.cjs} +4 -4
- package/dist/{chunk-X6TXMWBV.cjs → chunk-JGKPEGZN.cjs} +61 -61
- package/dist/{chunk-EYNQE2XN.cjs → chunk-LTF6UDGO.cjs} +6 -6
- package/dist/{chunk-2OYKOHFK.cjs → chunk-LUWYWYNC.cjs} +2 -2
- package/dist/{chunk-5PBWAF2D.cjs → chunk-MDGDL3C7.cjs} +44 -44
- package/dist/{chunk-N6YCOBLK.cjs → chunk-MGEUZRNQ.cjs} +101 -9
- package/dist/{chunk-YEJWNHD3.cjs → chunk-MKF6XX5A.cjs} +63 -63
- package/dist/{chunk-3IHGS44W.cjs → chunk-N2SVJJLU.cjs} +5 -5
- package/dist/{chunk-TZ6MTHUC.cjs → chunk-N5TPRCSS.cjs} +60 -60
- package/dist/{chunk-HLZUBJPL.cjs → chunk-N7QNWHJA.cjs} +197 -197
- package/dist/{chunk-YNDH72VU.cjs → chunk-NNNRN4OF.cjs} +14 -14
- package/dist/{chunk-JQWYXC2E.cjs → chunk-ODDUGLYF.cjs} +110 -110
- package/dist/{chunk-T4ZVKEDP.cjs → chunk-OMTH355I.cjs} +3 -3
- package/dist/{chunk-TH5X2BXK.cjs → chunk-QV4GHAWN.cjs} +115 -115
- package/dist/{chunk-DIY4SJZI.cjs → chunk-RT6QATX4.cjs} +19 -19
- package/dist/{chunk-UONQCE5N.cjs → chunk-TS6TISIF.cjs} +209 -208
- package/dist/{chunk-SMEX3BWO.cjs → chunk-UPQMFK5B.cjs} +7 -7
- package/dist/{chunk-XYKVOBIP.cjs → chunk-VH3KQSI2.cjs} +3 -3
- package/dist/{chunk-OFX6XEVN.cjs → chunk-VZUV2FCP.cjs} +13 -13
- package/dist/{chunk-QD7SKYCQ.cjs → chunk-WSBWP7IW.cjs} +3 -3
- package/dist/{chunk-RYIWADIB.cjs → chunk-XAA5LUHC.cjs} +12 -12
- package/dist/{chunk-XHJI7R4J.cjs → chunk-YX7X5QQN.cjs} +46 -46
- package/dist/{chunk-ZPYFPLPD.cjs → chunk-YXZOP726.cjs} +10 -10
- package/dist/{chunk-4XDYSGRL.cjs → chunk-ZFOMRALU.cjs} +17 -17
- package/dist/{chunk-AFJEUBDS.cjs → chunk-ZJS45HQZ.cjs} +29 -29
- package/dist/{cloud-tenants-UAFVHKX7.cjs → cloud-tenants-LXKEG5N4.cjs} +32 -32
- package/dist/components/calendar.cjs +10 -10
- package/dist/components/case-studies/index.cjs +52 -52
- package/dist/components/category-card.d.ts.map +1 -1
- package/dist/components/category-card.js +1 -0
- package/dist/components/chat/ask-display.js +2 -2
- package/dist/components/chat/chat-context-memory-bar.js +2 -2
- package/dist/components/chat/chat-context-picker.d.ts.map +1 -1
- package/dist/components/chat/chat-context-picker.js +4 -2
- package/dist/components/chat/chat-input.d.ts.map +1 -1
- package/dist/components/chat/chat-input.js +2 -1
- package/dist/components/chat/chat-nav-sidebar.d.ts.map +1 -1
- package/dist/components/chat/chat-nav-sidebar.js +12 -1
- package/dist/components/chat/guide-mode-banner.js +1 -1
- package/dist/components/chat/index.cjs +26 -26
- package/dist/components/chat/mingo-welcome.js +1 -1
- package/dist/components/contact/index.cjs +33 -33
- package/dist/components/docs/index.cjs +36 -36
- package/dist/components/embeds/index.cjs +33 -33
- package/dist/components/faq/index.cjs +34 -34
- package/dist/components/features/capability-explorer.d.ts.map +1 -1
- package/dist/components/features/capability-explorer.js +11 -1
- package/dist/components/features/command-box.js +1 -1
- package/dist/components/features/devices/devices-grid-filters.d.ts.map +1 -1
- package/dist/components/features/devices/devices-grid-filters.js +15 -4
- package/dist/components/features/filters-dropdown.d.ts.map +1 -1
- package/dist/components/features/filters-dropdown.js +6 -5
- package/dist/components/features/index.cjs +32 -32
- package/dist/components/features/model-token-rates.js +1 -1
- package/dist/components/features/notifications/notification-drawer.d.ts.map +1 -1
- package/dist/components/features/notifications/notification-drawer.js +1 -0
- package/dist/components/features/notifications/notification-tile.js +1 -1
- package/dist/components/features/paths-display.js +1 -1
- package/dist/components/features/remote-session/remote-session-events.d.ts.map +1 -1
- package/dist/components/features/remote-session/remote-session-events.js +1 -0
- package/dist/components/features/scripts/schedule-form/schedule-script-picker-card.js +1 -1
- package/dist/components/features/scripts/schedule-form/schedule-timing-fields.js +1 -1
- package/dist/components/features/select-button.js +0 -1
- package/dist/components/features/tags-selector.js +1 -1
- package/dist/components/help-center-pages/index.cjs +163 -163
- package/dist/components/index.cjs +205 -204
- package/dist/components/loading/loading-region.d.ts.map +1 -1
- package/dist/components/loading/loading-region.js +2 -2
- package/dist/components/meeting-scheduler/index.cjs +187 -187
- package/dist/components/navigation/index.cjs +35 -35
- package/dist/components/navigation/mobile-burger-menu.d.ts.map +1 -1
- package/dist/components/navigation/mobile-burger-menu.js +2 -1
- package/dist/components/navigation/multi-level-navigation.d.ts.map +1 -1
- package/dist/components/navigation/multi-level-navigation.js +4 -2
- package/dist/components/navigation/navigation-sidebar-item.js +3 -3
- package/dist/components/onboarding-guides/index.cjs +35 -35
- package/dist/components/product-demo/index.cjs +45 -45
- package/dist/components/related-content/index.cjs +17 -17
- package/dist/components/tickets/index.cjs +39 -39
- package/dist/components/ui/allowed-domains-input.d.ts.map +1 -1
- package/dist/components/ui/allowed-domains-input.js +1 -0
- package/dist/components/ui/button/button-styles.d.ts +12 -4
- package/dist/components/ui/button/button-styles.d.ts.map +1 -1
- package/dist/components/ui/button/button-styles.js +99 -7
- package/dist/components/ui/button/button.d.ts +1 -1
- package/dist/components/ui/button/button.d.ts.map +1 -1
- package/dist/components/ui/button/button.js +3 -0
- package/dist/components/ui/file-manager/file-manager-breadcrumb.d.ts.map +1 -1
- package/dist/components/ui/file-manager/file-manager-breadcrumb.js +1 -0
- package/dist/components/ui/file-manager/index.cjs +56 -55
- package/dist/components/ui/file-upload.d.ts.map +1 -1
- package/dist/components/ui/file-upload.js +5 -3
- package/dist/components/ui/hidden-tags-popup.js +1 -1
- package/dist/components/ui/hover-dropdown.js +1 -1
- package/dist/components/ui/index.cjs +32 -32
- package/dist/components/ui/info-card.js +1 -1
- package/dist/components/ui/info-section.d.ts.map +1 -1
- package/dist/components/ui/info-section.js +1 -0
- package/dist/components/ui/loading-scope.d.ts.map +1 -1
- package/dist/components/ui/loading-scope.js +2 -2
- package/dist/components/ui/modal-v2.js +1 -1
- package/dist/components/ui/organization-card.d.ts.map +1 -1
- package/dist/components/ui/organization-card.js +2 -1
- package/dist/components/ui/page-actions.d.ts +2 -2
- package/dist/components/ui/page-actions.d.ts.map +1 -1
- package/dist/components/ui/password-input.js +1 -1
- package/dist/components/ui/service-card.js +3 -3
- package/dist/components/ui/tab-selector.d.ts.map +1 -1
- package/dist/components/ui/tab-selector.js +3 -3
- package/dist/components/ui/test-run.d.ts.map +1 -1
- package/dist/components/ui/test-run.js +2 -1
- package/dist/components/ui/textarea.d.ts.map +1 -1
- package/dist/components/ui/textarea.js +2 -1
- package/dist/components/ui/ticket-attachments-list.d.ts.map +1 -1
- package/dist/components/ui/ticket-attachments-list.js +3 -2
- package/dist/components/ui/ticket-info-section.d.ts.map +1 -1
- package/dist/components/ui/ticket-info-section.js +1 -0
- package/dist/components/ui/ticket-note-card.d.ts.map +1 -1
- package/dist/components/ui/ticket-note-card.js +6 -4
- package/dist/components/ui/ticket-status-config-row.d.ts.map +1 -1
- package/dist/components/ui/ticket-status-config-row.js +1 -10
- package/dist/components/ui/toaster.js +1 -1
- package/dist/components/vendor-display-button.js +1 -1
- package/dist/{devices-TDKCKWRP.cjs → devices-PYJRYIQN.cjs} +33 -33
- package/dist/embed-shims/index.cjs +4 -4
- package/dist/embed-shims/next-image.cjs +4 -4
- package/dist/{embeddable-chat-HEL4Z2FL.cjs → embeddable-chat-7MSM62UC.cjs} +114 -114
- package/dist/hooks/index.cjs +10 -10
- package/dist/index.cjs +48 -48
- package/dist/{knowledge-A5KJ4CAD.cjs → knowledge-R4H2ZDX2.cjs} +33 -33
- package/dist/{logs-6WRBPIMM.cjs → logs-YWL6NK24.cjs} +41 -41
- package/dist/{policies-ICRXHW3H.cjs → policies-3COFYSKB.cjs} +36 -36
- package/dist/{remote-session-MEV5JL2Z.cjs → remote-session-IEOWFBF7.cjs} +17 -17
- package/dist/{scripts-AZVCZE6C.cjs → scripts-72EJDICT.cjs} +39 -39
- package/dist/{software-update-4ZBCGJGA.cjs → software-update-PPUVCLPO.cjs} +36 -36
- package/dist/{tickets-board-BJPQD3HE.cjs → tickets-board-EYKLSB36.cjs} +17 -17
- package/dist/{video-file-player-DETXW4OJ.cjs → video-file-player-ZU666VUY.cjs} +14 -14
- package/package.json +1 -1
- package/src/components/category-card.tsx +2 -0
- package/src/components/chat/ask-display.tsx +2 -2
- package/src/components/chat/chat-context-memory-bar.tsx +2 -2
- package/src/components/chat/chat-context-picker.tsx +4 -2
- package/src/components/chat/chat-input.tsx +3 -1
- package/src/components/chat/chat-nav-sidebar.tsx +10 -1
- package/src/components/chat/guide-mode-banner.tsx +1 -1
- package/src/components/chat/mingo-welcome.tsx +1 -1
- package/src/components/features/capability-explorer.tsx +8 -1
- package/src/components/features/command-box.tsx +1 -1
- package/src/components/features/devices/devices-grid-filters.tsx +8 -1
- package/src/components/features/filters-dropdown.tsx +6 -1
- package/src/components/features/model-token-rates.tsx +1 -1
- package/src/components/features/notifications/notification-drawer.tsx +1 -0
- package/src/components/features/notifications/notification-tile.tsx +1 -1
- package/src/components/features/paths-display.tsx +1 -1
- package/src/components/features/remote-session/remote-session-events.tsx +2 -0
- package/src/components/features/scripts/schedule-form/schedule-script-picker-card.tsx +1 -1
- package/src/components/features/scripts/schedule-form/schedule-timing-fields.tsx +1 -1
- package/src/components/features/select-button.tsx +2 -2
- package/src/components/features/tags-selector.tsx +1 -1
- package/src/components/loading/loading-region.tsx +4 -1
- package/src/components/navigation/mobile-burger-menu.tsx +3 -1
- package/src/components/navigation/multi-level-navigation.tsx +6 -2
- package/src/components/navigation/navigation-sidebar-item.tsx +5 -5
- package/src/components/ui/allowed-domains-input.tsx +1 -0
- package/src/components/ui/button/button-styles.ts +106 -9
- package/src/components/ui/button/button.tsx +3 -0
- package/src/components/ui/file-manager/file-manager-breadcrumb.tsx +1 -0
- package/src/components/ui/file-upload.tsx +5 -3
- package/src/components/ui/hidden-tags-popup.tsx +1 -1
- package/src/components/ui/hover-dropdown.tsx +1 -1
- package/src/components/ui/info-card.tsx +1 -1
- package/src/components/ui/info-section.tsx +2 -0
- package/src/components/ui/loading-scope.tsx +2 -1
- package/src/components/ui/modal-v2.tsx +1 -1
- package/src/components/ui/organization-card.tsx +3 -1
- package/src/components/ui/page-actions.tsx +14 -2
- package/src/components/ui/password-input.tsx +1 -1
- package/src/components/ui/service-card.tsx +3 -3
- package/src/components/ui/tab-selector.tsx +5 -3
- package/src/components/ui/test-run.tsx +2 -1
- package/src/components/ui/textarea.tsx +3 -1
- package/src/components/ui/ticket-attachments-list.tsx +3 -2
- package/src/components/ui/ticket-info-section.tsx +1 -0
- package/src/components/ui/ticket-note-card.tsx +6 -4
- package/src/components/ui/ticket-status-config-row.tsx +1 -6
- package/src/components/ui/toaster.tsx +1 -1
- package/src/components/vendor-display-button.tsx +1 -1
- package/dist/case-study-card-CYJ3JXU6.cjs +0 -23
|
@@ -325,7 +325,12 @@ function CapabilityExplorerSkeleton({
|
|
|
325
325
|
<div className="flex min-h-0 flex-col gap-1 overflow-hidden">
|
|
326
326
|
<LoadingItems count={count}>
|
|
327
327
|
{i => (
|
|
328
|
-
<div
|
|
328
|
+
<div
|
|
329
|
+
data-loading-item
|
|
330
|
+
data-state={i === 0 ? 'active' : undefined}
|
|
331
|
+
data-tone="card"
|
|
332
|
+
className={JOB_TAB_CLASS}
|
|
333
|
+
>
|
|
329
334
|
<JobHeadSkeleton />
|
|
330
335
|
</div>
|
|
331
336
|
)}
|
|
@@ -514,6 +519,8 @@ export function CapabilityExplorer({
|
|
|
514
519
|
aria-selected={selected}
|
|
515
520
|
aria-controls={panelId}
|
|
516
521
|
data-state={selected ? 'active' : undefined}
|
|
522
|
+
// The selected capability is a bordered card; the others keep a transparent border and a hover fill.
|
|
523
|
+
data-tone="card"
|
|
517
524
|
tabIndex={selected ? 0 : -1}
|
|
518
525
|
onClick={() => onActiveChange(item.id)}
|
|
519
526
|
className={JOB_TAB_LAYOUT_CLASS}
|
|
@@ -54,7 +54,14 @@ export function DevicesGridFilters({
|
|
|
54
54
|
<FiltersDropdown
|
|
55
55
|
key={column.key}
|
|
56
56
|
triggerElement={
|
|
57
|
-
<Button
|
|
57
|
+
<Button
|
|
58
|
+
variant="link"
|
|
59
|
+
size="compact"
|
|
60
|
+
noPaddingX
|
|
61
|
+
type="button"
|
|
62
|
+
data-tone="neutral"
|
|
63
|
+
aria-label={`Filter by ${column.label}`}
|
|
64
|
+
>
|
|
58
65
|
<span className="select-none whitespace-nowrap uppercase text-h5">{column.label}</span>
|
|
59
66
|
<Filter02Icon className={cn(active && 'text-ods-accent')} />
|
|
60
67
|
</Button>
|
|
@@ -395,9 +395,11 @@ export const FiltersDropdown: FC<FiltersDropdownProps> = ({
|
|
|
395
395
|
ref={triggerRef as RefObject<HTMLButtonElement>}
|
|
396
396
|
onClick={() => setIsOpen(!isOpen)}
|
|
397
397
|
aria-expanded={isOpen}
|
|
398
|
+
// Filters applied: the trigger holds the accent. Otherwise the secondary text, the primary on hover.
|
|
399
|
+
data-state={getActiveFiltersCount() > 0 ? 'active' : undefined}
|
|
400
|
+
data-tone="neutral"
|
|
398
401
|
>
|
|
399
402
|
<span className="text-h5">{triggerLabel}</span>
|
|
400
|
-
{getActiveFiltersCount() > 0 && <span className="size-1.5 rounded-full bg-ods-accent" />}
|
|
401
403
|
</Button>
|
|
402
404
|
)}
|
|
403
405
|
|
|
@@ -435,6 +437,7 @@ export const FiltersDropdown: FC<FiltersDropdownProps> = ({
|
|
|
435
437
|
variant="link"
|
|
436
438
|
size="compact"
|
|
437
439
|
noPaddingX
|
|
440
|
+
data-tone="neutral"
|
|
438
441
|
onClick={() => handleSelectAll(section.id, section)}
|
|
439
442
|
>
|
|
440
443
|
{allSelected ? 'Deselect All' : 'Select All'}
|
|
@@ -461,6 +464,8 @@ export const FiltersDropdown: FC<FiltersDropdownProps> = ({
|
|
|
461
464
|
key={`${section.id}-${option.id}-${index}`}
|
|
462
465
|
onClick={() => handleToggleOption(section.id, option.id, section.type)}
|
|
463
466
|
data-state={isSelected ? 'active' : undefined}
|
|
467
|
+
// A checked option sits on the raised surface; the hover still shows over it.
|
|
468
|
+
data-tone="surface"
|
|
464
469
|
>
|
|
465
470
|
<FilterCheckbox checked={isSelected} />
|
|
466
471
|
<span
|
|
@@ -131,7 +131,7 @@ export function PathsDisplay({
|
|
|
131
131
|
<span className="min-w-0 flex-1 truncate text-ods-text-primary text-h4">{path}</span>
|
|
132
132
|
{showCopyButtons && onCopyPath && (
|
|
133
133
|
<Button
|
|
134
|
-
variant="
|
|
134
|
+
variant="bare"
|
|
135
135
|
size="icon-sm"
|
|
136
136
|
type="button"
|
|
137
137
|
onClick={() => onCopyPath(path)}
|
|
@@ -35,6 +35,8 @@ export function RemoteSessionEventList({ events, activeEventId, onSelect, classN
|
|
|
35
35
|
type="button"
|
|
36
36
|
aria-current={event.id === activeEventId || undefined}
|
|
37
37
|
data-state={event.id === activeEventId ? 'active' : undefined}
|
|
38
|
+
// The current event holds the border-grey fill under the cursor.
|
|
39
|
+
data-tone="muted"
|
|
38
40
|
onClick={() => onSelect?.(event)}
|
|
39
41
|
className="items-start"
|
|
40
42
|
>
|
|
@@ -41,13 +41,13 @@ export const SelectButton = React.forwardRef<HTMLButtonElement, SelectButtonProp
|
|
|
41
41
|
) => {
|
|
42
42
|
return (
|
|
43
43
|
<Button
|
|
44
|
-
// A selectable option drawn as a field:
|
|
44
|
+
// A selectable option drawn as a field: the picked one (`aria-selected`) takes the accent border on the
|
|
45
|
+
// accent's light fill.
|
|
45
46
|
variant="field"
|
|
46
47
|
ref={ref}
|
|
47
48
|
type="button"
|
|
48
49
|
role="option"
|
|
49
50
|
aria-selected={selected}
|
|
50
|
-
data-state={selected ? 'open' : undefined}
|
|
51
51
|
disabled={disabled}
|
|
52
52
|
onClick={onClick}
|
|
53
53
|
className={cn('content-md:h-16', className)}
|
|
@@ -49,10 +49,13 @@ export function LoadingRegion({
|
|
|
49
49
|
const announce = announceGiven && !inScope;
|
|
50
50
|
// One tree for both states: `children` keeps its slot whether or not the status is drawn, so an
|
|
51
51
|
// `announce` that flips at runtime does not remount the content (and drop its state and focus).
|
|
52
|
+
// The status comes AFTER the content: it takes no space (visually hidden, absolutely positioned), but placed first
|
|
53
|
+
// in a `space-y-*` stack it made the content the second child, which takes the stack's top margin, so a region
|
|
54
|
+
// that announced stood a gap taller than the same region inside a loading scope (a jump at hydration).
|
|
52
55
|
return (
|
|
53
56
|
<Tag aria-busy={announce ? 'true' : undefined} className={className} {...props}>
|
|
54
|
-
{announce && status && <LoadingStatus label={label} />}
|
|
55
57
|
{children}
|
|
58
|
+
{announce && status && <LoadingStatus label={label} />}
|
|
56
59
|
</Tag>
|
|
57
60
|
);
|
|
58
61
|
}
|
|
@@ -83,6 +83,8 @@ export const MobileBurgerMenu = React.memo(function MobileBurgerMenuImpl({
|
|
|
83
83
|
onClick={() => handleItemClick(item)}
|
|
84
84
|
disabled={disabled}
|
|
85
85
|
data-state={isActive && !disabled ? 'active' : undefined}
|
|
86
|
+
// Every entry is a bordered card; the current page's takes the accent border.
|
|
87
|
+
data-tone="framed"
|
|
86
88
|
className={isGridItem ? 'min-w-0' : undefined}
|
|
87
89
|
aria-current={isActive ? 'page' : undefined}
|
|
88
90
|
// The same name the sidebar row announces — "Scripts (Beta)" — rather than
|
|
@@ -239,7 +241,7 @@ export const MobileBurgerMenu = React.memo(function MobileBurgerMenuImpl({
|
|
|
239
241
|
|
|
240
242
|
{/* Logout Button */}
|
|
241
243
|
{onLogout && (
|
|
242
|
-
<Button variant="row" onClick={onLogout} disabled={disabled}>
|
|
244
|
+
<Button variant="row" data-tone="framed" onClick={onLogout} disabled={disabled}>
|
|
243
245
|
<Logout02Icon className="size-4 text-ods-error" />
|
|
244
246
|
<span className="flex-1 text-left text-ods-text-primary text-h6">Log Out</span>
|
|
245
247
|
</Button>
|
|
@@ -270,6 +270,8 @@ function NavigationItem({
|
|
|
270
270
|
<Button
|
|
271
271
|
variant="row"
|
|
272
272
|
data-state={isSelected ? 'active' : undefined}
|
|
273
|
+
// The open page holds its line's border-grey fill: no hover over it.
|
|
274
|
+
data-tone="muted"
|
|
273
275
|
className={cn(NAV_ROW_LAYOUT_CLASS, NAV_ROW_HEIGHT.desktop)}
|
|
274
276
|
onClick={() => onNodeClick(node)}
|
|
275
277
|
aria-label={`${isSelected ? 'Selected' : 'Select'} ${node.name}`}
|
|
@@ -297,7 +299,7 @@ function NavigationItem({
|
|
|
297
299
|
|
|
298
300
|
{hasChildren && (
|
|
299
301
|
<Button
|
|
300
|
-
variant="
|
|
302
|
+
variant="bare"
|
|
301
303
|
size="icon-sm"
|
|
302
304
|
className="mr-[var(--spacing-system-xxs)] shrink-0"
|
|
303
305
|
onClick={e => {
|
|
@@ -399,6 +401,8 @@ function MobileNavigationItem({
|
|
|
399
401
|
<Button
|
|
400
402
|
variant="row"
|
|
401
403
|
data-state={isSelected ? 'active' : undefined}
|
|
404
|
+
// The open page holds its line's border-grey fill: no hover over it.
|
|
405
|
+
data-tone="muted"
|
|
402
406
|
className={cn(NAV_ROW_LAYOUT_CLASS, NAV_ROW_HEIGHT.mobile)}
|
|
403
407
|
onClick={() => onNodeClick(node)}
|
|
404
408
|
>
|
|
@@ -425,7 +429,7 @@ function MobileNavigationItem({
|
|
|
425
429
|
|
|
426
430
|
{hasChildren && (
|
|
427
431
|
<Button
|
|
428
|
-
variant="
|
|
432
|
+
variant="bare"
|
|
429
433
|
size="icon-sm"
|
|
430
434
|
className="mr-[var(--spacing-system-xxs)] shrink-0"
|
|
431
435
|
onClick={e => {
|
|
@@ -10,7 +10,7 @@ import { useLoadingScope } from '../ui/loading-scope';
|
|
|
10
10
|
import { NavigationItemBadge } from './navigation-item-badge';
|
|
11
11
|
import { UnreadDot } from './unread-dot';
|
|
12
12
|
|
|
13
|
-
/** A sidebar row's height: the loaded row (a `
|
|
13
|
+
/** A sidebar row's height: the loaded row (a `rail` button or link) and its loading form are one box. */
|
|
14
14
|
const NAV_SIDEBAR_ROW_LAYOUT_CLASS = 'h-14';
|
|
15
15
|
|
|
16
16
|
interface IconProps {
|
|
@@ -118,7 +118,7 @@ function LoadedNavigationSidebarItemButton({
|
|
|
118
118
|
// A row whose route is still committing: announced, never drawn as the current page.
|
|
119
119
|
'aria-busy': isPending || undefined,
|
|
120
120
|
};
|
|
121
|
-
// The current page's
|
|
121
|
+
// The current page's entry: the rail kind's accent fill, text and bar (`aria-busy` above holds its hover wash).
|
|
122
122
|
const rowState = isActive && !disabled ? 'active' : undefined;
|
|
123
123
|
|
|
124
124
|
// An entry with a custom onClick has no destination of its own, and a
|
|
@@ -126,7 +126,7 @@ function LoadedNavigationSidebarItemButton({
|
|
|
126
126
|
if (disabled || !item.path || item.onClick) {
|
|
127
127
|
return (
|
|
128
128
|
<Button
|
|
129
|
-
variant="
|
|
129
|
+
variant="rail"
|
|
130
130
|
type="button"
|
|
131
131
|
onClick={event => onClick(item, event)}
|
|
132
132
|
disabled={disabled}
|
|
@@ -140,7 +140,7 @@ function LoadedNavigationSidebarItemButton({
|
|
|
140
140
|
}
|
|
141
141
|
|
|
142
142
|
return (
|
|
143
|
-
<Button asChild variant="
|
|
143
|
+
<Button asChild variant="rail" data-state={rowState} className={NAV_SIDEBAR_ROW_LAYOUT_CLASS}>
|
|
144
144
|
<Link href={item.path} onClick={event => onClick(item, event)} {...shared}>
|
|
145
145
|
{content}
|
|
146
146
|
</Link>
|
|
@@ -160,7 +160,7 @@ function LoadedNavigationSidebarItemButton({
|
|
|
160
160
|
*/
|
|
161
161
|
function NavigationSidebarItemSkeleton({ showLabel }: { showLabel: boolean }) {
|
|
162
162
|
return (
|
|
163
|
-
<div className={cn(BUTTON_KIND_CLASS.
|
|
163
|
+
<div className={cn(BUTTON_KIND_CLASS.rail, NAV_SIDEBAR_ROW_LAYOUT_CLASS)} aria-hidden="true">
|
|
164
164
|
<div className="relative flex flex-shrink-0 items-center justify-center">
|
|
165
165
|
<UnifiedSkeleton className="h-6 w-6 rounded" />
|
|
166
166
|
</div>
|
|
@@ -6,8 +6,9 @@
|
|
|
6
6
|
export const buttonSurfaceClasses = {
|
|
7
7
|
accent:
|
|
8
8
|
'bg-ods-accent text-ods-text-on-accent hover:bg-ods-accent-hover active:bg-ods-accent-active disabled:bg-ods-disabled aria-disabled:bg-ods-disabled',
|
|
9
|
+
// `data-tone="accent"`: the accent fill on hover (a card's "view" action).
|
|
9
10
|
outline:
|
|
10
|
-
'bg-ods-card text-ods-text-primary hover:bg-ods-bg-hover active:bg-ods-bg-active disabled:bg-ods-card disabled:text-ods-text-disabled aria-disabled:bg-ods-card aria-disabled:text-ods-text-disabled',
|
|
11
|
+
'bg-ods-card text-ods-text-primary hover:bg-ods-bg-hover active:bg-ods-bg-active disabled:bg-ods-card disabled:text-ods-text-disabled aria-disabled:bg-ods-card aria-disabled:text-ods-text-disabled data-[tone=accent]:hover:bg-ods-accent',
|
|
11
12
|
transparent:
|
|
12
13
|
'bg-transparent text-ods-text-primary hover:bg-ods-bg-hover active:bg-ods-bg-active disabled:bg-transparent disabled:text-ods-text-disabled aria-disabled:bg-transparent aria-disabled:text-ods-text-disabled',
|
|
13
14
|
destructive:
|
|
@@ -31,7 +32,39 @@ export const buttonSurfaceClasses = {
|
|
|
31
32
|
// hover, and no surface in any state. Promoted to a variant because the
|
|
32
33
|
// disclosure toggle was a primitive <button> restating these classes. Pair
|
|
33
34
|
// with size="compact" and noPaddingX so the label aligns with the text above.
|
|
34
|
-
|
|
35
|
+
//
|
|
36
|
+
// States, from the element's attributes: `data-state="active"` holds the accent (a filter trigger with filters
|
|
37
|
+
// applied). `data-tone="neutral"` takes the primary text on hover instead of the accent (a secondary text action:
|
|
38
|
+
// "Select all", "Mark all read"); `data-tone="primary"` sits in the primary text and takes the accent on hover (a
|
|
39
|
+
// value that opens something: an info row's link, a breadcrumb).
|
|
40
|
+
link: [
|
|
41
|
+
'bg-transparent text-ods-text-secondary hover:bg-transparent hover:text-ods-accent active:bg-transparent active:text-ods-accent-active disabled:bg-transparent disabled:text-ods-text-disabled aria-disabled:bg-transparent aria-disabled:text-ods-text-disabled',
|
|
42
|
+
'data-[tone=neutral]:hover:text-ods-text-primary',
|
|
43
|
+
'data-[tone=primary]:text-ods-text-primary data-[tone=primary]:hover:text-ods-accent',
|
|
44
|
+
'data-[state=active]:text-ods-accent data-[state=active]:hover:text-ods-accent data-[tone=neutral]:data-[state=active]:hover:text-ods-accent',
|
|
45
|
+
].join(' '),
|
|
46
|
+
// A bare glyph control with no surface (a composer's send / add-context, a copy, a close, a field's clear): the
|
|
47
|
+
// secondary text, the primary on hover and keyboard focus, faded when disabled. Distinct from `transparent`, which
|
|
48
|
+
// is primary text on a hover fill. States, from the element's attributes:
|
|
49
|
+
// - `aria-expanded="true"`: its popup is open, the glyph stays lit (primary);
|
|
50
|
+
// - `data-state="active"`: the glyph is armed (the composer's send while the editor has focus), the accent;
|
|
51
|
+
// - `data-tone="accent"`: a trigger that opens and presses in the accent (the composer's add-context);
|
|
52
|
+
// - `data-tone="danger"`: a removal that takes the error colour on hover;
|
|
53
|
+
// - `data-tone="error"` / `data-tone="success"`: a glyph drawn in that colour (an error's copy, a done state),
|
|
54
|
+
// dimmed on hover;
|
|
55
|
+
// - `data-tone="field"`: a field's adornment, lit in the accent while the field (the enclosing `group`) has focus
|
|
56
|
+
// and in the error colour while it is invalid (`data-invalid` on the group).
|
|
57
|
+
bare: [
|
|
58
|
+
'bg-transparent text-ods-text-secondary outline-none hover:bg-transparent hover:text-ods-text-primary focus-visible:text-ods-text-primary active:bg-transparent',
|
|
59
|
+
'aria-expanded:text-ods-text-primary',
|
|
60
|
+
'data-[state=active]:text-ods-accent',
|
|
61
|
+
'data-[tone=accent]:aria-expanded:text-ods-accent data-[tone=accent]:active:text-ods-accent',
|
|
62
|
+
'data-[tone=danger]:hover:text-ods-error',
|
|
63
|
+
'data-[tone=error]:text-ods-error data-[tone=error]:hover:text-ods-error data-[tone=error]:hover:opacity-80',
|
|
64
|
+
'data-[tone=success]:text-ods-success data-[tone=success]:hover:text-ods-success data-[tone=success]:hover:opacity-80',
|
|
65
|
+
'data-[tone=field]:group-has-[textarea:focus]:text-ods-accent data-[tone=field]:focus-visible:text-ods-accent data-[tone=field]:group-data-[invalid]:text-ods-error',
|
|
66
|
+
'disabled:cursor-not-allowed disabled:bg-transparent disabled:opacity-40 disabled:hover:text-ods-text-secondary aria-disabled:opacity-40',
|
|
67
|
+
].join(' '),
|
|
35
68
|
// Chrome that sits ON media (video cards, image lightboxes): a scrim disc so
|
|
36
69
|
// the glyph stays legible over an arbitrary frame. Promoted to a variant
|
|
37
70
|
// because the walkthrough card, its theater and the bite cards were each
|
|
@@ -138,9 +171,14 @@ const KIND_FOCUS_INSET =
|
|
|
138
171
|
* - `data-state="active"` (Radix's convention): the selected row, tab or chip;
|
|
139
172
|
* - `data-state="open"` / `aria-expanded="true"`: the field whose popup is open;
|
|
140
173
|
* - `data-invalid`: the field that failed validation (the marker every field exposes);
|
|
141
|
-
* - `aria-pressed="true"`: the pressed chip
|
|
174
|
+
* - `aria-pressed="true"`: the pressed chip;
|
|
175
|
+
* - `aria-selected="true"`: the chosen field (a choice drawn as a field);
|
|
176
|
+
* - `aria-busy="true"`: the rail entry whose route is committing.
|
|
177
|
+
*
|
|
178
|
+
* Where a kind has a second look for the same state (a selected row marked with the accent rather than the hover
|
|
179
|
+
* surface, the segmented control's accent segment), the control names it with `data-tone`, declared on the kind below.
|
|
142
180
|
*
|
|
143
|
-
* A call site's `className` on a kind is layout only (width, flex, position, margin).
|
|
181
|
+
* A call site's `className` on a kind is layout only (width, flex, position, margin): never a colour.
|
|
144
182
|
*/
|
|
145
183
|
export const BUTTON_KIND_CLASS = {
|
|
146
184
|
// A control drawn as a form field (a date picker's, a searchable select's, a popup's trigger): Input's box, border
|
|
@@ -150,22 +188,62 @@ export const BUTTON_KIND_CLASS = {
|
|
|
150
188
|
'h-11 rounded-[6px] md:h-12',
|
|
151
189
|
'border-ods-border bg-ods-card text-ods-text-primary text-h4 transition-colors duration-200',
|
|
152
190
|
'enabled:hover:border-ods-border-hover enabled:hover:bg-ods-bg-hover enabled:active:border-ods-border-active enabled:active:bg-ods-bg-active',
|
|
191
|
+
// Open: the accent border, held under the cursor (a hover must not read as closing it).
|
|
153
192
|
'data-[state=open]:border-ods-accent aria-expanded:border-ods-accent',
|
|
154
|
-
'data-[
|
|
193
|
+
'enabled:data-[state=open]:hover:border-ods-accent enabled:aria-expanded:hover:border-ods-accent',
|
|
194
|
+
// Selected (a choice drawn as a field, `aria-selected="true"`): the accent border on the accent's light fill,
|
|
195
|
+
// whose hover and press are the fill's own steps.
|
|
196
|
+
'aria-selected:border-ods-accent aria-selected:bg-ods-open-yellow-light',
|
|
197
|
+
'enabled:aria-selected:hover:border-ods-accent enabled:aria-selected:hover:bg-ods-open-yellow-light-hover',
|
|
198
|
+
'enabled:aria-selected:active:border-ods-accent enabled:aria-selected:active:bg-ods-open-yellow-light-action',
|
|
199
|
+
// Invalid wins over open.
|
|
200
|
+
'data-[invalid]:border-ods-error enabled:data-[invalid]:hover:border-ods-error enabled:data-[invalid]:active:border-ods-error',
|
|
201
|
+
'data-[invalid]:data-[state=open]:border-ods-error data-[invalid]:aria-expanded:border-ods-error',
|
|
202
|
+
'enabled:data-[invalid]:data-[state=open]:hover:border-ods-error enabled:data-[invalid]:aria-expanded:hover:border-ods-error',
|
|
155
203
|
'disabled:cursor-not-allowed disabled:bg-ods-bg disabled:text-ods-text-disabled disabled:[&_svg]:text-ods-text-disabled',
|
|
156
204
|
'outline-none focus-visible:border-ods-accent',
|
|
157
205
|
'[&_svg]:shrink-0',
|
|
158
206
|
].join(' '),
|
|
159
207
|
// A clickable row of a list, a menu or a navigation: full width, its content on the left, the hover and the
|
|
160
|
-
// selected surface of the list.
|
|
208
|
+
// selected surface of the list. The selected row (`data-state="active"`) takes the hover surface; a list that marks
|
|
209
|
+
// its selection differently names its look with `data-tone` (the attribute, on the row and on its skeleton):
|
|
210
|
+
// - `accent`: the accent's secondary fill, no hover surface (a chat list's open conversation);
|
|
211
|
+
// - `link`: the accent text, no surface at all (a chat rail's navigation entries);
|
|
212
|
+
// - `surface`: the raised surface, the hover still showing over it (a filter dropdown's checked option);
|
|
213
|
+
// - `muted`: the border-grey fill, held under the cursor (a timeline's current event, a docs tree's open page);
|
|
214
|
+
// - `card`: a card with its border, no hover over it; idle rows keep a transparent border (a capability list);
|
|
215
|
+
// - `framed`: every row a bordered card, the selected one with the accent border (the mobile menu's entries).
|
|
161
216
|
row: [
|
|
162
217
|
'flex w-full items-center gap-[var(--spacing-system-s)] rounded-md px-[var(--spacing-system-m)] py-[var(--spacing-system-s)] text-left',
|
|
163
218
|
'bg-transparent text-ods-text-primary text-h4 transition-colors duration-150',
|
|
164
|
-
'hover:bg-ods-bg-hover active:bg-ods-bg-active data-[state=active]:bg-ods-bg-
|
|
219
|
+
'hover:bg-ods-bg-hover active:bg-ods-bg-active data-[state=active]:bg-ods-bg-hover',
|
|
220
|
+
'data-[tone=accent]:hover:bg-transparent data-[tone=accent]:active:bg-transparent',
|
|
221
|
+
'data-[tone=accent]:data-[state=active]:bg-ods-accent-secondary data-[tone=accent]:data-[state=active]:hover:bg-ods-accent-secondary data-[tone=accent]:data-[state=active]:active:bg-ods-accent-secondary',
|
|
222
|
+
'data-[tone=link]:hover:bg-transparent data-[tone=link]:active:bg-transparent data-[tone=link]:data-[state=active]:bg-transparent data-[tone=link]:data-[state=active]:text-ods-accent',
|
|
223
|
+
'data-[tone=surface]:data-[state=active]:bg-ods-bg-surface data-[tone=surface]:data-[state=active]:hover:bg-ods-bg-hover',
|
|
224
|
+
'data-[tone=muted]:data-[state=active]:bg-ods-border',
|
|
225
|
+
'data-[tone=card]:border data-[tone=card]:border-transparent data-[tone=card]:data-[state=active]:border-ods-border data-[tone=card]:data-[state=active]:bg-ods-card',
|
|
226
|
+
'data-[tone=framed]:border data-[tone=framed]:border-ods-border data-[tone=framed]:bg-ods-card data-[tone=framed]:data-[state=active]:border-ods-accent data-[tone=framed]:data-[state=active]:bg-ods-card data-[tone=framed]:data-[state=active]:hover:bg-ods-bg-hover',
|
|
165
227
|
'disabled:cursor-not-allowed disabled:text-ods-text-disabled disabled:hover:bg-transparent',
|
|
166
228
|
KIND_FOCUS_INSET,
|
|
167
229
|
'[&_svg]:shrink-0',
|
|
168
230
|
].join(' '),
|
|
231
|
+
// A navigation rail's entry (the app sidebar): the row's box with the rail's two layers. The hover is a wash on its
|
|
232
|
+
// own layer (`::after`), so it can fade while the current page switches in a single frame: the current page's entry
|
|
233
|
+
// (`data-state="active"`) takes the accent's light fill, the accent text and glyphs and the accent bar on its leading
|
|
234
|
+
// edge (`::before`). An entry whose route is still committing (`aria-busy="true"`) holds the hover wash and nothing
|
|
235
|
+
// else.
|
|
236
|
+
rail: [
|
|
237
|
+
'relative isolate flex w-full items-center justify-start gap-[var(--spacing-system-s)] px-[var(--spacing-system-m)] py-[var(--spacing-system-s)] text-left',
|
|
238
|
+
'bg-transparent text-ods-text-primary text-h4 [&_svg]:fill-ods-text-secondary',
|
|
239
|
+
"after:pointer-events-none after:absolute after:inset-0 after:-z-10 after:bg-ods-bg-hover after:opacity-0 after:transition-opacity after:duration-150 after:content-['']",
|
|
240
|
+
"before:absolute before:bottom-0 before:left-0 before:top-0 before:w-1 before:content-['']",
|
|
241
|
+
'hover:after:opacity-100 aria-busy:after:opacity-100',
|
|
242
|
+
'data-[state=active]:bg-ods-open-yellow-light data-[state=active]:text-ods-accent data-[state=active]:[&_svg]:fill-ods-accent data-[state=active]:before:bg-ods-accent data-[state=active]:after:opacity-0',
|
|
243
|
+
'disabled:cursor-not-allowed disabled:text-ods-text-secondary disabled:opacity-50 disabled:after:opacity-0',
|
|
244
|
+
KIND_FOCUS_INSET,
|
|
245
|
+
'[&_svg]:shrink-0',
|
|
246
|
+
].join(' '),
|
|
169
247
|
// A tab of a tab strip or a tab list: secondary until it is the open one. A strip that marks its open and hovered
|
|
170
248
|
// tab with the accent fade (the admin strip) says so on each tab with `data-emphasis="fade"`. ODS colour vars hold
|
|
171
249
|
// hex values, so a Tailwind alpha modifier would produce no CSS; color-mix() derives the 10% stop from the token.
|
|
@@ -179,12 +257,29 @@ export const BUTTON_KIND_CLASS = {
|
|
|
179
257
|
KIND_FOCUS_INSET,
|
|
180
258
|
'[&_svg]:shrink-0',
|
|
181
259
|
].join(' '),
|
|
260
|
+
// A segment of a segmented control (`TabSelector`): the label on the strip, a hover fill, and the selected segment
|
|
261
|
+
// (`data-state="active"`) filled with the raised surface; `data-tone="accent"` fills it with the accent instead. A
|
|
262
|
+
// disabled selected segment keeps the raised surface with secondary text.
|
|
263
|
+
segment: [
|
|
264
|
+
'flex items-center justify-center gap-[var(--spacing-system-xs)] whitespace-nowrap rounded-xs p-[var(--spacing-system-xsf)]',
|
|
265
|
+
'bg-transparent text-ods-text-primary text-h4 transition-colors duration-200',
|
|
266
|
+
'hover:bg-ods-bg-hover',
|
|
267
|
+
'data-[state=active]:cursor-default data-[state=active]:bg-ods-bg-surface data-[state=active]:text-ods-text-primary data-[state=active]:hover:bg-ods-bg-surface',
|
|
268
|
+
'data-[tone=accent]:data-[state=active]:bg-ods-accent data-[tone=accent]:data-[state=active]:text-ods-text-on-accent data-[tone=accent]:data-[state=active]:hover:bg-ods-accent',
|
|
269
|
+
'disabled:cursor-not-allowed disabled:bg-transparent disabled:text-ods-text-secondary disabled:hover:bg-transparent',
|
|
270
|
+
'disabled:data-[state=active]:bg-ods-bg-surface disabled:data-[state=active]:text-ods-text-secondary disabled:data-[state=active]:hover:bg-ods-bg-surface',
|
|
271
|
+
'disabled:data-[tone=accent]:data-[state=active]:bg-ods-bg-surface disabled:data-[tone=accent]:data-[state=active]:text-ods-text-secondary disabled:data-[tone=accent]:data-[state=active]:hover:bg-ods-bg-surface',
|
|
272
|
+
KIND_FOCUS_INSET,
|
|
273
|
+
'[&_svg]:shrink-0',
|
|
274
|
+
].join(' '),
|
|
182
275
|
// A choice drawn as a pill (a filter, a quick question, an answer option): bordered, the accent when picked.
|
|
183
276
|
chip: [
|
|
184
277
|
'inline-flex h-8 items-center gap-[var(--spacing-system-xxs)] rounded-full border px-[var(--spacing-system-sf)]',
|
|
185
278
|
'border-ods-border bg-ods-card text-ods-text-primary text-h6 transition-colors duration-200',
|
|
186
279
|
'hover:border-ods-border-hover hover:bg-ods-bg-hover',
|
|
187
280
|
'aria-pressed:border-ods-accent data-[state=active]:border-ods-accent',
|
|
281
|
+
// `data-tone="accent"`: a pill that links somewhere takes the accent border on hover (a vendor pill).
|
|
282
|
+
'data-[tone=accent]:hover:border-ods-accent',
|
|
188
283
|
'disabled:cursor-not-allowed disabled:text-ods-text-disabled disabled:hover:bg-ods-card',
|
|
189
284
|
KIND_FOCUS,
|
|
190
285
|
'[&_svg]:h-4 [&_svg]:w-4 [&_svg]:shrink-0',
|
|
@@ -193,11 +288,13 @@ export const BUTTON_KIND_CLASS = {
|
|
|
193
288
|
// content is the look; the button gives it the click, the keyboard and the focus ring.
|
|
194
289
|
card: ['relative block w-full rounded-md text-left text-ods-text-primary', KIND_FOCUS].join(' '),
|
|
195
290
|
// A cell of a bar (a header's or a chat's top bar): the bar's full height, an icon or a short label, secondary
|
|
196
|
-
// until hovered
|
|
291
|
+
// until hovered. The current cell (`data-state="active"`: the header's open section) takes the pressed surface and
|
|
292
|
+
// the primary text.
|
|
197
293
|
cell: [
|
|
198
294
|
'flex h-full shrink-0 items-center justify-center gap-[var(--spacing-system-xsf)] px-[var(--spacing-system-m)]',
|
|
199
295
|
'bg-transparent text-ods-text-secondary text-h4 transition-colors duration-200',
|
|
200
|
-
'hover:bg-ods-bg-hover hover:text-ods-text-primary aria-
|
|
296
|
+
'hover:bg-ods-bg-hover hover:text-ods-text-primary aria-expanded:text-ods-text-primary',
|
|
297
|
+
'data-[state=active]:bg-ods-bg-active data-[state=active]:text-ods-text-primary',
|
|
201
298
|
KIND_FOCUS_INSET,
|
|
202
299
|
'[&_svg]:h-6 [&_svg]:w-6 [&_svg]:shrink-0',
|
|
203
300
|
].join(' '),
|
|
@@ -41,11 +41,14 @@ const buttonVariants = cva(
|
|
|
41
41
|
glyph: buttonSurfaceClasses.glyph,
|
|
42
42
|
overlay: buttonSurfaceClasses.overlay,
|
|
43
43
|
link: buttonSurfaceClasses.link,
|
|
44
|
+
bare: buttonSurfaceClasses.bare,
|
|
44
45
|
// The kinds that are not a plain push button own their whole box (`BUTTON_KIND_CLASS`); resolved
|
|
45
46
|
// before this map is read, so `size` never reaches them. The entries only type the prop.
|
|
46
47
|
field: '',
|
|
47
48
|
row: '',
|
|
49
|
+
rail: '',
|
|
48
50
|
tab: '',
|
|
51
|
+
segment: '',
|
|
49
52
|
chip: '',
|
|
50
53
|
card: '',
|
|
51
54
|
cell: '',
|
|
@@ -17,6 +17,7 @@ export function FileManagerBreadcrumb({ items, onItemClick, className }: FileMan
|
|
|
17
17
|
size="compact"
|
|
18
18
|
noPaddingX
|
|
19
19
|
type="button"
|
|
20
|
+
data-tone="primary"
|
|
20
21
|
aria-current={index === items.length - 1 ? 'page' : undefined}
|
|
21
22
|
onClick={() => onItemClick?.(item.path)}
|
|
22
23
|
className="shrink-0"
|
|
@@ -417,7 +417,7 @@ export function FileUpload<T extends FileUploadCandidate = File>({
|
|
|
417
417
|
</div>
|
|
418
418
|
{onDownloadManagedFile && entry.status === 'uploaded' && (
|
|
419
419
|
<Button
|
|
420
|
-
variant="
|
|
420
|
+
variant="bare"
|
|
421
421
|
size="icon-sm"
|
|
422
422
|
type="button"
|
|
423
423
|
onClick={() => onDownloadManagedFile(entry.id)}
|
|
@@ -429,7 +429,8 @@ export function FileUpload<T extends FileUploadCandidate = File>({
|
|
|
429
429
|
)}
|
|
430
430
|
{!disabled && (
|
|
431
431
|
<Button
|
|
432
|
-
variant="
|
|
432
|
+
variant="bare"
|
|
433
|
+
data-tone="error"
|
|
433
434
|
size="icon-sm"
|
|
434
435
|
type="button"
|
|
435
436
|
onClick={() => onRemoveManagedFile?.(entry.id)}
|
|
@@ -457,7 +458,8 @@ export function FileUpload<T extends FileUploadCandidate = File>({
|
|
|
457
458
|
</div>
|
|
458
459
|
{!disabled && (
|
|
459
460
|
<Button
|
|
460
|
-
variant="
|
|
461
|
+
variant="bare"
|
|
462
|
+
data-tone="error"
|
|
461
463
|
size="icon-sm"
|
|
462
464
|
type="button"
|
|
463
465
|
onClick={() => handleRemoveFile(index)}
|
|
@@ -87,6 +87,8 @@ function TextValue({ value }: { value: InfoSectionTextValue }) {
|
|
|
87
87
|
size="compact"
|
|
88
88
|
noPaddingX
|
|
89
89
|
type="button"
|
|
90
|
+
// The value reads in the primary text and takes the accent on hover.
|
|
91
|
+
data-tone="primary"
|
|
90
92
|
href={href}
|
|
91
93
|
openInNewTab={openInNewTab}
|
|
92
94
|
onClick={href ? undefined : onClick}
|
|
@@ -121,12 +121,13 @@ export function AnnouncedLoadingScope({
|
|
|
121
121
|
children: ReactNode;
|
|
122
122
|
}) {
|
|
123
123
|
const outer = useLoadingScope();
|
|
124
|
+
// The status follows the content, so in a `space-y-*` stack it never pushes the content down (see LoadingRegion).
|
|
124
125
|
return (
|
|
125
126
|
<>
|
|
126
|
-
{status && active && !outer && <LoadingStatus label={label} />}
|
|
127
127
|
<LoadingScope active={active} as={as} className={className}>
|
|
128
128
|
{children}
|
|
129
129
|
</LoadingScope>
|
|
130
|
+
{status && active && !outer && <LoadingStatus label={label} />}
|
|
130
131
|
</>
|
|
131
132
|
);
|
|
132
133
|
}
|
|
@@ -376,7 +376,7 @@ const ModalHeader = forwardRef<HTMLDivElement, ModalHeaderProps>(({ children, cl
|
|
|
376
376
|
<div className="flex min-w-0 flex-1 flex-col">{children}</div>
|
|
377
377
|
{onClose && (
|
|
378
378
|
<Button
|
|
379
|
-
variant="
|
|
379
|
+
variant="bare"
|
|
380
380
|
size="icon-sm"
|
|
381
381
|
type="button"
|
|
382
382
|
onClick={onClose}
|