pixelize-design-library 2.4.2-beta.66 → 2.4.2-beta.67

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
@@ -139,6 +139,7 @@ next major.
139
139
  - **`ChoiceCard` / `ChoiceCardGroup`**: radio cards for picking one of a few options that each need a line of
140
140
  explanation. Group: `value` / `defaultValue` / `onValueChange`; card: `label`, `description`, `icon`,
141
141
  `disabled`. One tab stop; arrows, Home and End move focus and selection. Same look as `PaymentOption`.
142
+ `Pagination` and `ChoiceCard`: reviewed on screen by the owner 2026-10-15, take as-is.
142
143
  - **Plain HTML attributes on the page primitives**: `PageHeader`, `StatCard`, `SaveBar`, `EmptyState`,
143
144
  `DescriptionList`, `FilterBar` and `Skeletons` pass `id`, `className`, `style`, `data-*`, `aria-*` and
144
145
  event handlers to their root element; the component's own props still win and Chakra style props are
@@ -430,6 +431,11 @@ next major.
430
431
 
431
432
  ### Changed
432
433
 
434
+ - **`Table` rows are keyboard-reachable when `onRowClick` is set.** Each row becomes a tab stop (`tabIndex` 0) and Enter or Space
435
+ on the focused row fires `onRowClick` with the first visible column that has no `node`, the same call a click on that cell makes.
436
+ Rows of a table without `onRowClick`, with every column on `node`, or while `isLoading` are unchanged. **Consumers that pass
437
+ `onRowClick` gain one Tab stop per row**: update tab-order tests and expect long tables to need more Tab presses to cross.
438
+
433
439
  - **`ProfileCard` shares the dropped-slot dev warning with `Modal` and `Drawer`.** The helper takes any owner name and
434
440
  warns once per owner and type (previously one set across owners); `ProfileCard` keeps its own message text.
435
441
  - **`MediaViewer` image pan no longer re-renders the viewer on every pointer move.** The pan offset is held in a ref and
@@ -556,6 +562,10 @@ next major.
556
562
 
557
563
  ### Changed (visual)
558
564
 
565
+ - **`Table` rows with `onRowClick` show a keyboard focus ring.** A focused row draws the library's two-tone ring inset around its
566
+ cells (sticky cells included), on `:focus-visible` only, so a mouse click draws nothing. It clears 3:1 on every row plane in light and dark.
567
+
568
+ - **`NavLauncher` slides in with the library's 200 ms enter tween instead of Chakra's drawer spring.** The spring took about 570 ms to come to rest on a full-height panel; the tween (`motionTransition("enter", "out")`, instant under `prefers-reduced-motion`) lands in 200 ms. Measured at 4x CPU throttle, 1280x800, 12 runs against an unchanged build: click to panel at rest and search field focused, median 765 to 413 ms (spotlight, -46%), 819 to 481 ms (classic, -41%), 787 to 460 ms (dark spotlight, -42%). The resting layout and the exit are unchanged.
559
569
  - **`NavLauncher` text snaps to the type scale.** The trigger, panel and spotlight (`NavLauncher`, `launcherParts`, `spotlightParts`) read
560
570
  `xs-plus` (13px) where they drew `12.5px` and `xs-minus` (11px) where they drew `11.5px`; the `13.5px` sizes stay. Each size moves by 0.5px.
561
571
  - **Disabled `Button` dims to the shared 0.5.** The base style drew `opacity: 0.6` while every other disabled control reads
@@ -708,14 +708,14 @@ accepted, typed, never called.
708
708
  **Apply:** leave at least one column without a `node`, or put an explicit control inside a `node`
709
709
  renderer instead of relying on row click.
710
710
 
711
- Row click is also mouse-only: a `Table` row has no `tabIndex`, `role` or key handler, so a keyboard
712
- user can never activate `onRowClick`. The column resize handle is a bare `div` with a
713
- `mousedown` handler and is likewise unreachable by keyboard. Neither is a bug to work around inside
714
- the `Table`; making every row a tab stop would add a focus ring to every consumer.
715
-
716
- **Apply:** whatever `onRowClick` does must also be reachable through a real control, such as a
717
- `Button` or link in a `node` column (the name or an actions cell), so keyboard and
718
- screen-reader users have the same path.
711
+ Setting `onRowClick` makes every row a tab stop: Enter or Space on the focused row (not on a checkbox,
712
+ button or link inside it) fires `onRowClick` with the first visible column that has no `node`. A table
713
+ without `onRowClick`, one whose every column has a `node`, and a table that is `isLoading` get no tab
714
+ stop. The column resize handle is a bare `div` with a `mousedown` handler and is unreachable by keyboard.
715
+
716
+ **Apply:** expect one extra Tab stop per row once you pass `onRowClick`, and update any tab-order test.
717
+ Controls inside a row keep their own keys; give a `node` column a real `Button` or link for the actions
718
+ that must not depend on the row.
719
719
 
720
720
  ### `Table.renderRowDetail` runs for every row on every render, and `expandedRows` ids match strictly
721
721
 
@@ -63,6 +63,7 @@ const LauncherTabs_1 = require("./LauncherTabs");
63
63
  const match_1 = require("./match");
64
64
  const NewTabLink_1 = __importDefault(require("./NewTabLink"));
65
65
  const PinToggle_1 = __importDefault(require("./PinToggle"));
66
+ const launcherMotion_1 = require("./launcherMotion");
66
67
  const resultNavigation_1 = require("./resultNavigation");
67
68
  const ScopeBar_1 = require("./ScopeBar");
68
69
  const searchLayout_1 = require("./searchLayout");
@@ -243,6 +244,7 @@ function NavLauncher({ isOpen, onClose, sections: rawSections, pinnedIds, freque
243
244
  const isDesktop = (0, useMatchMedia_1.useMatchMedia)(MD_QUERY, true);
244
245
  const isLg = (0, useMatchMedia_1.useMatchMedia)(LG_QUERY, true);
245
246
  const isWide = (0, useMatchMedia_1.useMatchMedia)(XL_QUERY, false);
247
+ const isReducedMotion = (0, motion_1.usePrefersReducedMotion)();
246
248
  const columns = isWide ? 3 : isDesktop ? 2 : 1;
247
249
  const [innerQuery, setInnerQuery] = (0, react_2.useState)("");
248
250
  const [activeIndex, setActiveIndex] = (0, react_2.useState)(0);
@@ -828,6 +830,7 @@ function NavLauncher({ isOpen, onClose, sections: rawSections, pinnedIds, freque
828
830
  borderBottomRightRadius: { base: 0, lg: "16px" },
829
831
  boxShadow: colors.boxShadow.default,
830
832
  overflow: "hidden",
833
+ motionProps: (0, launcherMotion_1.launcherSlide)(isReducedMotion),
831
834
  onKeyDown: onContentKeyDown,
832
835
  ...{ "data-testid": testId },
833
836
  }, children: [(0, jsx_runtime_1.jsxs)(Drawer_1.DrawerHeader, { p: 0, flexShrink: 0, children: [(0, jsx_runtime_1.jsxs)(react_1.Flex, { "data-testid": "launcher-header-row", align: "center", gap: { base: "8px", md: "12px" }, minH: { base: "60px", md: "68px" }, pl: { base: "12px", md: "18px" }, pr: { base: "8px", md: "12px" }, children: [(0, jsx_runtime_1.jsx)(react_1.VisuallyHidden, { as: "h2", id: titleId, children: labels.title }), (0, jsx_runtime_1.jsx)(SearchField, { inputRef: inputRef, value: query, onChange: setQuery, onKeyDown: onInputKeyDown, labels: labels, placeholder: (_c = currentScope === null || currentScope === void 0 ? void 0 : currentScope.placeholder) !== null && _c !== void 0 ? _c : labels.searchPlaceholder, hint: searchHint, listboxId: listboxId, activeId: isListView && hasResults ? optionId(active) : undefined, isExpanded: isListView, hasResults: hasResults, minW: inlineScopes ? FIELD_MIN_WIDTH : 0 }), inlineScopes, (0, jsx_runtime_1.jsx)(react_1.Box, { "aria-hidden": true, "data-testid": "launcher-count", display: { base: "none", sm: "block" }, flexShrink: 0, overflow: "hidden", w: countText ? "88px" : "0", opacity: countText ? 1 : 0, textAlign: "right", fontSize: "13px", whiteSpace: "nowrap", color: colors.textMuted, transition: (0, motion_2.transitionFor)(["width", "opacity"]), sx: { fontVariantNumeric: "tabular-nums", ...(0, motion_1.reducedMotionSx)() }, children: countText }), headerActions ? ((0, jsx_runtime_1.jsx)(react_1.Flex, { align: "center", gap: "4px", flexShrink: 0, children: headerActions })) : null, (0, jsx_runtime_1.jsx)(react_1.IconButton, { "aria-label": labels.close, icon: (0, jsx_runtime_1.jsx)(lucide_react_1.X, { size: 18, "aria-hidden": true }), variant: "ghost", boxSize: { base: "40px", md: "44px" }, minW: { base: "40px", md: "44px" }, borderRadius: "10px", flexShrink: 0, color: colors.textMuted, onClick: onClose })] }), scopeRow ? ((0, jsx_runtime_1.jsx)(react_1.Box, { "data-testid": "launcher-scope-row", pl: "7px", pr: "3px", mt: "-6px", pb: "4px", children: scopeRow })) : null] }), (0, jsx_runtime_1.jsx)(Drawer_1.DrawerBody, { p: 0, display: "flex", flexDirection: "column", overflowY: "hidden", minH: 0, children: (0, jsx_runtime_1.jsxs)(react_1.Flex, { ref: bodyRef, direction: "column", flex: 1, minH: 0, minW: 0, children: [(0, jsx_runtime_1.jsx)(react_1.VisuallyHidden, { "data-testid": "launcher-live", "aria-live": "polite", "aria-atomic": "true", children: countText }), (0, jsx_runtime_1.jsx)(react_1.VisuallyHidden, { "data-testid": "launcher-announce", "aria-live": "polite", "aria-atomic": "true", children: (0, jsx_runtime_1.jsx)("span", { children: announcement.text }, announcement.n) }), isTabbed ? ((0, jsx_runtime_1.jsx)(LauncherTabs_1.LauncherTabs, { tabs: tabs, selected: activeTab, onSelect: setTab, idBase: baseId, label: labels.tabsLabel, onLeaveUp: () => focusField(), onLeaveDown: () => moveFocus("first") })) : null, isLg ? ((0, jsx_runtime_1.jsx)(react_1.Flex, { direction: "row", flex: 1, minH: 0, minW: 0, children: body })) : (compactBody), dock] }) }), (0, jsx_runtime_1.jsxs)(Drawer_1.DrawerFooter, { p: 0, minH: "32px", flexShrink: 0, px: "18px", py: "6px", gap: "6px 14px", flexWrap: "wrap", bg: colors.backgroundColor.subtle, fontSize: "xs-minus", color: colors.textMuted, whiteSpace: "nowrap", justifyContent: "flex-start", children: [(0, jsx_runtime_1.jsxs)(react_1.Flex, { display: { base: "none", md: "flex" }, gap: "6px 14px", align: "center", wrap: "wrap", "aria-hidden": true, sx: { "@media (hover: none)": { display: "none" } }, children: [(0, jsx_runtime_1.jsxs)(react_1.Flex, { as: "span", align: "center", gap: "5px", children: [(0, jsx_runtime_1.jsx)(react_1.Flex, { as: "span", gap: "2px", children: ARROW_KEYS.map((arrow) => ((0, jsx_runtime_1.jsx)(Kbd_1.default, { size: "xs", children: arrow }, arrow))) }), labels.hintMove] }), (0, jsx_runtime_1.jsxs)(react_1.Flex, { as: "span", align: "center", gap: "5px", children: [(0, jsx_runtime_1.jsx)(Kbd_1.KbdShortcut, { shortcut: "enter", size: "xs" }), (0, jsx_runtime_1.jsx)(launcherParts_1.HintLabel, { text: enterLabel, reserve: enterReserve })] }), (0, jsx_runtime_1.jsxs)(react_1.Flex, { as: "span", align: "center", gap: "5px", opacity: canOpenInTab ? 1 : 0.45, transition: (0, motion_2.transitionFor)(["opacity"]), sx: (0, motion_1.reducedMotionSx)(), children: [modKeyLabel ? ((0, jsx_runtime_1.jsxs)(react_1.Flex, { as: "span", gap: "4px", children: [(0, jsx_runtime_1.jsx)(Kbd_1.default, { size: "xs", children: modKeyLabel }), (0, jsx_runtime_1.jsx)(Kbd_1.default, { size: "xs", children: ENTER_KEY })] })) : ((0, jsx_runtime_1.jsx)(Kbd_1.KbdShortcut, { shortcut: "mod+enter", size: "xs" })), labels.hintNewTab] }), (0, jsx_runtime_1.jsxs)(react_1.Flex, { as: "span", align: "center", gap: "5px", display: { base: "none", lg: "flex" }, children: [(0, jsx_runtime_1.jsx)(Kbd_1.default, { size: "xs", children: modKeyLabel !== null && modKeyLabel !== void 0 ? modKeyLabel : MOD_KEY }), labels.hintClickNewTab] }), onTogglePin ? ((0, jsx_runtime_1.jsxs)(react_1.Flex, { as: "span", align: "center", gap: "5px", children: [(0, jsx_runtime_1.jsx)(Kbd_1.default, { size: "xs", children: "P" }), labels.hintPin] })) : null, (0, jsx_runtime_1.jsxs)(react_1.Flex, { as: "span", align: "center", gap: "5px", children: [(0, jsx_runtime_1.jsx)(Kbd_1.KbdShortcut, { shortcut: "esc", size: "xs" }), labels.hintClose] })] }), (0, jsx_runtime_1.jsx)(react_1.Text, { as: "span", ml: "auto", children: labels.footerNote })] })] }) }));
@@ -0,0 +1,19 @@
1
+ export declare const launcherSlide: (isReducedMotion: boolean) => {
2
+ variants: {
3
+ enter: {
4
+ x: number;
5
+ y: number;
6
+ transition: {
7
+ duration: number;
8
+ };
9
+ };
10
+ exit: {
11
+ x: string;
12
+ y: number;
13
+ transition: {
14
+ duration: number;
15
+ ease: (0 | 1 | 0.2 | 0.4)[];
16
+ };
17
+ };
18
+ };
19
+ };
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.launcherSlide = void 0;
4
+ const react_1 = require("@chakra-ui/react");
5
+ const motion_1 = require("../../Theme/tokens/primitives/motion");
6
+ const ENTER = (0, motion_1.motionTransition)("enter", "out");
7
+ const INSTANT = { duration: 0 };
8
+ const EXIT = { duration: 0.15, ease: [...react_1.EASINGS.easeInOut] };
9
+ const launcherSlide = (isReducedMotion) => ({
10
+ variants: {
11
+ enter: { x: 0, y: 0, transition: isReducedMotion ? INSTANT : ENTER },
12
+ exit: { x: "-100%", y: 0, transition: EXIT },
13
+ },
14
+ });
15
+ exports.launcherSlide = launcherSlide;
@@ -68,7 +68,7 @@ export type TableProps = {
68
68
  isPagination?: boolean;
69
69
  /** Controlled selected row ids; a new array replaces the internal selection. */
70
70
  selections?: (string | number)[];
71
- /** Fires per cell, gated on the column: a column with `node` swallows its clicks. A node `label` arrives as its plain text. */
71
+ /** Fires per cell, gated on the column: a column with `node` swallows its clicks. Also makes rows tab stops; Enter or Space fires it for the first column without `node`. A node `label` arrives as its plain text. */
72
72
  onRowClick?: (row: DataObject, header: Record<string | number, string | number>) => void;
73
73
  /** Sticky-positions the trailing action/link column during horizontal scroll. Defaults true. */
74
74
  isActionFreeze?: boolean;
@@ -58,6 +58,8 @@ const motion_2 = require("../../../Theme/chakra/motion");
58
58
  const rowDetail_1 = require("./rowDetail");
59
59
  const rowMeasurer_1 = require("./rowMeasurer");
60
60
  const borderWidths_1 = require("../../../Theme/tokens/primitives/borderWidths");
61
+ const activationKey_1 = require("../../Common/activationKey");
62
+ const rowFocusRing_1 = require("./rowFocusRing");
61
63
  const getRowId = (row) => row.id;
62
64
  const getRowContent = (row) => typeof row.content === "function"
63
65
  ? row.content
@@ -117,6 +119,12 @@ const TableRow = react_2.default.memo(({ row, rowIndex, isChecked, isExpanded, i
117
119
  });
118
120
  }
119
121
  }, [row, onRowClick]);
122
+ const keyboardHeader = onRowClick && !isLoading ? columns.find((c) => !c.isHidden && !c.node) : undefined;
123
+ const handleRowKeyDown = (0, react_2.useCallback)((event) => {
124
+ if (event.target !== event.currentTarget || event.repeat || !keyboardHeader)
125
+ return;
126
+ (0, activationKey_1.onActivationKey)(() => handleCellClick(keyboardHeader))(event);
127
+ }, [keyboardHeader, handleCellClick]);
120
128
  const variant = (0, TableVariantContext_1.useTableVariant)();
121
129
  const firstDataColIndex = columns.findIndex((c) => !c.isHidden);
122
130
  const accentSx = accentColor ? `inset 3px 0 0 ${accentColor}` : undefined;
@@ -127,6 +135,7 @@ const TableRow = react_2.default.memo(({ row, rowIndex, isChecked, isExpanded, i
127
135
  : accentSx;
128
136
  const restsOnIndex = variant.slot.rest === "index";
129
137
  const rowSx = {
138
+ ...(keyboardHeader ? (0, rowFocusRing_1.rowFocusRingSx)(theme.colors) : {}),
130
139
  ...(variant.row.hoverScope === "row"
131
140
  ? { "&:hover > td[data-hoverable='true']": { backgroundColor: variant.row.hoverBg } }
132
141
  : {}),
@@ -153,7 +162,7 @@ const TableRow = react_2.default.memo(({ row, rowIndex, isChecked, isExpanded, i
153
162
  const chromeHoverable = rowStyle ? "false" : "true";
154
163
  const rowContent = getRowContent(row);
155
164
  const restBg = isStriped ? variant.row.stripeBg : theme.colors.background[50];
156
- return ((0, jsx_runtime_1.jsxs)(react_2.default.Fragment, { children: [(0, jsx_runtime_1.jsxs)(react_1.Tr, { ref: mainRowRef, "aria-rowindex": ariaRowIndex, opacity: isLoading ? 0.4 : 1, pointerEvents: isLoading ? "none" : "auto", transition: (0, motion_1.transitionFor)(["opacity"], "base"), sx: { ...rowSx, ...(0, motion_2.reducedMotionSx)() }, children: [isContent && ((0, jsx_runtime_1.jsx)(react_1.Td, { w: "6", p: 0, fontSize: "sm", background: isChecked ? selectedFrozenBg : frozenCellBg, color: freezedTextColor, position: "sticky", borderBottom: borderStyle, boxShadow: leadSx, boxSizing: "border-box", "data-hoverable": chromeHoverable, left: "0px", zIndex: 1, className: "columns sticky-columns", children: hasContent && ((0, jsx_runtime_1.jsx)(react_1.IconButton, { "aria-label": isExpanded ? "Collapse row" : "Expand row", color: theme.colors.textMuted, icon: isExpanded ? ((0, jsx_runtime_1.jsx)(lucide_react_1.ChevronDown, {})) : ((0, jsx_runtime_1.jsx)(lucide_react_1.ChevronRight, {})), _hover: { transform: "scale(1.1)" }, size: "sm", onClick: () => toggleRowExpansion(rowIndex), variant: "ghost" })) })), isCheckbox && ((0, jsx_runtime_1.jsx)(react_1.Td, { w: variant.slot.width, minW: variant.slot.width, px: variant.slot.centered ? 0 : undefined, textAlign: variant.slot.centered ? "center" : undefined, fontSize: "sm", fontWeight: 600, color: theme.colors.background[50], textTransform: "capitalize", background: isChecked ? selectedFrozenBg : frozenCellBg, position: "sticky", borderBottom: borderStyle, boxShadow: !isContent ? leadSx : undefined, "data-hoverable": chromeHoverable, boxSizing: "border-box", left: "0px", zIndex: 1, className: "columns sticky-columns", children: (0, jsx_runtime_1.jsxs)(react_1.Box, { display: restsOnIndex ? "grid" : undefined, placeItems: "center", children: [restsOnIndex && ((0, jsx_runtime_1.jsx)(react_1.Box, { as: "span", className: "table-slot-index", gridArea: "1 / 1", color: variant.slot.indexInk, fontSize: "0.6875rem", fontWeight: 500, transition: (0, motion_1.transitionFor)(["opacity"]), sx: { fontVariantNumeric: "tabular-nums", ...(0, motion_2.reducedMotionSx)() }, children: rowIndex + 1 })), (0, jsx_runtime_1.jsx)(react_1.Box, { as: "span", className: restsOnIndex ? "table-slot-box" : undefined, gridArea: restsOnIndex ? "1 / 1" : undefined, display: "flex", alignItems: "center", justifyContent: "center", transition: (0, motion_1.transitionFor)(["opacity"]), sx: (0, motion_2.reducedMotionSx)(), children: (0, jsx_runtime_1.jsx)(Checkbox_1.default, { "aria-label": `Select row ${rowIndex + 1}`, onChange: () => handleCheckbox(getRowId(row)), isChecked: isChecked }) })] }) })), rowDetail && detailIds && ((0, jsx_runtime_1.jsx)(react_1.Td, { w: `${rowDetail_1.DETAIL_SLOT_PX}px`, minW: `${rowDetail_1.DETAIL_SLOT_PX}px`, maxW: `${rowDetail_1.DETAIL_SLOT_PX}px`, p: 0, textAlign: "center", background: isChecked ? selectedFrozenBg : frozenCellBg, position: "sticky", borderBottom: borderStyle, boxShadow: !isContent && !isCheckbox ? leadSx : undefined, "data-hoverable": chromeHoverable, boxSizing: "border-box", left: `${detailLeft}px`, zIndex: 1, className: "columns sticky-columns", children: hasDetail && ((0, jsx_runtime_1.jsx)(rowDetail_1.RowDetailToggle, { isOpen: detailOpen, detailId: detailIds.detailId, color: theme.colors.textMuted, theme: theme, onToggle: () => rowDetail.toggle(getRowId(row)) })) })), columns.map((header, headerIndex) => {
165
+ return ((0, jsx_runtime_1.jsxs)(react_2.default.Fragment, { children: [(0, jsx_runtime_1.jsxs)(react_1.Tr, { ref: mainRowRef, "aria-rowindex": ariaRowIndex, tabIndex: keyboardHeader ? 0 : undefined, onKeyDown: keyboardHeader ? handleRowKeyDown : undefined, opacity: isLoading ? 0.4 : 1, pointerEvents: isLoading ? "none" : "auto", transition: (0, motion_1.transitionFor)(["opacity"], "base"), sx: { ...rowSx, ...(0, motion_2.reducedMotionSx)() }, children: [isContent && ((0, jsx_runtime_1.jsx)(react_1.Td, { w: "6", p: 0, fontSize: "sm", background: isChecked ? selectedFrozenBg : frozenCellBg, color: freezedTextColor, position: "sticky", borderBottom: borderStyle, boxShadow: leadSx, boxSizing: "border-box", "data-hoverable": chromeHoverable, left: "0px", zIndex: 1, className: "columns sticky-columns", children: hasContent && ((0, jsx_runtime_1.jsx)(react_1.IconButton, { "aria-label": isExpanded ? "Collapse row" : "Expand row", color: theme.colors.textMuted, icon: isExpanded ? ((0, jsx_runtime_1.jsx)(lucide_react_1.ChevronDown, {})) : ((0, jsx_runtime_1.jsx)(lucide_react_1.ChevronRight, {})), _hover: { transform: "scale(1.1)" }, size: "sm", onClick: () => toggleRowExpansion(rowIndex), variant: "ghost" })) })), isCheckbox && ((0, jsx_runtime_1.jsx)(react_1.Td, { w: variant.slot.width, minW: variant.slot.width, px: variant.slot.centered ? 0 : undefined, textAlign: variant.slot.centered ? "center" : undefined, fontSize: "sm", fontWeight: 600, color: theme.colors.background[50], textTransform: "capitalize", background: isChecked ? selectedFrozenBg : frozenCellBg, position: "sticky", borderBottom: borderStyle, boxShadow: !isContent ? leadSx : undefined, "data-hoverable": chromeHoverable, boxSizing: "border-box", left: "0px", zIndex: 1, className: "columns sticky-columns", children: (0, jsx_runtime_1.jsxs)(react_1.Box, { display: restsOnIndex ? "grid" : undefined, placeItems: "center", children: [restsOnIndex && ((0, jsx_runtime_1.jsx)(react_1.Box, { as: "span", className: "table-slot-index", gridArea: "1 / 1", color: variant.slot.indexInk, fontSize: "0.6875rem", fontWeight: 500, transition: (0, motion_1.transitionFor)(["opacity"]), sx: { fontVariantNumeric: "tabular-nums", ...(0, motion_2.reducedMotionSx)() }, children: rowIndex + 1 })), (0, jsx_runtime_1.jsx)(react_1.Box, { as: "span", className: restsOnIndex ? "table-slot-box" : undefined, gridArea: restsOnIndex ? "1 / 1" : undefined, display: "flex", alignItems: "center", justifyContent: "center", transition: (0, motion_1.transitionFor)(["opacity"]), sx: (0, motion_2.reducedMotionSx)(), children: (0, jsx_runtime_1.jsx)(Checkbox_1.default, { "aria-label": `Select row ${rowIndex + 1}`, onChange: () => handleCheckbox(getRowId(row)), isChecked: isChecked }) })] }) })), rowDetail && detailIds && ((0, jsx_runtime_1.jsx)(react_1.Td, { w: `${rowDetail_1.DETAIL_SLOT_PX}px`, minW: `${rowDetail_1.DETAIL_SLOT_PX}px`, maxW: `${rowDetail_1.DETAIL_SLOT_PX}px`, p: 0, textAlign: "center", background: isChecked ? selectedFrozenBg : frozenCellBg, position: "sticky", borderBottom: borderStyle, boxShadow: !isContent && !isCheckbox ? leadSx : undefined, "data-hoverable": chromeHoverable, boxSizing: "border-box", left: `${detailLeft}px`, zIndex: 1, className: "columns sticky-columns", children: hasDetail && ((0, jsx_runtime_1.jsx)(rowDetail_1.RowDetailToggle, { isOpen: detailOpen, detailId: detailIds.detailId, color: theme.colors.textMuted, theme: theme, onToggle: () => rowDetail.toggle(getRowId(row)) })) })), columns.map((header, headerIndex) => {
157
166
  var _a, _b, _c, _d;
158
167
  if (header.isHidden)
159
168
  return null;
@@ -0,0 +1,21 @@
1
+ import type { FocusRingTokens } from "../../../Theme/tokens/types";
2
+ export declare const rowFocusRingSx: (colors: {
3
+ focusRing: FocusRingTokens;
4
+ }) => {
5
+ "&:focus-visible": {
6
+ outline: string;
7
+ outlineOffset: string;
8
+ };
9
+ "&:focus-visible > td": {
10
+ boxShadow: string;
11
+ };
12
+ "&:focus-visible > td:first-of-type": {
13
+ boxShadow: string;
14
+ };
15
+ "&:focus-visible > td:last-of-type": {
16
+ boxShadow: string;
17
+ };
18
+ "&:focus-visible > td:only-of-type": {
19
+ boxShadow: string;
20
+ };
21
+ };
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.rowFocusRingSx = void 0;
4
+ const focusRing_styles_1 = require("../../../Theme/chakra/focusRing.styles");
5
+ const TOP = [0, 1];
6
+ const BOTTOM = [0, -1];
7
+ const LEFT = [1, 0];
8
+ const RIGHT = [-1, 0];
9
+ const RING_BAND = focusRing_styles_1.FOCUS_RING_WIDTH - focusRing_styles_1.FOCUS_HALO_WIDTH;
10
+ const band = ([x, y], width, color) => `inset ${x * width}px ${y * width}px 0 0 ${color}`;
11
+ const edgeShadow = (edges, { ring, halo }) => [...edges.map((edge) => band(edge, RING_BAND, ring)), ...edges.map((edge) => band(edge, focusRing_styles_1.FOCUS_RING_WIDTH, halo))].join(", ");
12
+ // NOTE: each cell draws its slice, so sticky cells keep the ring above scrolled content.
13
+ const rowFocusRingSx = (colors) => ({
14
+ "&:focus-visible": { outline: "2px solid transparent", outlineOffset: "-2px" },
15
+ "&:focus-visible > td": { boxShadow: edgeShadow([TOP, BOTTOM], colors.focusRing) },
16
+ "&:focus-visible > td:first-of-type": { boxShadow: edgeShadow([TOP, BOTTOM, LEFT], colors.focusRing) },
17
+ "&:focus-visible > td:last-of-type": { boxShadow: edgeShadow([TOP, BOTTOM, RIGHT], colors.focusRing) },
18
+ "&:focus-visible > td:only-of-type": { boxShadow: edgeShadow([TOP, BOTTOM, LEFT, RIGHT], colors.focusRing) },
19
+ });
20
+ exports.rowFocusRingSx = rowFocusRingSx;
@@ -4,7 +4,7 @@ import { Search as SearchIcon, X } from "lucide-react";
4
4
  import { memo, useCallback, useEffect, useId, useMemo, useRef, useState, } from "react";
5
5
  import { useMatchMedia } from "../../Hooks/useMatchMedia.js";
6
6
  import { focusVisibleStyles } from "../../Theme/chakra/focusRing.styles.js";
7
- import { reducedMotionSx } from "../../Theme/chakra/motion.js";
7
+ import { reducedMotionSx, usePrefersReducedMotion } from "../../Theme/chakra/motion.js";
8
8
  import { chartMode } from "../../Theme/tokens/builders/chartColorsFromTheme.js";
9
9
  import { placeholderInk } from "../../Theme/tokens/builders/placeholderInk.js";
10
10
  import { listRowBackgrounds } from "../../Theme/tokens/builders/rowStates.js";
@@ -24,6 +24,7 @@ import { LauncherTabs, panelId, tabId, } from "./LauncherTabs.js";
24
24
  import { filterItems, searchLauncherSections, } from "./match.js";
25
25
  import NewTabLink from "./NewTabLink.js";
26
26
  import PinToggle from "./PinToggle.js";
27
+ import { launcherSlide } from "./launcherMotion.js";
27
28
  import { moveResult } from "./resultNavigation.js";
28
29
  import { ScopeBar } from "./ScopeBar.js";
29
30
  import { copiesOnEnter, countByScope, inScope, layoutSearch, scopeGroups, takeTopHit, } from "./searchLayout.js";
@@ -204,6 +205,7 @@ export default function NavLauncher({ isOpen, onClose, sections: rawSections, pi
204
205
  const isDesktop = useMatchMedia(MD_QUERY, true);
205
206
  const isLg = useMatchMedia(LG_QUERY, true);
206
207
  const isWide = useMatchMedia(XL_QUERY, false);
208
+ const isReducedMotion = usePrefersReducedMotion();
207
209
  const columns = isWide ? 3 : isDesktop ? 2 : 1;
208
210
  const [innerQuery, setInnerQuery] = useState("");
209
211
  const [activeIndex, setActiveIndex] = useState(0);
@@ -789,6 +791,7 @@ export default function NavLauncher({ isOpen, onClose, sections: rawSections, pi
789
791
  borderBottomRightRadius: { base: 0, lg: "16px" },
790
792
  boxShadow: colors.boxShadow.default,
791
793
  overflow: "hidden",
794
+ motionProps: launcherSlide(isReducedMotion),
792
795
  onKeyDown: onContentKeyDown,
793
796
  ...{ "data-testid": testId },
794
797
  }, children: [_jsxs(DrawerHeader, { p: 0, flexShrink: 0, children: [_jsxs(Flex, { "data-testid": "launcher-header-row", align: "center", gap: { base: "8px", md: "12px" }, minH: { base: "60px", md: "68px" }, pl: { base: "12px", md: "18px" }, pr: { base: "8px", md: "12px" }, children: [_jsx(VisuallyHidden, { as: "h2", id: titleId, children: labels.title }), _jsx(SearchField, { inputRef: inputRef, value: query, onChange: setQuery, onKeyDown: onInputKeyDown, labels: labels, placeholder: (_c = currentScope === null || currentScope === void 0 ? void 0 : currentScope.placeholder) !== null && _c !== void 0 ? _c : labels.searchPlaceholder, hint: searchHint, listboxId: listboxId, activeId: isListView && hasResults ? optionId(active) : undefined, isExpanded: isListView, hasResults: hasResults, minW: inlineScopes ? FIELD_MIN_WIDTH : 0 }), inlineScopes, _jsx(Box, { "aria-hidden": true, "data-testid": "launcher-count", display: { base: "none", sm: "block" }, flexShrink: 0, overflow: "hidden", w: countText ? "88px" : "0", opacity: countText ? 1 : 0, textAlign: "right", fontSize: "13px", whiteSpace: "nowrap", color: colors.textMuted, transition: transitionFor(["width", "opacity"]), sx: { fontVariantNumeric: "tabular-nums", ...reducedMotionSx() }, children: countText }), headerActions ? (_jsx(Flex, { align: "center", gap: "4px", flexShrink: 0, children: headerActions })) : null, _jsx(IconButton, { "aria-label": labels.close, icon: _jsx(X, { size: 18, "aria-hidden": true }), variant: "ghost", boxSize: { base: "40px", md: "44px" }, minW: { base: "40px", md: "44px" }, borderRadius: "10px", flexShrink: 0, color: colors.textMuted, onClick: onClose })] }), scopeRow ? (_jsx(Box, { "data-testid": "launcher-scope-row", pl: "7px", pr: "3px", mt: "-6px", pb: "4px", children: scopeRow })) : null] }), _jsx(DrawerBody, { p: 0, display: "flex", flexDirection: "column", overflowY: "hidden", minH: 0, children: _jsxs(Flex, { ref: bodyRef, direction: "column", flex: 1, minH: 0, minW: 0, children: [_jsx(VisuallyHidden, { "data-testid": "launcher-live", "aria-live": "polite", "aria-atomic": "true", children: countText }), _jsx(VisuallyHidden, { "data-testid": "launcher-announce", "aria-live": "polite", "aria-atomic": "true", children: _jsx("span", { children: announcement.text }, announcement.n) }), isTabbed ? (_jsx(LauncherTabs, { tabs: tabs, selected: activeTab, onSelect: setTab, idBase: baseId, label: labels.tabsLabel, onLeaveUp: () => focusField(), onLeaveDown: () => moveFocus("first") })) : null, isLg ? (_jsx(Flex, { direction: "row", flex: 1, minH: 0, minW: 0, children: body })) : (compactBody), dock] }) }), _jsxs(DrawerFooter, { p: 0, minH: "32px", flexShrink: 0, px: "18px", py: "6px", gap: "6px 14px", flexWrap: "wrap", bg: colors.backgroundColor.subtle, fontSize: "xs-minus", color: colors.textMuted, whiteSpace: "nowrap", justifyContent: "flex-start", children: [_jsxs(Flex, { display: { base: "none", md: "flex" }, gap: "6px 14px", align: "center", wrap: "wrap", "aria-hidden": true, sx: { "@media (hover: none)": { display: "none" } }, children: [_jsxs(Flex, { as: "span", align: "center", gap: "5px", children: [_jsx(Flex, { as: "span", gap: "2px", children: ARROW_KEYS.map((arrow) => (_jsx(Kbd, { size: "xs", children: arrow }, arrow))) }), labels.hintMove] }), _jsxs(Flex, { as: "span", align: "center", gap: "5px", children: [_jsx(KbdShortcut, { shortcut: "enter", size: "xs" }), _jsx(HintLabel, { text: enterLabel, reserve: enterReserve })] }), _jsxs(Flex, { as: "span", align: "center", gap: "5px", opacity: canOpenInTab ? 1 : 0.45, transition: transitionFor(["opacity"]), sx: reducedMotionSx(), children: [modKeyLabel ? (_jsxs(Flex, { as: "span", gap: "4px", children: [_jsx(Kbd, { size: "xs", children: modKeyLabel }), _jsx(Kbd, { size: "xs", children: ENTER_KEY })] })) : (_jsx(KbdShortcut, { shortcut: "mod+enter", size: "xs" })), labels.hintNewTab] }), _jsxs(Flex, { as: "span", align: "center", gap: "5px", display: { base: "none", lg: "flex" }, children: [_jsx(Kbd, { size: "xs", children: modKeyLabel !== null && modKeyLabel !== void 0 ? modKeyLabel : MOD_KEY }), labels.hintClickNewTab] }), onTogglePin ? (_jsxs(Flex, { as: "span", align: "center", gap: "5px", children: [_jsx(Kbd, { size: "xs", children: "P" }), labels.hintPin] })) : null, _jsxs(Flex, { as: "span", align: "center", gap: "5px", children: [_jsx(KbdShortcut, { shortcut: "esc", size: "xs" }), labels.hintClose] })] }), _jsx(Text, { as: "span", ml: "auto", children: labels.footerNote })] })] }) }));
@@ -0,0 +1,11 @@
1
+ import { EASINGS } from "@chakra-ui/react";
2
+ import { motionTransition } from "../../Theme/tokens/primitives/motion.js";
3
+ const ENTER = motionTransition("enter", "out");
4
+ const INSTANT = { duration: 0 };
5
+ const EXIT = { duration: 0.15, ease: [...EASINGS.easeInOut] };
6
+ export const launcherSlide = (isReducedMotion) => ({
7
+ variants: {
8
+ enter: { x: 0, y: 0, transition: isReducedMotion ? INSTANT : ENTER },
9
+ exit: { x: "-100%", y: 0, transition: EXIT },
10
+ },
11
+ });
@@ -19,6 +19,8 @@ import { reducedMotionSx } from "../../../Theme/chakra/motion.js";
19
19
  import { DETAIL_SLOT_PX, RowDetailRow, RowDetailToggle, detailDomIds } from "./rowDetail.js";
20
20
  import { useRowMeasurer } from "./rowMeasurer.js";
21
21
  import { BORDER_WIDTHS } from "../../../Theme/tokens/primitives/borderWidths.js";
22
+ import { onActivationKey } from "../../Common/activationKey.js";
23
+ import { rowFocusRingSx } from "./rowFocusRing.js";
22
24
  const getRowId = (row) => row.id;
23
25
  const getRowContent = (row) => typeof row.content === "function"
24
26
  ? row.content
@@ -77,6 +79,12 @@ const TableRow = React.memo(({ row, rowIndex, isChecked, isExpanded, isContent,
77
79
  });
78
80
  }
79
81
  }, [row, onRowClick]);
82
+ const keyboardHeader = onRowClick && !isLoading ? columns.find((c) => !c.isHidden && !c.node) : undefined;
83
+ const handleRowKeyDown = useCallback((event) => {
84
+ if (event.target !== event.currentTarget || event.repeat || !keyboardHeader)
85
+ return;
86
+ onActivationKey(() => handleCellClick(keyboardHeader))(event);
87
+ }, [keyboardHeader, handleCellClick]);
80
88
  const variant = useTableVariant();
81
89
  const firstDataColIndex = columns.findIndex((c) => !c.isHidden);
82
90
  const accentSx = accentColor ? `inset 3px 0 0 ${accentColor}` : undefined;
@@ -87,6 +95,7 @@ const TableRow = React.memo(({ row, rowIndex, isChecked, isExpanded, isContent,
87
95
  : accentSx;
88
96
  const restsOnIndex = variant.slot.rest === "index";
89
97
  const rowSx = {
98
+ ...(keyboardHeader ? rowFocusRingSx(theme.colors) : {}),
90
99
  ...(variant.row.hoverScope === "row"
91
100
  ? { "&:hover > td[data-hoverable='true']": { backgroundColor: variant.row.hoverBg } }
92
101
  : {}),
@@ -113,7 +122,7 @@ const TableRow = React.memo(({ row, rowIndex, isChecked, isExpanded, isContent,
113
122
  const chromeHoverable = rowStyle ? "false" : "true";
114
123
  const rowContent = getRowContent(row);
115
124
  const restBg = isStriped ? variant.row.stripeBg : theme.colors.background[50];
116
- return (_jsxs(React.Fragment, { children: [_jsxs(Tr, { ref: mainRowRef, "aria-rowindex": ariaRowIndex, opacity: isLoading ? 0.4 : 1, pointerEvents: isLoading ? "none" : "auto", transition: transitionFor(["opacity"], "base"), sx: { ...rowSx, ...reducedMotionSx() }, children: [isContent && (_jsx(Td, { w: "6", p: 0, fontSize: "sm", background: isChecked ? selectedFrozenBg : frozenCellBg, color: freezedTextColor, position: "sticky", borderBottom: borderStyle, boxShadow: leadSx, boxSizing: "border-box", "data-hoverable": chromeHoverable, left: "0px", zIndex: 1, className: "columns sticky-columns", children: hasContent && (_jsx(IconButton, { "aria-label": isExpanded ? "Collapse row" : "Expand row", color: theme.colors.textMuted, icon: isExpanded ? (_jsx(ChevronDown, {})) : (_jsx(ChevronRight, {})), _hover: { transform: "scale(1.1)" }, size: "sm", onClick: () => toggleRowExpansion(rowIndex), variant: "ghost" })) })), isCheckbox && (_jsx(Td, { w: variant.slot.width, minW: variant.slot.width, px: variant.slot.centered ? 0 : undefined, textAlign: variant.slot.centered ? "center" : undefined, fontSize: "sm", fontWeight: 600, color: theme.colors.background[50], textTransform: "capitalize", background: isChecked ? selectedFrozenBg : frozenCellBg, position: "sticky", borderBottom: borderStyle, boxShadow: !isContent ? leadSx : undefined, "data-hoverable": chromeHoverable, boxSizing: "border-box", left: "0px", zIndex: 1, className: "columns sticky-columns", children: _jsxs(Box, { display: restsOnIndex ? "grid" : undefined, placeItems: "center", children: [restsOnIndex && (_jsx(Box, { as: "span", className: "table-slot-index", gridArea: "1 / 1", color: variant.slot.indexInk, fontSize: "0.6875rem", fontWeight: 500, transition: transitionFor(["opacity"]), sx: { fontVariantNumeric: "tabular-nums", ...reducedMotionSx() }, children: rowIndex + 1 })), _jsx(Box, { as: "span", className: restsOnIndex ? "table-slot-box" : undefined, gridArea: restsOnIndex ? "1 / 1" : undefined, display: "flex", alignItems: "center", justifyContent: "center", transition: transitionFor(["opacity"]), sx: reducedMotionSx(), children: _jsx(CheckBox, { "aria-label": `Select row ${rowIndex + 1}`, onChange: () => handleCheckbox(getRowId(row)), isChecked: isChecked }) })] }) })), rowDetail && detailIds && (_jsx(Td, { w: `${DETAIL_SLOT_PX}px`, minW: `${DETAIL_SLOT_PX}px`, maxW: `${DETAIL_SLOT_PX}px`, p: 0, textAlign: "center", background: isChecked ? selectedFrozenBg : frozenCellBg, position: "sticky", borderBottom: borderStyle, boxShadow: !isContent && !isCheckbox ? leadSx : undefined, "data-hoverable": chromeHoverable, boxSizing: "border-box", left: `${detailLeft}px`, zIndex: 1, className: "columns sticky-columns", children: hasDetail && (_jsx(RowDetailToggle, { isOpen: detailOpen, detailId: detailIds.detailId, color: theme.colors.textMuted, theme: theme, onToggle: () => rowDetail.toggle(getRowId(row)) })) })), columns.map((header, headerIndex) => {
125
+ return (_jsxs(React.Fragment, { children: [_jsxs(Tr, { ref: mainRowRef, "aria-rowindex": ariaRowIndex, tabIndex: keyboardHeader ? 0 : undefined, onKeyDown: keyboardHeader ? handleRowKeyDown : undefined, opacity: isLoading ? 0.4 : 1, pointerEvents: isLoading ? "none" : "auto", transition: transitionFor(["opacity"], "base"), sx: { ...rowSx, ...reducedMotionSx() }, children: [isContent && (_jsx(Td, { w: "6", p: 0, fontSize: "sm", background: isChecked ? selectedFrozenBg : frozenCellBg, color: freezedTextColor, position: "sticky", borderBottom: borderStyle, boxShadow: leadSx, boxSizing: "border-box", "data-hoverable": chromeHoverable, left: "0px", zIndex: 1, className: "columns sticky-columns", children: hasContent && (_jsx(IconButton, { "aria-label": isExpanded ? "Collapse row" : "Expand row", color: theme.colors.textMuted, icon: isExpanded ? (_jsx(ChevronDown, {})) : (_jsx(ChevronRight, {})), _hover: { transform: "scale(1.1)" }, size: "sm", onClick: () => toggleRowExpansion(rowIndex), variant: "ghost" })) })), isCheckbox && (_jsx(Td, { w: variant.slot.width, minW: variant.slot.width, px: variant.slot.centered ? 0 : undefined, textAlign: variant.slot.centered ? "center" : undefined, fontSize: "sm", fontWeight: 600, color: theme.colors.background[50], textTransform: "capitalize", background: isChecked ? selectedFrozenBg : frozenCellBg, position: "sticky", borderBottom: borderStyle, boxShadow: !isContent ? leadSx : undefined, "data-hoverable": chromeHoverable, boxSizing: "border-box", left: "0px", zIndex: 1, className: "columns sticky-columns", children: _jsxs(Box, { display: restsOnIndex ? "grid" : undefined, placeItems: "center", children: [restsOnIndex && (_jsx(Box, { as: "span", className: "table-slot-index", gridArea: "1 / 1", color: variant.slot.indexInk, fontSize: "0.6875rem", fontWeight: 500, transition: transitionFor(["opacity"]), sx: { fontVariantNumeric: "tabular-nums", ...reducedMotionSx() }, children: rowIndex + 1 })), _jsx(Box, { as: "span", className: restsOnIndex ? "table-slot-box" : undefined, gridArea: restsOnIndex ? "1 / 1" : undefined, display: "flex", alignItems: "center", justifyContent: "center", transition: transitionFor(["opacity"]), sx: reducedMotionSx(), children: _jsx(CheckBox, { "aria-label": `Select row ${rowIndex + 1}`, onChange: () => handleCheckbox(getRowId(row)), isChecked: isChecked }) })] }) })), rowDetail && detailIds && (_jsx(Td, { w: `${DETAIL_SLOT_PX}px`, minW: `${DETAIL_SLOT_PX}px`, maxW: `${DETAIL_SLOT_PX}px`, p: 0, textAlign: "center", background: isChecked ? selectedFrozenBg : frozenCellBg, position: "sticky", borderBottom: borderStyle, boxShadow: !isContent && !isCheckbox ? leadSx : undefined, "data-hoverable": chromeHoverable, boxSizing: "border-box", left: `${detailLeft}px`, zIndex: 1, className: "columns sticky-columns", children: hasDetail && (_jsx(RowDetailToggle, { isOpen: detailOpen, detailId: detailIds.detailId, color: theme.colors.textMuted, theme: theme, onToggle: () => rowDetail.toggle(getRowId(row)) })) })), columns.map((header, headerIndex) => {
117
126
  var _a, _b, _c, _d;
118
127
  if (header.isHidden)
119
128
  return null;
@@ -0,0 +1,16 @@
1
+ import { FOCUS_HALO_WIDTH, FOCUS_RING_WIDTH } from "../../../Theme/chakra/focusRing.styles.js";
2
+ const TOP = [0, 1];
3
+ const BOTTOM = [0, -1];
4
+ const LEFT = [1, 0];
5
+ const RIGHT = [-1, 0];
6
+ const RING_BAND = FOCUS_RING_WIDTH - FOCUS_HALO_WIDTH;
7
+ const band = ([x, y], width, color) => `inset ${x * width}px ${y * width}px 0 0 ${color}`;
8
+ const edgeShadow = (edges, { ring, halo }) => [...edges.map((edge) => band(edge, RING_BAND, ring)), ...edges.map((edge) => band(edge, FOCUS_RING_WIDTH, halo))].join(", ");
9
+ // NOTE: each cell draws its slice, so sticky cells keep the ring above scrolled content.
10
+ export const rowFocusRingSx = (colors) => ({
11
+ "&:focus-visible": { outline: "2px solid transparent", outlineOffset: "-2px" },
12
+ "&:focus-visible > td": { boxShadow: edgeShadow([TOP, BOTTOM], colors.focusRing) },
13
+ "&:focus-visible > td:first-of-type": { boxShadow: edgeShadow([TOP, BOTTOM, LEFT], colors.focusRing) },
14
+ "&:focus-visible > td:last-of-type": { boxShadow: edgeShadow([TOP, BOTTOM, RIGHT], colors.focusRing) },
15
+ "&:focus-visible > td:only-of-type": { boxShadow: edgeShadow([TOP, BOTTOM, LEFT, RIGHT], colors.focusRing) },
16
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pixelize-design-library",
3
- "version": "2.4.2-beta.66",
3
+ "version": "2.4.2-beta.67",
4
4
  "description": "React component library for Pixelize apps: themeable Chakra-based components, design tokens and light/dark brand theming.",
5
5
  "keywords": [
6
6
  "react",