@mediaradar/design-components 0.10.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +4 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +111 -5
- package/dist/index.d.ts +111 -5
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -17,6 +17,9 @@ import { VariantProps } from 'class-variance-authority';
|
|
|
17
17
|
* not just a decorative hover effect. Both modes close on Escape and on any
|
|
18
18
|
* outside click. The bubble is portaled to document.body and repositions
|
|
19
19
|
* itself to stay clear of the right viewport edge.
|
|
20
|
+
* @a11y The trigger is a <button> reporting aria-expanded; the bubble is
|
|
21
|
+
* role="tooltip" and Escape dismisses it. It describes its anchor rather
|
|
22
|
+
* than naming it, so the anchor still needs its own accessible name.
|
|
20
23
|
* @usage
|
|
21
24
|
* ```tsx
|
|
22
25
|
* <InfoTip text="Trims time periods to data that has finalized across the selected media formats." />
|
|
@@ -61,6 +64,10 @@ declare function InfoTip({ text, size, label, trigger }: InfoTipProps): react.JS
|
|
|
61
64
|
* other close path discards the draft, so the trigger label never previews
|
|
62
65
|
* an unapplied change. The pinned "selected" section persists across
|
|
63
66
|
* searches and collapses when the search is cleared.
|
|
67
|
+
* @a11y Trigger is a <button> with aria-expanded and aria-haspopup; the menu is
|
|
68
|
+
* role="dialog", closed on Escape. Option rows are role="checkbox" with
|
|
69
|
+
* aria-checked, so each row is itself the control -- don't wrap them in
|
|
70
|
+
* another clickable element.
|
|
64
71
|
* @usage
|
|
65
72
|
* ```tsx
|
|
66
73
|
* <AdvertiserQuickFilter options={advertisers} selected={selected} onChange={setSelected} />
|
|
@@ -159,6 +166,13 @@ declare function AdvertiserSearchPrompt({ label }: AdvertiserSearchPromptProps):
|
|
|
159
166
|
* `stopPropagation` before firing `onChange` by default, so nesting this
|
|
160
167
|
* inside a row that toggles on its own click can't fire the toggle twice;
|
|
161
168
|
* pass `stopPropagation={false}` where the row should also see the click.
|
|
169
|
+
* @a11y The <button> itself carries role="checkbox" and aria-checked ("mixed"
|
|
170
|
+
* when indeterminate), so it IS the control -- never nest it inside
|
|
171
|
+
* another button or a row that is itself clickable. `ariaLabel` is
|
|
172
|
+
* required because the box renders no text. Where the whole row should be
|
|
173
|
+
* the control, use CheckBoxBox inside your own <button role="checkbox">
|
|
174
|
+
* instead: a <button> inside a <button> is invalid markup, and a <div
|
|
175
|
+
* onClick> wrapper is not keyboard-reachable at all.
|
|
162
176
|
* @usage
|
|
163
177
|
* ```tsx
|
|
164
178
|
* <CheckBox checked={selected} ariaLabel="Select row" onChange={toggle} />
|
|
@@ -221,6 +235,10 @@ declare function CheckBox({ checked, indeterminate, onChange, ariaLabel, disable
|
|
|
221
235
|
* the control has no correct option: nesting the interactive `CheckBox`
|
|
222
236
|
* produces a button inside a button, and dropping to a `<div>` with a click
|
|
223
237
|
* handler loses keyboard access entirely.
|
|
238
|
+
* @a11y Presentational only: aria-hidden, no focus stop, no click handling. The
|
|
239
|
+
* ancestor owns role="checkbox", aria-checked, the accessible name and the
|
|
240
|
+
* click. Use it exactly when that ancestor is itself the control; use
|
|
241
|
+
* CheckBox when the box is the control.
|
|
224
242
|
* @usage
|
|
225
243
|
* ```tsx
|
|
226
244
|
* <button type="button" role="checkbox" aria-checked={on} onClick={toggle}>
|
|
@@ -257,6 +275,9 @@ declare function CheckBoxBox({ checked, indeterminate, disabled, className }: Ch
|
|
|
257
275
|
* values, so a previous unsaved edit never lingers into the next open. Only
|
|
258
276
|
* the Apply button commits -- Cancel, Escape, and outside-click all discard
|
|
259
277
|
* the draft silently.
|
|
278
|
+
* @a11y Trigger is a <button> with aria-expanded and an aria-label from the
|
|
279
|
+
* caption; the panel is role="dialog" and Escape closes it. Focus is not
|
|
280
|
+
* moved into the panel, so it is reached by tabbing.
|
|
260
281
|
* @usage
|
|
261
282
|
* ```tsx
|
|
262
283
|
* <DateRangeFilter caption="Date Range" defaultValue="Rolling 6 months" onChange={setRange} />
|
|
@@ -327,6 +348,11 @@ declare function DateRangeFilter({ caption, defaultValue, value: controlledValue
|
|
|
327
348
|
* The text input carries an `aria-label` derived from `placeholder` — the
|
|
328
349
|
* wrapping `<label>` has no visible text content (just an icon and the
|
|
329
350
|
* input), so it grants the input no accessible name on its own.
|
|
351
|
+
* @a11y The <input> takes its accessible name from `ariaLabel`. The match-mode
|
|
352
|
+
* popover is a radio group (role="radio" + aria-checked) and its trigger
|
|
353
|
+
* reports aria-expanded. Escape closes the popover only, leaving focus in
|
|
354
|
+
* the field -- a consumer nesting this inside another dismissible layer
|
|
355
|
+
* must sequence the two dismissals itself.
|
|
330
356
|
* @usage
|
|
331
357
|
* ```tsx
|
|
332
358
|
* <SearchBar value={query} onChange={setQuery} />
|
|
@@ -390,6 +416,9 @@ declare function SearchBar({ placeholder, value, onChange, variant, matchValue,
|
|
|
390
416
|
* anchor rather than a framework router Link — this package has no router
|
|
391
417
|
* peer dependency, and the two consuming apps disagree on one (react-router-dom
|
|
392
418
|
* vs next/link); a plain anchor is the one thing that works unmodified in both.
|
|
419
|
+
* @a11y Rail items are buttons and take their accessible name from `ariaLabel`,
|
|
420
|
+
* since several render icon-only. Without it they announce as unnamed
|
|
421
|
+
* buttons.
|
|
393
422
|
* @usage
|
|
394
423
|
* ```tsx
|
|
395
424
|
* <SectionRail title="Sports" subtitle="Your tracked leagues" viewAllLabel="View all" viewAllHref="/sports">
|
|
@@ -432,6 +461,10 @@ declare function SectionRail({ title, titleSerif, subtitle, viewAllLabel, viewAl
|
|
|
432
461
|
* invalid HTML that breaks click targeting (confirmed against how
|
|
433
462
|
* mr-clientapps-insights-studio's own equivalent, `ChipOption`, already
|
|
434
463
|
* avoids exactly this by rendering its InfoTip as a sibling, not a child).
|
|
464
|
+
* @a11y Trigger is a <button> with aria-expanded and aria-haspopup; the menu is
|
|
465
|
+
* role="listbox" with role="option" rows carrying aria-selected. Escape
|
|
466
|
+
* closes it. Use the listbox semantics as given -- adding a second role to
|
|
467
|
+
* the wrapper breaks the option/listbox relationship.
|
|
435
468
|
* @usage
|
|
436
469
|
* ```tsx
|
|
437
470
|
* <DataScopeFilter value={finalOnly} onChange={setFinalOnly} />
|
|
@@ -467,6 +500,11 @@ declare function DataScopeFilter({ value, onChange, align }: DataScopeFilterProp
|
|
|
467
500
|
* `onChange` ever fires, so nothing would ever get selected. Selecting an
|
|
468
501
|
* option commits immediately and closes -- there's no separate draft/Apply
|
|
469
502
|
* step; Escape and outside-click just close without side effects.
|
|
503
|
+
* @a11y Trigger is a <button>; the popover is role="listbox" with role="option"
|
|
504
|
+
* rows carrying aria-selected. The trigger owns the accessible name via
|
|
505
|
+
* the caption. The popover is not a focus trap and does not move focus on
|
|
506
|
+
* open, so keyboard users tab into it; a consumer rendering it inside
|
|
507
|
+
* another dismissible layer has to sequence the two dismissals itself.
|
|
470
508
|
* @usage
|
|
471
509
|
* ```tsx
|
|
472
510
|
* <SelectFilter caption="Rank" value={rankFilter} onChange={setRankFilter} options={['All', 'VP / Director', 'Manager', 'Coordinator']} />
|
|
@@ -598,6 +636,10 @@ declare const QUIET_ACTION_CLASS = "rounded-control text-[13px] font-medium text
|
|
|
598
636
|
* recovery buttons (e.g. "Switch workspace") after the two named ones, for
|
|
599
637
|
* empty states whose fix isn't about filters at all -- primary gets the
|
|
600
638
|
* filled treatment, everything else the quiet one.
|
|
639
|
+
* @a11y The optional action is a real <button> with visible text as its
|
|
640
|
+
* accessible name; the illustration is aria-hidden. Nothing here announces
|
|
641
|
+
* automatically, so a consumer replacing results should manage its own
|
|
642
|
+
* live region if the change needs announcing.
|
|
601
643
|
* @usage
|
|
602
644
|
* ```tsx
|
|
603
645
|
* <NoResultsEmptyState hasFilters={hasFilters} onClearFilters={clearFilters} onEditFilters={openFilterTray} />
|
|
@@ -689,6 +731,8 @@ interface SummaryGroup {
|
|
|
689
731
|
* increase, including one added to an already-open or already
|
|
690
732
|
* manually-collapsed nonempty group, silently undoing the user's own
|
|
691
733
|
* collapse. Sub-groups render indented beneath their parent's own items.
|
|
734
|
+
* @a11y The card's toggle is a button reporting aria-expanded, with an aria-
|
|
735
|
+
* label since it renders icon-only. Decorative marks are aria-hidden.
|
|
692
736
|
* @usage
|
|
693
737
|
* ```tsx
|
|
694
738
|
* <WorkspaceSelectedCard groups={[{ id: 'advertisers', label: 'Advertisers', items: selected, onRemove: removeOne, onRemoveAll: clearAll }]} />
|
|
@@ -731,6 +775,9 @@ declare function WorkspaceSelectedCard({ groups, testIdPrefix }: WorkspaceSelect
|
|
|
731
775
|
* `aria-hidden="true"` throughout, since none of the boxes carry real
|
|
732
776
|
* content for assistive tech to announce. The bar count and profile are a
|
|
733
777
|
* fixed shape, not driven by `height`.
|
|
778
|
+
* @a11y role="presentation" with aria-hidden marks: a visual stand-in with no
|
|
779
|
+
* data, deliberately invisible to assistive tech. Don't add a caption
|
|
780
|
+
* expecting it to be announced.
|
|
734
781
|
* @usage
|
|
735
782
|
* ```tsx
|
|
736
783
|
* <BarChartPlaceholder />
|
|
@@ -756,6 +803,9 @@ declare function BarChartPlaceholder({ height }: BarChartPlaceholderProps): reac
|
|
|
756
803
|
* @behavior Purely presentational -- `role="presentation"` and
|
|
757
804
|
* `aria-hidden="true"` throughout (inherited from `AxisFrame`). The series
|
|
758
805
|
* count and shapes are fixed; `height` is the only variable.
|
|
806
|
+
* @a11y role="presentation" with aria-hidden marks: a visual stand-in with no
|
|
807
|
+
* data, deliberately invisible to assistive tech. Don't add a caption
|
|
808
|
+
* expecting it to be announced.
|
|
759
809
|
* @usage
|
|
760
810
|
* ```tsx
|
|
761
811
|
* <LineChartPlaceholder />
|
|
@@ -780,6 +830,9 @@ declare function LineChartPlaceholder({ height }: LineChartPlaceholderProps): re
|
|
|
780
830
|
* @behavior Purely presentational -- `role="presentation"` and
|
|
781
831
|
* `aria-hidden="true"` throughout. `legendRows` controls the blank legend
|
|
782
832
|
* only; the disc's seam count is a fixed shape.
|
|
833
|
+
* @a11y role="presentation" with aria-hidden marks: it is a visual stand-in with
|
|
834
|
+
* no data, deliberately invisible to assistive tech. Don't add a caption
|
|
835
|
+
* expecting it to be announced.
|
|
783
836
|
* @usage
|
|
784
837
|
* ```tsx
|
|
785
838
|
* <PieChartPlaceholder />
|
|
@@ -809,6 +862,8 @@ declare function PieChartPlaceholder({ height, legendRows }: PieChartPlaceholder
|
|
|
809
862
|
* `bg-subtle` fill the default-strength seam disappears and the stack reads
|
|
810
863
|
* as one undivided block. Legend rows are reversed (bottom-up) when `axis`
|
|
811
864
|
* is off, matching a bare stack's usual bottom-anchored reading order.
|
|
865
|
+
* @a11y role="presentation" with aria-hidden marks: a visual stand-in with no
|
|
866
|
+
* data, deliberately invisible to assistive tech.
|
|
812
867
|
* @usage
|
|
813
868
|
* ```tsx
|
|
814
869
|
* <StackedColumnPlaceholder />
|
|
@@ -858,6 +913,10 @@ declare function StackedColumnPlaceholder({ height, width, legendRows, axis, }:
|
|
|
858
913
|
* right-aligned to the anchor's right edge -- both meant for `anchorRef`
|
|
859
914
|
* anchors near the viewport's right edge, where a centred box would run
|
|
860
915
|
* off-screen or read awkwardly beside a narrow icon.
|
|
916
|
+
* @a11y Renders role="tooltip" and is wired to its anchor by aria-describedby,
|
|
917
|
+
* so the anchor must exist and keep a stable id. It describes rather than
|
|
918
|
+
* labels: it is announced in addition to the anchor's own name, not
|
|
919
|
+
* instead of it, so never put the only label for a control in here.
|
|
861
920
|
* @usage
|
|
862
921
|
* ```tsx
|
|
863
922
|
* <Tooltip label="Full advertiser name" whenTruncated>
|
|
@@ -959,6 +1018,10 @@ declare function AdvertiserNoResults({ query, hint, }: AdvertiserNoResultsProps)
|
|
|
959
1018
|
* between "Select all" and "Deselect" based on `allSelected`.
|
|
960
1019
|
* @tokens rounded-control, text-text-link, hover:bg-subtle
|
|
961
1020
|
* @dependencies lucide-react
|
|
1021
|
+
* @a11y A plain <button>, not a checkbox -- it performs a bulk action rather
|
|
1022
|
+
* than holding a checked state, so it deliberately carries no
|
|
1023
|
+
* role="checkbox" or aria-checked. Its icon is aria-hidden and the visible
|
|
1024
|
+
* text is the accessible name.
|
|
962
1025
|
* @usage
|
|
963
1026
|
* ```tsx
|
|
964
1027
|
* {results.length > 5 && (
|
|
@@ -992,6 +1055,9 @@ declare function SelectAllVisible({ count, allSelected, onToggle, testIdPrefix }
|
|
|
992
1055
|
* need. Self-hides at `count === 0` so a caller can render it unconditionally.
|
|
993
1056
|
* @tokens rounded-control, text-text-tertiary, hover:text-text-primary
|
|
994
1057
|
* @dependencies lucide-react
|
|
1058
|
+
* @a11y The disclosure header is a button reporting aria-expanded, and the
|
|
1059
|
+
* chevron is aria-hidden. It is a disclosure, not a selection control --
|
|
1060
|
+
* the rows inside own their own semantics.
|
|
995
1061
|
* @usage
|
|
996
1062
|
* ```tsx
|
|
997
1063
|
* <SelectedSection count={selected.length} open={open} onToggle={() => setOpen((o) => !o)}>
|
|
@@ -1147,6 +1213,10 @@ interface SelectionPickerProps<T extends PickerRow> {
|
|
|
1147
1213
|
* with both an `onChange` and the row's own `onClick` -- `CheckBox` stops
|
|
1148
1214
|
* click propagation before firing `onChange`, which is exactly what lets it
|
|
1149
1215
|
* sit inside a row that toggles on its own click without double-firing.
|
|
1216
|
+
* @a11y Search is an <input>; result rows and the account-list menu
|
|
1217
|
+
* (role="menu") are buttons. Escape closes the menu. Loading, empty and
|
|
1218
|
+
* error states announce through role="status", so a consumer should NOT
|
|
1219
|
+
* wrap this in its own live region -- that would double-announce.
|
|
1150
1220
|
* @usage
|
|
1151
1221
|
* ```tsx
|
|
1152
1222
|
* <SelectionPicker
|
|
@@ -1234,6 +1304,9 @@ interface PublisherBreakdownListProps {
|
|
|
1234
1304
|
* the kind of forked-with-extra-indirection outcome this package's README
|
|
1235
1305
|
* calls out as not actually shared. Per that guidance, this component stays
|
|
1236
1306
|
* the flat-list case only; mr-clientapps' accordion stays where it is, un-migrated.
|
|
1307
|
+
* @a11y Rows are buttons. One row manages tabIndex directly and a row tooltip
|
|
1308
|
+
* uses role="tooltip", dismissed on Escape. The tooltip describes rather
|
|
1309
|
+
* than names, so never put a row's only label in it.
|
|
1237
1310
|
* @usage
|
|
1238
1311
|
* ```tsx
|
|
1239
1312
|
* <PublisherBreakdownList rows={publishers} defaultVisibleCount={10} />
|
|
@@ -1275,6 +1348,9 @@ interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement>, VariantPr
|
|
|
1275
1348
|
* and relies on its per-variant hover/brightness treatment instead. `loading`
|
|
1276
1349
|
* implies `disabled` (and sets `aria-busy`), since a control mid-submit
|
|
1277
1350
|
* shouldn't accept another click.
|
|
1351
|
+
* @a11y Renders a native <button>, so it keeps native keyboard behaviour.
|
|
1352
|
+
* `loading` sets aria-busy, and the spinner is aria-hidden. Icon-only
|
|
1353
|
+
* usage needs an aria-label from the caller -- nothing here supplies one.
|
|
1278
1354
|
* @usage
|
|
1279
1355
|
* ```tsx
|
|
1280
1356
|
* <Button variant="primary" size="md">Save changes</Button>
|
|
@@ -1300,6 +1376,9 @@ interface FilterDropdownFooterProps {
|
|
|
1300
1376
|
* visible. Shared by the Media/Advertiser/Date/Group By/Time Increment quick
|
|
1301
1377
|
* filters on Sports Dashboard, Publisher Intel, and Opportunities.
|
|
1302
1378
|
* @tokens border-border-default
|
|
1379
|
+
* @a11y Clear and Apply are real Buttons with visible text as their accessible
|
|
1380
|
+
* names, in that DOM order. It adds no roles or live regions of its own --
|
|
1381
|
+
* the menu that contains it owns dismissal and focus.
|
|
1303
1382
|
* @usage
|
|
1304
1383
|
* ```tsx
|
|
1305
1384
|
* <FilterDropdownFooter onApply={handleApply} onClear={handleClear} />
|
|
@@ -1343,12 +1422,16 @@ interface NameListModalProps {
|
|
|
1343
1422
|
* checkboxes under it. Shared by the Account Lists table and the list detail
|
|
1344
1423
|
* page so create/rename look identical; `fieldLabel`/`placeholder` relabel it
|
|
1345
1424
|
* for dialogs that name something other than a list.
|
|
1346
|
-
* @tokens rounded-card, border-border-default, bg-surface, shadow-overlay, text-text-primary, text-text-secondary, rounded-control, bg-input, focus:border-brand-primaryAction
|
|
1425
|
+
* @tokens bg-scrim, rounded-card, border-border-default, bg-surface, shadow-overlay, text-text-primary, text-text-secondary, rounded-control, bg-input, focus:border-brand-primaryAction
|
|
1347
1426
|
* @behavior Escape closes the dialog via `onCancel`, same as clicking the
|
|
1348
1427
|
* scrim backdrop. Submit is disabled until the name is non-empty (trimmed).
|
|
1349
1428
|
* When `options` are given they render as CheckBox rows below the field, and
|
|
1350
1429
|
* their state comes back as `onSubmit`'s second argument -- a handler that
|
|
1351
1430
|
* only takes the name stays valid.
|
|
1431
|
+
* @a11y role="dialog" with aria-modal, labelled by its title. The name field
|
|
1432
|
+
* takes focus on open and Escape closes via onCancel. Focus is NOT trapped
|
|
1433
|
+
* and NOT restored to the opener on close -- confirmed in the source -- so
|
|
1434
|
+
* a consumer that needs either must supply it around this component.
|
|
1352
1435
|
* @usage
|
|
1353
1436
|
* ```tsx
|
|
1354
1437
|
* <NameListModal title="Rename list" initialName={list.name} submitLabel="Save" onCancel={close} onSubmit={rename} />
|
|
@@ -1379,10 +1462,6 @@ interface ChipContentProps {
|
|
|
1379
1462
|
* @description Shared foundation for filter-bar chip triggers — pairs
|
|
1380
1463
|
* `chipTriggerClass` with `ChipContent` for the caption/value/icon layout, so
|
|
1381
1464
|
* every dropdown chip across the app matches.
|
|
1382
|
-
* @props
|
|
1383
|
-
* caption: string -- small uppercase label above the value
|
|
1384
|
-
* value: ReactNode -- the current selection, shown below the caption
|
|
1385
|
-
* icon?: ReactNode -- optional leading icon rendered before the caption/value stack
|
|
1386
1465
|
* @tokens rounded-control, bg-input, border-border-default, border-border-strong, text-text-secondary, text-text-tertiary, text-text-primary, hover:bg-subtle, focus-visible:outline-border-focus, hover:text-text-primary
|
|
1387
1466
|
* @behavior `chipTriggerClass` takes a `ChipVariant`: `box` (default, the
|
|
1388
1467
|
* boxed two-line chip on the default border) or `inline` (same fill, darker
|
|
@@ -1392,6 +1471,9 @@ interface ChipContentProps {
|
|
|
1392
1471
|
* treatment every dropdown trigger depends on — open/close, Escape, and
|
|
1393
1472
|
* outside-click dismissal all live in each consumer, not here. A new dropdown
|
|
1394
1473
|
* built on `chipTriggerClass` has to implement its own dismissal handling.
|
|
1474
|
+
* @a11y `chipTriggerClass` supplies only the shared focus-visible outline.
|
|
1475
|
+
* Roles, aria-expanded and dismissal all belong to the consumer's own
|
|
1476
|
+
* trigger -- this styles a control, it does not make one.
|
|
1395
1477
|
* @usage
|
|
1396
1478
|
* ```tsx
|
|
1397
1479
|
* <button className={chipTriggerClass("box")}>
|
|
@@ -1429,6 +1511,9 @@ interface FilterChipBarProps<T extends ChipLike> {
|
|
|
1429
1511
|
* @behavior A parked chip (key in `parkedKeys`) renders with no fill and a
|
|
1430
1512
|
* dashed edge instead of the solid applied style, and its hover tooltip
|
|
1431
1513
|
* reads "Not in this workspace" instead of the filter's group label.
|
|
1514
|
+
* @a11y Each chip's remove control is a button with its own aria-label naming
|
|
1515
|
+
* what it clears; the chip's icon is aria-hidden. An overflow tooltip uses
|
|
1516
|
+
* role="tooltip", which describes rather than labels.
|
|
1432
1517
|
* @usage
|
|
1433
1518
|
* ```tsx
|
|
1434
1519
|
* <FilterChipBar chips={activeChips} onRemove={removeChip} onClearAll={clearAll} />
|
|
@@ -1482,6 +1567,9 @@ interface SortButtonProps<K extends string> {
|
|
|
1482
1567
|
* standard three-state cycle — sort, reverse, then unsorted. `disabled` keeps
|
|
1483
1568
|
* the column's inherited header color rather than dimming it — the column
|
|
1484
1569
|
* isn't unavailable, there's just no data under it.
|
|
1570
|
+
* @a11y Renders a <button> and sets aria-sort on it. Intended for a table header
|
|
1571
|
+
* cell -- put it inside the <th> rather than replacing it, so the sort
|
|
1572
|
+
* state stays associated with the column for screen readers.
|
|
1485
1573
|
* @usage
|
|
1486
1574
|
* ```tsx
|
|
1487
1575
|
* const [sort, setSort] = useState<SortState<'spend'>>(null)
|
|
@@ -1503,6 +1591,9 @@ interface PagerProps {
|
|
|
1503
1591
|
* ellipsis gaps. Shared by My Exports and Account Matcher.
|
|
1504
1592
|
* @tokens rounded-control, text-text-secondary, bg-brand-primaryAction, text-brand-onprimary, hover:bg-subtle, hover:text-text-primary, text-text-tertiary
|
|
1505
1593
|
* @dependencies lucide-react
|
|
1594
|
+
* @a11y Page controls are buttons with their own aria-labels, and the current
|
|
1595
|
+
* page is marked with aria-current. Don't relabel them with visible text
|
|
1596
|
+
* alone -- the labels are what a screen reader announces.
|
|
1506
1597
|
* @usage
|
|
1507
1598
|
* ```tsx
|
|
1508
1599
|
* <Pager page={page} totalPages={totalPages} onPage={setPage} />
|
|
@@ -1571,6 +1662,10 @@ declare function Tag({ children, className }: TagProps): react.JSX.Element;
|
|
|
1571
1662
|
* Changing the per-page count reports it and leaves the host to reset to page
|
|
1572
1663
|
* 1. With one page of results the pager still renders, so the bar's height
|
|
1573
1664
|
* and the range readout don't come and go as filters narrow.
|
|
1665
|
+
* @a11y A <nav aria-label="Pagination"> wrapping <button> controls, each with
|
|
1666
|
+
* its own aria-label (Previous/Next/Last). The chevron icons are aria-
|
|
1667
|
+
* hidden, so the labels are the only accessible names -- don't override
|
|
1668
|
+
* them with visible text alone.
|
|
1574
1669
|
* @usage
|
|
1575
1670
|
* ```tsx
|
|
1576
1671
|
* <TablePagination
|
|
@@ -1655,6 +1750,10 @@ interface MultiSelectGroup {
|
|
|
1655
1750
|
* selection floor by silently ignoring any toggle that would drop below it —
|
|
1656
1751
|
* there's no error state, the click just does nothing. Group parents are
|
|
1657
1752
|
* tri-state and toggle all of their children in one action.
|
|
1753
|
+
* @a11y Trigger is a <button> with aria-expanded; the menu is role="dialog" and
|
|
1754
|
+
* Escape closes it. Option rows carry their own checkbox semantics. Focus
|
|
1755
|
+
* is not moved into the menu on open, so keyboard users tab into it in DOM
|
|
1756
|
+
* order.
|
|
1658
1757
|
* @usage
|
|
1659
1758
|
* ```tsx
|
|
1660
1759
|
* <MultiSelectFilter caption="Media" options={mediaOptions} selected={selected} onChange={setSelected} />
|
|
@@ -1755,6 +1854,10 @@ interface ToggleProps {
|
|
|
1755
1854
|
* need (usually label left, switch pushed right).
|
|
1756
1855
|
* @variant md - Settings panels and modals, where the switch is the row's subject.
|
|
1757
1856
|
* @variant sm - Dense rows next to 13px body text, where the md track overpowers its own label.
|
|
1857
|
+
* @a11y The <button> carries role="switch" and aria-checked, so it is the
|
|
1858
|
+
* control -- don't nest it in another interactive element. `label`
|
|
1859
|
+
* supplies the accessible name; without it the switch is announced
|
|
1860
|
+
* unlabelled.
|
|
1758
1861
|
* @usage
|
|
1759
1862
|
* ```tsx
|
|
1760
1863
|
* <Toggle checked={enabled} onChange={setEnabled} label="Email news alerts" />
|
|
@@ -1790,6 +1893,9 @@ interface FreshnessProps {
|
|
|
1790
1893
|
* timestamps stops reading as a wall of identical text. Color carries the
|
|
1791
1894
|
* urgency signal at a glance.
|
|
1792
1895
|
* @tokens bg-status-success, bg-status-warning, bg-text-tertiary
|
|
1896
|
+
* @a11y role="img" with an aria-label per level, so the dot has a text
|
|
1897
|
+
* alternative rather than announcing as decoration. The label is the only
|
|
1898
|
+
* thing a screen reader gets -- the colour carries no meaning on its own.
|
|
1793
1899
|
* @usage
|
|
1794
1900
|
* ```tsx
|
|
1795
1901
|
* <Freshness level="fresh" />
|
package/dist/index.js
CHANGED
|
@@ -2683,13 +2683,13 @@ function NameListModal({
|
|
|
2683
2683
|
return () => window.removeEventListener("keydown", onKey);
|
|
2684
2684
|
}, [onCancel]);
|
|
2685
2685
|
return createPortal5(
|
|
2686
|
-
//
|
|
2687
|
-
//
|
|
2688
|
-
//
|
|
2686
|
+
// bg-scrim, not a literal: design-tokens gained a scrim token in 2.5.0.
|
|
2687
|
+
// No in-data-[theme=dark] override needed any more -- the token redefines
|
|
2688
|
+
// itself under that attribute in dark.css, so one class covers both themes.
|
|
2689
2689
|
/* @__PURE__ */ jsx26(
|
|
2690
2690
|
"div",
|
|
2691
2691
|
{
|
|
2692
|
-
className: "fixed inset-0 z-70 flex items-center justify-center bg-
|
|
2692
|
+
className: "fixed inset-0 z-70 flex items-center justify-center bg-scrim px-4",
|
|
2693
2693
|
onMouseDown: (e) => e.target === e.currentTarget && onCancel(),
|
|
2694
2694
|
children: /* @__PURE__ */ jsxs24(
|
|
2695
2695
|
"div",
|