@nice2dev/ui-presentations 1.2.2 → 1.3.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 CHANGED
@@ -1,5 +1,381 @@
1
1
  # @nice2dev/ui-presentations — Changelog
2
2
 
3
+ ## 1.3.0
4
+
5
+ ### Patch Changes
6
+
7
+ - ada5a2d: Keyboard, gamepad and remote input for every Nice control (TODO_1.3.0, ADR-005).
8
+
9
+ - `@nice2dev/ui-core` gets the input layer, also as its own entry `@nice2dev/ui-core/input`:
10
+ one engine per page that turns keys, pad buttons and remote keys into intents (`navigate`,
11
+ `activate`, `back`, `secondary`, `tertiary`, `menu`, `view`, `sectionPrev` / `sectionNext`,
12
+ `pagePrev` / `pageNext`, `first` / `last`, `scroll`, `toggleHints`). No animation frame without a
13
+ pad; changes only, no re-render per frame; repeat with acceleration, stick hysteresis, several
14
+ pads, Xbox / PlayStation / Nintendo / Steam / generic families (Nintendo confirms with the right
15
+ button). Pads also emulate the matching key on the focused element, so controls with a keyboard
16
+ pattern work with a pad as they are.
17
+ - Focus without registration: spatial moves between tabbable elements, focus scopes
18
+ (`useFocusScope`, `<NiceFocusScope>`) with memory, wrapping, traps and escalation at an edge,
19
+ regions for F6 / Select, focus recovery when the focused element disappears. Value controls are
20
+ engaged first on a pad (`useEngage`): the d-pad passes them by until A.
21
+ - `useRovingFocus` (APG keys, 1-D and 2-D, typeahead, RTL), `useOverlayFocus` (initial focus,
22
+ trap, Escape / B, overlay stack, return to the opener), `useIntent`, `useInputMethod`,
23
+ `useGamepadFamily`, `useInputPreferences`, `NiceInputProvider` (preferences persisted in
24
+ `NiceUserPreferences` as `global.input`; `useUserPreferencesOptional` added).
25
+ - `@nice2dev/testing`: `mockGamepad()` with a controlled frame clock, `pressKey()`,
26
+ `pressIntent()`, `describeInputContract()` / `runInputContract()`, `stubLayout()` /
27
+ `stubGridLayout()` for jsdom.
28
+ - Focus visibility: in pad and remote modes the ring shows on plain `:focus` (the browsers'
29
+ `:focus-visible` heuristics miss focus moved by a pad); an engaged control wears
30
+ `--nice-focus-ring-engaged`; `scroll-padding` on the root from `--nice-scroll-padding-top` /
31
+ `-bottom`. `NiceDisplayValue` drew no ring: its outline used the box-shadow token as a colour.
32
+ - The old APIs are layers over the engine and `@deprecated` (removal only in a breaking release):
33
+ `useGamepad` reads the engine's frames — no animation loop of its own and no render per frame;
34
+ `NiceSpatialNavProvider` takes intents instead of a `window` keydown listener, so it no longer
35
+ steals the arrow keys of text fields; `useRovingTabIndex` runs on `useRovingFocus` (2-D in
36
+ `grid`); `createNavigationActions` fires once per stick push instead of every frame.
37
+ - Button prompts (B1–B4, B6, B7): 41 glyphs of pad buttons (Xbox, PlayStation, Nintendo, generic
38
+ positions), bumpers, triggers, d-pad, sticks, remote keys and the macOS key symbols — outline
39
+ built-ins of `NiceIcon` and filled, coloured `Ntd*` icons of `@nice2dev/icons` under the same
40
+ names (`pad-xbox-a` → `NtdPadXboxA`); `NiceKeyCap` (words translated, arrows and ⌘ ⌥ ⇧ as
41
+ glyphs); `NiceButtonPrompt` (the button or key of an intent for the device in use, the pad
42
+ family and the user's bindings); `NiceInputHintBar` + `useInputHints` (the actions of the focus
43
+ path); `useNiceAction` (application actions with a key, a pad intent, a scope, `when`,
44
+ `aria-keyshortcuts`, conflict warnings) and `useNiceActions` / `triggerNiceAction` for command
45
+ palettes. `NiceKeyboardHint` is reachable with Tab, draws an icon instead of "?", keycaps, and
46
+ the pad button of shortcuts that carry an `intent` (`COMMON_SHORTCUTS` do); `NiceSkipLink`
47
+ translates its default text. 64 dictionary keys in six languages.
48
+ - `NiceDeviceManager`, the karaoke pad player, the note particles (ui-audio) and the model viewer
49
+ (ui-3d) read pads through the engine (`getInputEngine().gamepadSnapshot`,
50
+ `useConnectedGamepads`). `@nice2dev/ui` re-exports the app-facing part of the input layer.
51
+ - `NiceInputSettings` (new): the input preferences and the rebinding of every intent to keys or a
52
+ pad button, captured from the next press. `NiceCommandPalette` opens on the `menu` intent
53
+ (Ctrl+K, Start, the remote's menu key), keeps focus inside, moves with the d-pad, runs with A
54
+ and lists the `useNiceAction` actions (`includeActions`, default on).
55
+ - Shells are focus scopes (D1, D2): `NiceNavShell`, `NiceAppShell` and the shells of
56
+ `NiceShells` move with the arrows and the d-pad, have F6 / Select regions, switch sections with
57
+ LB / RB and show the hint bar in pad mode (`hintBar`: `bottom` by default, `top`, `none`).
58
+ `NiceNavShell` gets an APG tab strip with a tab menu and moving tabs without dragging
59
+ (Ctrl+Shift+← →), moves focus into the new page after navigating (`focusContentOnNavigate`),
60
+ remembers focus per route and announces the page; `contentArrows: 'native'` gives the arrows
61
+ back to the page.
62
+ - Tabs (C6): every tab list moves with ← → Home End and the d-pad (`useRovingFocus`, also new
63
+ `activateOnMove`). `NiceTabs` links each tab to its panel (`aria-controls` /
64
+ `aria-labelledby`), sets `aria-orientation`, switches with LB / RB in its scope and shows those
65
+ prompts with `showHints`. `NiceCarousel` moves between its dots; ← → on the carousel go on to
66
+ the page at an end without wrapping. The sheet buttons of `NiceSpreadsheet` and the tabs of
67
+ `NiceMobileTabs` are now `role="tab"` with `aria-selected` (they were buttons with
68
+ `aria-pressed` — tests that look them up as buttons must look up tabs); stepping onto "More"
69
+ does not open its sheet.
70
+ - Overlays (C12): every modal, drawer, sheet, popover, lightbox, picker popup and confirmation
71
+ runs on `useOverlayFocus`. Escape / B close only the top overlay — they listened on the
72
+ document before, so one Escape closed every open overlay at once — and focus returns to the
73
+ element that opened it. `useFocusTrap` runs on `useOverlayFocus` (it took its element list
74
+ once, so elements added later broke the trap); a modal no longer pulls focus back from a popup
75
+ opened above it (a select's list portalled after it). An overlay that can be closed shows
76
+ "B Close" in the hint bar (`closeHint`); `useInputHints` takes several publishers per element
77
+ (`fallback` hints give way). Consent dialogs (`NiceCookieConsent`, `NiceGDPRConsent`) keep focus
78
+ until answered. `NiceLightbox`, the mobile `NiceImageGallery`, both print previews and
79
+ `NiceTutorial` take LB / RB (and LT / RT for zoom) on a pad; their keys listen on the overlay
80
+ instead of the window. The context menus (`NiceOverlayContextMenu`, `NiceTouchMenuPopover`)
81
+ open from the menu key, Shift+F10 and X, move with the arrows and letters, and a submenu
82
+ closes on ← / Escape alone. `NiceWindowManager` / `NiceWindow`: windows are F6 / View regions,
83
+ raised when focus enters them, and the taskbar moves with the arrows. `NiceCommandBar` gets
84
+ `aria-activedescendant` and unique ids. The raw glyphs used as icons in `NiceTutorial`, the
85
+ print preview of `@nice2dev/ui-printing` and `NiceGlobalSearch` are `NiceIcon` / `NiceKeyCap`.
86
+ - Menus (C7): `useMenuButton` (new) — ↓ / ↑ on the trigger open the menu on its first / last
87
+ item, the arrows, Home End and letters move, Enter / Space activate items that are not buttons,
88
+ Escape / B, focus leaving and a press outside close it, and a pad's d-pad moves past the trigger
89
+ (A opens). It runs `NiceDropDownButton`, `NiceSpeedDialAction`, `NiceUserMenu`, the extra-action
90
+ menus of `NiceTopNav`, `NiceHamburgerMenu`, the desktop Start menu and the "Open" menu of
91
+ `NiceThemeBuilder`. `NiceUserMenu` and the `NiceTopNav` action menus closed 200 / 180 ms after
92
+ their button lost focus, so focus could never move into them. `NiceTopMenu` is an APG menubar;
93
+ `NiceNavMenu` moves focus into an opened panel (it never did), adds Home / End, moves in two
94
+ dimensions in a mega panel and opens / closes its flyouts from the keyboard; panels opened by
95
+ hovering leave focus where it is. The closed panel of `NiceHamburgerMenu` is inert (Tab reached
96
+ its hidden items). The quick settings of `NiceDeviceTile` are a `dialog`, not a `menu`.
97
+ - Select lists (C3): with the default `searchable`, `NiceSelect` moved focus into a search
98
+ field that had no keys — the list could not be used from the keyboard at all. The field and the
99
+ trigger now share the keys (↑ ↓ PageUp PageDown, Home / End on the trigger, Enter, Escape), the
100
+ list opens on the selected option, names the highlighted one (`aria-activedescendant`), keeps
101
+ it in view and gives focus back to the trigger after a pick; a pad moves and picks in the field.
102
+ The same for `NiceLookup`, `NiceCountryPicker`, `NiceLanguagePicker` and `NiceThemePicker`
103
+ (after a pick from their search field focus was lost to the page), `NiceAutocomplete`,
104
+ `NiceMention` and `NiceSearchInput`. A select open inside a modal now closes alone on Escape.
105
+ `useOverlayFocus` takes `initialFocus: 'none'` and returns focus to the element focused before
106
+ an `autoFocus` child took it.
107
+ - Lists (C8): every list of items is an APG listbox with one tab stop — the arrows, Home End,
108
+ PageUp PageDown and letters move, Enter / Space (A on a pad) pick: `NiceList` (one listbox with
109
+ groups too), both columns of `NicePickList`, `NiceRevisionHistory`, `NiceTaskInbox` and both
110
+ panels of `NiceReconciliationView` (Space picks a row, Enter opens its details as a double
111
+ click does; its rows were `role="row"`, each a tab stop, and `focusStatements()` /
112
+ `focusEntries()` focused nothing). The fields with a list of suggestions drive it from the field
113
+ (`aria-activedescendant`) and with a pad: `NiceTagBox` (a list opened by focus alone has no
114
+ highlight, so Enter still submits a form), `NiceTagInput` (a combobox only with `suggestions`),
115
+ `NiceAccountPicker`, `NiceContactPicker`, `NiceCommandBar` and `NiceGlobalSearch` (Enter and the
116
+ pad took the result from before the filter). The dropdowns of `NiceModeSelector` and
117
+ `NiceDisplayStylePicker` are select-only comboboxes that open on the current item. These fields
118
+ and triggers are `role="combobox"` now — tests that look them up as textboxes or buttons must
119
+ look up comboboxes. Each column of `NiceCascadeSelect` is a listbox: → / Enter go into an
120
+ option's children, ← back; it opens on the selected path and Escape returns focus to the
121
+ trigger. The panel of `NiceIconPicker` is a dialog on the overlay stack (it listened for Escape
122
+ on the document) with a two-dimensional icon grid. The time columns of the `NiceDateTimePicker`
123
+ popup are spinbuttons (Home / End, PageUp / PageDown); the wheel beside them is for the pointer.
124
+ The palette of `NiceWorkflowDesigner` inserts an element on Enter / Space.
125
+ - Trees (C9): `useTreeFocus` (new, also exported from `@nice2dev/ui`) — the APG tree view on
126
+ nested or flat (`aria-level`) trees: one tab stop, ↑ ↓ Home End and letters move, → opens an
127
+ item or enters it, ← closes it or goes to its parent, `*` opens the siblings; Enter / Space and
128
+ a pad's A click the item's row and a pad's X / Shift+F10 open its context menu, so the
129
+ components keep their click handlers. `NiceTreeView` (the items had only the pointer; F2 edits
130
+ and focus comes back after the edit; its context menu is a real menu with focus in it and
131
+ Escape back to the item), `NiceTreeSelect` (↓ / ↑ / Enter on the field open the tree with
132
+ focus in it, ↓ from the search box goes to the tree, a pick returns focus to the field),
133
+ the page tree of `NiceWiki`, the resource tree of `NiceAccessManager` and the mobile tree of
134
+ `NiceTopNav` (each node was two tab stops — its toggle and its link — and the mobile tree had
135
+ `role="tree"` with no items in it).
136
+ - Data grids (C10): `useGridFocus` (new, also exported from `@nice2dev/ui`) — the APG data grid:
137
+ one tab stop, the arrows move by row and column, Home / End along a row, Ctrl+Home / Ctrl+End
138
+ to the corners, PageUp / PageDown by rows; Enter / Space / a pad's A click the cell, and a cell
139
+ holding one control (a header's "toggle all", a row checkbox, a link) is reached on that
140
+ control. `NicePermissionMatrix` (the grants had only the pointer), `NiceModuleGrid` (its cells
141
+ are `gridcell`s now and `role="grid"` sits on the table, no longer on the whole control with
142
+ its toolbar and pagination — tests that look the grid up still find it, by its label too; a
143
+ cell's Enter selects its row, a header's sorts; the mobile cards are a listbox of options, not
144
+ rows), `NiceWarehouseView` (ui-erp; every bin was a tab stop, and a focused bin shows its
145
+ details as a hovered one does). `NiceSpreadsheet` adds Home / End, Ctrl+Home / Ctrl+End and
146
+ PageUp / PageDown.
147
+ - One of several (C4): `NiceSegmentedControl` is a radio group — one tab stop, the arrows (a
148
+ pad's d-pad) move and select; its options were toggle buttons with `aria-pressed`, one tab stop
149
+ each (tests that look them up as pressed buttons must look up checked radios). So are the
150
+ true / false, NPS and star scales of the assessment widgets (`NiceSurvey`, `NiceQuiz`,
151
+ `NicePollLive`). `NiceRadioGroup` and the payment method selector were native radio groups
152
+ already.
153
+ - Sliders (C5): `NiceRangeSlider`'s thumbs had no keys at all — the arrows step, PageUp /
154
+ PageDown take a tenth of the range, Home / End go as far as the thumb may, and they are named
155
+ "Minimum" / "Maximum" with the formatted value as `aria-valuetext`. `NiceKnob`, `NiceTempDial`
156
+ and `NiceRating` add PageUp / PageDown and Home / End; `NiceTempDial` consumes its keys (the
157
+ arrows also scrolled the page, and an engaged pad's d-pad moved focus away instead of stepping).
158
+ - Toolbars (C13): the toolbars of `NiceDocumentEditor`, `NiceImageEditor`, `NicePDFViewer`, the
159
+ file manager, the component playground's canvas and `NiceDock` are one tab stop with the arrows
160
+ along the bar and Home / End between their buttons (their fields and selects keep their own
161
+ keys); they are named, a side dock is a vertical toolbar and a focused dock item magnifies as a
162
+ hovered one does. The file manager's panels name the item under their cursor
163
+ (`aria-activedescendant`) — its rows were no options, so ↑ ↓ moved a cursor no screen reader
164
+ could follow.
165
+ - Dates (C11): `NiceCalendar` is an APG date grid — its days had no keys at all though the hint
166
+ listed them: focus sits on a day (one tab stop), ← → a day, ↑ ↓ a week, Home / End the week,
167
+ PageUp / PageDown a month, Shift+PageUp / PageDown a year, crossing into the next month as
168
+ needed; Enter / Space pick; a pad's LB / RB change the month and LT / RT the year; the month
169
+ and year pickers move in two dimensions and a pick keeps focus in the calendar. The
170
+ `NiceDateTimePicker` field opens its picker with Alt+↓, the context-menu key, Shift+F10 or a
171
+ pad's X (its button is no tab stop), focus on the day; the clock's hour and minute are
172
+ spinbuttons. The single-field `NiceDateRangeBox` opens with Enter / Space / ↓, its popup is on
173
+ the overlay stack (it closed on any Escape on the page) and a picked range returns focus to
174
+ the field. In the engine a read-only text field is not engaged: a pad's A acts as its Enter.
175
+ - Number fields (C2): WAI-ARIA spinbutton keys — ↑ ↓ a step, PageUp / PageDown ten, Home / End
176
+ the minimum / maximum (without a bound they stay the caret's). `NiceNumericInput` had no keys
177
+ at all; `NiceNumberInput` adds the big step and the bounds, a stepped value replaces the typed
178
+ text (it stayed on screen) and a read-only field no longer steps. With `showSteppers`
179
+ `NiceMoneyInput`'s amount is a `spinbutton` with the same keys — its stepper buttons are out of
180
+ the tab order, so the steps were pointer-only (the buttons show `NiceIcon`s instead of "−" /
181
+ "+"); without steppers it stays a text field. On a pad B on an engaged number field cancels:
182
+ the engine puts a native `<input type="number">`'s value from before back, and the new
183
+ `useEngage` option `restoreOnCancel` does it for a custom control (put the value back in
184
+ `onRelease(true)`). LT / RT on an engaged native field (minimum / maximum) went past React's
185
+ value tracker unseen — a controlled input never heard of it. The hint bar names what the
186
+ buttons do on an engaged control — "Adjust", "A Done, B Cancel" on number fields, "Start
187
+ Confirm, B Done" on a text field, "A Select, B Close" with a list open — and follows engaging
188
+ and opening a list (it only changed when focus moved).
189
+ - Composites (C14, part 1): `NiceAccordion` headers move with ↑ ↓ Home / End (each stays a Tab
190
+ stop; `type="button"` — in a form a header submitted it; `aria-controls` only while the panel
191
+ exists). `NiceCollapse`'s panel is named by its trigger; a header-toggled
192
+ `NiceCollapsibleCard` no longer takes Enter / Space from the controls in it. `NiceFAQ`'s
193
+ folded answers are `inert` (their buttons stayed in the Tab order while hidden) and a
194
+ foldable group has a button. `NiceStepper` steps are buttons with `allowStepClick` (pointer
195
+ only before) and the active one is `aria-current="step"`. `NiceWizard` and
196
+ `NiceSetupWizard` step back and on with LB / RB (Ctrl+PageUp / Ctrl+PageDown) — validated as
197
+ the buttons are, with hints; the wizard's progress is a `progressbar`, its step content a
198
+ named `group` (a `tabpanel` without tabs) and its validation error an `alert`; the setup
199
+ wizard's vertical layout moves through the steps with ↑ ↓. `NiceCarousel` waits while the
200
+ pointer is over it or focus is in it, has a button that stops / starts the rotation
201
+ (WCAG 2.2.2 — it never stopped), takes slides out of view out of the Tab order (`inert`),
202
+ announces a slide the user changed and changes slides on LB / RB. `NiceGallery`'s
203
+ thumbnails are one Tab stop (← → Home End move and show), `aria-pressed` on the shown one;
204
+ its autoplay waits the same way; LB / RB change the image. `NicePagination` buttons are
205
+ `type="button"` (in a form, Enter in a field "clicked" First / Previous), pages are named
206
+ ("Page 3"), the ellipsis is hidden, the jump field is labelled, the page change is announced
207
+ and LT / RT (PageUp / PageDown) turn the page, the prev / next buttons showing the triggers
208
+ next to them (B5). In a paged `NiceDataGrid` a pad's LT / RT turn the page from anywhere in
209
+ the grid — the keyboard's PageUp / PageDown stay the cell's. A breadcrumb with only `onClick`
210
+ is a button (an `<a>` without `href` had no Tab stop), separators are hidden. A clickable
211
+ `NiceTag` takes Enter / Space and, when removable, Delete / Backspace; `aria-pressed` with
212
+ `selected`; its remove button names the tag ("Remove: React").
213
+ - Composites (C14, part 2): `NiceColorPicker`'s saturation / brightness box is a slider — it
214
+ took only the pointer (← → saturation, ↑ ↓ brightness, Shift by ten, PageUp / PageDown,
215
+ Home / End); its presets are one Tab stop moved in two dimensions (as its shortcut hint
216
+ already promised), `aria-pressed` on the current one; every channel field is named and a
217
+ disabled picker is no Tab stop. `NiceGradientPicker`'s stops are sliders (← → move,
218
+ Delete removes; focus selects as a click does), its toggle groups show `aria-pressed`, every
219
+ field is named. `NiceColorPalette`'s hue wheel is a slider of the base hue (pointer only
220
+ before); its tints and shades took focus but no keys — one Tab stop now, Enter / Space
221
+ apply; focus into a colour row selects it. `NiceUpload`: an icon-only drop zone is named,
222
+ progress is a `progressbar`, a file's actions name the file and status changes are
223
+ announced. `NiceTutorial` is named by its step and described by its text, says the title of
224
+ a new step (focus stays on the Next button) and goes to the first / last step with Home /
225
+ End. In `useRovingFocus` the pressed button of a toggle group is the initial stop.
226
+ - TV / 10-foot mode (D4): `data-nice-tv` on any element applies the 10-foot variant of the
227
+ theme below it — type of 24–28 px on a 1080p picture, targets of 48–64 px, spacing × 1.5, a
228
+ stronger focus ring (`styles/tv.css`, part of the `@nice2dev/ui` stylesheet); the input engine
229
+ sets it on `<html>` in a TV browser (webOS, Tizen, Android TV …; `engine.isTv`), and
230
+ `NiceKioskShell` / `NiceNavShell` take `tv`, which also keeps a 5 % safe area for overscan.
231
+ Remote keys were already the engine's (A1).
232
+ - `NiceMdiWorkspace` (D1): the tab menu (right click, X on a pad, Shift+F10) is a menu that
233
+ takes focus, moves with ↑ ↓ and closes on Escape / B with focus back on its tab — it was a
234
+ plain box the keyboard never reached; it moves a tab left or right (the way without
235
+ dragging); Delete closes the focused tab; the unsaved-changes question is a modal dialog with
236
+ focus on Cancel; LB / RB (Ctrl+PageUp / Ctrl+PageDown) switch tabs from anywhere in the
237
+ workspace.
238
+ - Hover has a focus counterpart (C15): `NiceRate` previews the focused star; an auto-hidden
239
+ `NiceDockMenu` shows while focus is in it (a Tab reached its buttons while they stayed
240
+ hidden) and its icon or letter items are named by their text; a hover `NicePopover` opens on
241
+ focus of its trigger too and Escape there hides it first; `NiceTimeline` events took only the
242
+ pointer — they are one Tab stop moved by the arrows, Enter / Space open one and focus shows
243
+ its details; `NiceScheduler` events are Tab stops with Enter / Space and their details on
244
+ focus; the comment button of `NiceGitDiffViewer` shows on focus as on hover.
245
+ - Typing with a pad (H1, H2): `NiceOnScreenKeyboard` (new, `@nice2dev/ui`) — the d-pad moves
246
+ over the keys and A types; X deletes, Y types a space, LT / RT move the cursor, LB / RB change
247
+ the layout (letters with the accents of the interface language, symbols, more languages),
248
+ Start confirms and B closes; the buttons show next to their keys in pad mode; a physical
249
+ keyboard and touch type too; `modal={false}` makes it a standing keyboard of a page.
250
+ `NiceOnScreenKeyboardHost` (new) opens it for the text field a pad or remote engages (A on the
251
+ field) — every key goes into the field as typing would (a controlled field hears it in
252
+ `onChange`), Start submits as Enter (a form submits), B leaves the text as it is; number
253
+ fields get digits, a text area new lines; the `onScreenKeyboard` preference turns it off or
254
+ also opens it on touch (kiosks). The application shells render the host. Its layouts are the
255
+ keyboard core now in `@nice2dev/ui-core` (`NICE_KEYBOARD_LAYOUTS`, `buildKeyboardRows`,
256
+ `insertAtCaret` …), which `NiceTouchKeyboard` (ui-mobile) uses too — its exported type names
257
+ are unchanged. New built-in glyphs `key-backspace`, `key-space`, `key-caps` (and
258
+ `NtdKeyBackspace`, `NtdKeySpace`, `NtdKeyCaps` in `@nice2dev/icons`); `setFieldText` writes a
259
+ field's text past React's value tracker.
260
+ - Toasts (D3): `NiceToastContainer` is a region named "Notifications", so F6 or a pad's View
261
+ reaches the toasts while they never take focus; Escape / B dismisses the toast with focus,
262
+ which goes on to the next toast or back where it came from (it was lost with the toast). The
263
+ countdown waits while the pointer is over a toast or focus is in it (WCAG 2.2.1). A toast can
264
+ carry an `action` (`{ label, onClick }`, also in `useNiceToast`'s options, `NiceToastOptions`)
265
+ — it runs and dismisses the toast.
266
+ - `NiceScientificChart` (ui-science): the export buttons had no handler — CSV and JSON of the
267
+ visible data and SVG / PNG of the plot download now, and the new `onExport` takes every format
268
+ over (PDF is offered only with it); the tooltip sits beside the hovered point instead of the
269
+ plot's corner. The VLAN panel of `@nice2dev/ui-buildings` labels its connections with a key of
270
+ their own (in Polish it read "połączeń", the counted form).
271
+ - `NiceCodeEditor`: an inline `lsp={{ … }}` object re-created the Monaco editor on every render,
272
+ dropping its undo history and cursor — it is re-created only when the LSP config's content
273
+ changes. The audio editor's project hooks (`useProjectCRUD`, `useAutoSave`) word their status
274
+ messages and questions through the translator (some were Polish without diacritics).
275
+ - Prompts next to controls (B5): `NiceControlHint`, and `hint` / `showHint` on `NiceButton` — the
276
+ button or keys of its action, shown while hints are visible; keys also become
277
+ `aria-keyshortcuts`. `NiceButton` also passes `role`, `aria-selected`, `aria-pressed`,
278
+ `aria-expanded`, `aria-controls`, `aria-haspopup`, `tabIndex` and `onKeyDown`.
279
+ - Found by the showcase crawler (I4, `scripts/audit-input-crawl.mjs`): **no `NiceButton` showed a
280
+ focus ring** — the display styles write `box-shadow` inline (`none` for the default `flat`) and
281
+ that beat the `:focus-visible` rule; the ring is `!important` now, also for the `underlined` and
282
+ `neumorphic` fields. `NiceCodeEditor`, `NiceCodeDiffEditor`, `NiceSimpleCodeEditor` and
283
+ `NiceMarkdownEditor` were keyboard traps (Tab indents and Shift+Tab outdents, nothing left the
284
+ field): Escape, then Tab moves focus on (WCAG 2.1.2), said in the field's description, and a
285
+ read-only editor lets Tab through (it indented its text); `createTabEscape()` (new, ui-core
286
+ and ui) gives a control of your own the same. These editors, `NiceHtmlEditor`,
287
+ `NiceTerminalUI` and the search of `NicePickList` drew no focus at all — their frame shows the
288
+ ring now. The diagram buttons of `NiceGamepad` were pointer-only, so arming a button for an
289
+ assignment took a mouse: with a handler or an action tree they are buttons (one Tab stop, the
290
+ arrows move by geometry, Enter / Space / A press, `aria-pressed` while armed); an SVG element
291
+ has no `click()`, so a pad's A dispatches a click to one (`clickElement`, new). A sortable
292
+ `NiceDataGrid` header sorted only on a click: it is a Tab stop and sorts on
293
+ Enter / Space / A. `NicePasswordInput`'s show / hide button is a Tab stop (showing the password
294
+ took a pointer). The `NiceDateTimePicker` field says how its picker opens (`aria-haspopup`,
295
+ `aria-keyshortcuts="Alt+ArrowDown"`).
296
+ - More from the crawler (I4). `NiceDataGrid` took keys from anything inside it: with a focused
297
+ cell Tab never left the grid (a trap, also from a header) and the search field's arrows did
298
+ not move its caret — the cell cursor follows only the grid's own focus, and Tab at the edge of
299
+ a row leaves. `NiceSpreadsheet`'s formula bar kept Tab without an edit. `NiceModelEditor`
300
+ (ui-3d) listened on the whole page: Tab cycled its mode anywhere (focus moved nowhere on a page
301
+ with the editor), Space pressed no button and Ctrl+Z took the undo of every text field — its
302
+ shortcuts work inside the editor only, Tab and Space on its controls are theirs, Escape then
303
+ Tab leaves the viewport. `NiceDocumentEditor` indents a block on Tab and lets the keyboard out
304
+ as the code editors do (Escape, then Tab; its shortcut list says so). `NicePlaylistDualPane` (ui-audio)
305
+ switches panes on Tab, and Escape then Tab moves on. `NiceSeatingChart` / `NiceSeatPicker`
306
+ (events) take focus to the cursor seat — it stayed on the chart, out of a screen reader's
307
+ reach. Rings where there were none: the cursor row of `NiceKaraokeSongBrowser` (it looked the
308
+ same focused as not), `NiceFileManager`'s panels, `NiceTagInput`, the name field of
309
+ `NiceWorkflowDesigner`, `NiceDocumentEditor`, the chat and search fields of ui-communication
310
+ (`outline: none` inline), the search of `NiceGlobalSearch` and `NiceAccessLog`
311
+ (ui-enterprise), the fields of `NiceTaskManager` and `NiceTorrentUI` (templates) and of the
312
+ automation and scene editors (ui-buildings), the viewport of `NiceModelViewer` (ui-3d).
313
+ - `useOverlayFocus` gave focus back to the opener whenever an overlay closed with focus on the
314
+ page body — also for the moment of a Tab, when the opener's blur closed a popup it showed on
315
+ focus: a `NiceDataGrid` header with column stats took focus back on every Tab, a trap. Focus
316
+ goes back now only when it was in the overlay. The keyboard shortcuts of `GenericPlayer`
317
+ (ui-audio) and `NicePresentationPlayer` (ui-presentations) listened on the whole page — the
318
+ arrows of every list and a pad's d-pad (they move focus with them) did nothing on a page with a
319
+ player, Space pressed no button, and with a presentation Backspace deleted nothing and Enter
320
+ submitted nothing in any field; they work in the player or with focus on the page body, and
321
+ Space / Enter on the player's own buttons press them. A pad has no Tab: on a control of a
322
+ player its d-pad moves focus (as seek, volume or the next slide it kept focus in the player for
323
+ good); on the player itself or the page body a remote's arrows still turn the slides.
324
+ - Lint (I2): the whole jsx-a11y recommended set is on, with the input program's own rules against
325
+ page-wide key listeners and inline `outline: 'none'`. Found on the way: the reply box of
326
+ `NiceHelpdesk` and the search of `NiceCommandBar` took the outline away and showed nothing
327
+ instead — they show focus now.
328
+ - `NicePopover` (the one anchored to a `targetRef`) had no keyboard at all — it closed only on a
329
+ click outside it. It is a `dialog` named by its `title`, takes focus when it opens, closes on
330
+ Escape / B and gives focus back to its target (tests that count the page's dialogs see it now).
331
+ A pick in a `NiceSelect` inside it closed it and was lost (the select's list is portalled out
332
+ of the popover): such a click keeps it open.
333
+ - Rows, cards, tiles and list entries that answered a pointer only (C1) are buttons for the
334
+ keyboard and the pad: `role="button"`, a Tab stop, Enter / Space / A press them — a selection
335
+ toggle says `aria-pressed`, a folder or summary row `aria-expanded`, a check box drawn with a
336
+ `div` is a `checkbox` with its item's name. `clickOnActivationKey` (new, ui-core and ui) is the
337
+ `onKeyDown` for such an element: Enter and Space click it, once per press and with the
338
+ modifiers, so Ctrl+Enter selects as Ctrl+click does; keys of a control inside it stay that
339
+ control's. Dialog backdrops and click stoppers are `role="presentation"` (Escape / B close the
340
+ dialogs). Done so far in events (attraction picker and voting, round list), game-engine (the
341
+ Godot, Unity and Unreal project browsers, the asset store, the editor's hierarchy), licensing
342
+ (portal, transfer, the license table), templates (health, life dashboard, personal finance,
343
+ task manager, torrent UI) and `OmniWerkLogo`, whose `role="button"` took no key; ui-3d (model
344
+ editor outliner with expand / show-hide buttons, Add menu, context menu, timeline, particle
345
+ editor), ui-ai (dataset, experiment, model and labeling cards), ui-api (endpoints, schemas,
346
+ history), ui-audio (sample browser, bar-fill swatches, DMX cues and tracks, the "activate
347
+ audio" overlay, playlist grid / overview / sidebar / search / tags / track list),
348
+ ui-bi (ETL palette and nodes), ui-buildings (automations, zone card, scenes, network paths,
349
+ object library), ui-diagrams, ui-enterprise (access log, contract sections), ui-erp (capacity
350
+ planner — its time cells are named buttons, the only way to add an allocation — and inventory
351
+ cards), ui-forms, and in ui-core `NiceIcon` and `NiceTouchTarget` with an `onClick` and the
352
+ profiler's header — `NiceTouchTarget` also draws a focus ring now; ui-graphics (font glyphs, 2D game asset lists and state nodes, photo
353
+ overlays and colour swatches, pixel layers with show / lock buttons, palette and frames,
354
+ texture and UI designer layers, vector gradients and layers), ui-iot cards, ui-math templates,
355
+ ui-monitoring (saved queries, expandable log rows), ui-presentations (slide thumbnails and the
356
+ overview), ui-printing (template cards, schema fields, layers), ui-science (citations,
357
+ notebooks) and ui-video (live sources, timeline tracks and clips). A clickable `NiceIcon` is a
358
+ button now. `ImportPreviewDialog` (ui-buildings) carried `role="dialog"` on its backdrop — it
359
+ is on the dialog box now. The wheel of `NiceMobilePicker` still has no keys (it gets a
360
+ spinbutton column with E). Tests that count the buttons of these components find more.
361
+ - C1 in `@nice2dev/ui`: the rows, cards and items of the devops, data-branching, media, no-code,
362
+ tools, backup and chart components are buttons (selection toggles `aria-pressed`, folding rows
363
+ `aria-expanded`); a `NiceKanbanBoard` card that opens on a click and a `NiceTileView` tile with
364
+ `onTileClick` are buttons; `NiceTreeList` rows fold from the keyboard (the toggle is a named
365
+ button with `aria-expanded`); `NiceDataGrid`'s virtual group rows and detail toggles take
366
+ Enter / Space. A built-in `NiceIcon` with `onClick` is a button — it was `aria-hidden` and took
367
+ no key. `NiceSelect`, `NiceCountryPicker`, `NiceLanguagePicker` and `NiceThemePicker` clear with
368
+ Delete / Backspace on the trigger (`aria-keyshortcuts="Delete"`): the × in the trigger was
369
+ pointer-only (in `NiceSelect` a `role="button"` inside the trigger button) and is
370
+ `role="presentation"` now. `NiceModal`, `NiceConfirmDialog`, `NiceCommandPalette` and
371
+ `NiceGlobalSearch` stop clicks at the backdrop instead of the dialog — a click on the backdrop
372
+ itself closes, and no click inside or on it reaches a component around the overlay.
373
+ `NiceHtmlEditor`'s template list is a menu with keys, its emoji are buttons; `NiceGitManager`
374
+ opens a file's diff from its path, a button (a click elsewhere on the row did it before);
375
+ `NiceResourceAllocation`'s days are named buttons with `onSlotClick`. Options of comboboxes and
376
+ items of menus, trees and grids keep their click with a line disable naming the keys that
377
+ drive them. The empty cells of `NiceScheduler`'s grids get their keys with E.
378
+
3
379
  ## 1.2.2
4
380
 
5
381
  ### Patch Changes
@@ -0,0 +1 @@
1
+ export {};