@mediaradar/design-components 0.10.0 → 0.12.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 +526 -443
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +185 -7
- package/dist/index.d.ts +185 -7
- package/dist/index.js +385 -303
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/scripts/tailwind-coverage.mjs +11 -0
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} />
|
|
@@ -139,6 +146,78 @@ interface AdvertiserSearchPromptProps {
|
|
|
139
146
|
}
|
|
140
147
|
declare function AdvertiserSearchPrompt({ label }: AdvertiserSearchPromptProps): react.JSX.Element;
|
|
141
148
|
|
|
149
|
+
/**
|
|
150
|
+
* Fill and ink. `tone` answers "what kind of thing is this", never "what
|
|
151
|
+
* colour do I want" -- a caller reaching for `danger` because red looks good
|
|
152
|
+
* is the start of the drift this component replaces.
|
|
153
|
+
*/
|
|
154
|
+
type BadgeTone = "neutral" | "brand" | "success" | "warning" | "danger" | "ai" | "overlay";
|
|
155
|
+
/**
|
|
156
|
+
* Shape and case. Orthogonal to tone: any tone can be any kind, which is what
|
|
157
|
+
* keeps this two small props instead of one list of every combination the
|
|
158
|
+
* product happens to use today.
|
|
159
|
+
*/
|
|
160
|
+
type BadgeKind = "label" | "count" | "eyebrow";
|
|
161
|
+
interface BadgeProps {
|
|
162
|
+
/** What kind of thing this marks. Not a colour choice. */
|
|
163
|
+
tone?: BadgeTone;
|
|
164
|
+
/** Shape and case. `count` for a number, `eyebrow` for a category label. */
|
|
165
|
+
kind?: BadgeKind;
|
|
166
|
+
/** Text, or an icon plus text. Keep it to a few words -- a badge annotates, it does not explain. */
|
|
167
|
+
children: ReactNode;
|
|
168
|
+
className?: string;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* @pattern Badge
|
|
172
|
+
* @description The one small label that annotates something else: a count on
|
|
173
|
+
* a filter, a status, a category, an AI marker, a flag over artwork. Two
|
|
174
|
+
* props -- `tone` (what kind of thing) and `kind` (shape and case) -- which
|
|
175
|
+
* between them cover every badge treatment in the product.
|
|
176
|
+
* @props
|
|
177
|
+
* tone?: 'neutral' | 'brand' | 'success' | 'warning' | 'danger' | 'ai' | 'overlay' (default 'neutral')
|
|
178
|
+
* kind?: 'label' | 'count' | 'eyebrow' (default 'label')
|
|
179
|
+
* children: ReactNode
|
|
180
|
+
* @tokens text-micro, rounded-full, bg-subtle, bg-brand-primarySoft,
|
|
181
|
+
* bg-status-success/15, bg-status-warning/30, bg-status-danger/15, bg-scrim,
|
|
182
|
+
* text-text-secondary, text-brand-primaryAction, text-text-success,
|
|
183
|
+
* text-text-warning, text-text-danger, text-ai-ontint, text-brand-onprimary,
|
|
184
|
+
* border-transparent
|
|
185
|
+
* @behavior Not interactive and carries no role: a badge is a label on
|
|
186
|
+
* something else, so it is read as part of that thing rather than announced
|
|
187
|
+
* separately. Anything clickable is a Button or a filter chip, not a Badge.
|
|
188
|
+
* Every badge is one size -- the `micro` step (11px) -- because a badge
|
|
189
|
+
* that competes with the content it annotates has stopped being a badge.
|
|
190
|
+
* @variant neutral - Default. A category, a count of something unremarkable, a quiet flag.
|
|
191
|
+
* @variant brand - This item is special in a way the product cares about -- primary, selected, yours.
|
|
192
|
+
* @variant success - A finished or healthy state. Never just "green because it is good news".
|
|
193
|
+
* @variant warning - Needs attention but is not broken. Partial data, an approaching limit.
|
|
194
|
+
* @variant danger - Failed, expired, or over a hard limit. Not merely "important".
|
|
195
|
+
* @variant ai - Generated or AI-assisted content, so the reader knows where it came from.
|
|
196
|
+
* @variant overlay - Sits on top of an image or video still, where no theme surface exists behind it.
|
|
197
|
+
* @use when you need to annotate something else -- a status on a row, a count
|
|
198
|
+
* on a filter tab, a category on a card, a flag over a thumbnail.
|
|
199
|
+
* @use when the label is a few words at most and the reader does not need to
|
|
200
|
+
* act on it.
|
|
201
|
+
* @avoid when the thing is clickable -- use Button, or a filter chip. A badge
|
|
202
|
+
* has no role, no focus state and no hit target, so making one clickable
|
|
203
|
+
* hides the action from keyboard and screen-reader users entirely.
|
|
204
|
+
* @avoid when the text is a sentence, or needs to wrap. A badge that wraps
|
|
205
|
+
* has become a callout; use one.
|
|
206
|
+
* @avoid when you are choosing the tone by colour rather than by meaning. A
|
|
207
|
+
* red badge that does not mean failure teaches readers to ignore red.
|
|
208
|
+
* @avoid when several sit in a row and all say something different -- that is
|
|
209
|
+
* a definition list wearing badges, and reads as noise.
|
|
210
|
+
* @usage
|
|
211
|
+
* ```tsx
|
|
212
|
+
* <Badge>Financial Services</Badge>
|
|
213
|
+
* <Badge tone="brand" kind="count">{selected.length}</Badge>
|
|
214
|
+
* <Badge tone="warning">Partial month</Badge>
|
|
215
|
+
* <Badge kind="eyebrow" tone="neutral">Saved view</Badge>
|
|
216
|
+
* <Badge tone="brand"><Check size={11} aria-hidden="true" />Primary</Badge>
|
|
217
|
+
* ```
|
|
218
|
+
*/
|
|
219
|
+
declare function Badge({ tone, kind, children, className }: BadgeProps): react.JSX.Element;
|
|
220
|
+
|
|
142
221
|
/**
|
|
143
222
|
* @pattern CheckBox
|
|
144
223
|
* @description Tri-state checkbox rendered as a `<button>` (not a native
|
|
@@ -159,6 +238,13 @@ declare function AdvertiserSearchPrompt({ label }: AdvertiserSearchPromptProps):
|
|
|
159
238
|
* `stopPropagation` before firing `onChange` by default, so nesting this
|
|
160
239
|
* inside a row that toggles on its own click can't fire the toggle twice;
|
|
161
240
|
* pass `stopPropagation={false}` where the row should also see the click.
|
|
241
|
+
* @a11y The <button> itself carries role="checkbox" and aria-checked ("mixed"
|
|
242
|
+
* when indeterminate), so it IS the control -- never nest it inside
|
|
243
|
+
* another button or a row that is itself clickable. `ariaLabel` is
|
|
244
|
+
* required because the box renders no text. Where the whole row should be
|
|
245
|
+
* the control, use CheckBoxBox inside your own <button role="checkbox">
|
|
246
|
+
* instead: a <button> inside a <button> is invalid markup, and a <div
|
|
247
|
+
* onClick> wrapper is not keyboard-reachable at all.
|
|
162
248
|
* @usage
|
|
163
249
|
* ```tsx
|
|
164
250
|
* <CheckBox checked={selected} ariaLabel="Select row" onChange={toggle} />
|
|
@@ -221,6 +307,10 @@ declare function CheckBox({ checked, indeterminate, onChange, ariaLabel, disable
|
|
|
221
307
|
* the control has no correct option: nesting the interactive `CheckBox`
|
|
222
308
|
* produces a button inside a button, and dropping to a `<div>` with a click
|
|
223
309
|
* handler loses keyboard access entirely.
|
|
310
|
+
* @a11y Presentational only: aria-hidden, no focus stop, no click handling. The
|
|
311
|
+
* ancestor owns role="checkbox", aria-checked, the accessible name and the
|
|
312
|
+
* click. Use it exactly when that ancestor is itself the control; use
|
|
313
|
+
* CheckBox when the box is the control.
|
|
224
314
|
* @usage
|
|
225
315
|
* ```tsx
|
|
226
316
|
* <button type="button" role="checkbox" aria-checked={on} onClick={toggle}>
|
|
@@ -257,6 +347,9 @@ declare function CheckBoxBox({ checked, indeterminate, disabled, className }: Ch
|
|
|
257
347
|
* values, so a previous unsaved edit never lingers into the next open. Only
|
|
258
348
|
* the Apply button commits -- Cancel, Escape, and outside-click all discard
|
|
259
349
|
* the draft silently.
|
|
350
|
+
* @a11y Trigger is a <button> with aria-expanded and an aria-label from the
|
|
351
|
+
* caption; the panel is role="dialog" and Escape closes it. Focus is not
|
|
352
|
+
* moved into the panel, so it is reached by tabbing.
|
|
260
353
|
* @usage
|
|
261
354
|
* ```tsx
|
|
262
355
|
* <DateRangeFilter caption="Date Range" defaultValue="Rolling 6 months" onChange={setRange} />
|
|
@@ -327,6 +420,11 @@ declare function DateRangeFilter({ caption, defaultValue, value: controlledValue
|
|
|
327
420
|
* The text input carries an `aria-label` derived from `placeholder` — the
|
|
328
421
|
* wrapping `<label>` has no visible text content (just an icon and the
|
|
329
422
|
* input), so it grants the input no accessible name on its own.
|
|
423
|
+
* @a11y The <input> takes its accessible name from `ariaLabel`. The match-mode
|
|
424
|
+
* popover is a radio group (role="radio" + aria-checked) and its trigger
|
|
425
|
+
* reports aria-expanded. Escape closes the popover only, leaving focus in
|
|
426
|
+
* the field -- a consumer nesting this inside another dismissible layer
|
|
427
|
+
* must sequence the two dismissals itself.
|
|
330
428
|
* @usage
|
|
331
429
|
* ```tsx
|
|
332
430
|
* <SearchBar value={query} onChange={setQuery} />
|
|
@@ -390,6 +488,9 @@ declare function SearchBar({ placeholder, value, onChange, variant, matchValue,
|
|
|
390
488
|
* anchor rather than a framework router Link — this package has no router
|
|
391
489
|
* peer dependency, and the two consuming apps disagree on one (react-router-dom
|
|
392
490
|
* vs next/link); a plain anchor is the one thing that works unmodified in both.
|
|
491
|
+
* @a11y Rail items are buttons and take their accessible name from `ariaLabel`,
|
|
492
|
+
* since several render icon-only. Without it they announce as unnamed
|
|
493
|
+
* buttons.
|
|
393
494
|
* @usage
|
|
394
495
|
* ```tsx
|
|
395
496
|
* <SectionRail title="Sports" subtitle="Your tracked leagues" viewAllLabel="View all" viewAllHref="/sports">
|
|
@@ -432,6 +533,10 @@ declare function SectionRail({ title, titleSerif, subtitle, viewAllLabel, viewAl
|
|
|
432
533
|
* invalid HTML that breaks click targeting (confirmed against how
|
|
433
534
|
* mr-clientapps-insights-studio's own equivalent, `ChipOption`, already
|
|
434
535
|
* avoids exactly this by rendering its InfoTip as a sibling, not a child).
|
|
536
|
+
* @a11y Trigger is a <button> with aria-expanded and aria-haspopup; the menu is
|
|
537
|
+
* role="listbox" with role="option" rows carrying aria-selected. Escape
|
|
538
|
+
* closes it. Use the listbox semantics as given -- adding a second role to
|
|
539
|
+
* the wrapper breaks the option/listbox relationship.
|
|
435
540
|
* @usage
|
|
436
541
|
* ```tsx
|
|
437
542
|
* <DataScopeFilter value={finalOnly} onChange={setFinalOnly} />
|
|
@@ -467,6 +572,11 @@ declare function DataScopeFilter({ value, onChange, align }: DataScopeFilterProp
|
|
|
467
572
|
* `onChange` ever fires, so nothing would ever get selected. Selecting an
|
|
468
573
|
* option commits immediately and closes -- there's no separate draft/Apply
|
|
469
574
|
* step; Escape and outside-click just close without side effects.
|
|
575
|
+
* @a11y Trigger is a <button>; the popover is role="listbox" with role="option"
|
|
576
|
+
* rows carrying aria-selected. The trigger owns the accessible name via
|
|
577
|
+
* the caption. The popover is not a focus trap and does not move focus on
|
|
578
|
+
* open, so keyboard users tab into it; a consumer rendering it inside
|
|
579
|
+
* another dismissible layer has to sequence the two dismissals itself.
|
|
470
580
|
* @usage
|
|
471
581
|
* ```tsx
|
|
472
582
|
* <SelectFilter caption="Rank" value={rankFilter} onChange={setRankFilter} options={['All', 'VP / Director', 'Manager', 'Coordinator']} />
|
|
@@ -598,6 +708,10 @@ declare const QUIET_ACTION_CLASS = "rounded-control text-[13px] font-medium text
|
|
|
598
708
|
* recovery buttons (e.g. "Switch workspace") after the two named ones, for
|
|
599
709
|
* empty states whose fix isn't about filters at all -- primary gets the
|
|
600
710
|
* filled treatment, everything else the quiet one.
|
|
711
|
+
* @a11y The optional action is a real <button> with visible text as its
|
|
712
|
+
* accessible name; the illustration is aria-hidden. Nothing here announces
|
|
713
|
+
* automatically, so a consumer replacing results should manage its own
|
|
714
|
+
* live region if the change needs announcing.
|
|
601
715
|
* @usage
|
|
602
716
|
* ```tsx
|
|
603
717
|
* <NoResultsEmptyState hasFilters={hasFilters} onClearFilters={clearFilters} onEditFilters={openFilterTray} />
|
|
@@ -689,6 +803,8 @@ interface SummaryGroup {
|
|
|
689
803
|
* increase, including one added to an already-open or already
|
|
690
804
|
* manually-collapsed nonempty group, silently undoing the user's own
|
|
691
805
|
* collapse. Sub-groups render indented beneath their parent's own items.
|
|
806
|
+
* @a11y The card's toggle is a button reporting aria-expanded, with an aria-
|
|
807
|
+
* label since it renders icon-only. Decorative marks are aria-hidden.
|
|
692
808
|
* @usage
|
|
693
809
|
* ```tsx
|
|
694
810
|
* <WorkspaceSelectedCard groups={[{ id: 'advertisers', label: 'Advertisers', items: selected, onRemove: removeOne, onRemoveAll: clearAll }]} />
|
|
@@ -731,6 +847,9 @@ declare function WorkspaceSelectedCard({ groups, testIdPrefix }: WorkspaceSelect
|
|
|
731
847
|
* `aria-hidden="true"` throughout, since none of the boxes carry real
|
|
732
848
|
* content for assistive tech to announce. The bar count and profile are a
|
|
733
849
|
* fixed shape, not driven by `height`.
|
|
850
|
+
* @a11y role="presentation" with aria-hidden marks: a visual stand-in with no
|
|
851
|
+
* data, deliberately invisible to assistive tech. Don't add a caption
|
|
852
|
+
* expecting it to be announced.
|
|
734
853
|
* @usage
|
|
735
854
|
* ```tsx
|
|
736
855
|
* <BarChartPlaceholder />
|
|
@@ -756,6 +875,9 @@ declare function BarChartPlaceholder({ height }: BarChartPlaceholderProps): reac
|
|
|
756
875
|
* @behavior Purely presentational -- `role="presentation"` and
|
|
757
876
|
* `aria-hidden="true"` throughout (inherited from `AxisFrame`). The series
|
|
758
877
|
* count and shapes are fixed; `height` is the only variable.
|
|
878
|
+
* @a11y role="presentation" with aria-hidden marks: a visual stand-in with no
|
|
879
|
+
* data, deliberately invisible to assistive tech. Don't add a caption
|
|
880
|
+
* expecting it to be announced.
|
|
759
881
|
* @usage
|
|
760
882
|
* ```tsx
|
|
761
883
|
* <LineChartPlaceholder />
|
|
@@ -780,6 +902,9 @@ declare function LineChartPlaceholder({ height }: LineChartPlaceholderProps): re
|
|
|
780
902
|
* @behavior Purely presentational -- `role="presentation"` and
|
|
781
903
|
* `aria-hidden="true"` throughout. `legendRows` controls the blank legend
|
|
782
904
|
* only; the disc's seam count is a fixed shape.
|
|
905
|
+
* @a11y role="presentation" with aria-hidden marks: it is a visual stand-in with
|
|
906
|
+
* no data, deliberately invisible to assistive tech. Don't add a caption
|
|
907
|
+
* expecting it to be announced.
|
|
783
908
|
* @usage
|
|
784
909
|
* ```tsx
|
|
785
910
|
* <PieChartPlaceholder />
|
|
@@ -809,6 +934,8 @@ declare function PieChartPlaceholder({ height, legendRows }: PieChartPlaceholder
|
|
|
809
934
|
* `bg-subtle` fill the default-strength seam disappears and the stack reads
|
|
810
935
|
* as one undivided block. Legend rows are reversed (bottom-up) when `axis`
|
|
811
936
|
* is off, matching a bare stack's usual bottom-anchored reading order.
|
|
937
|
+
* @a11y role="presentation" with aria-hidden marks: a visual stand-in with no
|
|
938
|
+
* data, deliberately invisible to assistive tech.
|
|
812
939
|
* @usage
|
|
813
940
|
* ```tsx
|
|
814
941
|
* <StackedColumnPlaceholder />
|
|
@@ -858,6 +985,10 @@ declare function StackedColumnPlaceholder({ height, width, legendRows, axis, }:
|
|
|
858
985
|
* right-aligned to the anchor's right edge -- both meant for `anchorRef`
|
|
859
986
|
* anchors near the viewport's right edge, where a centred box would run
|
|
860
987
|
* off-screen or read awkwardly beside a narrow icon.
|
|
988
|
+
* @a11y Renders role="tooltip" and is wired to its anchor by aria-describedby,
|
|
989
|
+
* so the anchor must exist and keep a stable id. It describes rather than
|
|
990
|
+
* labels: it is announced in addition to the anchor's own name, not
|
|
991
|
+
* instead of it, so never put the only label for a control in here.
|
|
861
992
|
* @usage
|
|
862
993
|
* ```tsx
|
|
863
994
|
* <Tooltip label="Full advertiser name" whenTruncated>
|
|
@@ -959,6 +1090,10 @@ declare function AdvertiserNoResults({ query, hint, }: AdvertiserNoResultsProps)
|
|
|
959
1090
|
* between "Select all" and "Deselect" based on `allSelected`.
|
|
960
1091
|
* @tokens rounded-control, text-text-link, hover:bg-subtle
|
|
961
1092
|
* @dependencies lucide-react
|
|
1093
|
+
* @a11y A plain <button>, not a checkbox -- it performs a bulk action rather
|
|
1094
|
+
* than holding a checked state, so it deliberately carries no
|
|
1095
|
+
* role="checkbox" or aria-checked. Its icon is aria-hidden and the visible
|
|
1096
|
+
* text is the accessible name.
|
|
962
1097
|
* @usage
|
|
963
1098
|
* ```tsx
|
|
964
1099
|
* {results.length > 5 && (
|
|
@@ -992,6 +1127,9 @@ declare function SelectAllVisible({ count, allSelected, onToggle, testIdPrefix }
|
|
|
992
1127
|
* need. Self-hides at `count === 0` so a caller can render it unconditionally.
|
|
993
1128
|
* @tokens rounded-control, text-text-tertiary, hover:text-text-primary
|
|
994
1129
|
* @dependencies lucide-react
|
|
1130
|
+
* @a11y The disclosure header is a button reporting aria-expanded, and the
|
|
1131
|
+
* chevron is aria-hidden. It is a disclosure, not a selection control --
|
|
1132
|
+
* the rows inside own their own semantics.
|
|
995
1133
|
* @usage
|
|
996
1134
|
* ```tsx
|
|
997
1135
|
* <SelectedSection count={selected.length} open={open} onToggle={() => setOpen((o) => !o)}>
|
|
@@ -1147,6 +1285,10 @@ interface SelectionPickerProps<T extends PickerRow> {
|
|
|
1147
1285
|
* with both an `onChange` and the row's own `onClick` -- `CheckBox` stops
|
|
1148
1286
|
* click propagation before firing `onChange`, which is exactly what lets it
|
|
1149
1287
|
* sit inside a row that toggles on its own click without double-firing.
|
|
1288
|
+
* @a11y Search is an <input>; result rows and the account-list menu
|
|
1289
|
+
* (role="menu") are buttons. Escape closes the menu. Loading, empty and
|
|
1290
|
+
* error states announce through role="status", so a consumer should NOT
|
|
1291
|
+
* wrap this in its own live region -- that would double-announce.
|
|
1150
1292
|
* @usage
|
|
1151
1293
|
* ```tsx
|
|
1152
1294
|
* <SelectionPicker
|
|
@@ -1234,6 +1376,9 @@ interface PublisherBreakdownListProps {
|
|
|
1234
1376
|
* the kind of forked-with-extra-indirection outcome this package's README
|
|
1235
1377
|
* calls out as not actually shared. Per that guidance, this component stays
|
|
1236
1378
|
* the flat-list case only; mr-clientapps' accordion stays where it is, un-migrated.
|
|
1379
|
+
* @a11y Rows are buttons. One row manages tabIndex directly and a row tooltip
|
|
1380
|
+
* uses role="tooltip", dismissed on Escape. The tooltip describes rather
|
|
1381
|
+
* than names, so never put a row's only label in it.
|
|
1237
1382
|
* @usage
|
|
1238
1383
|
* ```tsx
|
|
1239
1384
|
* <PublisherBreakdownList rows={publishers} defaultVisibleCount={10} />
|
|
@@ -1242,7 +1387,7 @@ interface PublisherBreakdownListProps {
|
|
|
1242
1387
|
declare function PublisherBreakdownList({ rows, defaultVisibleCount, padded, viewAllHref, renderLogo }: PublisherBreakdownListProps): react.JSX.Element;
|
|
1243
1388
|
|
|
1244
1389
|
declare const buttonVariants: (props?: ({
|
|
1245
|
-
variant?: "link" | "
|
|
1390
|
+
variant?: "link" | "danger" | "primary" | "secondary" | "ghost" | null | undefined;
|
|
1246
1391
|
size?: "icon" | "sm" | "md" | "lg" | null | undefined;
|
|
1247
1392
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
1248
1393
|
interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
|
|
@@ -1275,6 +1420,9 @@ interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement>, VariantPr
|
|
|
1275
1420
|
* and relies on its per-variant hover/brightness treatment instead. `loading`
|
|
1276
1421
|
* implies `disabled` (and sets `aria-busy`), since a control mid-submit
|
|
1277
1422
|
* shouldn't accept another click.
|
|
1423
|
+
* @a11y Renders a native <button>, so it keeps native keyboard behaviour.
|
|
1424
|
+
* `loading` sets aria-busy, and the spinner is aria-hidden. Icon-only
|
|
1425
|
+
* usage needs an aria-label from the caller -- nothing here supplies one.
|
|
1278
1426
|
* @usage
|
|
1279
1427
|
* ```tsx
|
|
1280
1428
|
* <Button variant="primary" size="md">Save changes</Button>
|
|
@@ -1300,6 +1448,9 @@ interface FilterDropdownFooterProps {
|
|
|
1300
1448
|
* visible. Shared by the Media/Advertiser/Date/Group By/Time Increment quick
|
|
1301
1449
|
* filters on Sports Dashboard, Publisher Intel, and Opportunities.
|
|
1302
1450
|
* @tokens border-border-default
|
|
1451
|
+
* @a11y Clear and Apply are real Buttons with visible text as their accessible
|
|
1452
|
+
* names, in that DOM order. It adds no roles or live regions of its own --
|
|
1453
|
+
* the menu that contains it owns dismissal and focus.
|
|
1303
1454
|
* @usage
|
|
1304
1455
|
* ```tsx
|
|
1305
1456
|
* <FilterDropdownFooter onApply={handleApply} onClear={handleClear} />
|
|
@@ -1343,12 +1494,16 @@ interface NameListModalProps {
|
|
|
1343
1494
|
* checkboxes under it. Shared by the Account Lists table and the list detail
|
|
1344
1495
|
* page so create/rename look identical; `fieldLabel`/`placeholder` relabel it
|
|
1345
1496
|
* 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
|
|
1497
|
+
* @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
1498
|
* @behavior Escape closes the dialog via `onCancel`, same as clicking the
|
|
1348
1499
|
* scrim backdrop. Submit is disabled until the name is non-empty (trimmed).
|
|
1349
1500
|
* When `options` are given they render as CheckBox rows below the field, and
|
|
1350
1501
|
* their state comes back as `onSubmit`'s second argument -- a handler that
|
|
1351
1502
|
* only takes the name stays valid.
|
|
1503
|
+
* @a11y role="dialog" with aria-modal, labelled by its title. The name field
|
|
1504
|
+
* takes focus on open and Escape closes via onCancel. Focus is NOT trapped
|
|
1505
|
+
* and NOT restored to the opener on close -- confirmed in the source -- so
|
|
1506
|
+
* a consumer that needs either must supply it around this component.
|
|
1352
1507
|
* @usage
|
|
1353
1508
|
* ```tsx
|
|
1354
1509
|
* <NameListModal title="Rename list" initialName={list.name} submitLabel="Save" onCancel={close} onSubmit={rename} />
|
|
@@ -1379,10 +1534,6 @@ interface ChipContentProps {
|
|
|
1379
1534
|
* @description Shared foundation for filter-bar chip triggers — pairs
|
|
1380
1535
|
* `chipTriggerClass` with `ChipContent` for the caption/value/icon layout, so
|
|
1381
1536
|
* 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
1537
|
* @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
1538
|
* @behavior `chipTriggerClass` takes a `ChipVariant`: `box` (default, the
|
|
1388
1539
|
* boxed two-line chip on the default border) or `inline` (same fill, darker
|
|
@@ -1392,6 +1543,9 @@ interface ChipContentProps {
|
|
|
1392
1543
|
* treatment every dropdown trigger depends on — open/close, Escape, and
|
|
1393
1544
|
* outside-click dismissal all live in each consumer, not here. A new dropdown
|
|
1394
1545
|
* built on `chipTriggerClass` has to implement its own dismissal handling.
|
|
1546
|
+
* @a11y `chipTriggerClass` supplies only the shared focus-visible outline.
|
|
1547
|
+
* Roles, aria-expanded and dismissal all belong to the consumer's own
|
|
1548
|
+
* trigger -- this styles a control, it does not make one.
|
|
1395
1549
|
* @usage
|
|
1396
1550
|
* ```tsx
|
|
1397
1551
|
* <button className={chipTriggerClass("box")}>
|
|
@@ -1429,6 +1583,9 @@ interface FilterChipBarProps<T extends ChipLike> {
|
|
|
1429
1583
|
* @behavior A parked chip (key in `parkedKeys`) renders with no fill and a
|
|
1430
1584
|
* dashed edge instead of the solid applied style, and its hover tooltip
|
|
1431
1585
|
* reads "Not in this workspace" instead of the filter's group label.
|
|
1586
|
+
* @a11y Each chip's remove control is a button with its own aria-label naming
|
|
1587
|
+
* what it clears; the chip's icon is aria-hidden. An overflow tooltip uses
|
|
1588
|
+
* role="tooltip", which describes rather than labels.
|
|
1432
1589
|
* @usage
|
|
1433
1590
|
* ```tsx
|
|
1434
1591
|
* <FilterChipBar chips={activeChips} onRemove={removeChip} onClearAll={clearAll} />
|
|
@@ -1482,6 +1639,9 @@ interface SortButtonProps<K extends string> {
|
|
|
1482
1639
|
* standard three-state cycle — sort, reverse, then unsorted. `disabled` keeps
|
|
1483
1640
|
* the column's inherited header color rather than dimming it — the column
|
|
1484
1641
|
* isn't unavailable, there's just no data under it.
|
|
1642
|
+
* @a11y Renders a <button> and sets aria-sort on it. Intended for a table header
|
|
1643
|
+
* cell -- put it inside the <th> rather than replacing it, so the sort
|
|
1644
|
+
* state stays associated with the column for screen readers.
|
|
1485
1645
|
* @usage
|
|
1486
1646
|
* ```tsx
|
|
1487
1647
|
* const [sort, setSort] = useState<SortState<'spend'>>(null)
|
|
@@ -1503,6 +1663,9 @@ interface PagerProps {
|
|
|
1503
1663
|
* ellipsis gaps. Shared by My Exports and Account Matcher.
|
|
1504
1664
|
* @tokens rounded-control, text-text-secondary, bg-brand-primaryAction, text-brand-onprimary, hover:bg-subtle, hover:text-text-primary, text-text-tertiary
|
|
1505
1665
|
* @dependencies lucide-react
|
|
1666
|
+
* @a11y Page controls are buttons with their own aria-labels, and the current
|
|
1667
|
+
* page is marked with aria-current. Don't relabel them with visible text
|
|
1668
|
+
* alone -- the labels are what a screen reader announces.
|
|
1506
1669
|
* @usage
|
|
1507
1670
|
* ```tsx
|
|
1508
1671
|
* <Pager page={page} totalPages={totalPages} onPage={setPage} />
|
|
@@ -1571,6 +1734,10 @@ declare function Tag({ children, className }: TagProps): react.JSX.Element;
|
|
|
1571
1734
|
* Changing the per-page count reports it and leaves the host to reset to page
|
|
1572
1735
|
* 1. With one page of results the pager still renders, so the bar's height
|
|
1573
1736
|
* and the range readout don't come and go as filters narrow.
|
|
1737
|
+
* @a11y A <nav aria-label="Pagination"> wrapping <button> controls, each with
|
|
1738
|
+
* its own aria-label (Previous/Next/Last). The chevron icons are aria-
|
|
1739
|
+
* hidden, so the labels are the only accessible names -- don't override
|
|
1740
|
+
* them with visible text alone.
|
|
1574
1741
|
* @usage
|
|
1575
1742
|
* ```tsx
|
|
1576
1743
|
* <TablePagination
|
|
@@ -1655,6 +1822,10 @@ interface MultiSelectGroup {
|
|
|
1655
1822
|
* selection floor by silently ignoring any toggle that would drop below it —
|
|
1656
1823
|
* there's no error state, the click just does nothing. Group parents are
|
|
1657
1824
|
* tri-state and toggle all of their children in one action.
|
|
1825
|
+
* @a11y Trigger is a <button> with aria-expanded; the menu is role="dialog" and
|
|
1826
|
+
* Escape closes it. Option rows carry their own checkbox semantics. Focus
|
|
1827
|
+
* is not moved into the menu on open, so keyboard users tab into it in DOM
|
|
1828
|
+
* order.
|
|
1658
1829
|
* @usage
|
|
1659
1830
|
* ```tsx
|
|
1660
1831
|
* <MultiSelectFilter caption="Media" options={mediaOptions} selected={selected} onChange={setSelected} />
|
|
@@ -1755,6 +1926,10 @@ interface ToggleProps {
|
|
|
1755
1926
|
* need (usually label left, switch pushed right).
|
|
1756
1927
|
* @variant md - Settings panels and modals, where the switch is the row's subject.
|
|
1757
1928
|
* @variant sm - Dense rows next to 13px body text, where the md track overpowers its own label.
|
|
1929
|
+
* @a11y The <button> carries role="switch" and aria-checked, so it is the
|
|
1930
|
+
* control -- don't nest it in another interactive element. `label`
|
|
1931
|
+
* supplies the accessible name; without it the switch is announced
|
|
1932
|
+
* unlabelled.
|
|
1758
1933
|
* @usage
|
|
1759
1934
|
* ```tsx
|
|
1760
1935
|
* <Toggle checked={enabled} onChange={setEnabled} label="Email news alerts" />
|
|
@@ -1790,6 +1965,9 @@ interface FreshnessProps {
|
|
|
1790
1965
|
* timestamps stops reading as a wall of identical text. Color carries the
|
|
1791
1966
|
* urgency signal at a glance.
|
|
1792
1967
|
* @tokens bg-status-success, bg-status-warning, bg-text-tertiary
|
|
1968
|
+
* @a11y role="img" with an aria-label per level, so the dot has a text
|
|
1969
|
+
* alternative rather than announcing as decoration. The label is the only
|
|
1970
|
+
* thing a screen reader gets -- the colour carries no meaning on its own.
|
|
1793
1971
|
* @usage
|
|
1794
1972
|
* ```tsx
|
|
1795
1973
|
* <Freshness level="fresh" />
|
|
@@ -1797,4 +1975,4 @@ interface FreshnessProps {
|
|
|
1797
1975
|
*/
|
|
1798
1976
|
declare function Freshness({ level }: FreshnessProps): react.JSX.Element;
|
|
1799
1977
|
|
|
1800
|
-
export { AISpark, type AISparkProps, AdvertiserNoResults, type AdvertiserNoResultsProps, AdvertiserQuickFilter, type AdvertiserQuickFilterProps, AdvertiserSearchPrompt, type AdvertiserSearchPromptProps, BarChartPlaceholder, type BarChartPlaceholderProps, Button, type ButtonProps, Card, type CardProps, CheckBox, CheckBoxBox, type CheckBoxBoxProps, type CheckBoxProps, ChipContent, type ChipContentProps, type ChipVariant, DEFAULT_SEARCH_MATCH, DataScopeFilter, type DataScopeFilterProps, type DateGranularity, DateRangeFilter, type DateRangeFilterProps, DateRangePicker, type DateRangePickerProps, FilterChipBar, type FilterChipBarProps, FilterDropdownFooter, type FilterDropdownFooterProps, Freshness, type FreshnessLevel, type FreshnessProps, InfoTip, type InfoTipProps, LineChartPlaceholder, type LineChartPlaceholderProps, MultiSelectFilter, type MultiSelectFilterProps, type MultiSelectGroup, NO_RESULTS_BODY, NO_RESULTS_TITLE, NameListModal, type NameListModalProps, type NoResultsAction, NoResultsEmptyState, type NoResultsEmptyStateProps, PRIMARY_ACTION_CLASS, Pager, type PagerProps, type PickerColumn, type PickerFilter, type PickerRow, PieChartPlaceholder, type PieChartPlaceholderProps, type PubBreak, PublisherBreakdownList, type PublisherBreakdownListProps, QUIET_ACTION_CLASS, SearchBar, type SearchBarProps, type SearchBarVariant, type SearchMatchMode, type SearchMatchValue, SectionRail, type SectionRailProps, SelectAllVisible, type SelectAllVisibleProps, SelectFilter, type SelectFilterProps, SelectedSection, type SelectedSectionProps, SelectionPicker, type SelectionPickerAccountList, type SelectionPickerProps, SortButton, type SortButtonProps, type SortDir, type SortState, StackedColumnPlaceholder, type StackedColumnPlaceholderProps, type SummaryGroup, type SummaryGroupItemValue, TablePagination, type TablePaginationProps, Tag, type TagProps, Toggle, type ToggleProps, Tooltip, type TooltipProps, WorkspaceAvatar, type WorkspaceAvatarProps, WorkspaceSelectedCard, type WorkspaceSelectedCardProps, buttonVariants, chipTriggerClass, cycleSort, noResultsBody, resolveRange, sortProp };
|
|
1978
|
+
export { AISpark, type AISparkProps, AdvertiserNoResults, type AdvertiserNoResultsProps, AdvertiserQuickFilter, type AdvertiserQuickFilterProps, AdvertiserSearchPrompt, type AdvertiserSearchPromptProps, Badge, type BadgeKind, type BadgeProps, type BadgeTone, BarChartPlaceholder, type BarChartPlaceholderProps, Button, type ButtonProps, Card, type CardProps, CheckBox, CheckBoxBox, type CheckBoxBoxProps, type CheckBoxProps, ChipContent, type ChipContentProps, type ChipVariant, DEFAULT_SEARCH_MATCH, DataScopeFilter, type DataScopeFilterProps, type DateGranularity, DateRangeFilter, type DateRangeFilterProps, DateRangePicker, type DateRangePickerProps, FilterChipBar, type FilterChipBarProps, FilterDropdownFooter, type FilterDropdownFooterProps, Freshness, type FreshnessLevel, type FreshnessProps, InfoTip, type InfoTipProps, LineChartPlaceholder, type LineChartPlaceholderProps, MultiSelectFilter, type MultiSelectFilterProps, type MultiSelectGroup, NO_RESULTS_BODY, NO_RESULTS_TITLE, NameListModal, type NameListModalProps, type NoResultsAction, NoResultsEmptyState, type NoResultsEmptyStateProps, PRIMARY_ACTION_CLASS, Pager, type PagerProps, type PickerColumn, type PickerFilter, type PickerRow, PieChartPlaceholder, type PieChartPlaceholderProps, type PubBreak, PublisherBreakdownList, type PublisherBreakdownListProps, QUIET_ACTION_CLASS, SearchBar, type SearchBarProps, type SearchBarVariant, type SearchMatchMode, type SearchMatchValue, SectionRail, type SectionRailProps, SelectAllVisible, type SelectAllVisibleProps, SelectFilter, type SelectFilterProps, SelectedSection, type SelectedSectionProps, SelectionPicker, type SelectionPickerAccountList, type SelectionPickerProps, SortButton, type SortButtonProps, type SortDir, type SortState, StackedColumnPlaceholder, type StackedColumnPlaceholderProps, type SummaryGroup, type SummaryGroupItemValue, TablePagination, type TablePaginationProps, Tag, type TagProps, Toggle, type ToggleProps, Tooltip, type TooltipProps, WorkspaceAvatar, type WorkspaceAvatarProps, WorkspaceSelectedCard, type WorkspaceSelectedCardProps, buttonVariants, chipTriggerClass, cycleSort, noResultsBody, resolveRange, sortProp };
|