@dcs-tech/ui 0.8.0 → 0.10.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/CHANGELOG.md +496 -0
- package/README.md +56 -5
- package/dist/{ChartImageMenu-AsfvmdTH.js → ChartImageMenu-3OfqNFyt.js} +557 -546
- package/dist/{ChartView-CW3m4Z_1.js → ChartView-n4G5_2ro.js} +35 -31
- package/dist/{SummaryChart-CxRjK_HU.js → SummaryChart-i6fOdrDM.js} +2 -2
- package/dist/{SummaryImage-DeYs2Jgj.js → SummaryImage-CCt5ozD9.js} +2 -2
- package/dist/{SummarySeeAll-CrmROhBv.js → SummarySeeAll-BY8knsRe.js} +5 -5
- package/dist/assets/fileTask.worker--Q3rI3Bn.js +1 -0
- package/dist/{columnValue-DwUqueZ6.js → columnValue-74XDBcVF.js} +219 -192
- package/dist/{exportContext-BKFnNQ0q.js → exportContext-C52ZuHd8.js} +2 -2
- package/dist/{exportEngine-CZ22cX7a.js → exportEngine-BmDly7iw.js} +3 -3
- package/dist/file-worker.js +1 -1
- package/dist/{fileActions-COf5Q4Eg.js → fileActions-CFNO14Aj.js} +1 -1
- package/dist/{geometry-yZmKN662.js → geometry-DG134nYI.js} +379 -273
- package/dist/index.js +12808 -9621
- package/dist/{labels-CnqqTrne.js → labels-BPItSeRU.js} +2 -0
- package/dist/{runFileTask--4YjQH7Y.js → runFileTask-BIZTFnZP.js} +55 -39
- package/dist/scrollArea-D84Cwm4o.js +310 -0
- package/dist/style.css +1 -1
- package/dist/{summaryChartData-CARqGRUl.js → summaryChartData-BiQYJbYZ.js} +8 -2
- package/dist/types/components/Alert/Alert.d.ts +16 -0
- package/dist/types/components/Alert/index.d.ts +2 -0
- package/dist/types/components/Card/Card.d.ts +4 -3
- package/dist/types/components/Card/index.d.ts +1 -1
- package/dist/types/components/Charts/Funnel.d.ts +2 -1
- package/dist/types/components/Charts/chartImage.d.ts +1 -0
- package/dist/types/components/ChipInput/ChipTags.d.ts +3 -0
- package/dist/types/components/CommandPalette/CommandPaletteTrigger.d.ts +9 -0
- package/dist/types/components/CommandPalette/index.d.ts +2 -0
- package/dist/types/components/DataTable/TablePagination.d.ts +1 -1
- package/dist/types/components/DataTable/TableToolbar.d.ts +2 -1
- package/dist/types/components/DataTable/TableView.d.ts +1 -0
- package/dist/types/components/DataTable/cards/cardFields.d.ts +1 -0
- package/dist/types/components/DataTable/defaults.d.ts +4 -0
- package/dist/types/components/DataTable/index.d.ts +1 -1
- package/dist/types/components/DataTable/labels.d.ts +2 -0
- package/dist/types/components/DataTable/types.d.ts +19 -2
- package/dist/types/components/DataTable/ui-local/TableReorderList.d.ts +13 -0
- package/dist/types/components/DataTable/ui.d.ts +2 -1
- package/dist/types/components/DataTable/useTable.d.ts +1 -0
- package/dist/types/components/DatePicker/PeriodGrid.d.ts +13 -0
- package/dist/types/components/DatePicker/PeriodPicker.d.ts +19 -0
- package/dist/types/components/DatePicker/index.d.ts +1 -1
- package/dist/types/components/Dialog/dialogSlots.d.ts +9 -0
- package/dist/types/components/DropdownMenu/DropdownMenu.d.ts +8 -0
- package/dist/types/components/FieldWrapper/index.d.ts +1 -1
- package/dist/types/components/Fields/index.d.ts +1 -1
- package/dist/types/components/Image/ImageEditor.d.ts +21 -0
- package/dist/types/components/Image/ImagePicker.d.ts +10 -1
- package/dist/types/components/Image/imageRender.d.ts +33 -0
- package/dist/types/components/Image/index.d.ts +3 -1
- package/dist/types/components/Image/prepareImage.d.ts +4 -3
- package/dist/types/components/Link/Link.d.ts +22 -0
- package/dist/types/components/Link/index.d.ts +2 -0
- package/dist/types/components/NavList/NavList.d.ts +13 -0
- package/dist/types/components/NavList/index.d.ts +2 -0
- package/dist/types/components/PageProgress/PageProgress.d.ts +10 -0
- package/dist/types/components/PageProgress/index.d.ts +2 -0
- package/dist/types/components/Pagination/Pagination.d.ts +19 -0
- package/dist/types/components/Pagination/index.d.ts +2 -0
- package/dist/types/components/Popover/Popover.d.ts +1 -1
- package/dist/types/components/Popover/floatingPosition.d.ts +4 -0
- package/dist/types/components/ReorderList/ReorderGroup.d.ts +16 -0
- package/dist/types/components/ReorderList/ReorderList.d.ts +55 -0
- package/dist/types/components/ReorderList/crossListDrag.d.ts +61 -0
- package/dist/types/components/ReorderList/index.d.ts +5 -0
- package/dist/types/components/ReorderList/useReorderDrag.d.ts +28 -0
- package/dist/types/components/Tooltip/useTooltip.d.ts +4 -0
- package/dist/types/components/UIProvider/UILabelsContext.d.ts +86 -0
- package/dist/types/core/hooks/index.d.ts +1 -0
- package/dist/types/core/hooks/useMeasuredState.d.ts +1 -0
- package/dist/types/core/logic/alert.logic.d.ts +3 -0
- package/dist/types/core/logic/commandPalette.logic.d.ts +2 -0
- package/dist/types/core/logic/datePicker.logic.d.ts +12 -0
- package/dist/types/core/logic/fieldWrapper.logic.d.ts +6 -1
- package/dist/types/core/logic/imageEditor.logic.d.ts +132 -0
- package/dist/types/core/logic/imageTransform.logic.d.ts +57 -0
- package/dist/types/core/logic/index.d.ts +9 -0
- package/dist/types/core/logic/inertProps.d.ts +3 -0
- package/dist/types/core/logic/pageProgress.logic.d.ts +3 -0
- package/dist/types/core/logic/pagination.logic.d.ts +7 -0
- package/dist/types/core/logic/periodPicker.logic.d.ts +86 -0
- package/dist/types/core/logic/reorder.logic.d.ts +49 -0
- package/dist/types/core/types/chipinput.types.d.ts +3 -1
- package/dist/types/core/types/collapsible.types.d.ts +3 -0
- package/dist/types/core/types/datePicker.types.d.ts +7 -0
- package/dist/types/core/types/field.types.d.ts +6 -3
- package/dist/types/core/types/fieldWrapper.types.d.ts +2 -0
- package/dist/types/core/types/fields.types.d.ts +6 -1
- package/dist/types/core/types/form.types.d.ts +1 -0
- package/dist/types/core/types/format.types.d.ts +2 -0
- package/dist/types/core/types/input.types.d.ts +2 -0
- package/dist/types/core/types/navigation.types.d.ts +1 -0
- package/dist/types/core/types/select.types.d.ts +2 -6
- package/dist/types/core/types/suggest.types.d.ts +2 -0
- package/dist/types/index.d.ts +25 -7
- package/package.json +3 -2
- package/dist/assets/fileTask.worker-BHT1olUk.js +0 -1
- package/dist/scrollArea-Dd2dNMV4.js +0 -236
- package/dist/types/components/DataTable/ui-local/DragAndDropList/DragAndDropList.d.ts +0 -4
- package/dist/types/components/DataTable/ui-local/DragAndDropList/index.d.ts +0 -3
- package/dist/types/components/DataTable/ui-local/DragAndDropList/types.d.ts +0 -70
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,496 @@
|
|
|
1
|
+
# @dcs-tech/ui
|
|
2
|
+
|
|
3
|
+
## 0.10.0
|
|
4
|
+
|
|
5
|
+
### Upgrading from 0.9
|
|
6
|
+
|
|
7
|
+
Most of this release adds to what is there. These can change an existing screen:
|
|
8
|
+
|
|
9
|
+
- **Bulk actions:** an `onRun` that returns nothing now shows no toast and keeps the rows selected. An action that does its work and returns nothing should return a result, or call `api.clearSelection()`. Rows turned down by `eligible` are then not summarised; the handler gets them as `ctx.skipped`.
|
|
10
|
+
- **Select and Suggest lists** fit their content by default, up to a limit. `listWidth="field"` gives the old width for one field.
|
|
11
|
+
- **Icons** in icon-only buttons and the Sidebar are larger (20px at `small`). The buttons stay the same size. An icon with its own `size` keeps it. Check dense toolbars.
|
|
12
|
+
- **DataTable page size:** `pagination: { pageSize: 10 }` with no `pageSizeOptions` shows 10 rows and offers 10. A `pageSize` outside the app's own options starts on the first option.
|
|
13
|
+
- **DataTable `emptyMessage`** now applies only with no search or filter active. Set `noResultsMessage` for the other case.
|
|
14
|
+
- **DatePicker:** the confirm button's default text is "Apply" (pass `applyLabel="Search"` to keep the old word). In a Form, Tab moves on instead of submitting. A press outside reports `onOpenChange(false, 'blur')`, not `'escape'`.
|
|
15
|
+
- **DropdownMenu:** a controlled menu takes focus when it opens, which can blur a field being edited. A `header` passed as an element no longer gets the forced text style.
|
|
16
|
+
- **Input `type="file"`** no longer takes `value`. Read `event.target.files`.
|
|
17
|
+
- **`reorder` on Select** now really drags, and `fixedItems` also locks those first places.
|
|
18
|
+
- **`fullWidth` on text fields** is deprecated: it warns once and does not change the width. Use `width`.
|
|
19
|
+
|
|
20
|
+
Removed with no deprecation period, for anyone using the `useSelect` hook directly: `handlers.handleDragStart`, `handleDragOver`, `handleDragEnd`, `handleDrop`, `state.draggedItem` and `draggedOver`. Use `handlers.handleReorder`. Also removed: the DataTable classes `.drag-and-drop-list`, `.drag-and-drop-item` and `.drag-and-drop-handle`; use `.dt-reorder-frame` and `.dt-reorder-item`.
|
|
21
|
+
|
|
22
|
+
### Minor Changes
|
|
23
|
+
|
|
24
|
+
- aff428a: Breadcrumbs: new `iconOnly` on `NavItem` shows only a crumb's icon, on the home crumb, any crumb or the last one. The label stays the accessible name as visually hidden text, so a non-string label works, and an item with no icon still shows its label. Only Breadcrumbs reads it.
|
|
25
|
+
- f06bc9d: Card: `selected` shows a card as chosen (and sets `aria-pressed` on a clickable one); `aria-*`, `data-*`, drag events and other element attributes pass through to the root; the title is now a real heading, `h3` by default with `headingLevel` to choose (or `'none'` for a span). The title looks the same at every level. A clickable card is a button, so its title stays a span.
|
|
26
|
+
- b0fa6e8: ChipInput: `tags` and `onTagsChange` make it a field of free-text tags. Enter, a comma or leaving the field adds what is typed, a pasted list is split, duplicates are ignored, and Backspace in the empty input removes the last. `sources` is now optional. Without `tags` it is the format-string editor, unchanged. New label `chipInput.removeTag`.
|
|
27
|
+
- d1e907e: Collapsible: `keepMounted` (on the container or one item) renders closed panels' content too, so an FAQ is in the server-rendered HTML. Closed content stays hidden and out of the tab order. The default is unchanged: content mounts on first expand.
|
|
28
|
+
- 88aaeba: DataTable: a search or filter that leaves no rows now says so, separately from a view with no data. New `noResults` label and `noResultsMessage` view option. `emptyMessage` and the `empty` label keep their meaning but now apply only when no search or filter is active, so an app that set only `emptyMessage` shows the new default text for an empty search.
|
|
29
|
+
- a7d56b9: **DataTable: `toolbarActions`** (view option): an app's own buttons on the toolbar line, such as "Add", whatever is selected. Each has `label`, `icon`, `variant`, `display`, `tooltip`, `disabled`, `onClick`, and is left out by its own `authorize` or by `authorize('toolbarAction', action)` (a new gate). On a phone an action with an icon shows only the icon; when the line runs out of room the buttons move to a second line at the right.
|
|
30
|
+
- 6fefbd7: DatePicker: `picker="month"` and `picker="year"` pick a month or a year with no day. The value is `yyyy-mm` or `yyyy` (`{ from, to }` of the same with `range`) and the field reads by the locale ("Nov 2026"). The panel has a month grid with year navigation or a paged year grid, typing (`11/2026`, `nov`, `2026`), full keyboard navigation (arrows, Home/End, PageUp/PageDown, Enter, Escape, Tab) and `min`/`max` that also take `yyyy-mm` and `yyyy`. Fields and Form get `field: 'date'` (`DateFieldDefinition`), for days, months and years. New `labels.datePicker` words: `previousYear`, `nextYear`, `previousYears`, `nextYears`, `month`, `year`, `from`, `to`, `rangeTo`, `selected`, `chooseMonth`, `chooseYear`.
|
|
31
|
+
- 4f10dfb: DatePicker: the year list now reaches 100 years back and 10 ahead, long enough for a date of birth. New `yearRange` prop (`{ back, ahead }`) changes that; `min` and `max` always cut the list and set any end `yearRange` leaves out. New `autoComplete` prop for the typing boxes, default still `off`.
|
|
32
|
+
- 4e83751: DropdownMenu: rail icons get `selected` (shown and announced as `menuitemcheckbox`); `closeOnSelect` on one icon or row overrides the menu's; `className` and `style` on one icon or row; `onOpen`, for controlled and trigger menus. A `header` that is not plain text no longer gets the forced semibold, secondary colour, nowrap and ellipsis, so a name over an email shows as written; a text header looks the same.
|
|
33
|
+
|
|
34
|
+
Keyboard fixes: in a browser the first row never took focus when opened by key (the surface is hidden while measured), so the arrows did nothing. Fixed. A controlled menu now takes focus as it opens and gives it back on close, so its arrows work. Tab closes and carries on from the trigger, also when it was opened by pointer. The icon rail is reachable by arrow keys, and focus follows into and out of a pane.
|
|
35
|
+
|
|
36
|
+
- f5ef4ac: Add a `width` prop to the text fields (Input, Select, Suggest, DatePicker, ChipInput), to custom
|
|
37
|
+
widgets through `FieldWrapper`, and to `Fields` / `Form` definitions under `fprop`. Exported type:
|
|
38
|
+
`FieldWidth`.
|
|
39
|
+
|
|
40
|
+
- no `width`: today's field, the row up to `--field-control-max-width` (320px). No existing field
|
|
41
|
+
changes.
|
|
42
|
+
- `width="full"`: the row, with no limit.
|
|
43
|
+
- `width="auto"`: the content. Given less room it fits its parent and the text is cut.
|
|
44
|
+
- a number or a CSS length: exactly that, and never wider than its parent.
|
|
45
|
+
|
|
46
|
+
It works the same in `default`, `inline` and `horizontal` (where it sizes the control column; the
|
|
47
|
+
label keeps `--field-label-width`) and in every variant. In `cell` it is ignored: the column owns
|
|
48
|
+
the width. Checkbox, Radio and Switch do not take it.
|
|
49
|
+
|
|
50
|
+
**Deprecated:** `fullWidth` on these fields. It keeps working for one release and warns once,
|
|
51
|
+
naming `width`, when it is passed. It has never changed a field's width, and it still does not:
|
|
52
|
+
`fullWidth`, `fullWidth={true}` and `fullWidth={false}` all render as a field with no `width`. To
|
|
53
|
+
fit the content use `width="auto"`; to fill the row, `width="full"`. If both are passed, `width`
|
|
54
|
+
wins. `fullWidth` on Button, ButtonGroup, Tabs, Checkbox, Radio and Switch is unchanged.
|
|
55
|
+
|
|
56
|
+
- 6c06908: Form: `dialogSlots` puts the form's header and actions in the header and footer bands of the Dialog it is rendered in, so they stay in view while the fields scroll. Save is tied to the form by the `form` attribute, so submit, Enter and validation keep working. Outside a Dialog it does nothing, and the default is unchanged.
|
|
57
|
+
- 70a858b: `useFormat()`: `dateTime(value)` writes the day in the date format with the time as the locale writes it (`03-11-2026 2:30 pm`), and `shortDate(value)` writes the day with the month as a word (`3 Nov 2026`).
|
|
58
|
+
- 9f8ffb6: Summary funnel cards for figures that are not narrowing steps (an amount per payment method). `showChange: false` hides the change from the step before, on the rows, in the tooltip and the picture, and gives its column to the bars (`Funnel` takes the same prop). `chart: 'bars'` draws the card as bars, and users can pick it in Manage.
|
|
59
|
+
- 69971b5: New `ImageEditor`: crop (drag and resize box, ratios, free, circle mask), zoom, pan, quarter turns, straighten and flip, with mouse, touch and keyboard, in place or in a Dialog. A compact row of icon buttons under the image. A host allows or restricts each tool with `crop`, `zoom`, `pan`, `rotate`, `straighten`, `flip` and `reset`: a restricted tool has no button and no key, and cannot appear in the output, even through `initialTransform`. `crop.minWidth` and `crop.minHeight` refuse an output below them with a message, and nothing is ever enlarged. `output` sets the size limits, type and quality. EXIF orientation is honoured once. A remote image whose server does not allow CORS shows a clear message. `panel` adds the host's own content, such as a preview of the result.
|
|
60
|
+
|
|
61
|
+
ImagePicker: `editable` opens each chosen or replacing file in the editor first, so `onAdd` and `onReplace` get the edited file. `editor` passes the editor's options through. `onEdit` adds an Edit action to each tile, and with `editable` and `onReplace` it opens the editor on `item.editSrc` (or `item.src`). Existing callers are unchanged.
|
|
62
|
+
|
|
63
|
+
`prepareImage` takes a `transform`, the same one the editor gives, so crop, rotate and flip can run with no UI. `ImagePrepareError` has a `code`. New exports `resolveImageTransform` and `imageOutputSize`, and new labels under `imageEditor`.
|
|
64
|
+
|
|
65
|
+
- 8b1c25f: ImagePicker: `onReplace` swaps a single image at `max={1}` (click or drop on a Replace tile), `dropZone` draws the add tile as a wide drop zone, `max={Infinity}` means no limit and drops the "2 / 5" count, and `onRemove` is optional (no remove button without it). New labels `image.replace` and `image.drop`.
|
|
66
|
+
- dd19a67: Input: `type="file"` takes `accept` and `multiple`, has a styled choose-file button on the browser's own control, and is no longer controlled, so a re-render cannot clear the chosen file (read `event.target.files`). `type="color"` is a proper swatch with its value beside it. Read-only disables both, since neither has a read-only mode of its own.
|
|
67
|
+
- e699ab8: Select and Suggest lists fit their content. By default a list is as wide as its longest option: never narrower than its field, up to a limit (320px for Select, 480px for Suggest; `--popup-list-width-max` changes it), and always on screen. A row past the limit is cut off, with the full text on hover. The new `listWidth="field"` makes the list exactly the field's width, as does `position.matchWidth: true`. Fields are not changed. Select no longer passes `fullWidth` to the DOM.
|
|
68
|
+
- 16fd40f: New components. `Link`: a styled anchor; `as` takes a router's link. `Alert`: status tones (info, success, warning, danger), optional title, icon, action and dismiss, the right live-region role for each tone, and a page-wide `banner` form. `Pagination`: controlled page controls for anything paged that is not a DataTable, with a page list or a simple "Page 1 of 8", the row range and a size select. `CommandPaletteTrigger`: a ready button for `CommandPalette`, with text and keycap on wide screens and an icon button on small ones. `PageProgress`: a thin bar along the top while a route changes, driven by `active`, showing nothing for a quick navigation and standing still under reduced motion. `NavList`: a vertical list of links for inside a page, over `NavItem` and by the same link rule as `Sidebar`. Their words are in new `UIProvider labels` groups: `link`, `alert`, `pagination`, `pageProgress`, `navList`, and `commandPalette.trigger`.
|
|
69
|
+
- e8bd2f0: One reorder everywhere. `Select`'s `reorder` and the DataTable's Card fields / List fields editor now run on `ReorderList` instead of their own native drag and drop, so rows slide live, and both work on touch and with the keyboard.
|
|
70
|
+
|
|
71
|
+
`ReorderList` gains (all additive): `role` and `itemRole`; `axis="wrap"` for chips on several lines; `ReorderGroup` with `onMove`, for rows that travel between lists, with `listId`, `maxItems`, `whenFull` (`reject` or `replace`) and `sortable`, live sliding in the destination, keyboard steps through the lists in order and announcements (new `labels.reorder.movedToList` and `droppedInList`); `autoScroll` and `autoScrollSpeed`; `handleRef`, whose `move(key, step)` moves a row for an owner that keeps the focus elsewhere; and `data-reorder-grab` for a control inside a row that should drag on a press that travels and click otherwise.
|
|
72
|
+
|
|
73
|
+
`Select`: the selected options render as a `ReorderList` with the rest below them. A selected row drags from anywhere on it (on touch, its handle at once or the row after a long press). The focus stays on the search box or trigger: Alt+Up / Alt+Down moves the row under the keyboard cursor, and the plain arrows, Enter and Escape are unchanged. Escape during a drag cancels only the drag. Dragging is off while a search narrows the list. `reorder={true}` now drags too (it used to only put the selected options first). `fixedItems` also locks those first places by position. All of `ReorderConfig` is still accepted, and `dragHandleClassName` and `autoScrollSpeed`, which nothing read before, now work. In reorder mode the rows are `role="option"` and the selected ones are `<div>`s inside the ReorderList (new labels `select.selectedOptions` and `select.reorderInstructions`).
|
|
74
|
+
|
|
75
|
+
Card fields editor: fields can also be placed at a position within a part, the grip now shows on touch, and each field in the "not shown" pool has a grip for the keyboard. Enter on a pool field still adds it. New label `fieldsMove`. CSS: `.dt-cle-slot--drop` is gone, use `[data-reorder-over]`; `.dt-cle-chip-grip` is gone, the grip is `ReorderList`'s handle.
|
|
76
|
+
|
|
77
|
+
Breaking, for anyone using the `useSelect` hook directly: `handlers.handleDragStart`, `handleDragOver`, `handleDragEnd` and `handleDrop` and `state.draggedItem` and `draggedOver` are removed (use `handlers.handleReorder`). The `AutoScrollState` type is still exported, deprecated.
|
|
78
|
+
|
|
79
|
+
- 8873e83: New `ReorderList`: a drag-to-reorder list where the dragged row lifts with a shadow and follows the pointer while the other rows slide apart. One code path for mouse, touch and pen (a handle drags at once; `dragFrom="row"` asks for a long press on touch, so the page still scrolls). Vertical or horizontal, rows of any size, auto-scroll near the edges of scrolling containers, works inside a Dialog, honours reduced motion. Keyboard: Space or Enter on a focused handle picks up, arrows move, Space or Enter drops, Escape cancels, announced to screen readers through the new `labels.reorder` of `UIProvider`. Controlled, with `items`, `getKey`, `renderItem`, `onReorder`, plus `canDrag` and `isFixed`.
|
|
80
|
+
|
|
81
|
+
DataTable now uses it for the column chooser, the export columns, Manage's view tabs and templates, its summary cards and the "Grouped by" chips, so these all slide live and can be reordered with the keyboard and on touch. The private drag list and its classes (`.drag-and-drop-list`, `.drag-and-drop-item`, `.drag-and-drop-handle`) are gone; CSS that reached into them should target `.dt-reorder-frame` and `.dt-reorder-item`.
|
|
82
|
+
|
|
83
|
+
- 5eeae92: DataTable: `disableTextTransform` on a row action shows its button's label as written. Labels are uppercase otherwise, as on every Button.
|
|
84
|
+
|
|
85
|
+
### Patch Changes
|
|
86
|
+
|
|
87
|
+
- aff428a: Breadcrumbs: the home crumb sizes only its icon, so a text label reads at the trail's size. A home crumb with a text label is also named by that label, not by a fixed "Home".
|
|
88
|
+
- a7d56b9: **DataTable: what a bulk action's `onRun` returns now decides the feedback** (behaviour change).
|
|
89
|
+
|
|
90
|
+
- **Returns nothing** (or a promise of nothing): the table says nothing and keeps the selection. It used to show "N done" and clear the selection straight away, even when the action had only opened a dialog that still needed the rows. An action that wants the old result returns one: `{}` gives the counted summary. An action that finishes later lets go of the rows with `api.clearSelection()`.
|
|
91
|
+
- **Returns a result**: reported exactly as before (`done`, `skipped`, `reason`, `message`, `status`, `undo`, `keepSelection`).
|
|
92
|
+
- **Throws or rejects**: the failure is always reported and the selection stays, as before.
|
|
93
|
+
|
|
94
|
+
Rows `eligible` turned down are no longer counted in a toast when `onRun` returns nothing: the action receives them as `skipped`. In server mode the table still fetches the rows again after an action that returned nothing.
|
|
95
|
+
|
|
96
|
+
- a7d56b9: **DataTable: an explicit `pageSize` wins when the app set no `pageSizeOptions`.** `pagination: { pageSize: 10 }` shows 10 rows (it showed 25), in client and server mode, and the selector offers 10 among the default sizes. The same goes for `initialState.pageSize`, and for a view's `pageSize` when switching to a view with no options of its own. The fallback to the first option now applies only to options the app set itself (on the view's `pagination` or on the `dataSource`).
|
|
97
|
+
|
|
98
|
+
The table's page size selector also keeps its sizes in order (10, 25, 50, 100, not 10, 100, 25, 50) and has no search box, like the standalone `Pagination`.
|
|
99
|
+
|
|
100
|
+
- 88aaeba: DataTable: a `pageSize` that is not in the app's own `pageSizeOptions` now starts on the first option, so the page-size selector no longer shows a placeholder. "All" is skipped when another option exists. This also applies when another view offers different options. With no `pageSizeOptions` from the app, the explicit `pageSize` wins (see below).
|
|
101
|
+
- 88aaeba: DataTable server mode: changing a view's `params` returns to page 1, with no request for the old page of the new params. Params are compared by value, so a new object with the same contents changes nothing, and a restored page index survives the mount.
|
|
102
|
+
- 4d09353: DatePicker: the confirm button's default text is now "Apply", not "Search". `applyLabel` still sets it per field (`''` hides it), and `labels.datePicker.apply` on `UIProvider` sets it for the app. A screen that relied on the default to read "Search" should pass `applyLabel="Search"`.
|
|
103
|
+
- b756194: DatePicker, days: the panel's date and time boxes no longer act on the grid or form around them (an arrow moved the table's cell, Tab moved it twice, Enter submitted the form). A failed Form submit now finds `field: 'date'` and focuses it (`data-name` on the trigger). A read-only or disabled field no longer opens by keyboard or by the `open` prop. Space opens the panel without replacing the box's text with a blank.
|
|
104
|
+
- b929252: DatePicker, days: closing the panel with Enter, Escape or the confirm button puts the focus back on the field, so Enter-to-next carries on in a Form or a table. A press outside now reports `onOpenChange(false, 'blur')` instead of `'escape'`, and leaves the focus where it landed. In a Form, Tab from the panel closes it and moves to the next field; it used to submit the form. Time boxes are still reached with Tab first.
|
|
105
|
+
|
|
106
|
+
Fields in a grid: Delete or Backspace no longer empties a read-only or disabled cell. This covers every field that clears through the grid, not only the DatePicker.
|
|
107
|
+
|
|
108
|
+
- 0665a92: Icons fill their space. An icon-only `Button`'s icon scaled with the button's text, about 13px in a 36px button; it now uses the new `--icon-size-xxs` … `--icon-size-xl` tokens (20px at `small`) and the button stays the same size. Sidebar icons use them too (20px, 16px on child rows), and the box and child indent now follow `--ui-scale`, so they zoom with the text. An icon given its own `size` keeps it.
|
|
109
|
+
- 656912e: Input: a `Button` in `icon.start` or `icon.end` no longer makes the field taller, at any pairing of button size and field size.
|
|
110
|
+
- f5ef4ac: Fix a Select's list running past the right edge of a phone screen when an option is long, and a
|
|
111
|
+
ChipInput tag longer than its field pushing out of the field. The tag's text is now cut instead.
|
|
112
|
+
- 14d7aba: The build's leak check now also scans `src/`, stories and tests included.
|
|
113
|
+
- a3d762c: Fix `Input type="password"` being taller than other fields at small sizes (32px against 28 at
|
|
114
|
+
`xxs`, up to 44 against 42 at `medium`). The show/hide button no longer sets the field's height.
|
|
115
|
+
- da337de: DatePicker `picker="month"` and `picker="year"`: one click or Enter chooses a single period and closes the panel, with the focus back on the field; clicking the period already chosen keeps it instead of clearing it. A single value has no confirm button, so the "Search" default no longer appears and `applyLabel=""` is no longer needed. A `range` closes once a click leaves two different ends, and shows a confirm button only when `applyLabel` is passed. `onApply` is called when a click or Enter chooses. Enter now also takes a cell reached with the panel's page buttons or year list, and the year list no longer jumps back to the value.
|
|
116
|
+
- 8324f7b: Fix opening a Select crashing with "Maximum update depth exceeded" on React 18. The list's
|
|
117
|
+
position is measured on every render, and React 18 kept replaying a waiting update against old
|
|
118
|
+
state, so the measurement never settled. Suggest's list had the same pattern and is fixed with it.
|
|
119
|
+
Also fix the `inert` attribute on React 18, where it was dropped with a warning, so leaving
|
|
120
|
+
surfaces and closed Collapsible content stayed reachable by keyboard.
|
|
121
|
+
- a5e99a5: DataTable: pressing a button, link or field inside a row no longer tints the whole row. The browser's `:active` also matches a parent of the pressed control, so a row looked clicked on every button press. Only a press on the row itself shows the tint and opens the row.
|
|
122
|
+
- 52af1d3: Sidebar: the expand chevrons and the collapse bar's chevron follow `--ui-scale`, so they zoom with the row's icon and text.
|
|
123
|
+
- 7a987e6: Sidebar: the collapsed rail's flyout keeps its title and rows while it animates out. It used to empty at once, so the exit played on a bare strip where the panel had been.
|
|
124
|
+
- 9f8ffb6: - ScrollStrip (Tabs, filter chips, view tabs): while the strip overflows, slim rectangular ‹ › boxes stand either side of it, always there, with the one that has nothing further that way disabled. They go when everything fits.
|
|
125
|
+
- DatePicker: the preset's name no longer stays after the app changes the value. It stays only if the new dates still match a preset; otherwise the dates show.
|
|
126
|
+
- Input: the password toggle is an icon, not an emoji.
|
|
127
|
+
- 0dc8be7: Tooltips and the collapsed Sidebar's flyouts no longer flicker. There is one tip at a time, and appearing from nothing or leaving to nothing are the only moves that animate: moving from one trigger to the next swaps in a single frame, with no delay and no fade, and never two tips on screen. In the collapsed Sidebar, flyouts and tips hand over the same way, and a flyout re-entered during its exit no longer restarts its entrance from invisible. A tip the pointer left during its delay was never seen, so it no longer shortens the next tip's wait. Rail tips anchor to their row, so they all line up.
|
|
128
|
+
|
|
129
|
+
## 0.9.0
|
|
130
|
+
|
|
131
|
+
### Minor Changes
|
|
132
|
+
|
|
133
|
+
- 1f3104b: Dialog, export and packaging fixes found while adopting 0.8.0.
|
|
134
|
+
|
|
135
|
+
- **Dialog: focus on open.** The contents render once the dialog is open, so a child with `autoFocus` (or one that focuses itself as it mounts) gets the focus. It used to land on the close button.
|
|
136
|
+
- **Dialog: Esc can no longer get past a veto.** Escape is handled on keydown, so Chrome's own close (which skips `cancel` after a repeated Esc) never starts. `onBeforeClose` returning false and `closeOnEscape={false}` now hold however many times Esc is pressed. A child that handles Esc itself (a list closing) is left alone. If the browser closes the dialog anyway while `open` is true, it reopens, so the screen and `open` always agree.
|
|
137
|
+
- **Dialog: focus returns when an open dialog unmounts** (`{cond && <Dialog open />}`, a `useDialog()` confirm), to the element that had it before, as on a normal close.
|
|
138
|
+
- **PDF export on a dev server with engine fonts.** With `createFileEngine({ pdfFonts })`, PDFs in the Vite dev server failed with "Roboto-Regular.ttf not found": the raw pdfmake font file registers its fonts privately, and the engine's fonts hid them. They are now caught and merged, as in a build.
|
|
139
|
+
- **DataTable: failed export messages.** The result in the export panel is announced (`role="alert"` for an error, `status` otherwise). If the panel was closed while the file was being made, a failure or warning shows as a toast instead of being lost.
|
|
140
|
+
- **DataTable: `actionsHeader`** (view option) shows the actions column's "Actions" header. Default stays hidden (screen readers only).
|
|
141
|
+
- **`DialogHost` is exported**, so `useDialog()` works without the whole `UIProvider`.
|
|
142
|
+
- **`--dialog-width` is documented** as the supported way to size a dialog beyond `size` (README, `size` prop docs, Dialog → Custom Width story).
|
|
143
|
+
- **The package ships `CHANGELOG.md`.**
|
|
144
|
+
- **Sidebar: the collapsed rail's flyout closes** when the pointer moves on to a row with no children. It used to stay open, with that row's tooltip on top of it.
|
|
145
|
+
|
|
146
|
+
## 0.8.0
|
|
147
|
+
|
|
148
|
+
### Minor Changes
|
|
149
|
+
|
|
150
|
+
- 12b372e: DataTable defaults closer to a compact report table:
|
|
151
|
+
|
|
152
|
+
- Nothing is pinned by default: the first column is pinned only with `pinning: { firstColumn: true }`, a column's `sticky`, or the user pinning it.
|
|
153
|
+
- Row selection is on by default (on demand): the toolbar's Select button shows without bulk actions (the summary and the export follow the selection). Started with that button, selecting stays on until the button or Clear — unticking every row no longer hides the checkboxes. `selection: false` turns it off.
|
|
154
|
+
- The actions column stays pinned on the right at every width (it was unpinned at phone width and scrolled away). `pinning: { actions: false }` unpins it.
|
|
155
|
+
- Up to two row actions are buttons on each table row (new view option `inlineActions`, default 2; 0 = only ⋮): primary ones first, a 'danger' one only when primary. Cards and list items keep their one primary action.
|
|
156
|
+
- Shorter rows and header: the duplicate density paddings that overrode Compact / Default / Comfortable are gone; row action buttons are 28px and the header's filter / menu buttons 20px (default row 57px → 41px, header 46px → 33px).
|
|
157
|
+
- The "Showing all N rows" status line is not drawn while idle (the toolbar shows the count); it appears with selection, filters, grouping or a changed sort.
|
|
158
|
+
- The table fits where it stands: content above it (a date filter, a title) stays on screen with the toolbar, rows and bottom bar, as long as the rows keep 320px; otherwise the rows take the viewport's height as before.
|
|
159
|
+
|
|
160
|
+
ButtonGroup: a button with a tooltip no longer breaks the group's corners (the last button came out square on the right).
|
|
161
|
+
|
|
162
|
+
- 28a17ff: Select and Suggest lists fit the viewport: placed on the side of the field with more room (flipping on the height the list wants), and capped to the room there so their rows scroll inside the list — a long list no longer runs off-screen, where in a modal it could not be reached, and scrolling it never scrolls the page. An inline Suggest list (outside tables) measures its room inside the box that clips it (a dialog body) and opens upward when that side has more. A list whose field scrolls out of sight HIDES and comes back with it (the place in the list is kept); a popover (date calendar, menus) closes. `computePopoverPosition` returns `available` (the room on the chosen side). New Dialog story "All dropdowns inside" (Select, Suggest, calendar, menu; top and bottom of a scrolling body) and tests that each renders inside the dialog and that Escape closes the list, not the dialog.
|
|
163
|
+
|
|
164
|
+
Toasts show above modal dialogs: while a modal is open they render inside the topmost one (in `<body>` the modal — top layer — covered them and made them unclickable, including the error of a save made from that dialog), and move back once it has closed. Modal dialogs carry `data-modal` and their opening order; `useDialogOpen()` now stays true until a dialog has finished closing. New Dialog story "Everything over modals": toasts, tooltips, a confirm and a select over a dialog and a nested dialog.
|
|
165
|
+
|
|
166
|
+
DataTable's own toast (bulk action results, Undo) renders in the portal container too, so a table inside a modal dialog shows it above the dialog.
|
|
167
|
+
|
|
168
|
+
Suggest joins its list on the right side: when the list opens above, the field squares its TOP corners (and the list its bottom edge) instead of the bottom ones — Select already did. `SuggestionListProps.onPlacementChange` reports the side.
|
|
169
|
+
|
|
170
|
+
Lists opened ABOVE their field sit exactly as they do below: joined (outlined / filled) with no gap, floating (standard / underlined) 4px clear on the field's side — they overlapped by 3px (Select) or stood 6px off (Suggest). Placed by their exact rendered height (fractional, untouched by the entrance animation), so no hairline. An inline Suggest list hides while its field is out of sight, like Select's. New `--field-border-t` on the field control. New story: Fields / List placement — every variant of Select and Suggest, top and bottom of a page and of a scrolling modal.
|
|
171
|
+
|
|
172
|
+
- 39d51ae: Navigation gaps found moving an app onto Sidebar and Breadcrumbs:
|
|
173
|
+
|
|
174
|
+
- Sidebar: a parent row that is also a page (`href`, or a router link's `to` in `props`, plus `children`) is a link, and gets its own expand chevron beside it (a sibling button, never inside the link). Without a target a parent stays an expander row.
|
|
175
|
+
- Sidebar: new `beforeNav` slot between the header and the menu (a switcher, a search — the app's own JSX), outside the scrolling list.
|
|
176
|
+
- Sidebar: `header`, `beforeNav` and `footer` take a `SidebarSlot` — plain content, `{ expanded, collapsed }`, or `({ collapsed }) => content`. A state with no content draws no band at all (an `expanded`-only header leaves no empty band in the rail). A phone drawer is never collapsed. New export: type `SidebarSlot`.
|
|
177
|
+
- Sidebar and Breadcrumbs: the collapsed rail's hover menu and the breadcrumb related-pages menu render real links (`as` / `href` / `props`), like the rows, so an app never has to navigate in `onSelect` — and so never navigates twice. `onSelect(item, event)` now receives the click; on a link it is for side effects only.
|
|
178
|
+
- Breadcrumbs: `siblingsOf` may return groups (`group: true` with `children`), shown as section headings; the crumb's own page may be in the list and is marked current (✓, `aria-current`) instead of being offered. A crumb whose only sibling is itself gets no switcher.
|
|
179
|
+
- Sidebar: new `onCollapsedChange` — the sidebar's own collapse control: expanded, a full-width bar at the bottom; in the icon rail, an expand icon right after the last icon (pinned to the bottom when the icons overflow), and every empty space below it expands too, down to the bottom edge (desktop only; a drawer below 600px has none of it).
|
|
180
|
+
- New labels: `sidebar.showChildren`, `sidebar.collapse`, `sidebar.expand`. New stories: Navigation/Sidebar (parent rows that are pages, a branch switcher in `beforeNav` that opens a menu — the same menu from an icon in the rail, never expanding it — the collapse bar, the collapsed rail), Breadcrumbs "Grouped related pages".
|
|
181
|
+
- Sidebar collapse / expand is smooth end to end: the areas keep their width while moving (no squeezed switcher), their content fades out and the other state's fades in, an area the coming state has nothing for folds away (and grows back), open branches fold up during the collapse, and rail rows keep the expanded rows' height — nothing jumps when the rail arrives.
|
|
182
|
+
|
|
183
|
+
- 44afd0a: Form validates any Standard Schema (Zod, Valibot, ArkType, Yup 1.7+) with no `validate` adapter; blur checks only the field left; a failed submit shows every error (they used to stay hidden on untouched fields) and focuses the first. Form's `onChange`, `onBlur` and `validateOnBlur` now fire (they were never wired to the fields). Form's Submit/Reset and error toasts come from `labels.form`. New `Fields` prop `onFieldBlur`; new exports `validateStandardSchema`, `isStandardSchema`, `StandardSchemaV1`.
|
|
184
|
+
|
|
185
|
+
Dialog: a failing `action` in `confirm()` / `choose()` now rejects the caller's promise (it resolved as if it had succeeded). New `useDialogOpen()` for an app's own loading overlay.
|
|
186
|
+
|
|
187
|
+
Scroll: Tabs scroll inside ScrollStrip (fades and ‹ › arrows; the active tab is centred); edge fades on Dialog body, CommandPalette, Select / Suggest lists and Sidebar nav; Dialog body keeps a stable scrollbar gutter; Sidebar and DatePicker no longer override the shared scrollbar. `ScrollStrip` takes `as` and `stripRef`.
|
|
188
|
+
|
|
189
|
+
DropdownMenu: the icon row's tooltips use the library Tooltip, so the menu's edge no longer cuts them off.
|
|
190
|
+
|
|
191
|
+
- ba4fbe3: Tooltip `tone`: `'default' | 'info' | 'success' | 'warning' | 'danger'` — the theme's status colours with their readable text colours (light and dark), on `<Tooltip>` and on every component's `tooltip` prop (`tooltip={{ content, tone: 'danger' }}`). Default stays the neutral tip. New export: type `TooltipTone`.
|
|
192
|
+
|
|
193
|
+
### Patch Changes
|
|
194
|
+
|
|
195
|
+
- 0a00022: Scroll fades no longer fade the scrollbars. The fade and the scrollbar say the same thing ("there is more this way"), and the thumb only shows while the area is pointed at, focused or scrolling — so at those moments the fade on the edge that carries a bar (the bottom one when there is a horizontal scrollbar, the inline-end one when there is a vertical scrollbar) fades out with the thumb's timing, and back in when the thumb hides. A table with many rows keeps its "more rows" fade at rest, and its horizontal bar is never faded. The listener marks `data-scroll-overflow-x` / `-y`.
|
|
196
|
+
- f3fbd35: DataTable Manage ▸ summary: typing straight into a card's name field just opened could be wiped (the field re-synced to the old name after the first keystrokes) and the rename lost. It now follows the name only when it changes from outside.
|
|
197
|
+
|
|
198
|
+
## 0.7.0
|
|
199
|
+
|
|
200
|
+
### Minor Changes
|
|
201
|
+
|
|
202
|
+
- dd961d4: Engine-level PDF fonts. `createFileEngine({ pdfFonts: { fonts, vfs } })` (or `UIProvider fileEngine={{ pdfFonts }}`) sends large fonts, such as a Unicode or script font, to each background worker once, when it starts, instead of with every PDF task. Tasks can then leave `fonts` out; a task's own fonts still go over the engine's. Builds on the main thread use the same fonts.
|
|
203
|
+
- eeaafc1: Stable styling hooks on fields, and Select's `onBlur` fixed.
|
|
204
|
+
|
|
205
|
+
- Every field marks its parts with `data-part`: `root`, `label-row`, `label`, `content`, `control` (the bordered box, or the box / circle / track of Checkbox, Radio and Switch), `trigger` (Select and DatePicker, as `"control trigger"`), `messages`, `error` and `hint`. Class names are hashed per build, so style through these, e.g. `.my-form [data-part~="control"] { … }`.
|
|
206
|
+
- **Fix:** Select's `onBlur` prop was never called. It now fires like every other field's.
|
|
207
|
+
- Select's blur and focus events carry the field name: the trigger has `name` (as a property, like an input) and `data-name`, so one shared `onBlur` can read `event.target.name` for Input, Suggest and Select alike.
|
|
208
|
+
|
|
209
|
+
- fec33a9: The file helpers are public: `downloadBlob`, `shareFile`, `openPreview`, `rawDataToBlob`, `createPdfBlob`, `executeFileAction`, `getExtension`, `getFormatLabel`, `safeFileName`, `safeFileBaseName`, `EXTENSION_MAP`, `MIME_MAP`, and the types `PdfFontConfig` and `FileAction`. An app that kept its own copies for one-off files (an importer, an older export) can use these instead. `createPdfBlob` builds through the hang-safe PDF builder; pdfmake loads on the first PDF.
|
|
210
|
+
- 6a7c4ed: File-engine notices through the app's own toasts. `FileEngineProvider`'s `notify` now also takes a function, and `UIProvider host={{ onFileNotice }}` sets one app-wide. It receives a `FileJobNotice`: `'awaiting-click'` (with `message`, `actionLabel`, `deliver()` and `dismiss()`), `'failed'` (with `message`, `actionLabel`, `retry()` and `dismiss()`), or `'resolved'` (close what you showed for that job). When a function is set, the library's toasts stay silent. Without one, nothing changes.
|
|
211
|
+
- e80ef21: The file engine's worker is published under a stable name, `@dcs-tech/ui/file-worker`, for bundlers other than Vite and webpack 5: build a module worker that imports it and pass `createWorker` to the engine. The README's new "Files and the background worker" section explains when this is needed. Vite and webpack 5 apps need no changes.
|
|
212
|
+
- b8357fc: App-wide hooks on `UIProvider`, and Form confirmations in the library's dialog.
|
|
213
|
+
|
|
214
|
+
- `UIProvider host={{ renderAuthorize, onToast, onNavigate, renderLoading, onConfirm }}` sets the app's hooks once for every Form, Fields, Collapsible and EditableTable below. A component's own prop still wins. `HostProvider` changes them for one section, and `useUIHost()` reads them. New types: `UIHostDefaults` and `UIConfirmRequest`.
|
|
215
|
+
- **Behaviour change:** a Form action with `confirm` no longer uses the browser's `window.confirm`. It asks the form's new `onConfirm` prop first, then `host.onConfirm`, then the library's dialog. Only with no `UIProvider` at all does it fall back to `window.confirm`.
|
|
216
|
+
|
|
217
|
+
- fec33a9: DataTable's Excel and PDF exports build in the file engine's background worker, so a large export no longer freezes the page. The file looks the same: title lines, header colours, stripes, `cellStyle` colours, totals, summary, page numbers.
|
|
218
|
+
|
|
219
|
+
- The worker's task types take plain-data styling. `XlsxSheetSpec` has new optional `before` / `after` rows (`XlsxRowSpec`, with `merge`), `headerStyle`, `stripe`, `cellStyles`, `autoFilter` and `freeze`, using `XlsxCellStyle` and `XlsxBorder`. `XlsxColumnSpec` has a new `style`. A `pdf` task has new `tableLayouts` (`PdfTableLayoutSpec`, used by name as a table's `layout`) and `footer` (`PdfPageFooterSpec`, with `{page}` and `{pages}`). Existing tasks build as before, except that the header row of an XLSX task is now always bold.
|
|
220
|
+
- ExcelJS now loads only when an Excel file is built. Before, the table's export code loaded it as soon as the export code loaded.
|
|
221
|
+
- Where the browser has no workers, or `fileEngine={{ workers: 'off' }}` is set, the same files build on the main thread as before.
|
|
222
|
+
|
|
223
|
+
## 0.6.0
|
|
224
|
+
|
|
225
|
+
### Minor Changes
|
|
226
|
+
|
|
227
|
+
- e8c7791: App-wide formatting: set locale, currency and date format once on `UIProvider`.
|
|
228
|
+
|
|
229
|
+
- `UIProvider` takes `locale` (e.g. `'en-IN'`), `currency` (e.g. `'INR'`) and `dateFormat` (`'dd-mm-yyyy'` | `'dd/mm/yyyy'` | `'yyyy-mm-dd'`). `FormatProvider` changes one of them for a section of the app; the rest is inherited.
|
|
230
|
+
- `useFormat()` formats through the browser's `Intl`: `number(1250000.5)` → `12,50,000.5`, `money(1250000)` → `₹12,50,000.00`, `percent(0.725, 1)` → `72.5%`, `day('2026-11-03')` → `03-11-2026`.
|
|
231
|
+
- DataTable (its `locale` prop still wins), DataTable date columns, DatePicker (its `displayFormat` still wins), EditableTable read-only numbers and totals, and Charts (numbers, dates, weekday names, the image) follow these settings.
|
|
232
|
+
- **Behaviour change:** with no locale set anywhere, numbers and dates now use the browser's locale. Summary figures, Charts and export dates used to be fixed to `en-IN` — set `locale="en-IN"` on `UIProvider` to keep Indian formatting.
|
|
233
|
+
|
|
234
|
+
- 222d56d: Collapsible API cleanup (breaking, minor on 0.x).
|
|
235
|
+
|
|
236
|
+
- **`CollapsibleAuthorize` is now any value your app chooses** (`unknown`) — a role, a feature key, an object. The library never reads it; it only passes it to `renderAuthorize`, which now receives it as `any`. It used to be a fixed object shape (`type` / `tab` / `subtab` / `featurename` / …) from one application's permission model. Existing objects still work; code that relied on the type's fields should declare its own type.
|
|
237
|
+
- **Removed `Component`, `JSX` and `props` from `CollapsibleItemProps`.** Pass the content as `children` (`<CollapsibleItem><MyPanel {...p} /></CollapsibleItem>`, or `children: <MyPanel {...p} />` in `items`).
|
|
238
|
+
- A `loading` item now marks its header `aria-disabled` and its panel `aria-busy`.
|
|
239
|
+
- `CollapsibleItem` is no longer wrapped in `React.memo` (it re-rendered on every toggle and every new `children` anyway).
|
|
240
|
+
|
|
241
|
+
- c614d05: File engine: build files, queue them, follow their progress and deliver them — with XLSX and PDF built in a background worker so the page never freezes.
|
|
242
|
+
|
|
243
|
+
- `createFileEngine({ concurrency, maxQueued, timeoutMs, keepFinished, workers, deliver, createWorker })`. Jobs are either a `build` function (main thread) or a plain-data `task` — `{ kind: 'xlsx', workbook }` or `{ kind: 'pdf', document, fonts }` — built in a background worker where possible. Per job: `priority`, `dedupeKey` (a double click makes one file), `replace`, `retry`, `action` (`download` / `share` / `preview` / `print` / `open` / `none`), `onReady`.
|
|
244
|
+
- Cancel (a worker is stopped mid-file), automatic and manual retry, a timeout instead of a hang, progress reporting.
|
|
245
|
+
- Share / preview / print / open need a fresh click in the browser. A file that finishes after that window waits as ready (`awaitingClick`) for `deliver(id)` from a click, instead of failing silently.
|
|
246
|
+
- Falls back to the main thread by itself when a worker cannot start (an unsupported bundler) or a task cannot be copied into one (a pdfmake document with layout functions). Tested with Vite 8 (production and dev) and webpack 5.
|
|
247
|
+
- `UIProvider` provides one engine to the whole app (`fileEngine` prop: options or an engine instance); `FileEngineProvider` gives a section its own.
|
|
248
|
+
- `useFileEngine()`, `useFileJob(id)`, and `<FileJobsTray>` — progress, cancel, retry, dismiss and the deliver button — with `labels`. Under `UIProvider`, a file waiting for a click and a failed file are also toasted, with the button that acts on them.
|
|
249
|
+
- The package now ships `dist/assets/fileTask.worker-*.js`. It imports `exceljs` and `pdfmake` by name — they stay dependencies, not bundled.
|
|
250
|
+
- DataTable exports and the Charts image menu (Download / Share) now run as jobs on the app's file engine: one shared queue, one file per double click, and they appear in `<FileJobsTray>`. Export results are reported in the export popover as before.
|
|
251
|
+
- **Fix:** a PDF export whose document pdfmake could not render (an undefined font, a broken table) hung forever. It now fails with pdfmake's reason.
|
|
252
|
+
- Engine additions: `wait(id)` (resolves with a job's outcome), and per-job `title` (the share sheet / preview window name) and `notify` (`'all'` or `'awaiting-click'`, for callers that report failures themselves).
|
|
253
|
+
- DataTable labels: `exportCancelled`, `exportAwaitingClick`.
|
|
254
|
+
|
|
255
|
+
- 8af90a0: DataTable dates: sorting, filters, grouping, the summary and exports work on the date, not on its text.
|
|
256
|
+
|
|
257
|
+
- New column options for `type: 'date'`: `parse` (`'dd-mm-yyyy'`, `'dd/mm/yyyy'`, `'yyyy-mm-dd'`, or a function) says how the stored value is read; `dateFormat` says how it is shown and exported as text (default `'dd-mm-yyyy'`).
|
|
258
|
+
- Date columns sort chronologically — for Date objects, ISO strings and `parse`d text — with blanks last in both directions. (Before, every date sorted as text: `dd-mm-yyyy` by day of month, Date objects by weekday name.)
|
|
259
|
+
- Date filters (the from / to column search, before / after / equals) compare days read through `parse`. `before` / `after` no longer use `new Date()`, which read `03-11-2026` as 11 March.
|
|
260
|
+
- Grouping uses the local day (a Date used to group by its UTC day, so rows near midnight landed on the wrong day), labelled in the column's format; the summary's per-day / per-month cards read through `parse`; the row menu's Only / Hide use the day.
|
|
261
|
+
- **Behaviour changes:** a date column without `cell` now shows its dates in `dateFormat` (`03-11-2026`) instead of the raw value, and exports them the same way; filter chips show dates in that format. Digits-only date text in an unknown order (`03-11-2026` without `parse`) is now read as no date rather than guessed — set `parse`.
|
|
262
|
+
|
|
263
|
+
- bb4e43b: DataTable value / format: one value per cell that every feature uses, and its text for people.
|
|
264
|
+
|
|
265
|
+
- New column options: `value(row)` (a computed or typed value — `cell` receives it, and sorting, filters, search, grouping and exports read it), `format(value, row)` (the text shown without `cell`, searched, and used by cards, copy and exports), and `numberFormat` presets `'integer'` / `'amount'` / `'currency'` / `'percent'` in the app's locale and currency (UIProvider).
|
|
266
|
+
- Per-feature overrides where they genuinely differ: `sortValue`, `compare`, `searchText`, `groupValue`.
|
|
267
|
+
- Global search matches a cell's text as shown (`03-11-2026`, `₹12,50,000.00`, an option's label) as well as its stored value.
|
|
268
|
+
- **Behaviour changes:** every column sorts blanks last in both directions (blank numbers used to sort as 0; blank text first when ascending). Select columns sort by their option labels.
|
|
269
|
+
|
|
270
|
+
- 95e0601: DataTable exports: each file format gets the right form of each value.
|
|
271
|
+
|
|
272
|
+
- **Excel:** real numbers and real dates (not text), with the column's number format — the date format, the `numberFormat` preset (`"₹"#,##0.00` with the app's currency), `#,##0` for whole numbers. The spreadsheet can sort, filter and sum them. Number formats now apply to date cells too.
|
|
273
|
+
- **CSV, PDF, HTML:** the text as shown on screen (`format`, the date format, the number preset).
|
|
274
|
+
- **JSON, XML:** typed values; dates as ISO days.
|
|
275
|
+
- **Totals** are summed from the typed values (formatted money used to total 0).
|
|
276
|
+
- **Two columns with the same header** no longer overwrite each other: the second becomes `Amount (2)` — also in `prepareExportRows`.
|
|
277
|
+
- **Formula injection:** text starting with `=`, `+`, `-`, `@`, a tab or a carriage return is prefixed with `'` in CSV and Excel, so a spreadsheet shows it instead of running it. Numbers are never touched.
|
|
278
|
+
|
|
279
|
+
- 8483ee6: Built-in words in the app's language: one `labels` dictionary for the whole library.
|
|
280
|
+
|
|
281
|
+
- `UIProvider` takes `labels` — any subset of `DEFAULT_UI_LABELS` (dialog buttons, Clear, Loading…, Select / Suggest / CommandPalette texts, DatePicker words and its 13 preset names, EditableTable row actions, Image picker / viewer, screen-reader names). `LabelsProvider` overrides some for a section; `useUILabels()` reads them. A component's own prop (`confirmLabel`, `clearLabel`, `loadingText`, `placeholder`, …) still wins.
|
|
282
|
+
- `labels.table` and `labels.charts` set DataTable's and Charts' dictionaries app-wide, under each component's own `labels`.
|
|
283
|
+
- DatePicker month and weekday names now come from the browser's `Intl` in the app's locale (English keeps "Su Mo Tu"); `monthNames` / `weekdayNames` still override.
|
|
284
|
+
- No visible change for English apps.
|
|
285
|
+
|
|
286
|
+
## 0.5.0
|
|
287
|
+
|
|
288
|
+
### Minor Changes
|
|
289
|
+
|
|
290
|
+
- 04735b6: Collapsible: state, nesting and id fixes.
|
|
291
|
+
|
|
292
|
+
- An item's own `defaultExpanded` now works inside `<Collapsible>` (as a direct child with an `id`, or as an `items` entry). It was ignored, so `Form` sections set to start open started closed.
|
|
293
|
+
- **Behaviour change — controlled mode is now truly controlled.** When `expanded` is passed, a click only calls `onChange`; the panel moves when the parent passes the new value back. Before, it also flipped an internal copy, so a parent that ignored `onChange` still saw panels move and then drift out of sync. If you pass `expanded`, store what `onChange` reports.
|
|
294
|
+
- `onChange` no longer fires twice under React StrictMode.
|
|
295
|
+
- An item's own `onChange` now fires when its header is toggled inside a container.
|
|
296
|
+
- Nested accordions: opening an outer item no longer opens, rotates or tints the items of an accordion inside it, and arrow keys stay within one level.
|
|
297
|
+
- A `CollapsibleItem` used on its own now gets the default (small) size and a turning chevron.
|
|
298
|
+
- Clicking the chevron of an open item now closes it. The rotated chevron used to sit above the header's click area and swallow the click.
|
|
299
|
+
- `animationDuration={0}` now disables the animation instead of falling back to 300ms.
|
|
300
|
+
- Header/panel DOM ids now always include a generated prefix, so two accordions using the same item ids no longer produce duplicate ids. Code that looked up `${id}-header` / `${id}-content` by id must use the `aria-controls` / `aria-labelledby` attributes instead.
|
|
301
|
+
- `items` entries without an `id` now get `item-<index>` as their id.
|
|
302
|
+
- New type exports: `CollapsibleDisclosure`, `CollapsibleTone`, `CollapsibleHeadingLevel`.
|
|
303
|
+
|
|
304
|
+
### Patch Changes
|
|
305
|
+
|
|
306
|
+
- e6c2a6c: Fix webpack 5 builds: DataTable's PDF export now imports `pdfmake/build/pdfmake.js` and `pdfmake/build/vfs_fonts.js` with their extensions. This package is an ES module package, so webpack 5 resolves its imports strictly, and the extensionless paths failed every webpack 5 build that included DataTable ("failed to resolve only because it was resolved as fully specified"). Vite builds were not affected. A test now requires an extension on any deep import into a dependency without an `exports` map.
|
|
307
|
+
|
|
308
|
+
## 0.4.0
|
|
309
|
+
|
|
310
|
+
### Minor Changes
|
|
311
|
+
|
|
312
|
+
- 93177d2: Charts: a button per part when pickable, and the charts follow the UI scale.
|
|
313
|
+
|
|
314
|
+
- **A button per part.** With `onSelect`, a chart is no longer one `role="button"` for the whole plot. Each bar row, column, line point, donut / pie slice, stacked segment, funnel step, treemap tile and calendar day is its own button. It is named by what it shows ("North: 1,500") and carries `aria-pressed` for the selected one. The chart is still ONE tab stop (roving tabindex): Tab lands on the selected part (else the first), and the arrows, Home and End move the focus with the same steps as before. Enter / Space pick the focused part. The focused part is ringed (a donut, a stacked bar and a line ring the plot instead). A part with `selectable: false` is an `aria-disabled` button that is never picked. A BarList row with `href` is its link, not a button, and the arrows skip it. Read-only charts are unchanged (`role="img"`). The pointer, hit testing and tooltips are unchanged.
|
|
315
|
+
- **The UI scale.** Chart text, paddings, label columns, legends, tooltips and the image menu follow `--ui-scale`, through the spacing / font-size tokens or `calc(Npx * var(--ui-scale))`. Sizes laid out in script grow too: plot heights, ring and dial diameters, the room an x label needs, treemap label room, and calendar day and name sizes. **`height` / `size` props are now px at UI scale 1**, so a chart passed `height={72}` is 72 px at scale 1 and 93.6 px at 1.3. At scale 1 nothing moves. The PNG export is unchanged.
|
|
316
|
+
- `treemapLayout`, `calendarCellSize` and `calendarMonthLabels` take an optional trailing `scale` (default 1).
|
|
317
|
+
- BarList rows, treemap tiles and funnel rows have a space between name and number in their text content. On screen this changes nothing; `textContent` reads "North 1,500".
|
|
318
|
+
- ImageStrip: the "+N" thumbnail is named "+2 more, open image 5 of 6" (it opens the first image not shown).
|
|
319
|
+
|
|
320
|
+
DataTable's summary strip switches to four card columns only from 1000px × `--ui-scale` (1300px at 1.3), so larger text no longer squeezes four cards side by side.
|
|
321
|
+
|
|
322
|
+
- 73a86ec: Colour scales, readable text colours, and contrast fixes.
|
|
323
|
+
|
|
324
|
+
**New tokens** (`tokens.css`)
|
|
325
|
+
|
|
326
|
+
- Twelve-step scales for `primary`, `secondary`, `success`, `warning`, `error`, `info` and `neutral` (`--primary-1` … `--primary-12`, …). Each step has one job: 1–2 backgrounds, 3–5 component fills (rest, hover, selected), 6–8 borders, 9–10 solid, 11–12 text. Step 9 is the existing colour and step 10 its hover, so nothing that already uses them changes. The scales are derived from the semantic colours with `color-mix()`, so changing a hue still re-themes every step, in both themes. They're also declared on `[data-theme]`, so a themed subtree gets its own scales.
|
|
327
|
+
- `-text` for each colour (`--accent-primary-text`, `--success-text`, …): the colour as text, at least 5.2:1 on every surface and on its own `-soft`, in both themes.
|
|
328
|
+
- `-soft` for each colour: a translucent tint that reads the same on the page, a card or a tinted panel.
|
|
329
|
+
|
|
330
|
+
**Changed**
|
|
331
|
+
|
|
332
|
+
- Every component that used a solid as **text** now uses its `-text` token (116 declarations). The solids are tuned as fills and failed as text: `--accent-primary` measured 4.4:1 on the light page, info 3.6, warning 2.6, and the dark error 4.5. Light-mode text gets a slightly deeper shade of the same colour; dark-mode text gets slightly lighter.
|
|
333
|
+
- `--text-tertiary` (light) 45% → 41% grey: it measured 4.35:1 on the page and 3.98 on `--bg-tertiary`.
|
|
334
|
+
- Badge `filled`: text now uses the solid's `--on-*` colour instead of white, which failed on warning and info in light mode and on every solid in dark mode.
|
|
335
|
+
- Button: outlined, text, elevated and tonal labels use the tone's readable text colour. The tonal hover label uses `--on-*`.
|
|
336
|
+
- Badge neutral in dark mode, and the badge on an active pill tab, now pass AA.
|
|
337
|
+
|
|
338
|
+
Measured with axe on every story: contrast failures went from 265 to 48 in light and from 179 to 39 in dark. What remains is hardcoded colours in DataTable, Charts and Avatar, plus the Palette story's own sample labels.
|
|
339
|
+
|
|
340
|
+
- 9a8da76: DataTable follows the UI scale and the theme; DataTable and Charts move onto tokens.
|
|
341
|
+
|
|
342
|
+
**DataTable now follows `--ui-scale`.** It used fixed pixels throughout, so at any scale other than 100% its fields and dropdowns grew while the table text, headers, toolbar and rows stayed the same size. Every spacing value, font size and dimension in its CSS (padding, margin, gap, width, height, insets) is now a token where an exact one exists, and `calc(N * var(--ui-scale))` otherwise. That includes the per-table "font size" display setting and DataTable's local `--field-height-xs`. At 100% nothing moves: the 253-story screenshot comparison differs only in the avatar colours below.
|
|
343
|
+
|
|
344
|
+
**Contrast and dark mode (DataTable, Avatar)**
|
|
345
|
+
|
|
346
|
+
- White text on the primary solid (the tonal button, badges, dialog header icons, the active pill) now uses `--on-primary`. White failed on the light dark-mode primary. The ui-local modal's close-button hover uses `--on-error`.
|
|
347
|
+
- Export notice and result messages used fixed amber, green and red that never changed in dark mode. They now use `-soft` / `-text` / scale tokens.
|
|
348
|
+
- The loading overlay was a white wash in dark mode too. It now uses the panel colour.
|
|
349
|
+
- Unavailable summary cards are shown recessed (sunken surface, dashed edge) instead of at 70% opacity, which took their explanation text below AA.
|
|
350
|
+
- Avatars (DataTable and Avatar `tone`) use OKLCH instead of HSL, so every hue gets the same contrast: at least 5.2:1 in DataTable (white on colour), and 5.5:1 light / 7.7:1 dark for Avatar tones. The HSL versions dropped to 2.6:1 and 3.6:1 on yellow hues. **Each person's avatar colour shifts** (OKLCH and HSL hue angles differ), but it's still stable per person.
|
|
351
|
+
- axe now reports no contrast failures in DataTable, Avatar, Card, Badge or Button, in either theme.
|
|
352
|
+
|
|
353
|
+
**Tokens**
|
|
354
|
+
|
|
355
|
+
- DataTable and Charts: exact transition durations and keyword easings use the motion tokens. Exact radii use radius tokens; `--dt-radius` is `--border-radius-lg`.
|
|
356
|
+
- Charts keeps fixed pixel sizes: its SVG layout is computed in JavaScript, so it can't follow `--ui-scale` from CSS alone.
|
|
357
|
+
|
|
358
|
+
- a45fd0d: Token documentation, contrast and accessibility checks in CI, and a visual diff on pull requests.
|
|
359
|
+
|
|
360
|
+
**Changed**
|
|
361
|
+
|
|
362
|
+
- `--info-hover` (light theme) is now **lighter** than `--info` instead of darker. Info carries dark text (`--on-info`), and the darker hover took that text down to 3.6:1, so an info button's label was unreadable on hover. The new contrast check found it.
|
|
363
|
+
|
|
364
|
+
**Docs**
|
|
365
|
+
|
|
366
|
+
- New Storybook pages: **Foundations / Typography, Space and shape, Motion, Elevation and layers**, and **Token reference**, which lists all 288 tokens, read from `tokens.css` itself, with their live values in the current theme, filterable. All of them pass axe in both themes.
|
|
367
|
+
- A design-token guide in the repository: the rules for using and adding tokens, the colour roles and scale steps, motion, layers, and what each check enforces.
|
|
368
|
+
|
|
369
|
+
**Checks** (tooling only, nothing that ships)
|
|
370
|
+
|
|
371
|
+
- `npm run verify:contrast` loads the tokens in Chromium and fails if any of 254 promised pairs is under WCAG AA, in light or dark.
|
|
372
|
+
- `npm run check:a11y` runs axe on every story in both themes. It fails on any colour-contrast violation (currently none, across 253 stories) and reports the other axe rules without failing.
|
|
373
|
+
- CI runs both. A new `visual` job on pull requests builds the base branch's Storybook and the PR's, screenshots every story in both, and reports what changed, with before / after / diff images as an artifact. It never fails the PR.
|
|
374
|
+
|
|
375
|
+
- 9a7d129: Motion system, exit animations, sliding tab indicator, and a token guardrail in the build.
|
|
376
|
+
|
|
377
|
+
**New tokens** (`tokens.css`)
|
|
378
|
+
|
|
379
|
+
- Durations named by what moves: `--duration-micro` 100ms, `--duration-short` 150ms, `--duration-medium` 200ms, `--duration-long` 300ms. Exits use the step below their enter.
|
|
380
|
+
- Easing by purpose: `--ease-standard`, `--ease-enter`, `--ease-exit`, and `--ease-spring` (a `linear()` spring with ~4% overshoot).
|
|
381
|
+
- `--motion-scale`: 1 normally, 0 under `prefers-reduced-motion`. Reduced motion removes movement and keeps the short fade.
|
|
382
|
+
- `--motion-enter-offset` and `--motion-enter-scale`: the shared distance and scale every floating surface enters from.
|
|
383
|
+
- `--transition-fast`, `--transition-base` and `--transition-slow` are now aliases of the new durations, with the same values as before.
|
|
384
|
+
|
|
385
|
+
**Components**
|
|
386
|
+
|
|
387
|
+
- Popover, and everything built on it (DropdownMenu, DatePicker, Breadcrumbs, Sidebar flyout), Select's list and Suggest's list now **animate out** instead of disappearing. They enter from their anchor, flipping direction when placed above it. Joined Select/Suggest lists are revealed from the field's edge. While leaving, a surface is `inert`.
|
|
388
|
+
- Tabs (`line`, `pill`): one indicator now **slides** to the active tab with the spring easing. Under reduced motion it jumps.
|
|
389
|
+
- Tabs: hovering the active tab no longer repaints it (the active pill turned grey, with dark text). The `line` underline now shows its full 2px; half of it was clipped under the strip border.
|
|
390
|
+
- Select: its inline z-index (1000, or 10000 in a modal) overrode the `--z-popover` layer; removed.
|
|
391
|
+
- `SuggestionList`: `zIndex` no longer defaults to 1000. When omitted, the list uses `--z-popover`; a number you pass is still applied. New optional `exiting` prop, which Suggest sets itself.
|
|
392
|
+
|
|
393
|
+
**Build**
|
|
394
|
+
|
|
395
|
+
- New `verify:tokens` step. It fails on a `var(--x)` with no fallback that nothing defines (this would have caught the DropdownMenu hover bug). It also fails when a component CSS file gains hardcoded colours, font sizes or weights, z-indexes, durations or easings beyond `scripts/token-baseline.json`. After removing literals, lower the baseline with `npm run verify:tokens -- --update`.
|
|
396
|
+
|
|
397
|
+
- bbcc4d2: DataTable: its own buttons now use the shared Press feedback. Toolbar and pagination icon buttons, header filter and ⋮ buttons, dialog close buttons, export and template buttons, the bulk-action, retry and footer buttons all show the wave from where you press, or from the centre for Space and Enter. Clickable table rows, cards and split list items show the Press tint while pressed. There is no wave and they do not shrink. Layout, hover colours, handlers and keyboard behaviour are unchanged.
|
|
398
|
+
- 1512a3d: A shared Press engine for press feedback, and an opt-in `feedback` prop on Button.
|
|
399
|
+
|
|
400
|
+
- **Press engine** (`components/Press`, internal): one stylesheet plus a `usePress` hook that any pressable element opts into, so components stop writing their own press and ripple rules.
|
|
401
|
+
- **Every press is seen.** `usePress` holds the pressed look for at least 150ms, however quick the click. CSS `:active` ends the instant the pointer lifts, which is why the old ripple showed nothing on a normal click. Mouse, touch, pen, Space and Enter all count.
|
|
402
|
+
- **State layer:** the element's own text colour over its background. It fades both ways and works on every variant, colour and theme.
|
|
403
|
+
- **Press-down:** shrinks to 97% and springs back. It uses the `scale` property, so it never conflicts with a component's `transform`.
|
|
404
|
+
- **Ripple mode:** a wave that starts exactly where you pressed (the centre for the keyboard) and grows across the element. It holds while pressed and fades as it spreads on release, so a quick click still sends a visible wave across. Each press gets its own wave, so rapid presses overlap. In this mode the wave is the only effect: no pressed tint, no press-down.
|
|
405
|
+
- **Reduced motion:** no press-down, and waves appear in place instead of spreading, so a press is still always visible.
|
|
406
|
+
- **New tokens:** `--state-hover-opacity`, `--state-press-opacity`, `--press-scale`, `--press-transition`, `--ripple-duration`, `--ripple-opacity`. `--state-layer-opacity` is a registered property, so it can animate.
|
|
407
|
+
- **Button press feedback is now a wave by default** (`feedback`, default `'ripple'`). It starts where you press, spreads across the button and fades as it spreads. This replaces the old centred ripple, which grew only while the mouse was held and vanished on release. `feedback="press"` gives a pressed tint and press-down instead; `feedback="none"` turns press feedback off. `ripple={false}` still works and means `feedback="none"`. The hover lift on filled and elevated buttons is removed. Each variant keeps its hover colours.
|
|
408
|
+
- **New Storybook page, Foundations / Press feedback:** every Button variant three ways side by side, plus the engine on tabs, menu rows, chips and a card.
|
|
409
|
+
|
|
410
|
+
- **Fixed:** in dark mode, filled Buttons had light text on their light solids (1.65:1). An old dark-theme rule overrode `--on-*`; it is removed, so filled buttons use their readable on-colour.
|
|
411
|
+
- **Fixed:** the press tint is painted only while it can show (hover, press, fade). At rest it was a transparent background image, which stopped axe from measuring contrast on every pressable element. `check:a11y` now reports how much contrast it couldn't measure, so a blind spot like that shows up.
|
|
412
|
+
|
|
413
|
+
- 1910eee: Menu-like rows now show the shared Press wave when pressed: DropdownMenu items, Select options (and Select all), Suggest suggestions, CommandPalette results, and Sidebar nav items and flyout rows. Rows keep their own hover, cursor and selected fills; nothing moves.
|
|
414
|
+
- 1bee8f7: Tabs (panel and navigation mode) and clickable Cards now show the shared Press wave from where they are pressed; DatePicker day cells show a brief press tint (no wave, no press-down). ChipInput is unchanged: its chips are not clickable and the remove × deletes the chip on press, so there is nothing left to show feedback on.
|
|
415
|
+
- a840251: Checkbox, Radio and Switch now use the shared Press engine for their press feedback: a wave that starts from the centre of the control's round halo and is clipped to it, whether you press the control, its label or Space. Switch gets the wave too. The keyboard focus halo is now steady instead of pulsing forever. `usePress` gains two optional settings: `centered` (start every wave from the centre) and `target` (show the press on another element, such as a halo inside a label).
|
|
416
|
+
- 4cf7d1d: Source moved to its own repository. **Breaking:** `ReportDesigner`, `ReportPreview` and their editors (`BandList`, `Inspector`, `BlockEditor`, `TableEditor`, `ColumnEditor`, `AlignedRowsEditor`, `ConditionEditor`, `StyleEditor`, `FormatEditor`, `FieldSelect`, `FieldPicker`, `OptionsEditor`, `WatermarkEditor`, `BAND_KINDS`, `canSaveTemplate`, `conditionSummary`) are no longer part of this package.
|
|
417
|
+
- 32b0a4f: Shadow and scrim tokens. Popups, dialogs, drawers, sheets, pinned-column edges, knobs and backdrops no longer hardcode their shadow or dim colour, so they deepen in dark mode like the rest of the shadows.
|
|
418
|
+
|
|
419
|
+
New tokens (light / dark):
|
|
420
|
+
|
|
421
|
+
- `--shadow-control`: knobs, slider thumbs, small round buttons that float on content.
|
|
422
|
+
- `--shadow-popover`: floating menus and popovers.
|
|
423
|
+
- `--shadow-dialog`: modal panels (dialogs, drawers, bottom sheets), with a 1px edge ring.
|
|
424
|
+
- `--shadow-edge`: the edge of a pinned column while content scrolls under it; even on all sides, clip it to one side.
|
|
425
|
+
- `--scrim`: the dimming layer behind a dialog.
|
|
426
|
+
- `--scrim-soft`: a lighter dimming layer behind a drawer or action sheet.
|
|
427
|
+
|
|
428
|
+
Now on tokens: Dialog's backdrop, Switch's thumb, Image's viewer buttons and "+N" overlay, and DataTable's container, cards, menus, popovers, settings / sort / filter / export / column modals, keyboard-shortcuts dialog, fields editor, row-detail drawer and scrim, row menu popover and sheet, export bottom sheet, segmented controls, tabs and pinned-column edges.
|
|
429
|
+
|
|
430
|
+
Light mode looks nearly the same; values that were close were snapped to a shared token (the DataTable drawer and bottom sheet now use the dialog shadow instead of a one-sided one, and the keyboard-shortcuts and fields-editor dialogs use the dialog shadow). Dark mode shadows and scrims are now deeper.
|
|
431
|
+
|
|
432
|
+
- f89b4b6: New `Stepper`: a row of numbered steps (done, current, ahead) for a multi-step screen. Done steps can be clicked to go back; steps ahead cannot.
|
|
433
|
+
|
|
434
|
+
Done steps play the shared Press wave when clicked, and are announced as completed to screen readers (`completedLabel`, default "Completed", for translation). An `active` key that matches no step now marks no step current, instead of the first. The step states and clickability are decided in `core/logic` (`stepStates`, `isStepClickable`).
|
|
435
|
+
|
|
436
|
+
- 8effafb: Token fixes: missing variables, one z-index scale, and theme-driven Typography.
|
|
437
|
+
|
|
438
|
+
- DropdownMenu hover now uses `--hover-overlay` (it referenced an undefined `--bg-hover`, so it showed no hover). DataTable's muted cells now use `--disabled-text` instead of an undefined `--text-disabled`.
|
|
439
|
+
- New tokens: `--font-weight-bold`, `--z-appbar` (alias for `--z-fixed`) and `--z-popover` (560, above `--z-modal`).
|
|
440
|
+
- Every stacked layer now uses the `--z-*` scale instead of literals (900–2147483000). The AppBar no longer sits above modals and toasts. Menus, Select and Suggest lists, and DataTable popovers now use `--z-popover`. **If your app positions its own elements with a z-index around 1000, re-check them against these lower values, or override the `--z-*` tokens.**
|
|
441
|
+
- Typography no longer follows the OS `prefers-color-scheme` when the app has chosen a theme; it follows `data-theme` like everything else. `[data-theme="dark"]` now sets `color-scheme: dark`, so native scrollbars and pickers match.
|
|
442
|
+
|
|
443
|
+
- cd2a23c: Type and space tokens, with components moved onto them.
|
|
444
|
+
|
|
445
|
+
**New tokens** (`tokens.css`)
|
|
446
|
+
|
|
447
|
+
- `--font-sans`: the stack the reset always used, so nothing changes. An app with a web font sets it once. `--font-mono` replaces four different monospace stacks.
|
|
448
|
+
- `--font-size-h1` … `--font-size-h6`: fluid heading sizes. They keep Typography's previous min–max ranges but now also follow `--ui-scale` (the old viewport-only `clamp()`s ignored it).
|
|
449
|
+
- `--line-height-tight` (1.2, headings), `--line-height-snug` (1.4, UI text), `--line-height-normal` (1.5, body).
|
|
450
|
+
- `--font-weight-regular` (400), `--spacing-xxs` (2px), `--spacing-2xl` (24px), `--spacing-3xl` (32px), `--border-radius-xs` (4px), `--border-radius-full` (pills). Several of these were already referenced by components, with hardcoded fallbacks.
|
|
451
|
+
- `--label-spacing` and `--message-spacing` now follow `--ui-scale` (`--spacing-md` / `--spacing-sm`, same values at scale 1).
|
|
452
|
+
|
|
453
|
+
**Changed**
|
|
454
|
+
|
|
455
|
+
- Swaps with the same value, so nothing changes on screen: radii, line heights of 1.2/1.4/1.5, font weights and monospace stacks now use tokens in every component. Outside DataTable and Charts, exact font sizes and spacing also moved to the scaled tokens. Literal counts: font weights 170 → 2, radius 180 → 83, line height 90 → 46, spacing 731 → 692.
|
|
456
|
+
- 226 hardcoded fallbacks on tokens that are always defined were removed (`var(--font-size-sm, 13px)` → `var(--font-size-sm)`). Charts keeps its fallbacks deliberately.
|
|
457
|
+
- Typography: headings use the heading tokens. h3/h4 line height 1.3 → 1.2. body2 1.43 → 1.4, subtitle2 1.57 → 1.5 and caption 1.66 → 1.5. `code` and `pre` use `--font-mono` instead of Courier New.
|
|
458
|
+
- Breadcrumbs' focus radius is 4px (it fell back to 2px).
|
|
459
|
+
- DataTable: right-aligned (numeric) cells and the totals row use tabular numbers, so digits line up down the column.
|
|
460
|
+
|
|
461
|
+
**Build**
|
|
462
|
+
|
|
463
|
+
- `verify:tokens` now also tracks hardcoded spacing (`padding`/`margin`/`gap`), line heights and radii in component CSS.
|
|
464
|
+
|
|
465
|
+
Checked by screenshotting all 253 stories before and after: 238 are identical. The others differ by Typography's line-height changes, or are stories that differ between two runs of the same code.
|
|
466
|
+
|
|
467
|
+
### Patch Changes
|
|
468
|
+
|
|
469
|
+
- bcb0682: Accessible names for fields, tables, breadcrumbs, tabs and charts. axe now passes on every story.
|
|
470
|
+
|
|
471
|
+
- **EditableTable:** every field in a cell takes its column header as its accessible name. The header was the label visually but wasn't connected, so each input, select, checkbox and switch in the grid was announced with no name. A column that names its field itself (`fprop.label`, `aria-label` or `aria-labelledby`) keeps its own. A column with no header text gets a plain header cell, not an empty `<th>`.
|
|
472
|
+
- **Select:** a visible label now names the trigger. `<label for>` only names native form controls, and the trigger is a `div role="combobox"`, so every labelled Select had no accessible name. It now uses `aria-labelledby`, as Input and DatePicker already do.
|
|
473
|
+
- **Breadcrumbs:** the icon-only home link is named "Home". The name was on a wrapping span, where it named nothing.
|
|
474
|
+
- **Tabs:** `aria-controls` points only at panels that are actually rendered. A strip driving routes or other content no longer references missing ids.
|
|
475
|
+
- **DataTable:**
|
|
476
|
+
- cards are `div role="listitem"` (an `article` may not take that role)
|
|
477
|
+
- the loading overlay is a `role="status"`
|
|
478
|
+
- the filter row's selection and action cells are plain cells, not empty headers
|
|
479
|
+
- **Charts (BarList):** rows are divs. Inside a plot with `role="img"` or `"button"`, list items had no list.
|
|
480
|
+
|
|
481
|
+
Visual diff against the previous version: no component renders differently.
|
|
482
|
+
|
|
483
|
+
- a3bf02e: Button rendered as a link (`href`) keeps the button's text colour in every link state. A visited link button took the surrounding text colour (`:visited { color: inherit }`), and an app's own `a:link`, `a:visited` or `a:hover` colour rules outranked the variant colour. Each variant now routes its text colour through `--btn-fg`, and link states use it.
|
|
484
|
+
|
|
485
|
+
Typography `code` and `pre` use `--neutral-3` for their background. They referenced `--background-secondary`, which was never defined, so only a hardcoded fallback applied.
|
|
486
|
+
|
|
487
|
+
- 40164cd: Sidebar: smoother collapse and expand. The column width still animates (`--duration-long`,
|
|
488
|
+
`--ease-standard`), but the content no longer re-lays out on every frame: while moving, the
|
|
489
|
+
header, nav and footer keep their expanded width and are clipped, and labels and group headings
|
|
490
|
+
fade with opacity instead of being squeezed into an ellipsis. The rail layout is applied once the
|
|
491
|
+
width has arrived. Under reduced motion (`--motion-scale: 0`) the collapse is instant. End states
|
|
492
|
+
and the API are unchanged; the header no longer wraps.
|
|
493
|
+
|
|
494
|
+
Typography: `subtitle1` and `overline` use `--line-height-normal` (1.5) instead of the leftover
|
|
495
|
+
Material line heights 1.75 and 2.66, so both are slightly shorter; the colour transition uses
|
|
496
|
+
`--duration-medium`.
|