pixelize-design-library 2.4.2-beta.58 → 2.4.2-beta.60
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +149 -5
- package/COMPONENT-GOTCHAS.md +205 -18
- package/DESIGN-GUIDE.md +43 -9
- package/dist/Components/AppSwitcher/AppSwitcher.js +5 -1
- package/dist/Components/AppSwitcher/AppSwitcherProps.d.ts +2 -0
- package/dist/Components/AppSwitcher/AppSwitcherProps.js +7 -4
- package/dist/Components/AudioRecorder/AudioRecorder.d.ts +8 -0
- package/dist/Components/AudioRecorder/AudioRecorder.js +169 -0
- package/dist/Components/AudioRecorder/AudioRecorderProps.d.ts +20 -0
- package/dist/Components/AudioRecorder/AudioRecorderProps.js +2 -0
- package/dist/Components/Breadcrumbs/Breadcrumbs.d.ts +1 -1
- package/dist/Components/Breadcrumbs/Breadcrumbs.js +33 -10
- package/dist/Components/Breadcrumbs/BreadcrumbsProps.d.ts +16 -2
- package/dist/Components/BulkSelectionBar/BulkSelectionBar.d.ts +3 -0
- package/dist/Components/BulkSelectionBar/BulkSelectionBar.js +43 -0
- package/dist/Components/BulkSelectionBar/BulkSelectionBarProps.d.ts +35 -0
- package/dist/Components/BulkSelectionBar/BulkSelectionBarProps.js +2 -0
- package/dist/Components/BulkSelectionBar/index.d.ts +2 -0
- package/dist/Components/BulkSelectionBar/index.js +8 -0
- package/dist/Components/CalendarGrid/CalendarGrid.d.ts +3 -0
- package/dist/Components/CalendarGrid/CalendarGrid.js +173 -0
- package/dist/Components/CalendarGrid/CalendarGridProps.d.ts +54 -0
- package/dist/Components/CalendarGrid/CalendarGridProps.js +2 -0
- package/dist/Components/CalendarGrid/calendarMath.d.ts +49 -0
- package/dist/Components/CalendarGrid/calendarMath.js +178 -0
- package/dist/Components/Card/Card.d.ts +3 -1
- package/dist/Components/Card/Card.js +12 -2
- package/dist/Components/Card/CardProps.d.ts +5 -1
- package/dist/Components/CircularProgress/CircularProgress.d.ts +4 -0
- package/dist/Components/CircularProgress/CircularProgress.js +39 -0
- package/dist/Components/CircularProgress/CircularProgressProps.d.ts +22 -0
- package/dist/Components/CircularProgress/CircularProgressProps.js +2 -0
- package/dist/Components/CircularProgress/arc.d.ts +12 -0
- package/dist/Components/CircularProgress/arc.js +16 -0
- package/dist/Components/Common/fieldStyles.d.ts +1 -0
- package/dist/Components/Common/fieldStyles.js +2 -1
- package/dist/Components/Drawer/Drawer.d.ts +1 -1
- package/dist/Components/Drawer/Drawer.js +4 -2
- package/dist/Components/Drawer/DrawerProps.d.ts +3 -1
- package/dist/Components/Editor/Editor.js +50 -2
- package/dist/Components/Editor/EditorFieldBar.d.ts +15 -0
- package/dist/Components/Editor/EditorFieldBar.js +19 -0
- package/dist/Components/Editor/EditorProps.d.ts +74 -1
- package/dist/Components/Editor/MakeDynamicDialog.d.ts +12 -0
- package/dist/Components/Editor/MakeDynamicDialog.js +59 -0
- package/dist/Components/Editor/editorLabels.d.ts +4 -0
- package/dist/Components/Editor/editorLabels.js +24 -0
- package/dist/Components/Editor/editorTokenStyles.d.ts +28 -0
- package/dist/Components/Editor/editorTokenStyles.js +30 -0
- package/dist/Components/Editor/editorTokens.d.ts +26 -0
- package/dist/Components/Editor/editorTokens.js +134 -0
- package/dist/Components/Editor/useEditorBridge.d.ts +40 -0
- package/dist/Components/Editor/useEditorBridge.js +141 -0
- package/dist/Components/EmptyState/EmptyState.js +2 -1
- package/dist/Components/EmptyState/EmptyStateProps.d.ts +2 -2
- package/dist/Components/FormDrawer/FormDrawer.d.ts +2 -0
- package/dist/Components/FormDrawer/FormDrawer.js +97 -0
- package/dist/Components/FormDrawer/FormDrawerProps.d.ts +55 -0
- package/dist/Components/FormDrawer/FormDrawerProps.js +2 -0
- package/dist/Components/Kbd/Kbd.d.ts +6 -0
- package/dist/Components/Kbd/Kbd.js +33 -0
- package/dist/Components/Kbd/KbdProps.d.ts +17 -0
- package/dist/Components/Kbd/KbdProps.js +2 -0
- package/dist/Components/LauncherTrigger/LauncherTrigger.d.ts +4 -0
- package/dist/Components/LauncherTrigger/LauncherTrigger.js +48 -0
- package/dist/Components/LauncherTrigger/LauncherTriggerProps.d.ts +18 -0
- package/dist/Components/LauncherTrigger/LauncherTriggerProps.js +2 -0
- package/dist/Components/Modal/Modal.d.ts +1 -1
- package/dist/Components/Modal/Modal.js +4 -2
- package/dist/Components/Modal/ModalProps.d.ts +3 -1
- package/dist/Components/Modal/warnDroppedSlotChildren.d.ts +2 -0
- package/dist/Components/Modal/warnDroppedSlotChildren.js +45 -0
- package/dist/Components/NavLauncher/NavLauncher.d.ts +3 -0
- package/dist/Components/NavLauncher/NavLauncher.js +452 -0
- package/dist/Components/NavLauncher/NavLauncherProps.d.ts +187 -0
- package/dist/Components/NavLauncher/NavLauncherProps.js +2 -0
- package/dist/Components/NavLauncher/NewTabLink.d.ts +3 -0
- package/dist/Components/NavLauncher/NewTabLink.js +14 -0
- package/dist/Components/NavLauncher/PinToggle.d.ts +3 -0
- package/dist/Components/NavLauncher/PinToggle.js +21 -0
- package/dist/Components/NavLauncher/launcherParts.d.ts +152 -0
- package/dist/Components/NavLauncher/launcherParts.js +212 -0
- package/dist/Components/NavLauncher/match.d.ts +53 -0
- package/dist/Components/NavLauncher/match.js +178 -0
- package/dist/Components/NavLauncher/revealStyles.d.ts +4 -0
- package/dist/Components/NavLauncher/revealStyles.js +19 -0
- package/dist/Components/NavigationBar/NavigationBar.d.ts +1 -1
- package/dist/Components/NavigationBar/NavigationBar.js +2 -2
- package/dist/Components/NavigationBar/NavigationBarProps.d.ts +2 -0
- package/dist/Components/PageHeader/PageHeader.d.ts +1 -1
- package/dist/Components/PageHeader/PageHeader.js +9 -2
- package/dist/Components/PageHeader/PageHeaderProps.d.ts +8 -0
- package/dist/Components/PdfViewer/PdfViewer.d.ts +21 -4
- package/dist/Components/PdfViewer/PdfViewer.js +124 -3
- package/dist/Components/ProfilePhotoViewer/ProfilePhotoViewer.js +5 -0
- package/dist/Components/ProfilePhotoViewer/ProfilePhotoViewerProps.d.ts +1 -1
- package/dist/Components/QueryState/QueryStateBoundary.d.ts +2 -2
- package/dist/Components/QueryState/QueryStateBoundary.js +9 -3
- package/dist/Components/QueryState/QueryStateProps.d.ts +19 -2
- package/dist/Components/Search/Search.js +2 -1
- package/dist/Components/SectionRail/SectionRail.d.ts +3 -0
- package/dist/Components/SectionRail/SectionRail.js +49 -0
- package/dist/Components/SectionRail/SectionRailProps.d.ts +23 -0
- package/dist/Components/SectionRail/SectionRailProps.js +2 -0
- package/dist/Components/SectionRail/index.d.ts +2 -0
- package/dist/Components/SectionRail/index.js +8 -0
- package/dist/Components/SegmentedControl/SegmentedControl.js +9 -14
- package/dist/Components/SegmentedControl/segmentedInk.d.ts +0 -2
- package/dist/Components/SegmentedControl/segmentedInk.js +1 -5
- package/dist/Components/SideBar/SecondaryBar.js +4 -3
- package/dist/Components/SideBar/SideBar.d.ts +1 -1
- package/dist/Components/SideBar/SideBar.js +30 -9
- package/dist/Components/SideBar/SideBarProps.d.ts +32 -0
- package/dist/Components/SideBar/components/MenuItemBox.d.ts +6 -0
- package/dist/Components/SideBar/components/MenuItemBox.js +8 -4
- package/dist/Components/SideBar/components/MenuPopoverContent.js +3 -2
- package/dist/Components/SideBar/components/OtherApps.js +2 -1
- package/dist/Components/SideBar/components/PinnedSection.d.ts +17 -0
- package/dist/Components/SideBar/components/PinnedSection.js +98 -0
- package/dist/Components/SideBar/sidebarFocus.d.ts +23 -0
- package/dist/Components/SideBar/sidebarFocus.js +20 -0
- package/dist/Components/StageProgress/StageProgress.js +2 -2
- package/dist/Components/StageProgress/StageProgressProps.d.ts +2 -0
- package/dist/Components/StageProgress/StepperStage.js +5 -2
- package/dist/Components/StatCard/StatCard.d.ts +1 -1
- package/dist/Components/StatCard/StatCard.js +6 -2
- package/dist/Components/StatCard/StatCardProps.d.ts +3 -0
- package/dist/Components/StatusTag/StatusTag.d.ts +4 -0
- package/dist/Components/StatusTag/StatusTag.js +24 -0
- package/dist/Components/StatusTag/StatusTagProps.d.ts +20 -0
- package/dist/Components/StatusTag/StatusTagProps.js +2 -0
- package/dist/Components/Table/Table.d.ts +1 -1
- package/dist/Components/Table/Table.js +6 -2
- package/dist/Components/Table/TableProps.d.ts +20 -0
- package/dist/Components/Table/components/TableBody.d.ts +1 -1
- package/dist/Components/Table/components/TableBody.js +43 -18
- package/dist/Components/Table/components/TableHeader.d.ts +1 -1
- package/dist/Components/Table/components/TableHeader.js +7 -5
- package/dist/Components/Table/components/rowDetail.d.ts +32 -0
- package/dist/Components/Table/components/rowDetail.js +20 -0
- package/dist/Components/Table/hooks/useRowExpansion.d.ts +7 -0
- package/dist/Components/Table/hooks/useRowExpansion.js +27 -0
- package/dist/Components/Tabs/Tabs.d.ts +1 -1
- package/dist/Components/Tabs/Tabs.js +15 -2
- package/dist/Components/Tabs/TabsProps.d.ts +6 -2
- package/dist/Components/Tabs/components/Tab.js +4 -33
- package/dist/Components/Tabs/components/TabLinkList.d.ts +7 -0
- package/dist/Components/Tabs/components/TabLinkList.js +34 -0
- package/dist/Components/Tabs/useTabAppearance.d.ts +17 -0
- package/dist/Components/Tabs/useTabAppearance.js +67 -0
- package/dist/Components/Tag/Tag.js +11 -1
- package/dist/Components/Tag/TagProps.d.ts +4 -0
- package/dist/Components/Tag/tagDot.d.ts +3 -0
- package/dist/Components/Tag/tagDot.js +21 -0
- package/dist/Components/WizardDialog/WizardDialog.d.ts +9 -0
- package/dist/Components/WizardDialog/WizardDialog.js +102 -0
- package/dist/Components/WizardDialog/WizardDialogProps.d.ts +48 -0
- package/dist/Components/WizardDialog/WizardDialogProps.js +2 -0
- package/dist/Components/WizardDialog/useWizardFlow.d.ts +22 -0
- package/dist/Components/WizardDialog/useWizardFlow.js +47 -0
- package/dist/Components/WizardDialog/wizardSteps.d.ts +31 -0
- package/dist/Components/WizardDialog/wizardSteps.js +40 -0
- package/dist/esm/Components/AppSwitcher/AppSwitcher.js +2 -1
- package/dist/esm/Components/AppSwitcher/AppSwitcherProps.js +5 -3
- package/dist/esm/Components/AudioRecorder/AudioRecorder.js +161 -0
- package/dist/esm/Components/AudioRecorder/AudioRecorderProps.js +1 -0
- package/dist/esm/Components/Breadcrumbs/Breadcrumbs.js +35 -12
- package/dist/esm/Components/BulkSelectionBar/BulkSelectionBar.js +38 -0
- package/dist/esm/Components/BulkSelectionBar/BulkSelectionBarProps.js +1 -0
- package/dist/esm/Components/BulkSelectionBar/index.js +1 -0
- package/dist/esm/Components/CalendarGrid/CalendarGrid.js +168 -0
- package/dist/esm/Components/CalendarGrid/CalendarGridProps.js +1 -0
- package/dist/esm/Components/CalendarGrid/calendarMath.js +155 -0
- package/dist/esm/Components/Card/Card.js +12 -2
- package/dist/esm/Components/CircularProgress/CircularProgress.js +37 -0
- package/dist/esm/Components/CircularProgress/CircularProgressProps.js +1 -0
- package/dist/esm/Components/CircularProgress/arc.js +11 -0
- package/dist/esm/Components/Common/fieldStyles.js +2 -1
- package/dist/esm/Components/Drawer/Drawer.js +4 -2
- package/dist/esm/Components/Editor/Editor.js +48 -3
- package/dist/esm/Components/Editor/EditorFieldBar.js +13 -0
- package/dist/esm/Components/Editor/MakeDynamicDialog.js +20 -0
- package/dist/esm/Components/Editor/editorLabels.js +20 -0
- package/dist/esm/Components/Editor/editorTokenStyles.js +25 -0
- package/dist/esm/Components/Editor/editorTokens.js +121 -0
- package/dist/esm/Components/Editor/useEditorBridge.js +138 -0
- package/dist/esm/Components/EmptyState/EmptyState.js +2 -1
- package/dist/esm/Components/FormDrawer/FormDrawer.js +58 -0
- package/dist/esm/Components/FormDrawer/FormDrawerProps.js +1 -0
- package/dist/esm/Components/Kbd/Kbd.js +28 -0
- package/dist/esm/Components/Kbd/KbdProps.js +1 -0
- package/dist/esm/Components/LauncherTrigger/LauncherTrigger.js +41 -0
- package/dist/esm/Components/LauncherTrigger/LauncherTriggerProps.js +1 -0
- package/dist/esm/Components/Modal/Modal.js +4 -2
- package/dist/esm/Components/Modal/warnDroppedSlotChildren.js +38 -0
- package/dist/esm/Components/NavLauncher/NavLauncher.js +413 -0
- package/dist/esm/Components/NavLauncher/NavLauncherProps.js +1 -0
- package/dist/esm/Components/NavLauncher/NewTabLink.js +11 -0
- package/dist/esm/Components/NavLauncher/PinToggle.js +18 -0
- package/dist/esm/Components/NavLauncher/launcherParts.js +187 -0
- package/dist/esm/Components/NavLauncher/match.js +172 -0
- package/dist/esm/Components/NavLauncher/revealStyles.js +15 -0
- package/dist/esm/Components/NavigationBar/NavigationBar.js +3 -3
- package/dist/esm/Components/PageHeader/PageHeader.js +9 -2
- package/dist/esm/Components/PdfViewer/PdfViewer.js +123 -2
- package/dist/esm/Components/ProfilePhotoViewer/ProfilePhotoViewer.js +5 -0
- package/dist/esm/Components/QueryState/QueryStateBoundary.js +10 -4
- package/dist/esm/Components/Search/Search.js +3 -2
- package/dist/esm/Components/SectionRail/SectionRail.js +44 -0
- package/dist/esm/Components/SectionRail/SectionRailProps.js +1 -0
- package/dist/esm/Components/SectionRail/index.js +1 -0
- package/dist/esm/Components/SegmentedControl/SegmentedControl.js +11 -16
- package/dist/esm/Components/SegmentedControl/segmentedInk.js +0 -3
- package/dist/esm/Components/SideBar/SecondaryBar.js +4 -3
- package/dist/esm/Components/SideBar/SideBar.js +31 -10
- package/dist/esm/Components/SideBar/components/MenuItemBox.js +4 -2
- package/dist/esm/Components/SideBar/components/MenuPopoverContent.js +3 -2
- package/dist/esm/Components/SideBar/components/OtherApps.js +2 -1
- package/dist/esm/Components/SideBar/components/PinnedSection.js +92 -0
- package/dist/esm/Components/SideBar/sidebarFocus.js +15 -0
- package/dist/esm/Components/StageProgress/StageProgress.js +2 -2
- package/dist/esm/Components/StageProgress/StepperStage.js +5 -2
- package/dist/esm/Components/StatCard/StatCard.js +6 -2
- package/dist/esm/Components/StatusTag/StatusTag.js +19 -0
- package/dist/esm/Components/StatusTag/StatusTagProps.js +1 -0
- package/dist/esm/Components/Table/Table.js +7 -3
- package/dist/esm/Components/Table/components/TableBody.js +43 -18
- package/dist/esm/Components/Table/components/TableHeader.js +7 -5
- package/dist/esm/Components/Table/components/rowDetail.js +14 -0
- package/dist/esm/Components/Table/hooks/useRowExpansion.js +23 -0
- package/dist/esm/Components/Tabs/Tabs.js +15 -2
- package/dist/esm/Components/Tabs/components/Tab.js +4 -33
- package/dist/esm/Components/Tabs/components/TabLinkList.js +29 -0
- package/dist/esm/Components/Tabs/useTabAppearance.js +63 -0
- package/dist/esm/Components/Tag/Tag.js +12 -2
- package/dist/esm/Components/Tag/tagDot.js +17 -0
- package/dist/esm/Components/WizardDialog/WizardDialog.js +58 -0
- package/dist/esm/Components/WizardDialog/WizardDialogProps.js +1 -0
- package/dist/esm/Components/WizardDialog/useWizardFlow.js +44 -0
- package/dist/esm/Components/WizardDialog/wizardSteps.js +35 -0
- package/dist/esm/index.js +14 -0
- package/dist/index.d.ts +35 -6
- package/dist/index.js +38 -4
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -18,6 +18,105 @@ next major.
|
|
|
18
18
|
|
|
19
19
|
### Added
|
|
20
20
|
|
|
21
|
+
- **HRMS library requests** — a navigation launcher, key caps, a merge-field `Editor`, a wizard and
|
|
22
|
+
smaller gaps found by the HRMS migration:
|
|
23
|
+
- `NavLauncher` — full-height navigation launcher (browse modules, pins, Frequent, Recent, search
|
|
24
|
+
with actions and remote groups, optional suite-apps section below `md`), with `PinToggle`,
|
|
25
|
+
`NewTabLink`, `searchLauncher`, `searchLauncherSections` (sectioned search: modules, then their
|
|
26
|
+
screens, keyword-only hits get a `· keyword` hint) and `flattenScreens`. The pin control is a
|
|
27
|
+
star, shown with the ↗ link on row hover/focus only (always on touch); pinned rail items are tiles. It binds no global chord. `LauncherTrigger`
|
|
28
|
+
is the chip (10px radius, 36px, accent ink, one ⌘K hint) that opens an app-owned launcher (`aria-haspopup="dialog"`, `aria-expanded`,
|
|
29
|
+
`aria-keyshortcuts`); `display="icon"` is a 36px icon-only variant for a nav bar's `moreIcon`
|
|
30
|
+
(label is the accessible name, tooltip "Menu (⌘K)"). Types: `NavLauncherProps`, `LauncherScreen`, `LauncherModule`,
|
|
31
|
+
`LauncherSection`, `LauncherSearchItem`, `LauncherLabels` and friends, `LauncherTriggerProps`.
|
|
32
|
+
`NavLauncher` follows canvas `Launcher.dc.html`: stacked sections with "(n)" counts and a 1/2/3-column
|
|
33
|
+
grid, a "Quick access" rail of `clamp(20rem, 30%, 26rem)` in a panel whose `maxWidth` defaults to
|
|
34
|
+
1080px (Pinned tiles, Frequently visited, Recent), "Pins follow your account" footer. The footer's
|
|
35
|
+
key hints are key caps (ENTER, ⌘ ENTER / CTRL ENTER, ESC, four arrows) and are hidden on touch devices. New optional props `frequentLimit`, `suggestions` (no-results chips), `searchHint`,
|
|
36
|
+
`LauncherModule.isNew`, and labels `quickAccess`, `newBadge`, `screens`, `pinShort`, `footerNote`,
|
|
37
|
+
`suggestionsHint`, `found`, `pinTip`, `unpinTip`. The rail landmark is named "Quick access".
|
|
38
|
+
Keyboard: ←/→ and ↑/↓ are grid-aware (row-major, ↑/↓ cross sections), and `P` pins or unpins the
|
|
39
|
+
focused item (never while typing); ArrowUp from the first item returns to the search field and
|
|
40
|
+
pinned tiles are a 2-column grid. The keyboard-active row highlights as a whole (soft fill plus
|
|
41
|
+
one 1px inset ring, at least 3:1), the whole row is the link target (Cmd/middle-click opens a new
|
|
42
|
+
tab), and truncated titles, rail rows, pinned tiles, app names and search rows show a tooltip with
|
|
43
|
+
the full text. New optional `openShortcutHint` (e.g. "⌘K or /", app-owned),
|
|
44
|
+
labels `hintOpenMenu` and `hintPin`; hint label defaults are lowercase and follow the canvas order.
|
|
45
|
+
- `Kbd` / `KbdShortcut` — a key cap and a chord (`mod+k` renders ⌘ K or Ctrl K), in the
|
|
46
|
+
`AppSwitcher` notation. `Search` and `AppSwitcher` render their shortcut hints with `Kbd`.
|
|
47
|
+
- `NavigationBar` `leading` — a slot between the sidebar toggle/back button and the title, outside
|
|
48
|
+
the title `<p>`.
|
|
49
|
+
- `SideBar` pinned section: `pinnedItems`, `pinnedLabel`, `onUnpin`, `activePinnedId`,
|
|
50
|
+
`pinnedLimit`, `pinnedLabels`; `collapseTransition` (`"none"` or `{ speed, animateShadow }`);
|
|
51
|
+
`autoCollapse` (default `true`; `false` stops the rail calling `changeToggle` itself, which also
|
|
52
|
+
silences the `open` prop). Types `SidebarPinnedItem`, `SidebarPinnedLabels`,
|
|
53
|
+
`SidebarCollapseTransition`.
|
|
54
|
+
- `Breadcrumbs` `overflow` (`"nowrap"` | `"wrap"` | `"truncate"`), `maxItems` (default 3) and
|
|
55
|
+
`labels.showMore`; `"truncate"` folds middle crumbs into a "…" menu. A `BreadcrumbItem` without
|
|
56
|
+
`path` renders as plain text.
|
|
57
|
+
- `PageHeader` `titleSize` (`"md"` | `"lg"` | `"xl"`) and `actionsLayout`
|
|
58
|
+
(`"auto"` | `"stacked"` | `"inline"`).
|
|
59
|
+
- `Card` `padding` (`"none"` | `"2xs"` | `"xs"` | `"sm"` | `"md"` | `"lg"`) — one padding for
|
|
60
|
+
header, body and footer.
|
|
61
|
+
- `Editor` merge fields: `mergeFields` adds an Insert field menu (grouped, searchable),
|
|
62
|
+
non-editable token chips (stored HTML keeps the raw `${path}`), unknown-field error chips with
|
|
63
|
+
`onUnknownTokens`, and a Make dynamic dialog; plus `tokenSyntax`, `showMakeDynamic`,
|
|
64
|
+
`toolbarButtons`, `apiRef` / `onReady` (`EditorApi`) and `labels` (incl. `dynamicFieldPlaceholder`, default "Choose a field"). `Editor` also takes `label`,
|
|
65
|
+
`isRequired`, `helperText`, `error`, `errorMessage` and `data-testid`; the editable area gets
|
|
66
|
+
`role="textbox"` with `aria-labelledby` / `aria-invalid` / `aria-describedby` / `aria-required`.
|
|
67
|
+
Types `EditorProps`, `EditorApi`, `EditorMergeField`, `EditorTokenSyntax`, `EditorToolbarButton`,
|
|
68
|
+
`EditorLabels`.
|
|
69
|
+
- `WizardDialog` and inline `Wizard` — a multi-step flow that owns step state (validated
|
|
70
|
+
Continue, locked future steps, error summary, review on the last step); `wizardTransition` and
|
|
71
|
+
`firstInvalidStep` are exported.
|
|
72
|
+
- `PdfViewer` `getBlob` (authed files: the viewer makes and revokes the object URL, skeleton while
|
|
73
|
+
loading), `fallback`, `onLoad`, `onError`, `labels`; inline support is detected with
|
|
74
|
+
`navigator.pdfViewerEnabled`. `PdfViewerProps` / `PdfViewerLabels` are now exported types.
|
|
75
|
+
- Page examples: **App launcher** (`/examples/launcher`), **Wizard** (`/examples/wizard`),
|
|
76
|
+
**Template editor** (`/examples/template-editor`).
|
|
77
|
+
- `Tag` `display="dot"` — an 8px tone dot plus plain label for quiet rows (`variant` and icons
|
|
78
|
+
are ignored; the dot ink is lifted to 3:1 on both canvases). `StatusTag` (+ `StatusTagProps`,
|
|
79
|
+
`StatusAppearance`) maps an app's status union to a `Tag` tone once; an unknown status renders
|
|
80
|
+
neutral and warns once in development. (HRMS #13)
|
|
81
|
+
- `Drawer` / `Modal` `portalChildren` — rendered **inside** the dialog content after the slots (not
|
|
82
|
+
a sibling in the portal, which Chakra would `aria-hide`), for nested dialogs and live regions;
|
|
83
|
+
a nested `AlertDialog` still portals out, stacks above and returns focus. (HRMS #20)
|
|
84
|
+
- `FormDrawer` (+ `FormDrawerProps`, `FormDrawerSection`, `FormDrawerLabels`) — a sectioned
|
|
85
|
+
create/edit form in a `Drawer`: `role="alert"` error summary focused after a failed submit,
|
|
86
|
+
sticky footer with a real `<form>` submit, discard-changes confirm on every close path while
|
|
87
|
+
`isDirty`, all close paths blocked while `isSubmitting`. (HRMS #14)
|
|
88
|
+
- `Table` row detail expander — `renderRowDetail(row)` (null = no chevron), `expandedRows` /
|
|
89
|
+
`onExpandedRowsChange` (uncontrolled when `expandedRows` is omitted). Chevron column after the
|
|
90
|
+
checkbox, full-width detail row; works with pagination, virtualisation, frozen columns and
|
|
91
|
+
grouped mode. The chevron is a button with `aria-expanded` / `aria-controls`. (HRMS #17)
|
|
92
|
+
- `EmptyState` `description` accepts a `ReactNode` — a string keeps today's styling, a node sits in
|
|
93
|
+
the same muted block above `action`. (HRMS #18)
|
|
94
|
+
- `QueryStateBoundary` `isForbidden` (boolean or `(error) => boolean`), `forbidden`
|
|
95
|
+
(`{ title, description, icon, action }`) and `hasData`; type `QueryStateForbiddenProps`. Order is
|
|
96
|
+
now loading (only when `!hasData`) → forbidden → error → empty → children; forbidden is a lock
|
|
97
|
+
`EmptyState` with `role="status"`. Defaults unchanged. (HRMS #21)
|
|
98
|
+
- `Tabs` link mode — `TabItem.href` and `TabsProps.linkAs`: when every item has an `href`, `Tabs`
|
|
99
|
+
renders a `<nav aria-label>` of links (same variants and sizes, no panels, not a tablist) with
|
|
100
|
+
`aria-current="page"` on `value`; modifier and middle clicks are never intercepted. (HRMS #19)
|
|
101
|
+
- `BulkSelectionBar` (+ `BulkAction`, `BulkActionTone`, `BulkSelectionBarProps`) — selection bar for
|
|
102
|
+
beside a `Table`: "{n} selected", facts about the whole selection, tone-ranked actions, clear,
|
|
103
|
+
`inline` or `sticky`, polite count announcement; renders nothing at 0. (HRMS #15)
|
|
104
|
+
- `SectionRail` (+ `RailSection`, `SectionRailProps`) — section navigation for long settings
|
|
105
|
+
screens: a vertical `nav` with `aria-current` and a dirty dot per section, collapsing to a
|
|
106
|
+
`Select` below `collapseBelow` (default `md`). (HRMS #16)
|
|
107
|
+
- `StatCard` `iconTone` (neutral / info / success / warning / error) paints the icon chip with the
|
|
108
|
+
soft tone; unset keeps today's brand-primary chip. (HRMS #23)
|
|
109
|
+
- `CircularProgress` (+ `CircularProgressProps`, `CircularProgressSize`) — SVG ring, sm/md/lg =
|
|
110
|
+
32/48/72px, `thickness`, `tone`, centred `label`, `role="progressbar"`. (HRMS #24)
|
|
111
|
+
- `CalendarGrid` (+ `CalendarEvent`, `CalendarGridProps`, `CalendarGridView`, `CalendarGridLabels`) —
|
|
112
|
+
a controlled month/week/day grid of date-granularity events: multi-day spans, "+N more" opens the
|
|
113
|
+
day, `role="grid"` with arrow/Home/End/Page keys, link or button chips in `Tag` tones, `locale`,
|
|
114
|
+
`weekStartsOn`, `isLoading`. (HRMS #25)
|
|
115
|
+
- `AudioRecorder` (+ `AudioRecorderProps`, `AudioRecorderLabels`) — microphone recorder: asks for
|
|
116
|
+
the mic on Start, mm:ss timer, `maxDurationSec` auto-stop, hands a `File` named for the recorded
|
|
117
|
+
mime to `onRecorded`, permission-denied and unsupported states, releases the mic on unmount.
|
|
118
|
+
(HRMS #26)
|
|
119
|
+
|
|
21
120
|
- **Commerce kit** — the components for a shop front, designed mobile-first (Pebble principles:
|
|
22
121
|
chromeless tonal cards, one loud action per view, selection never by colour alone). Product:
|
|
23
122
|
`Rating`, `PriceBlock`, `StockStatus`, `ProductBadges`, `WishlistToggle`, `OptionChip`,
|
|
@@ -86,6 +185,32 @@ next major.
|
|
|
86
185
|
|
|
87
186
|
### Changed
|
|
88
187
|
|
|
188
|
+
- **`PageHeader` `actionsLayout` defaults to `"auto"`**: at `md` and up the actions wrap below the
|
|
189
|
+
title when they do not fit (before, they squeezed the title). Identical whenever title and
|
|
190
|
+
actions fit on one row; pass `actionsLayout="inline"` for the old behaviour.
|
|
191
|
+
- **`Card` `padding` is no longer Chakra's style prop** — it is omitted from the type and now takes
|
|
192
|
+
the `CardPadding` steps. A consumer passing `padding={4}` gets a compile error; use `p` or `sx`.
|
|
193
|
+
Staged for the next major (see Breaking); consumer blast radius not measured.
|
|
194
|
+
- **`SideBar` default box-shadow transition is 260ms** (was 200ms) so it follows `collapseTransition`
|
|
195
|
+
`speed="slow"`. The width transition is unchanged.
|
|
196
|
+
- **`StageProgress variant="stepper"` renders an `ol` of `li`** (`StepperStageProps.asListItem`).
|
|
197
|
+
Visual layout is unchanged; selectors that expected a `div` list no longer match.
|
|
198
|
+
- **`PdfViewer` `pdfUrl` is optional** — pass exactly one of `pdfUrl` / `getBlob`. In `getBlob` mode
|
|
199
|
+
the toolbar Open and Download are real buttons that fetch through it.
|
|
200
|
+
- `Editor` binds Jodit's `change` / `blur` itself on every Jodit instance and renders Jodit only once
|
|
201
|
+
its popup root exists (no throwaway first instance). Behaviour for existing props is unchanged.
|
|
202
|
+
- `BreadcrumbItem.path` is optional (type widening).
|
|
203
|
+
- **`Drawer` / `Modal` warn when they drop a child.** A child that is not a Header/Body/Footer slot
|
|
204
|
+
still renders nothing, but now logs a dev-only `console.warn` (once per child type) pointing at
|
|
205
|
+
`portalChildren`. (HRMS #20)
|
|
206
|
+
- **`Table` `studio` variant on touch devices:** under `@media (pointer: coarse)` the row checkbox is
|
|
207
|
+
always visible and the row number is hidden, instead of a hover-only reveal. (HRMS #17)
|
|
208
|
+
- **`ProfilePhotoViewer` re-syncs when `photoUrl` changes** (it used to seed on mount only), so
|
|
209
|
+
consumers can drop `key={photoUrl}`. A locally picked preview is replaced by the new URL — update
|
|
210
|
+
`photoUrl` only once an upload has finished. (HRMS #22)
|
|
211
|
+
- **Page examples:** `records.tsx` uses `BulkSelectionBar` instead of the `Table`'s `headerActions`;
|
|
212
|
+
`settings.tsx` uses `SectionRail` instead of a hand-built section nav.
|
|
213
|
+
|
|
89
214
|
- **`ProductCard` and `ProductDetails` are rewritten** — see Breaking below. `ProductCard` is a
|
|
90
215
|
chromeless 4:5 card (grid / list / rail, swatch dots that swap the photo, quick-add sheet or
|
|
91
216
|
direct add that morphs into a stepper, sold-out "Notify me", slots). `ProductDetails` is a
|
|
@@ -125,6 +250,19 @@ next major.
|
|
|
125
250
|
|
|
126
251
|
### Fixed
|
|
127
252
|
|
|
253
|
+
- **`NavLauncher` keyboard and link fixes.** Arrow keys, typing and Backspace were dead on rail and
|
|
254
|
+
apps rows while a search was active; Enter could throw when results shrank; Enter during IME
|
|
255
|
+
composition opened a result; removing the focused row (e.g. an app dropped from `apps`) dropped
|
|
256
|
+
focus to the page body (it now moves to the neighbouring row, or the field).
|
|
257
|
+
- **`Search` / `TextInput` / `Select` / `Textarea` / `NumberInput` / `FileUpload` / `PincodeChecker`
|
|
258
|
+
focus glow was transitioned in**, so a screenshot or accessibility check taken the instant a field
|
|
259
|
+
gained focus saw no ring. `FIELD_TRANSITION` no longer animates `box-shadow`; border-colour and
|
|
260
|
+
background transitions are unchanged and still honour reduced motion.
|
|
261
|
+
|
|
262
|
+
- **`SideBar` rail controls now show a `:focus-visible` ring** (rows, submenu and flyout rows,
|
|
263
|
+
`SecondaryBar`, collapse toggle, Add New, user footer, Collapse/Hide/Show, switch-app cells,
|
|
264
|
+
overlay close) — WCAG 2.4.7 / 2.4.11.
|
|
265
|
+
|
|
128
266
|
- **Commerce performance (consumer report on 2.4.2-beta.57).** `ProductCard` no longer loads the
|
|
129
267
|
hover image on devices that cannot hover; `QuickAddSheet` mounts on first open, not on first
|
|
130
268
|
paint; `formatPrice` caches its `Intl.NumberFormat`; every `matchMedia` consumer
|
|
@@ -299,8 +437,8 @@ next major.
|
|
|
299
437
|
which is deep in light and pale in dark, so the bar inverted and the whole comparison was
|
|
300
438
|
unreadable. It now derives the bar from `resolveFilledSurface(...).activeFill` and **measures**
|
|
301
439
|
both contrast ratios live against the active brand and mode, instead of printing two numbers that
|
|
302
|
-
were only ever true in light mode. `segmentedTrackSurface
|
|
303
|
-
|
|
440
|
+
were only ever true in light mode. `segmentedTrackSurface` and `segmentedRestInk`
|
|
441
|
+
are now one shared module, so the demo, the component and the contrast
|
|
304
442
|
gate cannot drift apart.
|
|
305
443
|
- **`SegmentedControl` on a brand-filled bar was unreadable mud.** `brandSlide`'s track is an 8%
|
|
306
444
|
brand tint, which on a brand bar composites straight back into the bar — the control lost its
|
|
@@ -316,9 +454,11 @@ next major.
|
|
|
316
454
|
the ring's surface-toned halo painted a white band and both bands landed outside the pill — a
|
|
317
455
|
thick double border that overflowed the track. A radiogroup is also a single tab stop, so ringing
|
|
318
456
|
one segment says nothing the selection does not already say. The **group** now carries the
|
|
319
|
-
indicator
|
|
320
|
-
|
|
321
|
-
`
|
|
457
|
+
indicator: Button's own two-tone ring (halo plus brand band, at least 3:1 on any fill, light and
|
|
458
|
+
dark) on the track while a segment has keyboard focus (never after a mouse click).
|
|
459
|
+
`underlineSlide` has no track chrome, so there the
|
|
460
|
+
segment wears `focusVisibleStyles`. `ThemeSwitcher`'s mode segments follow the same rule through
|
|
461
|
+
their own border.
|
|
322
462
|
- **`Switch` clipped long labels.** Its 12.5rem width was fixed, so labels wider than the track
|
|
323
463
|
overflowed the background; it is now a minimum. `SegmentedControl`'s track carries
|
|
324
464
|
`minW="max-content"` for the same reason.
|
|
@@ -379,6 +519,10 @@ known consumers in the Pixelize repos. `ProductCard` drops `id`, `label`, `descr
|
|
|
379
519
|
option and cart-callback props (it takes `product`, `selection`, `onAddToBag` and slots). Video
|
|
380
520
|
and YouTube/Vimeo frames are now `ProductMedia` items in `MediaGallery`.
|
|
381
521
|
|
|
522
|
+
**`Card` `padding` narrows from Chakra's style prop to `CardPadding`.** `padding={4}` stops
|
|
523
|
+
compiling; use `p` / `sx` for arbitrary values. No use inside this repo; consumers not measured, so
|
|
524
|
+
run `tsc --noEmit` in each before upgrading.
|
|
525
|
+
|
|
382
526
|
**`star` is a required `PaletteProps` token.** A hand-written palette without it throws in
|
|
383
527
|
`assertPixelizePalette` naming `star`; palettes built from the library's builders get it for free.
|
|
384
528
|
|
package/COMPONENT-GOTCHAS.md
CHANGED
|
@@ -177,6 +177,15 @@ is now the library's own themed component, with a real dual-thumb mode and a `ma
|
|
|
177
177
|
|
|
178
178
|
**Apply:** "on vs off" is always `ToggleSwitch`; 2+ named options is always `SegmentedControl`.
|
|
179
179
|
|
|
180
|
+
**`SegmentedControl`'s focus ring sits on the track, not the segment** (Button's two-tone ring). It is
|
|
181
|
+
driven by a `:focus-visible` check in `onFocus`, so a mouse click stays ringless. `underlineSlide` has no
|
|
182
|
+
track chrome, so its focused segment wears the ring instead.
|
|
183
|
+
|
|
184
|
+
**A focus indicator must never be in a `transition` list.** The 0ms computed style is the transparent
|
|
185
|
+
start value, so a screenshot or axe check taken on focus misses it. Field styles go through
|
|
186
|
+
`FIELD_TRANSITION` (`Common/fieldStyles.ts`), which animates `border-color` and `background-color`
|
|
187
|
+
only; keep `box-shadow` out of any transition you add around a field.
|
|
188
|
+
|
|
180
189
|
**`SegmentedControl` and `Tabs` look near-identical and are not interchangeable.** They share the
|
|
181
190
|
size scale and tokens, so `SegmentedControl variant="underlineSlide"` and `Tabs variant="line"`
|
|
182
191
|
render almost the same picture, as do `variant="default"` and `Tabs variant="subtle"`. The
|
|
@@ -233,6 +242,8 @@ and wires `aria-controls` to them. Pick by that, never by the picture. A screen
|
|
|
233
242
|
| Top bar: back control + user-avatar profile/logout dropdown | `NavigationBar` | No page-nav links at all — `navMenu` is only the avatar dropdown's own items |
|
|
234
243
|
| Top bar: horizontal page links with active-state highlighting + submenus | `Header` | Desktop submenus are hover-only, see gotcha below |
|
|
235
244
|
| Collapsible/dockable left rail — primary in-app navigation + secondary panel | `SideBar` | The persistent nav shell, not for switching between whole apps |
|
|
245
|
+
| In-app launcher: browse modules, pins, recents, search | `NavLauncher` opened by a `LauncherTrigger` in `NavigationBar`'s `leading` | An app-owned screen registry, not a cross-app switcher; pins can also surface in `SideBar` `pinnedItems` |
|
|
246
|
+
| Key cap or chord hint (`mod+k`) | `Kbd` / `KbdShortcut` | Never hand-style a `<kbd>`; `Search` and `AppSwitcher` already use it |
|
|
236
247
|
| Cross-app launcher (CRM/HRMS/Tickets/Billing/...) | `AppSwitcher` | Two-column popover grid of separate app origins — `SideBar`'s `otherApps` is the legacy predecessor; don't wire both into one shell |
|
|
237
248
|
| Floating Jira-style dialog to view/edit one record without leaving the page | `WorkspaceWindow` | Modal-based floating panel, not page navigation; pairs with `WorkspaceTray` |
|
|
238
249
|
|
|
@@ -253,10 +264,10 @@ Four components open a file, and only one of them is the general answer.
|
|
|
253
264
|
| --- | --- | --- |
|
|
254
265
|
| A gallery of mixed media with next/prev, a filmstrip and per-type stages | `MediaViewer` | The full lightbox: image/video/audio/pdf/doc stages, keyboard nav, fullscreen, download. Collapses the filmstrip and stepper automatically for a single item |
|
|
255
266
|
| One file, click-to-open, no gallery | `FilePreview` | Lighter controlled modal; auto-detects type, zoom/rotate for images |
|
|
256
|
-
| Always-visible inline PDF panel in the page flow | `PdfViewer` | Non-modal, PDF-only, small open/download toolbar |
|
|
267
|
+
| Always-visible inline PDF panel in the page flow | `PdfViewer` | Non-modal, PDF-only, small open/download toolbar; `getBlob` for files behind auth |
|
|
257
268
|
| Crop/preview a user avatar | `ProfilePhotoViewer` | Avatar-specific, not a general file viewer |
|
|
258
269
|
|
|
259
|
-
`PdfViewer`
|
|
270
|
+
`PdfViewer` shows a fallback when the browser cannot render a PDF inline (`navigator.pdfViewerEnabled === false`) or `getBlob` rejects; `FilePreview`'s `"pdf"` kind renders a bare `<embed type="application/pdf">` and tells you nothing. `MediaViewer` also handles it: formats a browser cannot decode (`.avi`, `.mkv`, `.m3u8`, `.heic`, `.tiff`) render an icon and a file-type chip with a download action instead of a blank frame.
|
|
260
271
|
|
|
261
272
|
`MediaViewer.labels` takes a `Partial<MediaViewerLabels>` — that type and `defaultMediaViewerLabels` are both exported from the package root, so you can merge rather than restate every string.
|
|
262
273
|
|
|
@@ -302,7 +313,7 @@ not enough when the overlay sits inside a transition wrapper — the wrapper kee
|
|
|
302
313
|
| --- | --- | --- |
|
|
303
314
|
| "Nothing here yet" with an optional action | `EmptyState` | Neutral placeholder |
|
|
304
315
|
| A failed load with retry | `ErrorState` | `role="alert"`, `onRetry`/`isRetrying` built in |
|
|
305
|
-
| One fetch that can be loading, failed, empty or ready | `QueryStateBoundary` | Picks for you: loading > error > empty > `children` |
|
|
316
|
+
| One fetch that can be loading, forbidden, failed, empty or ready | `QueryStateBoundary` | Picks for you: loading > forbidden > error > empty > `children` |
|
|
306
317
|
|
|
307
318
|
---
|
|
308
319
|
|
|
@@ -419,6 +430,12 @@ renders a plain tag with no way to remove it.
|
|
|
419
430
|
removable chip. `icon` alone (no `onIconClick`) is the decorative case — a plain right-side icon
|
|
420
431
|
with no click affordance, aria-hidden.
|
|
421
432
|
|
|
433
|
+
### `Tag display="dot"` ignores `variant` and icons; `StatusTag` renders an unknown status neutral
|
|
434
|
+
|
|
435
|
+
`display="dot"` ignores `variant`, `icon`, `leadingIcon` and `onIconClick`. `StatusTag`'s `map` is
|
|
436
|
+
keyed by your status union, but a runtime value outside it (API drift) renders a neutral chip and
|
|
437
|
+
only warns in development — guard upstream if a silent neutral would mislead.
|
|
438
|
+
|
|
422
439
|
### A rounded box with `overflow: hidden` clips glyphs at the corners — never round the clipping element
|
|
423
440
|
|
|
424
441
|
`border-radius` reshapes the overflow clip, so a pill-shaped element with `overflow: hidden`
|
|
@@ -455,20 +472,33 @@ popovers and menus now paint `colors.surfaceRaised` — identical `#ffffff` in l
|
|
|
455
472
|
step up in dark. A custom panel, popover or `ModalContent bg=` in an app should read
|
|
456
473
|
`surfaceRaised` too, and a divider inside it `raisedRule(colors)`.
|
|
457
474
|
|
|
458
|
-
### `Drawer` / `Modal` / `ProfileCard` drop any child that isn't a named slot
|
|
475
|
+
### `Drawer` / `Modal` / `ProfileCard` drop any child that isn't a named slot — use `portalChildren`
|
|
459
476
|
|
|
460
477
|
All three match children by exact type (`child.type === XHeader/XBody/XFooter`) and render only
|
|
461
478
|
those matches — nothing else in `children` is ever read. A sibling among the slots (a nested
|
|
462
|
-
`Modal`, `AlertDialog`, a confirm dialog, a
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
drops the slot
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
479
|
+
`Modal`, `AlertDialog`, a confirm dialog, a live region) silently never mounts; `Drawer` and `Modal`
|
|
480
|
+
now warn once per dropped child type in development, `ProfileCard` still says nothing. All three
|
|
481
|
+
unwrap **one** `<>...</>` level around a slot (so `<>{cond && <DrawerFooter>...}</>` still renders)
|
|
482
|
+
and spread styling props (`padding`, `borderBottom`, `sx`, …) from the matched slot onto the real
|
|
483
|
+
header/body/footer — a second nested fragment, or any other wrapper element, still drops the slot
|
|
484
|
+
silently.
|
|
485
|
+
|
|
486
|
+
**Apply:** pass a nested confirm dialog, toast host or live region to `Drawer` / `Modal` as
|
|
487
|
+
`portalChildren`. It renders **inside** the dialog content after the slots (a sibling in the portal
|
|
488
|
+
would be `aria-hidden` by Chakra, so a live region there is never announced); a nested `AlertDialog`
|
|
489
|
+
portals out on its own, stacks above and returns focus. It unmounts with the dialog, so reset its
|
|
490
|
+
open state when the parent closes. `ProfileCard` has no such prop — keep its confirm dialog outside,
|
|
491
|
+
as a sibling in a wrapping fragment. When a ternary picks between bodies, branch into a variable
|
|
492
|
+
rendered inside one body slot, rather than returning fragment-wrapped slots per branch. `Drawer`'s
|
|
493
|
+
misspelled `vaiant` is `@deprecated` — use `variant`.
|
|
494
|
+
|
|
495
|
+
### `FormDrawer` has no browser validation, and its submit button sits outside the `<form>`
|
|
496
|
+
|
|
497
|
+
It sets `noValidate`: validate in `onSubmit` and pass messages via `errors`. Error-summary focus
|
|
498
|
+
fires only after a submit; if validation is async, set `isSubmitting` synchronously in `onSubmit` so
|
|
499
|
+
focus waits for the result, otherwise errors that arrive later are not focused. The footer submit
|
|
500
|
+
button is tied to the form with the `form` attribute — Enter-to-submit works in browsers, but
|
|
501
|
+
jsdom / user-event does not simulate it, so use `fireEvent.submit(form)` in tests.
|
|
472
502
|
|
|
473
503
|
### `QueryStateBoundary` evaluates JSX `children` even while loading
|
|
474
504
|
|
|
@@ -476,11 +506,23 @@ JSX children are built before the boundary decides what to show, so `data.items.
|
|
|
476
506
|
while `data` is still `undefined`. **Apply:** pass `children` as a function — `{() => <List
|
|
477
507
|
items={data.items} />}` — whenever it reads data that may not exist yet.
|
|
478
508
|
|
|
509
|
+
### `QueryStateBoundary` `isForbidden` and `hasData`
|
|
510
|
+
|
|
511
|
+
An `isForbidden` function is only called when `error` is set (never with `undefined`); `isForbidden:
|
|
512
|
+
true` shows the panel even with no error. `isLoading` + `hasData` keeps `children` visible during a
|
|
513
|
+
refetch, so pass `hasData` only when data is genuinely loaded — otherwise a first load shows a blank
|
|
514
|
+
region.
|
|
515
|
+
|
|
479
516
|
### `StatCard`'s delta colour follows `trend` vs `goodDirection`, not `trend` alone
|
|
480
517
|
|
|
481
518
|
Green when `trend === goodDirection`, red otherwise — a falling cost with `goodDirection="down"` is
|
|
482
519
|
green. Pass `onClick` for a clickable card (it renders its own `<button>`); never wrap it in one.
|
|
483
520
|
|
|
521
|
+
### `CircularProgress` `tone="info"` is the brand primary, not blue
|
|
522
|
+
|
|
523
|
+
Unlike `Tag` and `StatCard`, where `info` is blue, the default `tone="info"` here paints the brand
|
|
524
|
+
primary scale. `aria-label` is required — the ring has no visible caption.
|
|
525
|
+
|
|
484
526
|
### A clickable `TextInput` icon is a real button — give it a name
|
|
485
527
|
|
|
486
528
|
With `onRightIconclick`/`onLeftIconClick` the icon renders as a `<button>`. Without
|
|
@@ -560,6 +602,14 @@ accepted, typed, never called.
|
|
|
560
602
|
**Apply:** leave at least one column without a `node`, or put an explicit control inside a `node`
|
|
561
603
|
renderer instead of relying on row click.
|
|
562
604
|
|
|
605
|
+
### `Table.renderRowDetail` runs for every row on every render, and `expandedRows` ids match strictly
|
|
606
|
+
|
|
607
|
+
It decides whether each row gets a chevron, so an inline function re-renders every row (defeating
|
|
608
|
+
`TableRow`'s memo) — wrap it in `useCallback` / `useMemo`. `expandedRows` ids compare with `===`, so
|
|
609
|
+
`1` and `"1"` are different: keep the id type the same as `row.id`. It is not the older
|
|
610
|
+
`row.content` + `isContent` expander (chevron before the checkbox, index-based); both can coexist,
|
|
611
|
+
but only `row.content` still disables grouped virtualisation.
|
|
612
|
+
|
|
563
613
|
### `error` without `errorMessage` renders the literal word "Error" — and erases `helperText`
|
|
564
614
|
|
|
565
615
|
Every field that shows validation errors (`TextInput`, `InputTextArea`, `Select`, `MultiSelect`,
|
|
@@ -948,6 +998,11 @@ draw nothing.
|
|
|
948
998
|
|
|
949
999
|
**Apply:** drop the nested `CardBody`, or pass `bodyProps={{ p: 0 }}`.
|
|
950
1000
|
|
|
1001
|
+
To change the padding, use `padding="none" | "2xs" | "xs" | "sm" | "md" | "lg"`. `sx={{ p: ... }}` on
|
|
1002
|
+
the container *adds* to the body padding (double inset) and `sx={{ p: 0 }}` does nothing. `padding`
|
|
1003
|
+
is no longer Chakra's style prop (omitted from the type) — use `p` for a raw value. With
|
|
1004
|
+
`padding="none"` the header keeps `xs` padding.
|
|
1005
|
+
|
|
951
1006
|
### Commerce kit — read before building a shop screen
|
|
952
1007
|
|
|
953
1008
|
`ProductCard`, `ProductDetails`, `VariantSelector` and the bag pieces share one contract: pass
|
|
@@ -1114,6 +1169,39 @@ is also `null` until Jodit's lazy-loaded chunk resolves — a mount-time effect
|
|
|
1114
1169
|
**Apply:** never set `theme`/`popupRoot` inside the `config` you pass to `Editor`. To force a
|
|
1115
1170
|
remount, wrap `<Editor>` itself in a keyed parent, not via `Editor`'s own `key` prop.
|
|
1116
1171
|
|
|
1172
|
+
### `PdfViewer` `getBlob` — fetched on mount only; the toolbar already has Open and Download
|
|
1173
|
+
|
|
1174
|
+
- **Swapping the file needs a new React `key`.** `getBlob` is read through a ref and fetched on mount,
|
|
1175
|
+
so an inline arrow is safe, but changing it never refetches — the old document silently stays.
|
|
1176
|
+
- **The default fallback shows only a message while the toolbar is visible**; with
|
|
1177
|
+
`showToolbar={false}` it adds its own Open and Download buttons. `getBlob` mode makes the toolbar's
|
|
1178
|
+
actions work for authed files, so an app need not render its own — or pass `showToolbar={false}`.
|
|
1179
|
+
- Pass exactly one of `pdfUrl` / `getBlob`.
|
|
1180
|
+
|
|
1181
|
+
### `WizardDialog` — `validate` must be pure; controlled `stepId` does not unlock steps
|
|
1182
|
+
|
|
1183
|
+
`validate` runs on Continue, on Finish, and again for every step on Finish. Passing `stepId` controls
|
|
1184
|
+
the visible step only: stages past the furthest valid step stay disabled. Esc, close, Back and Cancel
|
|
1185
|
+
are disabled while `isFinishing`.
|
|
1186
|
+
|
|
1187
|
+
### `PageHeader` actions wrap by default
|
|
1188
|
+
|
|
1189
|
+
`actionsLayout` defaults to `"auto"`, so actions that do not fit drop below the title at `md`+. A
|
|
1190
|
+
test asserting the old single-row layout needs `actionsLayout="inline"`.
|
|
1191
|
+
|
|
1192
|
+
### `Editor` merge fields — chips, raw values and stale closures
|
|
1193
|
+
|
|
1194
|
+
- **Chips are `<span data-field contenteditable="false">`.** Do not style or strip `[data-field]` in
|
|
1195
|
+
consumer CSS or sanitisers, and sanitise the raw `${path}` value `onChange` reports, not Jodit's HTML.
|
|
1196
|
+
- **A hand-typed `${path}` stays plain text** until `value` is next applied from outside; only tokens
|
|
1197
|
+
inserted through the menu / `apiRef` or already present in `value` become chips. Unknown-token
|
|
1198
|
+
detection still runs on the raw value.
|
|
1199
|
+
- **`config.extraButtons[].exec` goes stale** (the memo key is `JSON.stringify`, which drops functions).
|
|
1200
|
+
Use `toolbarButtons` — React buttons, always current.
|
|
1201
|
+
- **`jodit-react` binds `onChange` / `onBlur` once, keyed on handler identity, not `config`.** After
|
|
1202
|
+
Jodit is re-created (readonly or height change) a stable handler stops receiving events. `Editor`
|
|
1203
|
+
binds them itself per instance; don't copy the pattern when wrapping Jodit directly.
|
|
1204
|
+
|
|
1117
1205
|
### `Editor`'s Jodit toolbar is fixed for screen readers and keyboard, from our wrapper only
|
|
1118
1206
|
|
|
1119
1207
|
Jodit's own markup (`node_modules/jodit`) put `aria-label` on each button's `role="listitem"`
|
|
@@ -1182,6 +1270,47 @@ Each mounted `Search` registers its own `window` Ctrl+K listener, so two on one
|
|
|
1182
1270
|
keypress. **Apply:** pass `shortcut={false}` on all but one. `showShortcutHint={false}` only hides
|
|
1183
1271
|
the hint; the listener stays.
|
|
1184
1272
|
|
|
1273
|
+
The same applies to a launcher: `NavLauncher` and `LauncherTrigger` bind no chord, and the library
|
|
1274
|
+
reserves `mod+k` for the app's own palette. The app must pass `shortcut={false}` on every page
|
|
1275
|
+
`Search`, or claim the chord in capture phase (`keydown` on `window` with `capture: true`) before
|
|
1276
|
+
the `Search` listeners see it — otherwise the first mounted `Search` takes Ctrl+K.
|
|
1277
|
+
|
|
1278
|
+
### `NavLauncher` — the app owns routing, registry, query and chord
|
|
1279
|
+
|
|
1280
|
+
- **`linkAs` must forward `className`, `ref`, `onClick`, `href`, `target`, `rel`, `tabIndex` and
|
|
1281
|
+
`aria-hidden`** to its anchor. Dropping `className` loses all row styling; dropping `onClick` means
|
|
1282
|
+
a click never closes the launcher.
|
|
1283
|
+
- **`onNavigate` fires for keyboard opens only** (Enter, mod+Enter). Pointer clicks follow the
|
|
1284
|
+
rendered links, so a router `linkAs` must do the navigation.
|
|
1285
|
+
- **Controlled `query`:** the launcher still calls `onQueryChange("")` when it closes; the app must
|
|
1286
|
+
apply it or the stale query reopens.
|
|
1287
|
+
- **Search rows are not nested links.** The visible label is a text-only `role="option"`; the real
|
|
1288
|
+
anchor is an `aria-hidden`, `tabIndex={-1}` overlay (so copy-link and mod-click work) and pin / ↗
|
|
1289
|
+
are `aria-hidden` siblings. Screen readers use Enter / mod+Enter. Do not nest links inside the
|
|
1290
|
+
option — axe `nested-interactive` fails.
|
|
1291
|
+
- **The apps section decides "compact" with `matchMedia("(min-width: 48em)")`** and falls back to
|
|
1292
|
+
desktop (hidden) where `matchMedia` is missing (SSR, jsdom). Tests must stub it to see the section.
|
|
1293
|
+
- **`P` on a focused NavLauncher row pins it** instead of starting type-ahead; in the search field it types the letter. Rows without a star (Recent, key screens, apps) keep type-ahead.
|
|
1294
|
+
- **`NavLauncher` `suggestions` empty falls back to `noResultsHint`** instead of showing chips.
|
|
1295
|
+
- **`PinToggle` / `NewTabLink` are opacity 0 until row hover or focus-within**, so a consumer's own row must carry `data-group` (or `role="group"`) to reveal them.
|
|
1296
|
+
- **`LauncherLabels.screensGroup` is unused** by search now (sections replaced the flat group); kept so label objects still type-check.
|
|
1297
|
+
- **`apps` is data-driven.** Gate by plan by changing the array or setting `locked` / `lockedReason`;
|
|
1298
|
+
keep `id`s stable (hues and `key` derive from them), and pass `color` on an app whose mark must not
|
|
1299
|
+
shift when siblings are added or removed. Locked rows are not links, not focusable, `aria-disabled`,
|
|
1300
|
+
tooltip = `lockedReason`. Pass `appsVisibility="always"` to show them above `md`.
|
|
1301
|
+
- **Never use `:has()` in an emotion style.** jsdom's (nwsapi) `getComputedStyle` can throw ("not a valid selector") and takes every consumer test that opens a
|
|
1302
|
+
Drawer down with it. The launcher marks row focus with a `data-row-focus` attribute instead. If you
|
|
1303
|
+
hit that error in your own tests on a newer jsdom, report it with the selector.
|
|
1304
|
+
- **Launcher rows are CSS containers** (`container-type: inline-size`, name `launcher-row`); jsdom
|
|
1305
|
+
drops `@container` rules, so tests assert the style objects (`titleInset`, `WIDE_ROW`), not the
|
|
1306
|
+
stylesheet.
|
|
1307
|
+
- **A search row without `href` (an action with `run`) cannot open in a new tab:** any click, with or
|
|
1308
|
+
without Cmd/Ctrl, runs it and closes the launcher, same as Enter.
|
|
1309
|
+
- **`LauncherTrigger` does not bind its shortcut**; `shortcut={null}` removes the hint and
|
|
1310
|
+
`aria-keyshortcuts`. An explicit `aria-label` hides the visible label from assistive tech, so keep
|
|
1311
|
+
the visible text inside the label (WCAG 2.5.3). `display="icon"` has no visible text: the label is
|
|
1312
|
+
its accessible name and tooltip.
|
|
1313
|
+
|
|
1185
1314
|
### `Header`'s desktop submenus open on hover only — no keyboard or click trigger
|
|
1186
1315
|
|
|
1187
1316
|
Dropdown children are gated on local hover state (`onMouseEnter`/`onMouseLeave`), with no `onFocus`.
|
|
@@ -1217,6 +1346,9 @@ It's declared on the type but omitted from the component's destructure entirely.
|
|
|
1217
1346
|
|
|
1218
1347
|
**Apply:** don't pass it expecting it to mark or style the final crumb — there's nothing it can do.
|
|
1219
1348
|
|
|
1349
|
+
With `overflow="wrap" | "truncate"` each crumb is `noOfLines={1}` with a `title`, so one very long
|
|
1350
|
+
label ellipsizes; the default `"nowrap"` is unchanged.
|
|
1351
|
+
|
|
1220
1352
|
### `Accordion`'s `items[].buttonProps` replaces, not merges, the expanded/hover highlight
|
|
1221
1353
|
|
|
1222
1354
|
It spreads after the built-in `bg`/`_hover` that encode `isExpanded` state — passing `bg` or
|
|
@@ -1245,16 +1377,56 @@ error, no warning, `scrollTop` on a non-scrolling parent just stays `0` forever.
|
|
|
1245
1377
|
**Apply:** `ScrollToTop`'s JSX parent must be the actual scroll container, or pass `useWindow` when
|
|
1246
1378
|
the page itself scrolls.
|
|
1247
1379
|
|
|
1248
|
-
### `ProfilePhotoViewer`'s PDF detection breaks the moment a file is picked, and `photoUrl`
|
|
1380
|
+
### `ProfilePhotoViewer`'s PDF detection breaks the moment a file is picked, and a new `photoUrl` discards the preview
|
|
1249
1381
|
|
|
1250
1382
|
PDF detection is a literal `.endsWith(".pdf")` check — picking a file through the built-in editor
|
|
1251
1383
|
replaces the value with a base64 data URI that never ends in `.pdf`, so a freshly-picked PDF renders
|
|
1252
1384
|
as a broken image instead of the intended file badge (only the original URL prop is detected
|
|
1253
|
-
correctly). Separately, `photoUrl`
|
|
1254
|
-
|
|
1385
|
+
correctly). Separately, a changed `photoUrl` re-syncs the component and replaces any locally picked
|
|
1386
|
+
preview (a same-URL re-render keeps it), so a parent that updates `photoUrl` before the upload has
|
|
1387
|
+
finished makes the preview vanish mid-upload.
|
|
1255
1388
|
|
|
1256
1389
|
**Apply:** don't use the built-in edit flow for PDF documents; detect kind from `File.type` in your
|
|
1257
|
-
own handler instead.
|
|
1390
|
+
own handler instead. Update `photoUrl` only once the upload has finished. `key={photoUrl}` is no
|
|
1391
|
+
longer needed.
|
|
1392
|
+
|
|
1393
|
+
### `Tabs` link mode needs `href` on every item, and has no default current item
|
|
1394
|
+
|
|
1395
|
+
One item without `href` makes the whole thing a normal tablist and `href` is ignored everywhere (a
|
|
1396
|
+
dev-only `console.warn` is the only signal). Button tabs select the first enabled item when `value`
|
|
1397
|
+
is missing; link tabs mark nothing `aria-current` until you pass `value`. A plain left-click calls
|
|
1398
|
+
`onChange` but never `preventDefault`s; modifier and middle clicks only open the link. `isDisabled`
|
|
1399
|
+
link items render as a non-link `span`.
|
|
1400
|
+
|
|
1401
|
+
**Apply:** `Tabs items=[{ id, label, href }] linkAs={RouterLink} value={currentId}` with `value`
|
|
1402
|
+
derived from the route, and never hand-build `Box as={Link}` tabs.
|
|
1403
|
+
|
|
1404
|
+
### `BulkSelectionBar` renders nothing at `selectedCount` 0, and `sticky` needs a scroll ancestor
|
|
1405
|
+
|
|
1406
|
+
With no persistent live region it announces count changes itself (the node mounts empty and fills in
|
|
1407
|
+
an effect), so don't also announce from your own region. `placement="sticky"` pins only inside an
|
|
1408
|
+
ancestor scroll container — an ancestor with `overflow: hidden` silently disables it. Combining it
|
|
1409
|
+
with `Table`'s `headerActions` gives two action sets for one selection.
|
|
1410
|
+
|
|
1411
|
+
### `SectionRail` chooses rail vs `Select` with `matchMedia` at render time
|
|
1412
|
+
|
|
1413
|
+
It renders the rail when `matchMedia` is missing (SSR). In the `Select` branch a dirty section's
|
|
1414
|
+
option reads `"Label (dirtyHint)"` — a native `<option>` cannot hold a dot.
|
|
1415
|
+
|
|
1416
|
+
### `CalendarGrid` is fully controlled, ignores time of day, and `renderDayCell` turns multi-day bars off
|
|
1417
|
+
|
|
1418
|
+
Without `onDateChange` / `onViewChange` the toolbar's Today/Prev/Next and the view switcher are
|
|
1419
|
+
hidden and arrow keys stop at the edge of the visible range, so the grid looks static — wire both.
|
|
1420
|
+
`start` / `end` are read as local calendar dates (`end` inclusive): a UTC-midnight `Date` shows the
|
|
1421
|
+
previous day in a negative-offset zone, so build date-only values with `new Date(y, m, d)`.
|
|
1422
|
+
`renderDayCell` replaces each cell's chips wholesale: a 3-day event is passed to it for all 3 days
|
|
1423
|
+
but is no longer drawn as one bar, and `onEventClick` never fires from your own content.
|
|
1424
|
+
|
|
1425
|
+
### `AudioRecorder` needs a secure context, and `onRecorded` is not called after unmount
|
|
1426
|
+
|
|
1427
|
+
`getUserMedia` is undefined on plain http (except localhost), so the component shows its
|
|
1428
|
+
"unsupported" state there, not "permission denied". A parent that navigates away mid-recording gets
|
|
1429
|
+
no `onRecorded` call (the mic is released instead), and an empty recording never calls it either.
|
|
1258
1430
|
|
|
1259
1431
|
### `FilePreview` infers file kind from `fileName`, not `fileUrl`, and never resets zoom/rotation on its own
|
|
1260
1432
|
|
|
@@ -1378,6 +1550,21 @@ it; now `@deprecated` in `SideBarProps.tsx`.
|
|
|
1378
1550
|
|
|
1379
1551
|
**Apply:** don't pass `selectedSubMenu` expecting it to highlight a submenu row.
|
|
1380
1552
|
|
|
1553
|
+
### `SideBar` pinned rows, `autoCollapse` and `collapseTransition`
|
|
1554
|
+
|
|
1555
|
+
- **`autoCollapse={false}` also silences the `open` prop** (`open` works by calling `changeToggle`).
|
|
1556
|
+
Drive collapse with `toggle` only.
|
|
1557
|
+
- **A pinned id highlights only in the pinned block** while `activePinnedId` matches, and the parent
|
|
1558
|
+
submenu of a pinned child does not auto-open. An `activePinnedId` past `pinnedLimit` expands the
|
|
1559
|
+
list so the active state never disappears.
|
|
1560
|
+
- **Pinned rows are anchors with `href={url}`**: a plain click calls `handleMenuClick` (and closes the
|
|
1561
|
+
overlay), modified clicks fall through to the browser. Unpin is a sibling button, never nested.
|
|
1562
|
+
- **`collapseTransition` affects the `lg`+ inline rail only** — overlay slide, drag and `mobileNav`
|
|
1563
|
+
are untouched.
|
|
1564
|
+
- **The rail focus ring is lifted per surface** (`sidebarFocus.ts`) because `colors.focusRing.ring` is
|
|
1565
|
+
derived for the page canvas and fails 3:1 on the rail for five light brands. The lasting fix is a
|
|
1566
|
+
`sidebar.focusRing` theme token.
|
|
1567
|
+
|
|
1381
1568
|
### `KanbanBoard`'s `kanbanSelect`/`onOpen` don't check `permissions` — decision: accepted as-is
|
|
1382
1569
|
|
|
1383
1570
|
Looked like an asymmetry with the gated `kanbanEdit`/`kanbanCreate`/`onDelete`, but on inspection
|