pixelize-design-library 2.4.2-beta.44 → 2.4.2-beta.46

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.
Files changed (78) hide show
  1. package/CHANGELOG.md +75 -0
  2. package/COMPONENT-GOTCHAS.md +58 -1
  3. package/dist/Components/Common/fieldStyles.d.ts +1 -1
  4. package/dist/Components/Common/fieldStyles.js +4 -4
  5. package/dist/Components/DatePicker/CalendarPanel.js +2 -5
  6. package/dist/Components/EmailCards/VerifyEmailOtp/VerifyEmailOtp.js +2 -4
  7. package/dist/Components/FilterSidebar/FilterSidebar.js +2 -1
  8. package/dist/Components/Header/HeaderActions.d.ts +2 -0
  9. package/dist/Components/Header/HeaderActions.js +2 -2
  10. package/dist/Components/Input/TextInput.styles.js +1 -1
  11. package/dist/Components/KanbanBoard/KanbanActions/KanbanActions.js +1 -1
  12. package/dist/Components/KanbanBoard/KanbanBoardProps.d.ts +2 -0
  13. package/dist/Components/MultiSelect/MultiSelect.d.ts +1 -1
  14. package/dist/Components/MultiSelect/MultiSelect.js +23 -12
  15. package/dist/Components/MultiSelect/MultiSelectProps.d.ts +2 -0
  16. package/dist/Components/NotificationBell/notificationHelpers.d.ts +5 -2
  17. package/dist/Components/NotificationBell/notificationHelpers.js +13 -4
  18. package/dist/Components/PinInput/PinInput.js +2 -4
  19. package/dist/Components/SearchSelect/SearchSelect.js +1 -1
  20. package/dist/Components/SegmentedControl/SegmentedControl.d.ts +1 -1
  21. package/dist/Components/SegmentedControl/SegmentedControl.js +33 -16
  22. package/dist/Components/SegmentedControl/SegmentedControlProps.d.ts +2 -0
  23. package/dist/Components/SegmentedControl/segmentedInk.d.ts +11 -0
  24. package/dist/Components/SegmentedControl/segmentedInk.js +27 -0
  25. package/dist/Components/Select/SelectPopup.js +13 -4
  26. package/dist/Components/Select/optionRowInk.d.ts +3 -0
  27. package/dist/Components/Select/optionRowInk.js +6 -0
  28. package/dist/Components/SideBar/SecondaryBar.js +5 -4
  29. package/dist/Components/SideBar/SideBar.js +6 -5
  30. package/dist/Components/SideBar/SideBarProps.d.ts +2 -0
  31. package/dist/Components/SideBar/components/MenuItemBox.js +5 -4
  32. package/dist/Components/SideBar/components/MenuItems.js +1 -1
  33. package/dist/Components/SideBar/components/MenuPopoverContent.js +4 -3
  34. package/dist/Components/SideBar/sidebarScale.d.ts +15 -0
  35. package/dist/Components/SideBar/sidebarScale.js +18 -0
  36. package/dist/Components/Switch/Switch.d.ts +2 -2
  37. package/dist/Components/Switch/Switch.js +3 -3
  38. package/dist/Components/Switch/SwitchProps.d.ts +2 -0
  39. package/dist/Components/Table/components/Pagination.d.ts +1 -1
  40. package/dist/Components/Table/components/Pagination.js +12 -4
  41. package/dist/Components/Table/filters/SelectOperationControls.js +9 -1
  42. package/dist/Components/Table/filters/TextOperationControls.js +8 -1
  43. package/dist/Components/Table/hooks/useTable.d.ts +2 -1
  44. package/dist/Components/Table/hooks/useTable.js +5 -3
  45. package/dist/Components/Tabs/components/Tab.js +11 -1
  46. package/dist/Theme/chakra/focusRing.styles.d.ts +17 -1
  47. package/dist/Theme/chakra/focusRing.styles.js +16 -1
  48. package/dist/Theme/provider/ThemeSwitcher.js +15 -8
  49. package/dist/esm/Components/Common/fieldStyles.js +5 -5
  50. package/dist/esm/Components/DatePicker/CalendarPanel.js +2 -5
  51. package/dist/esm/Components/EmailCards/VerifyEmailOtp/VerifyEmailOtp.js +2 -4
  52. package/dist/esm/Components/FilterSidebar/FilterSidebar.js +2 -1
  53. package/dist/esm/Components/Header/HeaderActions.js +2 -2
  54. package/dist/esm/Components/Input/TextInput.styles.js +2 -2
  55. package/dist/esm/Components/KanbanBoard/KanbanActions/KanbanActions.js +1 -1
  56. package/dist/esm/Components/MultiSelect/MultiSelect.js +23 -12
  57. package/dist/esm/Components/NotificationBell/notificationHelpers.js +13 -4
  58. package/dist/esm/Components/PinInput/PinInput.js +2 -4
  59. package/dist/esm/Components/SearchSelect/SearchSelect.js +1 -1
  60. package/dist/esm/Components/SegmentedControl/SegmentedControl.js +32 -15
  61. package/dist/esm/Components/SegmentedControl/segmentedInk.js +20 -0
  62. package/dist/esm/Components/Select/SelectPopup.js +14 -5
  63. package/dist/esm/Components/Select/optionRowInk.js +2 -0
  64. package/dist/esm/Components/SideBar/SecondaryBar.js +5 -4
  65. package/dist/esm/Components/SideBar/SideBar.js +6 -5
  66. package/dist/esm/Components/SideBar/components/MenuItemBox.js +5 -4
  67. package/dist/esm/Components/SideBar/components/MenuItems.js +1 -1
  68. package/dist/esm/Components/SideBar/components/MenuPopoverContent.js +4 -3
  69. package/dist/esm/Components/SideBar/sidebarScale.js +15 -0
  70. package/dist/esm/Components/Switch/Switch.js +3 -3
  71. package/dist/esm/Components/Table/components/Pagination.js +13 -5
  72. package/dist/esm/Components/Table/filters/SelectOperationControls.js +8 -3
  73. package/dist/esm/Components/Table/filters/TextOperationControls.js +6 -2
  74. package/dist/esm/Components/Table/hooks/useTable.js +4 -3
  75. package/dist/esm/Components/Tabs/components/Tab.js +12 -2
  76. package/dist/esm/Theme/chakra/focusRing.styles.js +13 -0
  77. package/dist/esm/Theme/provider/ThemeSwitcher.js +16 -9
  78. package/package.json +1 -1
@@ -5,7 +5,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.default = SegmentedControl;
7
7
  const jsx_runtime_1 = require("react/jsx-runtime");
8
- const react_1 = require("@chakra-ui/react");
8
+ const react_1 = require("react");
9
+ const react_2 = require("@chakra-ui/react");
9
10
  const useCustomTheme_1 = require("../../Theme/useCustomTheme");
10
11
  const filledSurface_1 = require("../../Theme/tokens/builders/filledSurface");
11
12
  const controlSizes_1 = require("../../Theme/tokens/primitives/controlSizes");
@@ -14,9 +15,9 @@ const focusRing_styles_1 = require("../../Theme/chakra/focusRing.styles");
14
15
  const motion_2 = require("../../Theme/chakra/motion");
15
16
  const accentText_1 = require("../../Theme/tokens/builders/accentText");
16
17
  const outlineRung_1 = require("../../Theme/tokens/builders/outlineRung");
17
- const color_1 = require("../../Theme/tokens/builders/color");
18
18
  const Tag_1 = __importDefault(require("../Tag/Tag"));
19
19
  const useSlidingPill_1 = require("./useSlidingPill");
20
+ const segmentedInk_1 = require("./segmentedInk");
20
21
  const TRACK_PADDING = "0.125rem";
21
22
  const UNDERLINE_WIDTH = "0.0625rem";
22
23
  const SLIDE = (0, motion_1.transitionFor)(["transform", "width"], "base");
@@ -24,21 +25,33 @@ const MAX_COUNT = 99;
24
25
  const COUNT_TAG_SIZE = { sm: "xs", md: "sm", lg: "md" };
25
26
  const formatCount = (count) => (count > MAX_COUNT ? `${MAX_COUNT}+` : `${count}`);
26
27
  /** Renders role="radiogroup" of role="radio" buttons with roving tabindex, not a native form radio group; shares variant with Toggle/TableToggle (see MODULE.md). */
27
- function SegmentedControl({ options, value, onChange, size = "sm", isFullWidth = false, variant = "default", "aria-label": ariaLabel, }) {
28
- const { colors } = (0, useCustomTheme_1.useCustomTheme)();
28
+ function SegmentedControl({ options, value, onChange, size = "sm", isFullWidth = false, variant = "default", surface, "aria-label": ariaLabel, }) {
29
+ const { colors, radii } = (0, useCustomTheme_1.useCustomTheme)();
29
30
  const control = controlSizes_1.CONTROL_SIZES[size];
30
31
  const isBrandSlide = variant === "brandSlide";
31
32
  const isUnderlineSlide = variant === "underlineSlide";
32
33
  const hasIndicator = isBrandSlide || isUnderlineSlide;
33
34
  const brandFill = (0, filledSurface_1.resolveFilledSurface)(colors.primary, colors);
34
- // brandSlide's track is a translucent tint — composite it before measuring contrast.
35
- const trackSurface = isUnderlineSlide
36
- ? colors.backgroundColor.main
37
- : isBrandSlide
38
- ? (0, color_1.compositeOver)(colors.primary.opacity[8], colors.backgroundColor.main)
39
- : colors.background[600];
40
- const restInk = (0, outlineRung_1.liftToContrast)(colors.text[600], trackSurface, accentText_1.AA_NORMAL_TEXT);
35
+ const trackSurface = (0, segmentedInk_1.segmentedTrackSurface)(variant, colors, surface);
36
+ const restInk = (0, segmentedInk_1.segmentedRestInk)(colors, trackSurface);
37
+ const selectedInk = (0, outlineRung_1.liftToContrast)(colors.accentText, trackSurface, accentText_1.AA_NORMAL_TEXT);
38
+ const hoverInk = (0, outlineRung_1.liftToContrast)(colors.text[900], trackSurface, accentText_1.AA_NORMAL_TEXT);
41
39
  const segmentH = `calc(${control.height} - ${isUnderlineSlide ? UNDERLINE_WIDTH : `2 * ${TRACK_PADDING}`})`;
40
+ // Concentric: an inset child keeping the parent's radius bulges at the corners.
41
+ const innerRadius = isUnderlineSlide ? "none" : `calc(${radii.lg} - ${TRACK_PADDING})`;
42
+ const focusShadow = (0, segmentedInk_1.segmentedFocusShadow)(colors, trackSurface);
43
+ // Inset, never a border: a border consumes the content box and the absolute pill stops centring.
44
+ const plateEdge = isBrandSlide
45
+ ? `inset 0 0 0 1px ${(0, segmentedInk_1.segmentedPlateEdge)(colors, surface)}`
46
+ : undefined;
47
+ // The transparent outline replaces the UA ring and is what Windows high-contrast repaints.
48
+ const segmentFocus = {
49
+ outline: "2px solid transparent",
50
+ outlineOffset: "2px",
51
+ // underlineSlide has no track chrome to carry the indicator, so there the segment wears it.
52
+ ...(isUnderlineSlide ? { boxShadow: focusShadow } : {}),
53
+ };
54
+ const [showFocus, setShowFocus] = (0, react_1.useState)(false);
42
55
  const selectedIndex = options.findIndex((o) => o.value === value);
43
56
  const enabled = options.reduce((acc, o, i) => (o.isDisabled ? acc : [...acc, i]), []);
44
57
  // WAI-APG: with nothing selected, the first enabled segment owns the tab stop.
@@ -77,11 +90,11 @@ function SegmentedControl({ options, value, onChange, size = "sm", isFullWidth =
77
90
  selectAt(enabled[enabled.length - 1]);
78
91
  }
79
92
  };
80
- return ((0, jsx_runtime_1.jsxs)(react_1.Flex, { ref: trackRef, role: "radiogroup", "aria-label": ariaLabel, onKeyDown: handleKeyDown, position: "relative", display: "inline-flex", align: "center", gap: isUnderlineSlide ? "0" : TRACK_PADDING, p: isUnderlineSlide ? "0" : TRACK_PADDING, h: control.height, boxSizing: "border-box", borderRadius: isUnderlineSlide ? "none" : "lg", borderBottom: isUnderlineSlide ? `${UNDERLINE_WIDTH} solid ${colors.boxborder[200]}` : undefined, bg: isBrandSlide ? colors.primary.opacity[8] : isUnderlineSlide ? "transparent" : colors.background[600], w: isFullWidth ? "100%" : "fit-content", children: [isBrandSlide && pill && ((0, jsx_runtime_1.jsx)(react_1.Box, { "aria-hidden": "true", position: "absolute", top: TRACK_PADDING, left: 0, h: segmentH, w: `${pill.width}px`, borderRadius: "lg", bg: brandFill.fill, boxShadow: `0 0.125rem 0.5rem ${colors.boxShadow.primary}`, transform: `translateX(${pill.left}px)`, transition: SLIDE, sx: (0, motion_2.reducedMotionSx)() })), isUnderlineSlide && pill && ((0, jsx_runtime_1.jsx)(react_1.Box, { "aria-hidden": "true", position: "absolute", bottom: "-0.0625rem", left: 0, h: "0.125rem", w: `${pill.width}px`, borderRadius: "full", bg: colors.primary[500], transform: `translateX(${pill.left}px)`, transition: SLIDE, sx: (0, motion_2.reducedMotionSx)() })), options.map((option, index) => {
93
+ return ((0, jsx_runtime_1.jsxs)(react_2.Flex, { ref: trackRef, role: "radiogroup", "aria-label": ariaLabel, onKeyDown: handleKeyDown, onFocus: (event) => setShowFocus(event.target.matches(":focus-visible")), onBlur: () => setShowFocus(false), boxShadow: showFocus && !isUnderlineSlide ? focusShadow : plateEdge, position: "relative", display: "inline-flex", align: "center", gap: isUnderlineSlide ? "0" : TRACK_PADDING, p: isUnderlineSlide ? "0" : TRACK_PADDING, h: control.height, boxSizing: "border-box", borderRadius: isUnderlineSlide ? "none" : "lg", borderBottom: isUnderlineSlide ? `${UNDERLINE_WIDTH} solid ${colors.boxborder[200]}` : undefined, bg: isUnderlineSlide ? "transparent" : trackSurface, w: isFullWidth ? "100%" : "fit-content", minW: "max-content", children: [isBrandSlide && pill && ((0, jsx_runtime_1.jsx)(react_2.Box, { "aria-hidden": "true", position: "absolute", top: TRACK_PADDING, left: 0, h: segmentH, w: `${pill.width}px`, borderRadius: innerRadius, bg: brandFill.fill, boxShadow: `0 0.125rem 0.5rem ${colors.boxShadow.primary}`, transform: `translateX(${pill.left}px)`, transition: SLIDE, sx: (0, motion_2.reducedMotionSx)() })), isUnderlineSlide && pill && ((0, jsx_runtime_1.jsx)(react_2.Box, { "aria-hidden": "true", position: "absolute", bottom: "-0.0625rem", left: 0, h: "0.125rem", w: `${pill.width}px`, borderRadius: "full", bg: colors.primary[500], transform: `translateX(${pill.left}px)`, transition: SLIDE, sx: (0, motion_2.reducedMotionSx)() })), options.map((option, index) => {
81
94
  const isSelected = option.value === value;
82
- return ((0, jsx_runtime_1.jsxs)(react_1.Box, { as: "button", type: "button", ref: (node) => {
95
+ return ((0, jsx_runtime_1.jsxs)(react_2.Box, { as: "button", type: "button", ref: (node) => {
83
96
  refs.current[index] = node;
84
- }, role: "radio", "aria-checked": isSelected, disabled: option.isDisabled, tabIndex: index === tabIndex ? 0 : -1, onClick: () => onChange(option.value), position: "relative", zIndex: 1, display: "inline-flex", alignItems: "center", justifyContent: "center", gap: "0.375rem", flex: isFullWidth ? "1" : undefined, h: segmentH, px: control.paddingX, borderRadius: isUnderlineSlide ? "none" : "lg", borderWidth: "1px", borderStyle: "solid", borderColor: hasIndicator
97
+ }, role: "radio", "aria-checked": isSelected, disabled: option.isDisabled, tabIndex: index === tabIndex ? 0 : -1, onClick: () => onChange(option.value), position: "relative", zIndex: 1, display: "inline-flex", alignItems: "center", justifyContent: "center", gap: "0.375rem", flex: isFullWidth ? "1" : undefined, h: segmentH, px: control.paddingX, borderRadius: innerRadius, borderWidth: "1px", borderStyle: "solid", borderColor: hasIndicator
85
98
  ? "transparent"
86
99
  : isSelected
87
100
  ? colors.primary.opacity[32]
@@ -90,7 +103,11 @@ function SegmentedControl({ options, value, onChange, size = "sm", isFullWidth =
90
103
  ? brandFill.color
91
104
  : restInk
92
105
  : isSelected
93
- ? colors.accentText
94
- : restInk, fontSize: control.fontSize, fontWeight: isSelected ? 600 : 500, whiteSpace: "nowrap", opacity: option.isDisabled ? 0.5 : 1, cursor: option.isDisabled ? "not-allowed" : "pointer", transition: (0, motion_1.transitionFor)(["color"]), _hover: option.isDisabled || isSelected ? undefined : { color: colors.text[900] }, sx: { ...(0, focusRing_styles_1.focusVisibleStyles)(colors), ...(0, motion_2.reducedMotionSx)() }, children: [option.icon, option.label, option.count != null && ((0, jsx_runtime_1.jsx)(Tag_1.default, { label: formatCount(option.count), size: COUNT_TAG_SIZE[size], variant: "subtle", colorScheme: "gray" }))] }, option.value));
106
+ ? selectedInk
107
+ : restInk, fontSize: control.fontSize, fontWeight: isSelected ? 600 : 500, whiteSpace: "nowrap", opacity: option.isDisabled ? 0.5 : 1, cursor: option.isDisabled ? "not-allowed" : "pointer", transition: (0, motion_1.transitionFor)(["color"]), _hover: option.isDisabled || isSelected ? undefined : { color: hoverInk }, sx: {
108
+ _focusVisible: segmentFocus,
109
+ [focusRing_styles_1.FOCUS_VISIBLE_OVER_STATE]: segmentFocus,
110
+ ...(0, motion_2.reducedMotionSx)(),
111
+ }, children: [option.icon, option.label, option.count != null && ((0, jsx_runtime_1.jsx)(Tag_1.default, { label: formatCount(option.count), size: COUNT_TAG_SIZE[size], variant: "subtle", colorScheme: "gray" }))] }, option.value));
95
112
  })] }));
96
113
  }
@@ -27,5 +27,7 @@ export type SegmentedControlProps<T extends string = string> = {
27
27
  isFullWidth?: boolean;
28
28
  /** brandSlide = primary view switcher; underlineSlide = dense toolbars/headers. */
29
29
  variant?: SegmentedControlVariant;
30
+ /** Background this sits on. Optional: the track is opaque on any backdrop; pass it only to aim the plate's hairline edge at the real backdrop. */
31
+ surface?: string;
30
32
  "aria-label": string;
31
33
  };
@@ -0,0 +1,11 @@
1
+ import type { PaletteProps } from "../../Theme/tokens/types";
2
+ import type { SegmentedControlVariant } from "./SegmentedControlProps";
3
+ /** The surface a segment's label really sits on. */
4
+ export declare const segmentedTrackSurface: (variant: SegmentedControlVariant, colors: PaletteProps, surface?: string) => string;
5
+ /** Unselected label ink, lifted to AA against the track it is drawn on. */
6
+ export declare const segmentedRestInk: (colors: PaletteProps, trackSurface: string) => string;
7
+ /** A radiogroup is one tab stop, so the group wears the ring: a brand hairline plus the field bloom. */
8
+ export declare const segmentedFocusShadow: (colors: PaletteProps, trackSurface: string) => string;
9
+ /** The plate can match its backdrop's lightness, so its edge carries the boundary.
10
+ * Drawn inset by the caller: a real border consumes the content box and decentres the sliding pill. */
11
+ export declare const segmentedPlateEdge: (colors: PaletteProps, surface?: string) => string;
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.segmentedPlateEdge = exports.segmentedFocusShadow = exports.segmentedRestInk = exports.segmentedTrackSurface = void 0;
4
+ const focusRing_styles_1 = require("../../Theme/chakra/focusRing.styles");
5
+ const outlineRung_1 = require("../../Theme/tokens/builders/outlineRung");
6
+ const accentText_1 = require("../../Theme/tokens/builders/accentText");
7
+ /** The surface a segment's label really sits on. */
8
+ const segmentedTrackSurface = (variant, colors, surface) => {
9
+ if (variant === "underlineSlide")
10
+ return surface !== null && surface !== void 0 ? surface : colors.backgroundColor.main;
11
+ // brandSlide paints an opaque plate on every backdrop: a tint composites into an unknown
12
+ // parent, so its ink was derived from a canvas the control was not actually on.
13
+ if (variant === "brandSlide")
14
+ return colors.surfaceRaised;
15
+ return colors.background[600];
16
+ };
17
+ exports.segmentedTrackSurface = segmentedTrackSurface;
18
+ /** Unselected label ink, lifted to AA against the track it is drawn on. */
19
+ const segmentedRestInk = (colors, trackSurface) => (0, outlineRung_1.liftToContrast)(colors.text[600], trackSurface, accentText_1.AA_NORMAL_TEXT);
20
+ exports.segmentedRestInk = segmentedRestInk;
21
+ /** A radiogroup is one tab stop, so the group wears the ring: a brand hairline plus the field bloom. */
22
+ const segmentedFocusShadow = (colors, trackSurface) => `inset 0 0 0 1px ${(0, outlineRung_1.liftToContrast)(colors.primary[500], trackSurface, outlineRung_1.AA_NON_TEXT)}, ${(0, focusRing_styles_1.focusGlowShadow)(colors)}`;
23
+ exports.segmentedFocusShadow = segmentedFocusShadow;
24
+ /** The plate can match its backdrop's lightness, so its edge carries the boundary.
25
+ * Drawn inset by the caller: a real border consumes the content box and decentres the sliding pill. */
26
+ const segmentedPlateEdge = (colors, surface) => (0, outlineRung_1.liftToContrast)(colors.boxborder[500], surface !== null && surface !== void 0 ? surface : colors.backgroundColor.main, outlineRung_1.AA_NON_TEXT);
27
+ exports.segmentedPlateEdge = segmentedPlateEdge;
@@ -41,12 +41,13 @@ const react_1 = __importStar(require("react"));
41
41
  const react_2 = require("@chakra-ui/react");
42
42
  const lucide_react_1 = require("lucide-react");
43
43
  const useCustomTheme_1 = require("../../Theme/useCustomTheme");
44
+ const focusRing_styles_1 = require("../../Theme/chakra/focusRing.styles");
44
45
  const rowStates_1 = require("../../Theme/tokens/builders/rowStates");
46
+ const optionRowInk_1 = require("./optionRowInk");
45
47
  const scrollbar_1 = require("../../Theme/tokens/builders/scrollbar");
46
48
  const controlSizes_1 = require("../../Theme/tokens/primitives/controlSizes");
47
49
  const motion_1 = require("../../Theme/tokens/primitives/motion");
48
50
  const motion_2 = require("../../Theme/chakra/motion");
49
- const focusRing_styles_1 = require("../../Theme/chakra/focusRing.styles");
50
51
  const fieldStyles_1 = require("../Common/fieldStyles");
51
52
  const useFieldIds_1 = require("../Common/useFieldIds");
52
53
  const FieldMessage_1 = __importDefault(require("../Common/FieldMessage"));
@@ -80,7 +81,7 @@ const OptionRow = react_1.default.memo(function OptionRow({ option, index, listb
80
81
  const isSingleSelected = isSelected && !isMulti;
81
82
  const selectedBg = isActive ? backgrounds.selectedActive : backgrounds.selected;
82
83
  const restBg = isActive ? backgrounds.active : "transparent";
83
- return ((0, jsx_runtime_1.jsxs)(react_2.Box, { id: optionDomId(listboxId, option.id), "data-index": index, role: "option", "aria-selected": isSelected, "aria-disabled": option.isDisabled, onMouseEnter: () => onActivate(index), onClick: () => onSelect(option), mx: 1.5, px: 2.5, py: 1.5, borderRadius: "md", cursor: option.isDisabled ? "not-allowed" : "pointer", opacity: option.isDisabled ? 0.4 : 1, display: "flex", alignItems: "center", gap: 2, fontSize: "0.8125rem", fontWeight: isSingleSelected ? 600 : 400, color: isSingleSelected ? theme.colors.accentText : theme.colors.text[700], bg: isSingleSelected ? selectedBg : restBg, transition: ROW_TRANSITION, sx: (0, motion_2.reducedMotionSx)(), children: [isMulti ? ((0, jsx_runtime_1.jsx)(react_2.Checkbox, { id: `${optionDomId(listboxId, option.id)}-checkbox`, isChecked: isSelected, isDisabled: option.isDisabled, pointerEvents: "none", tabIndex: -1 })) : null, renderOption ? ((0, jsx_runtime_1.jsx)(react_2.Box, { flex: 1, minW: 0, children: renderOption(option, { isSelected, isActive }) })) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [option.icon ? ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "span", display: "inline-flex", flexShrink: 0, children: option.icon })) : null, (0, jsx_runtime_1.jsxs)(react_2.Box, { flex: 1, minW: 0, isTruncated: true, children: [(0, jsx_runtime_1.jsx)(react_2.Box, { as: "span", isTruncated: true, children: option.label }), option.description ? ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "span", display: "block", fontSize: "0.75rem", color: theme.colors.textMuted, isTruncated: true, children: option.description })) : null] })] }))] }));
84
+ return ((0, jsx_runtime_1.jsxs)(react_2.Box, { id: optionDomId(listboxId, option.id), "data-index": index, role: "option", "aria-selected": isSelected, "aria-disabled": option.isDisabled, onMouseEnter: () => onActivate(index), onClick: () => onSelect(option), mx: 1.5, px: 2.5, py: 1.5, borderRadius: "md", cursor: option.isDisabled ? "not-allowed" : "pointer", opacity: option.isDisabled ? 0.4 : 1, display: "flex", alignItems: "center", gap: 2, fontSize: "0.8125rem", fontWeight: isSingleSelected ? 600 : 400, color: (0, optionRowInk_1.optionRowInk)(theme.colors, isSingleSelected), bg: isSingleSelected ? selectedBg : restBg, transition: ROW_TRANSITION, sx: (0, motion_2.reducedMotionSx)(), children: [isMulti ? ((0, jsx_runtime_1.jsx)(react_2.Checkbox, { id: `${optionDomId(listboxId, option.id)}-checkbox`, isChecked: isSelected, isDisabled: option.isDisabled, pointerEvents: "none", tabIndex: -1 })) : null, renderOption ? ((0, jsx_runtime_1.jsx)(react_2.Box, { flex: 1, minW: 0, children: renderOption(option, { isSelected, isActive }) })) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [option.icon ? ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "span", display: "inline-flex", flexShrink: 0, children: option.icon })) : null, (0, jsx_runtime_1.jsxs)(react_2.Box, { flex: 1, minW: 0, isTruncated: true, children: [(0, jsx_runtime_1.jsx)(react_2.Box, { as: "span", isTruncated: true, children: option.label }), option.description ? ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "span", display: "block", fontSize: "0.75rem", color: theme.colors.textMuted, isTruncated: true, children: option.description })) : null] })] })), isSingleSelected ? ((0, jsx_runtime_1.jsx)(react_2.Box, { as: lucide_react_1.Check, size: 16, color: theme.colors.accentText, flexShrink: 0 })) : null] }));
84
85
  });
85
86
  const buildGroupedRows = (options) => {
86
87
  const rows = [];
@@ -108,6 +109,7 @@ const SelectPopup = (0, react_1.forwardRef)(function SelectPopup(props, ref) {
108
109
  const mergedTriggerRef = (0, react_2.useMergeRefs)(triggerRef, ref);
109
110
  const filterInputRef = (0, react_1.useRef)(null);
110
111
  const listRef = (0, react_1.useRef)(null);
112
+ const [triggerWidth, setTriggerWidth] = (0, react_1.useState)(0);
111
113
  const ids = (0, useFieldIds_1.useFieldIds)(id, { error, errorMessage, helperText });
112
114
  const listboxId = `${ids.inputId}-listbox`;
113
115
  const filterInputId = `${listboxId}-filter`;
@@ -200,6 +202,13 @@ const SelectPopup = (0, react_1.forwardRef)(function SelectPopup(props, ref) {
200
202
  },
201
203
  // eslint-disable-next-line react-hooks/exhaustive-deps
202
204
  [isInteractive, props.isMulti, props.onChange, isValueControlled, onClear]);
205
+ // The panel grows past the trigger to fit long labels, so it cannot inherit the anchor width.
206
+ (0, react_1.useEffect)(() => {
207
+ const node = triggerRef.current;
208
+ if (!isOpen || !node)
209
+ return;
210
+ setTriggerWidth(node.getBoundingClientRect().width);
211
+ }, [isOpen]);
203
212
  (0, react_1.useEffect)(() => {
204
213
  if (!isOpen || !isSearchable)
205
214
  return;
@@ -375,7 +384,7 @@ const SelectPopup = (0, react_1.forwardRef)(function SelectPopup(props, ref) {
375
384
  ...chipTriggerSizeStyles(size, showChips, chipSize),
376
385
  ...(selectedOptions.length ? {} : { color: colors.textMuted }),
377
386
  ...(isOpen
378
- ? { borderColor: error ? colors.semanticText.error : colors.primary[500], boxShadow: (0, focusRing_styles_1.focusRingShadow)(colors) }
387
+ ? { borderColor: error ? colors.semanticText.error : colors.primary[500], boxShadow: (0, focusRing_styles_1.focusGlowShadow)(colors) }
379
388
  : {}),
380
389
  ...(0, motion_2.reducedMotionSx)(),
381
390
  }), [colors, size, showChips, chipSize, selectedOptions.length, isOpen, error]);
@@ -402,7 +411,7 @@ const SelectPopup = (0, react_1.forwardRef)(function SelectPopup(props, ref) {
402
411
  const selectedValueIds = selectedOptions.map((option) => option.id.toString());
403
412
  const hiddenValues = !name ? [] : props.isMulti ? selectedValueIds : [(_c = selectedValueIds[0]) !== null && _c !== void 0 ? _c : ""];
404
413
  const groupedRows = (0, react_1.useMemo)(() => (hasGroups ? buildGroupedRows(filteredOptions) : []), [hasGroups, filteredOptions]);
405
- return ((0, jsx_runtime_1.jsxs)(react_2.FormControl, { isInvalid: error, isDisabled: isDisabled, isReadOnly: isReadOnly, style: formControlStyle, width: width, children: [label && ((0, jsx_runtime_1.jsx)(FormLabel_1.TextLabel, { label: label, id: ids.inputId, isRequired: isRequired, isInformation: isInformation, informationMessage: informationMessage })), (0, jsx_runtime_1.jsxs)(react_2.Popover, { isOpen: isOpen, onClose: () => resetAndClose(), placement: "bottom-start", matchWidth: true, autoFocus: false, returnFocusOnClose: false, gutter: 4, children: [(0, jsx_runtime_1.jsx)(react_2.PopoverAnchor, { children: (0, jsx_runtime_1.jsxs)(react_2.Box, { as: "div", ref: mergedTriggerRef, ...ids.controlProps, role: "combobox", tabIndex: isDisabled ? -1 : 0, "aria-haspopup": "listbox", "aria-expanded": isOpen, "aria-controls": listboxId, "aria-owns": `${listboxId} ${filterInputId}`, "aria-activedescendant": activeDescendantId, "aria-disabled": isDisabled || undefined, "data-readonly": isReadOnly || undefined, "aria-required": isRequired || undefined, "aria-label": triggerAriaLabel(), "aria-labelledby": ariaLabelledBy, onClick: handleOpen, onKeyDown: handleTriggerKeyDown, display: "flex", alignItems: "center", justifyContent: "space-between", width: "100%", textAlign: "left", cursor: isDisabled ? "not-allowed" : isReadOnly ? "default" : "pointer", "data-testid": dataTestId, sx: triggerSx, children: [(0, jsx_runtime_1.jsx)(react_2.Box, { as: "span", display: "inline-flex", flexWrap: showChips ? "wrap" : "nowrap", alignItems: "center", gap: showChips ? 1 : 1.5, minW: 0, flex: 1, isTruncated: !showChips, children: showChips ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [visibleChipOptions.map((option) => ((0, jsx_runtime_1.jsx)(Tag_1.default, { label: String(option.label), size: chipSize, variant: "subtle", icon: isInteractive ? lucide_react_1.X : undefined, onIconClick: isInteractive ? () => handleSelect(option) : undefined }, option.id))), overflowChipCount > 0 && ((0, jsx_runtime_1.jsx)(Tag_1.default, { label: `+${overflowChipCount}`, size: chipSize, variant: "subtle", colorScheme: "gray" }))] })) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [triggerIcon ? ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "span", display: "inline-flex", flexShrink: 0, children: triggerIcon })) : null, (0, jsx_runtime_1.jsx)(react_2.Box, { as: "span", isTruncated: true, children: renderValue ? renderValue(selectedOptions) : defaultTriggerContent() })] })) }), showClear && ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "button", type: "button", "aria-label": "Clear selection", onClick: handleClear, display: "inline-flex", alignItems: "center", justifyContent: "center", flexShrink: 0, ml: 2, color: colors.textMuted, _hover: { color: colors.text[700] }, children: (0, jsx_runtime_1.jsx)(lucide_react_1.X, { size: controlSizes_1.CONTROL_SIZES[size].iconSize }) })), (0, jsx_runtime_1.jsx)(react_2.Box, { as: "span", display: "inline-flex", flexShrink: 0, ml: 2, transition: CHEVRON_TRANSITION, transform: isOpen ? "rotate(180deg)" : "rotate(0deg)", color: colors.textMuted, sx: (0, motion_2.reducedMotionSx)(), children: (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronDown, { size: controlSizes_1.CONTROL_SIZES[size].iconSize }) })] }) }), (0, jsx_runtime_1.jsx)(react_2.Portal, { children: (0, jsx_runtime_1.jsxs)(react_2.PopoverContent, { width: "100%", borderRadius: "xl", boxShadow: theme.shadows.lg, overflow: "hidden", onKeyDown: handleListKeyDown, children: [(0, jsx_runtime_1.jsx)(react_2.Box, { p: 2, borderBottom: `0.063rem solid ${colors.boxborder[200]}`, display: isSearchable ? undefined : "none", children: (0, jsx_runtime_1.jsx)(react_2.Input, { ref: filterInputRef, id: filterInputId, size: "sm", placeholder: "Type to filter...", value: currentSearch, onChange: handleFilterChange, "aria-activedescendant": activeDescendantId, "aria-controls": listboxId, "aria-label": "Filter options", tabIndex: isSearchable ? undefined : -1 }) }), (0, jsx_runtime_1.jsxs)(react_2.Box, { id: listboxId, ref: listRef, role: "listbox", "aria-label": (_d = label !== null && label !== void 0 ? label : ariaLabel) !== null && _d !== void 0 ? _d : placeholder, "aria-multiselectable": props.isMulti || undefined, "aria-busy": isLoading || undefined, maxH: maxMenuHeight, overflowY: "auto", py: 1, sx: listScrollStyles, onScroll: handleListScroll, children: [filteredOptions.length === 0 && !isLoading && !showCreateRow && ((0, jsx_runtime_1.jsx)(react_2.Box, { px: 3, py: 2, fontSize: "0.8125rem", color: colors.textMuted, children: noOptionsMessage !== null && noOptionsMessage !== void 0 ? noOptionsMessage : "No Options" })), showCreateRow && ((0, jsx_runtime_1.jsx)(react_2.Box, { id: createRowId, role: "option", "aria-selected": false, "data-index": -1, onClick: handleCreate, mx: 1.5, px: 2.5, py: 1.5, borderRadius: "md", cursor: "pointer", fontSize: "0.8125rem", fontWeight: 600, color: colors.primary[600], bg: activeDescendantId === createRowId ? rowBackgrounds.active : "transparent", children: createLabel ? createLabel(currentSearch.trim()) : `Create "${currentSearch.trim()}"` })), hasGroups
414
+ return ((0, jsx_runtime_1.jsxs)(react_2.FormControl, { isInvalid: error, isDisabled: isDisabled, isReadOnly: isReadOnly, style: formControlStyle, width: width, children: [label && ((0, jsx_runtime_1.jsx)(FormLabel_1.TextLabel, { label: label, id: ids.inputId, isRequired: isRequired, isInformation: isInformation, informationMessage: informationMessage })), (0, jsx_runtime_1.jsxs)(react_2.Popover, { isOpen: isOpen, onClose: () => resetAndClose(), placement: "bottom-start", autoFocus: false, returnFocusOnClose: false, gutter: 4, children: [(0, jsx_runtime_1.jsx)(react_2.PopoverAnchor, { children: (0, jsx_runtime_1.jsxs)(react_2.Box, { as: "div", ref: mergedTriggerRef, ...ids.controlProps, role: "combobox", tabIndex: isDisabled ? -1 : 0, "aria-haspopup": "listbox", "aria-expanded": isOpen, "aria-controls": listboxId, "aria-owns": `${listboxId} ${filterInputId}`, "aria-activedescendant": activeDescendantId, "aria-disabled": isDisabled || undefined, "data-readonly": isReadOnly || undefined, "aria-required": isRequired || undefined, "aria-label": triggerAriaLabel(), "aria-labelledby": ariaLabelledBy, onClick: handleOpen, onKeyDown: handleTriggerKeyDown, display: "flex", alignItems: "center", justifyContent: "space-between", width: "100%", textAlign: "left", cursor: isDisabled ? "not-allowed" : isReadOnly ? "default" : "pointer", "data-testid": dataTestId, sx: triggerSx, children: [(0, jsx_runtime_1.jsx)(react_2.Box, { as: "span", display: "inline-flex", flexWrap: showChips ? "wrap" : "nowrap", alignItems: "center", gap: showChips ? 1 : 1.5, minW: 0, flex: 1, isTruncated: !showChips, children: showChips ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [visibleChipOptions.map((option) => ((0, jsx_runtime_1.jsx)(Tag_1.default, { label: String(option.label), size: chipSize, variant: "subtle", icon: isInteractive ? lucide_react_1.X : undefined, onIconClick: isInteractive ? () => handleSelect(option) : undefined }, option.id))), overflowChipCount > 0 && ((0, jsx_runtime_1.jsx)(Tag_1.default, { label: `+${overflowChipCount}`, size: chipSize, variant: "subtle", colorScheme: "gray" }))] })) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [triggerIcon ? ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "span", display: "inline-flex", flexShrink: 0, children: triggerIcon })) : null, (0, jsx_runtime_1.jsx)(react_2.Box, { as: "span", isTruncated: true, children: renderValue ? renderValue(selectedOptions) : defaultTriggerContent() })] })) }), showClear && ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "button", type: "button", "aria-label": "Clear selection", onClick: handleClear, display: "inline-flex", alignItems: "center", justifyContent: "center", flexShrink: 0, ml: 2, color: colors.textMuted, _hover: { color: colors.text[700] }, children: (0, jsx_runtime_1.jsx)(lucide_react_1.X, { size: controlSizes_1.CONTROL_SIZES[size].iconSize }) })), (0, jsx_runtime_1.jsx)(react_2.Box, { as: "span", display: "inline-flex", flexShrink: 0, ml: 2, transition: CHEVRON_TRANSITION, transform: isOpen ? "rotate(180deg)" : "rotate(0deg)", color: colors.textMuted, sx: (0, motion_2.reducedMotionSx)(), children: (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronDown, { size: controlSizes_1.CONTROL_SIZES[size].iconSize }) })] }) }), (0, jsx_runtime_1.jsx)(react_2.Portal, { children: (0, jsx_runtime_1.jsxs)(react_2.PopoverContent, { width: "max-content", minWidth: triggerWidth ? `${triggerWidth}px` : undefined, maxWidth: "min(24rem, calc(100vw - 2rem))", borderRadius: "xl", boxShadow: theme.shadows.lg, overflow: "hidden", onKeyDown: handleListKeyDown, children: [(0, jsx_runtime_1.jsx)(react_2.Box, { p: 2, borderBottom: `0.063rem solid ${colors.boxborder[200]}`, display: isSearchable ? undefined : "none", children: (0, jsx_runtime_1.jsx)(react_2.Input, { ref: filterInputRef, id: filterInputId, size: "sm", placeholder: "Type to filter...", value: currentSearch, onChange: handleFilterChange, "aria-activedescendant": activeDescendantId, "aria-controls": listboxId, "aria-label": "Filter options", tabIndex: isSearchable ? undefined : -1 }) }), (0, jsx_runtime_1.jsxs)(react_2.Box, { id: listboxId, ref: listRef, role: "listbox", "aria-label": (_d = label !== null && label !== void 0 ? label : ariaLabel) !== null && _d !== void 0 ? _d : placeholder, "aria-multiselectable": props.isMulti || undefined, "aria-busy": isLoading || undefined, maxH: maxMenuHeight, overflowY: "auto", py: 1, sx: listScrollStyles, onScroll: handleListScroll, children: [filteredOptions.length === 0 && !isLoading && !showCreateRow && ((0, jsx_runtime_1.jsx)(react_2.Box, { px: 3, py: 2, fontSize: "0.8125rem", color: colors.textMuted, children: noOptionsMessage !== null && noOptionsMessage !== void 0 ? noOptionsMessage : "No Options" })), showCreateRow && ((0, jsx_runtime_1.jsx)(react_2.Box, { id: createRowId, role: "option", "aria-selected": false, "data-index": -1, onClick: handleCreate, mx: 1.5, px: 2.5, py: 1.5, borderRadius: "md", cursor: "pointer", fontSize: "0.8125rem", fontWeight: 600, color: colors.primary[600], bg: activeDescendantId === createRowId ? rowBackgrounds.active : "transparent", children: createLabel ? createLabel(currentSearch.trim()) : `Create "${currentSearch.trim()}"` })), hasGroups
406
415
  ? groupedRows.map((row) => {
407
416
  var _a;
408
417
  return row.kind === "header" ? ((0, jsx_runtime_1.jsx)(react_2.Box, { px: 3, pt: 2, pb: 1, fontSize: "0.6875rem", fontWeight: 600, textTransform: "uppercase", letterSpacing: "0.03em", color: colors.textMuted, children: row.group }, row.key)) : ((0, jsx_runtime_1.jsx)(OptionRow, { option: row.option, index: row.index, listboxId: listboxId, isSelected: selectedIds.has(row.option.id.toString()), isActive: row.index === activeIndex, isMulti: (_a = props.isMulti) !== null && _a !== void 0 ? _a : false, theme: theme, backgrounds: rowBackgrounds, renderOption: renderOption, onSelect: handleSelect, onActivate: setActiveIndex }, row.key));
@@ -0,0 +1,3 @@
1
+ import type { PaletteProps } from "../../Theme/tokens/types";
2
+ /** Selection is carried by weight and a trailing brand check, so the label itself stays neutral. */
3
+ export declare const optionRowInk: (colors: PaletteProps, isSingleSelected: boolean) => string;
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.optionRowInk = void 0;
4
+ /** Selection is carried by weight and a trailing brand check, so the label itself stays neutral. */
5
+ const optionRowInk = (colors, isSingleSelected) => isSingleSelected ? colors.text[900] : colors.text[700];
6
+ exports.optionRowInk = optionRowInk;
@@ -18,6 +18,7 @@ const tone_1 = require("../../Theme/tokens/builders/tone");
18
18
  const sidebarAccent_1 = require("../../Theme/tokens/builders/sidebarAccent");
19
19
  const paletteFromTheme_1 = require("../../Theme/chakra/paletteFromTheme");
20
20
  const viewportHeight_1 = require("../../Theme/tokens/builders/viewportHeight");
21
+ const sidebarScale_1 = require("./sidebarScale");
21
22
  const softBadge = (colors, colorScheme, surface) => {
22
23
  const tone = (0, tone_1.resolveSoftTone)(colors, (0, paletteFromTheme_1.scaleFor)(colors, colorScheme), surface);
23
24
  return { bg: tone.bg, color: tone.fg };
@@ -46,7 +47,7 @@ const CollapsedItem = ({ item, isActive, itemFontSize, onItemClick }) => {
46
47
  e.preventDefault();
47
48
  if (!(0, menuDisabled_1.menuDisabled)(item))
48
49
  onItemClick === null || onItemClick === void 0 ? void 0 : onItemClick(item);
49
- }, bg: isActive ? "whiteAlpha.300" : "transparent", transition: "background 0.12s", children: (0, jsx_runtime_1.jsxs)(react_2.Box, { position: "relative", display: "flex", alignItems: "center", children: [(0, jsx_runtime_1.jsx)(react_2.Icon, { as: item.icon, fontSize: "1rem", color: isActive ? activeAccent.icon : theme.colors.sidebar.mutedIcon, _groupHover: isActive ? undefined : { color: theme.colors.white }, transition: "color 0.12s" }), badgeVal != null && ((0, jsx_runtime_1.jsx)(react_2.Box, { position: "absolute", top: "0", right: "0", w: "0.375rem", h: "0.375rem", borderRadius: "full", bg: theme.colors.red[400] }))] }) }) }), (0, jsx_runtime_1.jsx)(react_2.Portal, { children: (0, jsx_runtime_1.jsx)(react_2.PopoverContent, { borderRadius: "lg", bg: theme.colors.sidebar.elevated, boxShadow: "lg", minW: "10rem", maxW: "14rem", py: "0.125rem", ml: "-0.5rem", cursor: (0, menuDisabled_1.menuDisabled)(item) ? "not-allowed" : "pointer", zIndex: 1500, color: theme.colors.white, border: 'none', children: (0, jsx_runtime_1.jsx)(react_2.PopoverBody, { p: 3, children: (0, jsx_runtime_1.jsxs)(react_2.Flex, { align: "center", gap: 2, justify: "space-between", children: [(0, jsx_runtime_1.jsxs)(react_2.Flex, { align: "center", gap: 2, flex: "1", minW: 0, children: [(0, jsx_runtime_1.jsx)(react_2.Icon, { as: item.icon, fontSize: "md", flexShrink: 0 }), (0, jsx_runtime_1.jsx)(OverflowTooltipText_1.default, { placement: "right", maxWidth: "100%", fontSize: itemFontSize, fontWeight: "medium", as: "p", children: item.title })] }), badgeVal != null && ((0, jsx_runtime_1.jsx)(react_2.Badge, { ...softBadge(theme.colors, colorScheme, (0, sidebarAccent_1.sidebarRowPeak)(theme.colors.sidebar.elevated)), fontSize: "xs", variant: variant, borderRadius: radius, children: badgeVal }))] }) }) }) })] }));
50
+ }, bg: isActive ? "whiteAlpha.300" : "transparent", transition: "background 0.12s", children: (0, jsx_runtime_1.jsxs)(react_2.Box, { position: "relative", display: "flex", alignItems: "center", children: [(0, jsx_runtime_1.jsx)(react_2.Icon, { as: item.icon, fontSize: sidebarScale_1.SIDEBAR_ROW.iconSize, color: isActive ? activeAccent.icon : theme.colors.sidebar.mutedIcon, _groupHover: isActive ? undefined : { color: theme.colors.white }, transition: "color 0.12s" }), badgeVal != null && ((0, jsx_runtime_1.jsx)(react_2.Box, { position: "absolute", top: "0", right: "0", w: "0.375rem", h: "0.375rem", borderRadius: "full", bg: theme.colors.red[400] }))] }) }) }), (0, jsx_runtime_1.jsx)(react_2.Portal, { children: (0, jsx_runtime_1.jsx)(react_2.PopoverContent, { borderRadius: "lg", bg: theme.colors.sidebar.elevated, boxShadow: "lg", minW: "10rem", maxW: "14rem", py: "0.125rem", ml: "-0.5rem", cursor: (0, menuDisabled_1.menuDisabled)(item) ? "not-allowed" : "pointer", zIndex: 1500, color: theme.colors.white, border: 'none', children: (0, jsx_runtime_1.jsx)(react_2.PopoverBody, { p: 3, children: (0, jsx_runtime_1.jsxs)(react_2.Flex, { align: "center", gap: 2, justify: "space-between", children: [(0, jsx_runtime_1.jsxs)(react_2.Flex, { align: "center", gap: 2, flex: "1", minW: 0, children: [(0, jsx_runtime_1.jsx)(react_2.Icon, { as: item.icon, fontSize: "md", flexShrink: 0 }), (0, jsx_runtime_1.jsx)(OverflowTooltipText_1.default, { placement: "right", maxWidth: "100%", fontSize: itemFontSize, fontWeight: "medium", as: "p", children: item.title })] }), badgeVal != null && ((0, jsx_runtime_1.jsx)(react_2.Badge, { ...softBadge(theme.colors, colorScheme, (0, sidebarAccent_1.sidebarRowPeak)(theme.colors.sidebar.elevated)), fontSize: "xs", variant: variant, borderRadius: radius, children: badgeVal }))] }) }) }) })] }));
50
51
  };
51
52
  const ExpandedItem = ({ item, isActive, itemFontSize, onItemClick }) => {
52
53
  var _a;
@@ -59,14 +60,14 @@ const ExpandedItem = ({ item, isActive, itemFontSize, onItemClick }) => {
59
60
  e.preventDefault();
60
61
  if (!(0, menuDisabled_1.menuDisabled)(item))
61
62
  onItemClick === null || onItemClick === void 0 ? void 0 : onItemClick(item);
62
- }, borderLeft: "2px solid", borderLeftColor: isActive ? theme.colors.sidebar.activeIcon : "transparent", transition: "background 0.12s", children: [(0, jsx_runtime_1.jsxs)(react_2.Flex, { align: "center", gap: 2, flex: "1", minW: 0, overflow: "hidden", children: [(0, jsx_runtime_1.jsx)(react_2.Icon, { as: item.icon, fontSize: "0.95rem", flexShrink: 0, color: isActive ? activeAccent.icon : theme.colors.sidebar.mutedIcon, _groupHover: isActive ? undefined : { color: theme.colors.white }, transition: "color 0.12s" }), (0, jsx_runtime_1.jsx)(react_2.Box, { flex: "1", minW: 0, children: (0, jsx_runtime_1.jsx)(OverflowTooltipText_1.default, { placement: "right", maxWidth: "100%", fontSize: itemFontSize, fontWeight: isActive ? 600 : 500, color: isActive ? activeAccent.label : theme.colors.white, _groupHover: isActive ? undefined : { color: theme.colors.white }, as: "p", children: item.title }) })] }), badgeVal != null && ((0, jsx_runtime_1.jsx)(react_2.Badge, { ...softBadge(theme.colors, colorScheme, (0, sidebarAccent_1.sidebarRowPeak)(theme.colors.sidebar.background[500])), fontSize: "xs", variant: variant, borderRadius: radius, children: badgeVal }))] }));
63
+ }, borderLeft: "2px solid", borderLeftColor: isActive ? theme.colors.sidebar.activeIcon : "transparent", transition: "background 0.12s", children: [(0, jsx_runtime_1.jsxs)(react_2.Flex, { align: "center", gap: 2, flex: "1", minW: 0, overflow: "hidden", children: [(0, jsx_runtime_1.jsx)(react_2.Icon, { as: item.icon, fontSize: sidebarScale_1.SIDEBAR_ROW.iconSize, flexShrink: 0, color: isActive ? activeAccent.icon : theme.colors.sidebar.mutedIcon, _groupHover: isActive ? undefined : { color: theme.colors.white }, transition: "color 0.12s" }), (0, jsx_runtime_1.jsx)(react_2.Box, { flex: "1", minW: 0, children: (0, jsx_runtime_1.jsx)(OverflowTooltipText_1.default, { placement: "right", maxWidth: "100%", fontSize: itemFontSize, fontWeight: isActive ? 600 : 500, color: isActive ? activeAccent.label : theme.colors.white, _groupHover: isActive ? undefined : { color: theme.colors.white }, as: "p", children: item.title }) })] }), badgeVal != null && ((0, jsx_runtime_1.jsx)(react_2.Badge, { ...softBadge(theme.colors, colorScheme, (0, sidebarAccent_1.sidebarRowPeak)(theme.colors.sidebar.background[500])), fontSize: "xs", variant: variant, borderRadius: radius, children: badgeVal }))] }));
63
64
  };
64
- const SecondaryBar = ({ items = [], defaultCollapsed = true, collapsedWidth = "3.5rem", expandedWidth = "10rem", headerFontSize = "0.75rem", itemFontSize = "0.75rem", selected, onItemClick, title, icon, }) => {
65
+ const SecondaryBar = ({ items = [], defaultCollapsed = true, collapsedWidth = "3.5rem", expandedWidth = "10rem", headerFontSize = sidebarScale_1.SIDEBAR_ROW.fontSize, itemFontSize = sidebarScale_1.SIDEBAR_ROW.fontSize, selected, onItemClick, title, icon, }) => {
65
66
  const theme = (0, useCustomTheme_1.useCustomTheme)();
66
67
  const activeAccent = (0, sidebarAccentColors_1.getSidebarActiveAccent)(theme.colors);
67
68
  const [collapsed, setCollapsed] = (0, react_1.useState)(defaultCollapsed);
68
69
  const width = collapsed ? collapsedWidth : expandedWidth;
69
- return ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "nav", "aria-label": title ? `${title} navigation` : "Secondary navigation", transition: (0, motion_1.transitionFor)(["width"], "base"), pos: "sticky", top: 0, sx: viewportHeight_1.fullViewportHeight, w: width, bg: theme.colors.sidebar.background[500], borderLeft: "1px solid", borderColor: theme.colors.sidebar.divider, boxShadow: theme.shadows.md, zIndex: 1, children: (0, jsx_runtime_1.jsxs)(react_2.VStack, { align: "stretch", spacing: 0, h: "100%", children: [(0, jsx_runtime_1.jsxs)(react_2.Flex, { align: "center", justify: collapsed ? "center" : "space-between", px: collapsed ? 0 : "10px", gap: "7px", h: Sidebar_1.HEADER_HEIGHT, overflow: "hidden", borderBottom: "1px solid", borderColor: theme.colors.sidebar.divider, flexShrink: 0, children: [!collapsed && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [icon && ((0, jsx_runtime_1.jsx)(react_2.Icon, { as: icon, fontSize: "0.95rem", color: activeAccent.icon, flexShrink: 0 })), (0, jsx_runtime_1.jsx)(react_2.Box, { flex: "1", minW: 0, children: (0, jsx_runtime_1.jsx)(OverflowTooltipText_1.default, { placement: "right", maxWidth: "100%", fontSize: headerFontSize, fontWeight: 600, color: theme.colors.white, as: "p", children: title !== null && title !== void 0 ? title : "" }) })] })), (0, jsx_runtime_1.jsx)(react_2.Box, { as: "button", type: "button", "aria-label": collapsed ? "Expand navigation panel" : "Collapse navigation panel", "aria-expanded": !collapsed, border: "none", bg: "transparent", w: "24px", h: "24px", borderRadius: "lg", display: "flex", alignItems: "center", justifyContent: "center", cursor: "pointer", flexShrink: 0, onClick: () => setCollapsed((c) => !c), _hover: { bg: "whiteAlpha.100" }, transition: "background 0.15s", children: collapsed ? ((0, jsx_runtime_1.jsx)(ToolTip_1.default, { label: title !== null && title !== void 0 ? title : "", placement: "right", children: (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronRight, { size: 13, color: theme.colors.sidebar.mutedIcon }) })) : ((0, jsx_runtime_1.jsx)(lucide_react_1.ChevronLeft, { size: 13, color: theme.colors.sidebar.mutedIcon })) })] }), (0, jsx_runtime_1.jsx)(react_2.Box, { id: "secondary-scroll-container", flex: "1", minH: 0, overflowY: "auto", overflowX: "hidden", py: 2, px: "6px", children: items.map((item) => {
70
+ return ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "nav", "aria-label": title ? `${title} navigation` : "Secondary navigation", transition: (0, motion_1.transitionFor)(["width"], "base"), pos: "sticky", top: 0, sx: viewportHeight_1.fullViewportHeight, w: width, bg: theme.colors.sidebar.background[500], borderLeft: "1px solid", borderColor: theme.colors.sidebar.divider, boxShadow: theme.shadows.md, zIndex: 1, children: (0, jsx_runtime_1.jsxs)(react_2.VStack, { align: "stretch", spacing: 0, h: "100%", children: [(0, jsx_runtime_1.jsxs)(react_2.Flex, { align: "center", justify: collapsed ? "center" : "space-between", px: collapsed ? 0 : "10px", gap: "7px", h: Sidebar_1.HEADER_HEIGHT, overflow: "hidden", borderBottom: "1px solid", borderColor: theme.colors.sidebar.divider, flexShrink: 0, children: [!collapsed && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [icon && ((0, jsx_runtime_1.jsx)(react_2.Icon, { as: icon, fontSize: sidebarScale_1.SIDEBAR_ROW.iconSize, color: activeAccent.icon, flexShrink: 0 })), (0, jsx_runtime_1.jsx)(react_2.Box, { flex: "1", minW: 0, children: (0, jsx_runtime_1.jsx)(OverflowTooltipText_1.default, { placement: "right", maxWidth: "100%", fontSize: headerFontSize, fontWeight: 600, color: theme.colors.white, as: "p", children: title !== null && title !== void 0 ? title : "" }) })] })), (0, jsx_runtime_1.jsx)(react_2.Box, { as: "button", type: "button", "aria-label": collapsed ? "Expand navigation panel" : "Collapse navigation panel", "aria-expanded": !collapsed, border: "none", bg: "transparent", w: "24px", h: "24px", borderRadius: "lg", display: "flex", alignItems: "center", justifyContent: "center", cursor: "pointer", flexShrink: 0, onClick: () => setCollapsed((c) => !c), _hover: { bg: "whiteAlpha.100" }, transition: "background 0.15s", children: collapsed ? ((0, jsx_runtime_1.jsx)(ToolTip_1.default, { label: title !== null && title !== void 0 ? title : "", placement: "right", children: (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronRight, { size: 13, color: theme.colors.sidebar.mutedIcon }) })) : ((0, jsx_runtime_1.jsx)(lucide_react_1.ChevronLeft, { size: 13, color: theme.colors.sidebar.mutedIcon })) })] }), (0, jsx_runtime_1.jsx)(react_2.Box, { id: "secondary-scroll-container", flex: "1", minH: 0, overflowY: "auto", overflowX: "hidden", py: 2, px: "6px", children: items.map((item) => {
70
71
  var _a;
71
72
  const isActive = String(selected) === String(item.id) ||
72
73
  String(selected) === String(item.title);
@@ -32,6 +32,7 @@ const defaultLogo_1 = __importDefault(require("../../Assets/defaultLogo"));
32
32
  const OverflowTooltipText_1 = __importDefault(require("./components/OverflowTooltipText"));
33
33
  const SecondaryBar_1 = __importDefault(require("./SecondaryBar"));
34
34
  const OtherApps_1 = __importDefault(require("./components/OtherApps"));
35
+ const sidebarScale_1 = require("./sidebarScale");
35
36
  const viewportHeight_1 = require("../../Theme/tokens/builders/viewportHeight");
36
37
  const SidebarHeader = ({ logo, companyName, companySubtitle, toggle, isLoading, onToggle, overlay, onClose, }) => {
37
38
  const theme = (0, useCustomTheme_1.useCustomTheme)();
@@ -41,7 +42,7 @@ const SidebarHeader = ({ logo, companyName, companySubtitle, toggle, isLoading,
41
42
  const primaryFillRung = (0, filledSurface_1.solidFillRung)(theme.colors.primary, theme.colors.white);
42
43
  const primaryFill = theme.colors.primary[primaryFillRung];
43
44
  const logoNode = logo ? ((0, jsx_runtime_1.jsx)(react_2.Image, { borderRadius: "lg", boxSize: "1.75rem", src: logo, alt: "Company Logo", flexShrink: 0, cursor: toggle ? "pointer" : undefined, onClick: toggle ? onToggle : undefined })) : ((0, jsx_runtime_1.jsx)(react_2.Box, { bg: primaryFill, color: (0, filledSurface_1.labelOnFill)(primaryFill, theme.colors.white, theme.colors.black), borderRadius: "lg", boxSize: "1.75rem", display: "flex", alignItems: "center", justifyContent: "center", fontWeight: "bold", flexShrink: 0, cursor: toggle ? "pointer" : undefined, onClick: toggle ? onToggle : undefined, children: (0, jsx_runtime_1.jsx)(defaultLogo_1.default, {}) }));
44
- return ((0, jsx_runtime_1.jsxs)(react_2.Flex, { h: Sidebar_1.HEADER_HEIGHT, w: "100%", alignItems: "center", justifyContent: toggle ? "center" : "flex-start", gap: 2, px: toggle ? "8px" : "10px", borderBottom: "1px solid", borderColor: theme.colors.sidebar.divider, minW: 0, overflow: "hidden", flexShrink: 0, children: [logoNode, !toggle && ((0, jsx_runtime_1.jsxs)(react_2.Box, { flex: "1", minW: 0, children: [(0, jsx_runtime_1.jsx)(OverflowTooltipText_1.default, { placement: "right", fontWeight: 600, fontSize: "12.5px", textAlign: "left", color: theme.colors.white, lineHeight: "1.3", as: "p", width: "100%", children: companyName !== null && companyName !== void 0 ? companyName : "" }), companySubtitle && ((0, jsx_runtime_1.jsx)(react_2.Text, { fontSize: "10px", color: theme.colors.sidebar.mutedLabel, lineHeight: "1.3", isTruncated: true, children: companySubtitle }))] })), !toggle && ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "button", type: "button", onClick: overlay ? onClose : onToggle, "aria-label": overlay ? "Close menu" : "Collapse sidebar", w: "22px", h: "22px", borderRadius: "lg", bg: "whiteAlpha.100", display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0, position: "relative", _hover: { bg: "whiteAlpha.300" }, transition: "background 0.15s", sx: {
45
+ return ((0, jsx_runtime_1.jsxs)(react_2.Flex, { h: Sidebar_1.HEADER_HEIGHT, w: "100%", alignItems: "center", justifyContent: toggle ? "center" : "flex-start", gap: 2, px: toggle ? "8px" : "10px", borderBottom: "1px solid", borderColor: theme.colors.sidebar.divider, minW: 0, overflow: "hidden", flexShrink: 0, children: [logoNode, !toggle && ((0, jsx_runtime_1.jsxs)(react_2.Box, { flex: "1", minW: 0, children: [(0, jsx_runtime_1.jsx)(OverflowTooltipText_1.default, { placement: "right", fontWeight: 600, fontSize: sidebarScale_1.SIDEBAR_CHROME.titleFontSize, textAlign: "left", color: theme.colors.white, lineHeight: "1.3", as: "p", width: "100%", children: companyName !== null && companyName !== void 0 ? companyName : "" }), companySubtitle && ((0, jsx_runtime_1.jsx)(react_2.Text, { fontSize: sidebarScale_1.SIDEBAR_CHROME.metaFontSize, color: theme.colors.sidebar.mutedLabel, lineHeight: "1.3", isTruncated: true, children: companySubtitle }))] })), !toggle && ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "button", type: "button", onClick: overlay ? onClose : onToggle, "aria-label": overlay ? "Close menu" : "Collapse sidebar", w: "22px", h: "22px", borderRadius: "lg", bg: "whiteAlpha.100", display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0, position: "relative", _hover: { bg: "whiteAlpha.300" }, transition: "background 0.15s", sx: {
45
46
  "&::after": {
46
47
  content: '""',
47
48
  position: "absolute",
@@ -60,7 +61,7 @@ const SkeletonMenuRow = ({ toggle }) => {
60
61
  const AddNewButton = ({ toggle, onClick, overlay }) => {
61
62
  const theme = (0, useCustomTheme_1.useCustomTheme)();
62
63
  const activeAccent = (0, sidebarAccentColors_1.getSidebarActiveAccent)(theme.colors);
63
- return ((0, jsx_runtime_1.jsxs)(react_2.Flex, { as: "button", type: "button", "data-group": "", "aria-label": "Add New", alignItems: "center", gap: "9px", px: "10px", py: overlay ? "11px" : "7px", borderRadius: "lg", cursor: "pointer", border: "none", bg: "transparent", w: "100%", mb: "2px", justifyContent: toggle ? "center" : "flex-start", _hover: { backgroundColor: "whiteAlpha.100" }, transition: "background 0.12s", onClick: onClick, children: [(0, jsx_runtime_1.jsx)(react_2.Box, { w: "18px", h: "18px", display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0, children: (0, jsx_runtime_1.jsx)(lucide_react_1.Plus, { size: 16, color: activeAccent.icon }) }), !toggle && ((0, jsx_runtime_1.jsx)(react_2.Text, { fontSize: "12.5px", color: theme.colors.white, fontWeight: "medium", children: "Add New" }))] }));
64
+ return ((0, jsx_runtime_1.jsxs)(react_2.Flex, { as: "button", type: "button", "data-group": "", "aria-label": "Add New", alignItems: "center", gap: "9px", px: "10px", py: overlay ? "11px" : "7px", borderRadius: "lg", cursor: "pointer", border: "none", bg: "transparent", w: "100%", mb: "2px", justifyContent: toggle ? "center" : "flex-start", _hover: { backgroundColor: "whiteAlpha.100" }, transition: "background 0.12s", onClick: onClick, children: [(0, jsx_runtime_1.jsx)(react_2.Box, { w: "18px", h: "18px", display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0, children: (0, jsx_runtime_1.jsx)(lucide_react_1.Plus, { size: 16, color: activeAccent.icon }) }), !toggle && ((0, jsx_runtime_1.jsx)(react_2.Text, { fontSize: sidebarScale_1.SIDEBAR_ROW.fontSize, color: theme.colors.white, fontWeight: "medium", children: "Add New" }))] }));
64
65
  };
65
66
  const deriveInitials = (user) => {
66
67
  if (user.initials)
@@ -75,14 +76,14 @@ const deriveInitials = (user) => {
75
76
  const UserFooter = ({ user, toggle, overlay }) => {
76
77
  const theme = (0, useCustomTheme_1.useCustomTheme)();
77
78
  const activeAccent = (0, sidebarAccentColors_1.getSidebarActiveAccent)(theme.colors);
78
- const avatar = user.avatarUrl ? ((0, jsx_runtime_1.jsx)(react_2.Image, { src: user.avatarUrl, alt: user.name, boxSize: "26px", borderRadius: "full", objectFit: "cover", flexShrink: 0 })) : ((0, jsx_runtime_1.jsx)(react_2.Box, { boxSize: "26px", borderRadius: "full", bg: theme.colors.primary.opacity[32], color: activeAccent.label, display: "flex", alignItems: "center", justifyContent: "center", fontSize: "10px", fontWeight: 600, flexShrink: 0, children: deriveInitials(user) }));
79
- return ((0, jsx_runtime_1.jsx)(react_2.Box, { borderTop: "1px solid", borderColor: theme.colors.sidebar.divider, py: 2, px: "6px", flexShrink: 0, children: (0, jsx_runtime_1.jsxs)(react_2.Flex, { as: "button", type: "button", onClick: user.onClick, align: "center", gap: 2, px: 2, py: overlay ? "10px" : "6px", w: "100%", borderRadius: "lg", cursor: "pointer", bg: "transparent", border: "none", justify: toggle ? "center" : "flex-start", _hover: { bg: "whiteAlpha.100" }, transition: "background 0.12s", children: [avatar, !toggle && ((0, jsx_runtime_1.jsxs)(react_2.Box, { flex: "1", minW: 0, textAlign: "left", children: [(0, jsx_runtime_1.jsx)(react_2.Text, { fontSize: "11.5px", fontWeight: 500, color: theme.colors.white, isTruncated: true, children: user.name }), user.role && ((0, jsx_runtime_1.jsx)(react_2.Text, { fontSize: "10px", color: theme.colors.sidebar.mutedLabel, isTruncated: true, children: user.role }))] })), !toggle && (0, jsx_runtime_1.jsx)(lucide_react_1.MoreVertical, { size: 14, color: theme.colors.sidebar.mutedIcon })] }) }));
79
+ const avatar = user.avatarUrl ? ((0, jsx_runtime_1.jsx)(react_2.Image, { src: user.avatarUrl, alt: user.name, boxSize: "26px", borderRadius: "full", objectFit: "cover", flexShrink: 0 })) : ((0, jsx_runtime_1.jsx)(react_2.Box, { boxSize: "26px", borderRadius: "full", bg: theme.colors.primary.opacity[32], color: activeAccent.label, display: "flex", alignItems: "center", justifyContent: "center", fontSize: sidebarScale_1.SIDEBAR_CHROME.metaFontSize, fontWeight: 600, flexShrink: 0, children: deriveInitials(user) }));
80
+ return ((0, jsx_runtime_1.jsx)(react_2.Box, { borderTop: "1px solid", borderColor: theme.colors.sidebar.divider, py: 2, px: "6px", flexShrink: 0, children: (0, jsx_runtime_1.jsxs)(react_2.Flex, { as: "button", type: "button", onClick: user.onClick, align: "center", gap: 2, px: 2, py: overlay ? "10px" : "6px", w: "100%", borderRadius: "lg", cursor: "pointer", bg: "transparent", border: "none", justify: toggle ? "center" : "flex-start", _hover: { bg: "whiteAlpha.100" }, transition: "background 0.12s", children: [avatar, !toggle && ((0, jsx_runtime_1.jsxs)(react_2.Box, { flex: "1", minW: 0, textAlign: "left", children: [(0, jsx_runtime_1.jsx)(react_2.Text, { fontSize: sidebarScale_1.SIDEBAR_CHROME.labelFontSize, fontWeight: 500, color: theme.colors.white, isTruncated: true, children: user.name }), user.role && ((0, jsx_runtime_1.jsx)(react_2.Text, { fontSize: sidebarScale_1.SIDEBAR_CHROME.metaFontSize, color: theme.colors.sidebar.mutedLabel, isTruncated: true, children: user.role }))] })), !toggle && (0, jsx_runtime_1.jsx)(lucide_react_1.MoreVertical, { size: 14, color: theme.colors.sidebar.mutedIcon })] }) }));
80
81
  };
81
82
  // Footer "cell" — one segment of the Collapse | Hide/Show control.
82
83
  const ControlCell = ({ onClick, ariaLabel, label, accent, children }) => {
83
84
  const theme = (0, useCustomTheme_1.useCustomTheme)();
84
85
  const activeAccent = (0, sidebarAccentColors_1.getSidebarActiveAccent)(theme.colors);
85
- return ((0, jsx_runtime_1.jsxs)(react_2.Flex, { as: "button", type: "button", "aria-label": ariaLabel, flex: "1", minW: 0, alignItems: "center", justifyContent: "center", gap: "7px", px: "10px", py: "14px", cursor: "pointer", border: "none", bg: accent ? "whiteAlpha.300" : "transparent", onClick: onClick, _hover: { bg: accent ? "whiteAlpha.400" : "whiteAlpha.200" }, transition: "background 0.15s", children: [children, label && ((0, jsx_runtime_1.jsx)(react_2.Text, { fontSize: "11.5px", color: accent ? activeAccent.label : theme.colors.sidebar.mutedLabel, fontWeight: "medium", children: label }))] }));
86
+ return ((0, jsx_runtime_1.jsxs)(react_2.Flex, { as: "button", type: "button", "aria-label": ariaLabel, flex: "1", minW: 0, alignItems: "center", justifyContent: "center", gap: "7px", px: "10px", py: "14px", cursor: "pointer", border: "none", bg: accent ? "whiteAlpha.300" : "transparent", onClick: onClick, _hover: { bg: accent ? "whiteAlpha.400" : "whiteAlpha.200" }, transition: "background 0.15s", children: [children, label && ((0, jsx_runtime_1.jsx)(react_2.Text, { fontSize: sidebarScale_1.SIDEBAR_CHROME.labelFontSize, color: accent ? activeAccent.label : theme.colors.sidebar.mutedLabel, fontWeight: "medium", children: label }))] }));
86
87
  };
87
88
  // Collapse (mini-rail) sits next to the Hide/Show navbar-mode toggle. In the
88
89
  // desktop mobile-nav overlay only "Show" (return to the docked sidebar) is shown;
@@ -100,7 +100,9 @@ export type SecondaryBarProps = {
100
100
  collapsedWidth?: string | number;
101
101
  /** Defaults to "10rem". */
102
102
  expandedWidth?: string | number;
103
+ /** Drill-down title size. Defaults to the shared sidebar row size (13px). */
103
104
  headerFontSize?: string;
105
+ /** Row label size. Defaults to the shared sidebar row size (13px). */
104
106
  itemFontSize?: string;
105
107
  /** Matched by string equality against either the item's id or title, whichever matches. */
106
108
  selected?: string | number | null;
@@ -16,6 +16,7 @@ const sidebarAccent_1 = require("../../../Theme/tokens/builders/sidebarAccent");
16
16
  const paletteFromTheme_1 = require("../../../Theme/chakra/paletteFromTheme");
17
17
  const TextTruncation_1 = __importDefault(require("./TextTruncation"));
18
18
  const sidebarId_1 = require("../sidebarId");
19
+ const sidebarScale_1 = require("../sidebarScale");
19
20
  /**
20
21
  * These rows are real `<a href>`s now, so the browser's own gestures have to keep working —
21
22
  * cmd/ctrl-click for a new tab, shift for a window, middle-click. Only a plain left click is
@@ -34,7 +35,7 @@ const MenuItemBox = ({ menu, activeMenu, toggle, handleClick, isOpen, onToggle,
34
35
  const isBlocked = (0, menuDisabled_1.menuDisabled)(menu) || locked;
35
36
  const hasSubMenu = !!(subMenu === null || subMenu === void 0 ? void 0 : subMenu.length);
36
37
  const submenuPanelId = `submenu-${reactId}`;
37
- const rowHeight = overlay ? "48px" : "32px";
38
+ const rowHeight = overlay ? sidebarScale_1.SIDEBAR_ROW.overlayHeight : sidebarScale_1.SIDEBAR_ROW.height;
38
39
  // A submenu parent only expands, so it is a button; every other row navigates.
39
40
  // Cast: Chakra narrows `as` unions to their *shared* props, which drops `href`.
40
41
  const rowAs = (hasSubMenu ? "button" : "a");
@@ -94,7 +95,7 @@ const MenuItemBox = ({ menu, activeMenu, toggle, handleClick, isOpen, onToggle,
94
95
  // open={isOpen}
95
96
  , {
96
97
  // open={isOpen}
97
- fontSize: "13px", lineHeight: "1", flex: "1", color: isAnyActive ? activeAccent.label : theme.colors.white, fontWeight: isAnyActive ? 600 : 500, _groupHover: isAnyActive ? undefined : { color: theme.colors.white }, children: title }))] }), !toggle && ((0, jsx_runtime_1.jsxs)(react_2.Flex, { align: "center", gap: "0.375rem", children: [(() => {
98
+ fontSize: sidebarScale_1.SIDEBAR_ROW.fontSize, lineHeight: "1", flex: "1", color: isAnyActive ? activeAccent.label : theme.colors.white, fontWeight: isAnyActive ? 600 : 500, _groupHover: isAnyActive ? undefined : { color: theme.colors.white }, children: title }))] }), !toggle && ((0, jsx_runtime_1.jsxs)(react_2.Flex, { align: "center", gap: "0.375rem", children: [(() => {
98
99
  var _a, _b, _c;
99
100
  const value = badgeValue;
100
101
  if (value == null)
@@ -127,13 +128,13 @@ const MenuItemBox = ({ menu, activeMenu, toggle, handleClick, isOpen, onToggle,
127
128
  var _a, _b, _c;
128
129
  const isSubActive = activeMenu === sub.id;
129
130
  const isSubBlocked = (0, menuDisabled_1.menuDisabled)(sub) || sub.locked;
130
- return ((0, jsx_runtime_1.jsxs)(react_2.Box, { as: "a", href: (_a = sub.url) !== null && _a !== void 0 ? _a : "#", "data-group": "", "aria-current": isSubActive ? "page" : undefined, "aria-disabled": isSubBlocked ? true : undefined, textDecoration: "none", h: "20px", pl: "30px", pr: "10px", borderRadius: "lg", fontSize: "11.5px", backgroundColor: "transparent", _hover: { backgroundColor: "whiteAlpha.100" }, opacity: isSubBlocked ? 0.6 : 1, cursor: isSubBlocked ? "not-allowed" : "pointer", pointerEvents: isSubBlocked ? "none" : "auto", onClick: (e) => {
131
+ return ((0, jsx_runtime_1.jsxs)(react_2.Box, { as: "a", href: (_a = sub.url) !== null && _a !== void 0 ? _a : "#", "data-group": "", "aria-current": isSubActive ? "page" : undefined, "aria-disabled": isSubBlocked ? true : undefined, textDecoration: "none", h: sidebarScale_1.SIDEBAR_ROW.subHeight, pl: "30px", pr: "10px", borderRadius: "lg", fontSize: sidebarScale_1.SIDEBAR_ROW.fontSize, backgroundColor: "transparent", _hover: { backgroundColor: "whiteAlpha.100" }, opacity: isSubBlocked ? 0.6 : 1, cursor: isSubBlocked ? "not-allowed" : "pointer", pointerEvents: isSubBlocked ? "none" : "auto", onClick: (e) => {
131
132
  if (sub.url && isBrowserNavigationGesture(e))
132
133
  return;
133
134
  e.preventDefault();
134
135
  if (!isSubBlocked)
135
136
  handleClick === null || handleClick === void 0 ? void 0 : handleClick(sub);
136
- }, display: "flex", alignItems: "center", justifyContent: "space-between", gap: 2, transition: "background 0.12s", children: [(0, jsx_runtime_1.jsxs)(react_2.Flex, { align: "center", gap: "9px", overflow: "hidden", flex: "1", children: [sub.icon ? ((0, jsx_runtime_1.jsx)(react_2.Icon, { as: sub.icon, fontSize: "0.95rem", flexShrink: 0, color: isSubActive ? activeAccent.icon : theme.colors.sidebar.mutedIcon, _groupHover: isSubActive ? undefined : { color: theme.colors.white }, transition: "color 0.12s" })) : ((0, jsx_runtime_1.jsx)(react_2.Box, { w: "5px", h: "5px", borderRadius: "full", flexShrink: 0, bg: isSubActive ? activeAccent.icon : theme.colors.sidebar.mutedIcon, _groupHover: isSubActive ? undefined : { bg: theme.colors.white }, transition: "background 0.12s" })), (0, jsx_runtime_1.jsx)(TextTruncation_1.default, { fontSize: "xs", fontWeight: isSubActive ? 600 : 500, lineHeight: "1",
137
+ }, display: "flex", alignItems: "center", justifyContent: "space-between", gap: 2, transition: "background 0.12s", children: [(0, jsx_runtime_1.jsxs)(react_2.Flex, { align: "center", gap: "9px", overflow: "hidden", flex: "1", children: [sub.icon ? ((0, jsx_runtime_1.jsx)(react_2.Icon, { as: sub.icon, fontSize: sidebarScale_1.SIDEBAR_ROW.iconSize, flexShrink: 0, color: isSubActive ? activeAccent.icon : theme.colors.sidebar.mutedIcon, _groupHover: isSubActive ? undefined : { color: theme.colors.white }, transition: "color 0.12s" })) : ((0, jsx_runtime_1.jsx)(react_2.Box, { w: "5px", h: "5px", borderRadius: "full", flexShrink: 0, bg: isSubActive ? activeAccent.icon : theme.colors.sidebar.mutedIcon, _groupHover: isSubActive ? undefined : { bg: theme.colors.white }, transition: "background 0.12s" })), (0, jsx_runtime_1.jsx)(TextTruncation_1.default, { fontSize: sidebarScale_1.SIDEBAR_ROW.fontSize, fontWeight: isSubActive ? 600 : 500, lineHeight: "1",
137
138
  // open={isOpen}
138
139
  color: isSubActive ? theme.colors.white : theme.colors.sidebar.mutedLabel, _groupHover: isSubActive ? undefined : { color: theme.colors.white }, children: sub.title })] }), sub.locked ? ((0, jsx_runtime_1.jsx)(react_2.Icon, { as: lucide_react_1.LockKeyhole, fontSize: "md", color: theme.colors.sidebar.mutedIcon })) : (() => {
139
140
  var _a, _b, _c, _d;
@@ -148,7 +148,7 @@ const MenuItems = ({ menus, activeMenu, handleMenuClick, toggle, selectedSubMenu
148
148
  lastGroup = menu.group;
149
149
  groupCount += 1;
150
150
  }
151
- return ((0, jsx_runtime_1.jsxs)(react_1.default.Fragment, { children: [showGroup && !isFirstGroup && ((0, jsx_runtime_1.jsx)(react_2.Box, { h: "1px", bg: theme.colors.sidebar.divider, mx: 2, my: "5px" })), showGroup && !toggle && ((0, jsx_runtime_1.jsx)(react_2.Box, { "aria-hidden": "true", px: "10px", pt: "10px", pb: "3px", fontSize: "9.5px", fontWeight: 600, textTransform: "uppercase", letterSpacing: "0.1em", color: theme.colors.sidebar.mutedLabel, whiteSpace: "nowrap", overflow: "hidden", children: menu.group })), (0, jsx_runtime_1.jsx)(MenuItemBox_1.default, { menu: menu, activeMenu: activeMenu, toggle: toggle, handleClick: handleMenuClick, selectedSubMenu: selectedSubMenu, isOpen: openMenuId === menu.id, onToggle: handleToggle, overlay: overlay })] }, `${String((_c = (_b = (_a = menu.id) !== null && _a !== void 0 ? _a : menu.url) !== null && _b !== void 0 ? _b : menu.title) !== null && _c !== void 0 ? _c : idx)}-${idx}`));
151
+ return ((0, jsx_runtime_1.jsxs)(react_1.default.Fragment, { children: [showGroup && !isFirstGroup && ((0, jsx_runtime_1.jsx)(react_2.Box, { h: "1px", bg: theme.colors.sidebar.divider, mx: 2, my: overlay ? "3px" : "5px" })), showGroup && !toggle && ((0, jsx_runtime_1.jsx)(react_2.Box, { "aria-hidden": "true", px: "10px", pt: overlay ? "6px" : "10px", pb: "3px", fontSize: "9.5px", fontWeight: 600, textTransform: "uppercase", letterSpacing: "0.1em", color: theme.colors.sidebar.mutedLabel, whiteSpace: "nowrap", overflow: "hidden", children: menu.group })), (0, jsx_runtime_1.jsx)(MenuItemBox_1.default, { menu: menu, activeMenu: activeMenu, toggle: toggle, handleClick: handleMenuClick, selectedSubMenu: selectedSubMenu, isOpen: openMenuId === menu.id, onToggle: handleToggle, overlay: overlay })] }, `${String((_c = (_b = (_a = menu.id) !== null && _a !== void 0 ? _a : menu.url) !== null && _b !== void 0 ? _b : menu.title) !== null && _c !== void 0 ? _c : idx)}-${idx}`));
152
152
  }) }));
153
153
  };
154
154
  exports.default = MenuItems;
@@ -13,6 +13,7 @@ const tone_1 = require("../../../Theme/tokens/builders/tone");
13
13
  const sidebarAccent_1 = require("../../../Theme/tokens/builders/sidebarAccent");
14
14
  const paletteFromTheme_1 = require("../../../Theme/chakra/paletteFromTheme");
15
15
  const TextTruncation_1 = __importDefault(require("./TextTruncation"));
16
+ const sidebarScale_1 = require("../sidebarScale");
16
17
  const MenuPopoverContent = ({ menu, handleMenuClick, activeMenu, }) => {
17
18
  var _a;
18
19
  const theme = (0, useCustomTheme_1.useCustomTheme)();
@@ -27,7 +28,7 @@ const MenuPopoverContent = ({ menu, handleMenuClick, activeMenu, }) => {
27
28
  if (!isBlocked)
28
29
  handleMenuClick === null || handleMenuClick === void 0 ? void 0 : handleMenuClick(menu);
29
30
  }
30
- }, cursor: !hasSubMenu ? (isBlocked ? "not-allowed" : "pointer") : "default", "aria-disabled": !hasSubMenu && isBlocked ? true : undefined, children: [(0, jsx_runtime_1.jsx)(react_1.Icon, { as: icon, fontSize: "md", flexShrink: 0, color: !hasSubMenu && isParentActive ? activeAccent.icon : theme.colors.sidebar.mutedIcon }), (0, jsx_runtime_1.jsx)(TextTruncation_1.default, { fontWeight: 600, fontSize: "13px", flex: "1", color: theme.colors.white, children: title }), (() => {
31
+ }, cursor: !hasSubMenu ? (isBlocked ? "not-allowed" : "pointer") : "default", "aria-disabled": !hasSubMenu && isBlocked ? true : undefined, children: [(0, jsx_runtime_1.jsx)(react_1.Icon, { as: icon, fontSize: "md", flexShrink: 0, color: !hasSubMenu && isParentActive ? activeAccent.icon : theme.colors.sidebar.mutedIcon }), (0, jsx_runtime_1.jsx)(TextTruncation_1.default, { fontWeight: 600, fontSize: sidebarScale_1.SIDEBAR_ROW.fontSize, flex: "1", color: theme.colors.white, children: title }), (() => {
31
32
  var _a, _b, _c, _d;
32
33
  const cfg = typeof badge === "object" && badge !== null
33
34
  ? badge
@@ -48,10 +49,10 @@ const MenuPopoverContent = ({ menu, handleMenuClick, activeMenu, }) => {
48
49
  e.preventDefault();
49
50
  if (!isSubBlocked)
50
51
  handleMenuClick === null || handleMenuClick === void 0 ? void 0 : handleMenuClick(sub);
51
- }, px: 2, h: "20px", mb: "2px", borderRadius: "lg", align: "center", justify: "space-between", gap: 2, borderLeft: "2px solid", borderLeftColor: isSubActive ? theme.colors.sidebar.activeIcon : "transparent", bg: isSubActive ? "whiteAlpha.300" : "transparent", _hover: {
52
+ }, px: 2, h: sidebarScale_1.SIDEBAR_ROW.subHeight, mb: "2px", borderRadius: "lg", align: "center", justify: "space-between", gap: 2, borderLeft: "2px solid", borderLeftColor: isSubActive ? theme.colors.sidebar.activeIcon : "transparent", bg: isSubActive ? "whiteAlpha.300" : "transparent", _hover: {
52
53
  bg: !isSubBlocked ? "whiteAlpha.100" : "transparent",
53
54
  cursor: !isSubBlocked ? "pointer" : "not-allowed",
54
- }, opacity: isSubBlocked ? 0.5 : 1, pointerEvents: isSubBlocked ? "none" : "auto", transition: "background 0.12s", children: [(0, jsx_runtime_1.jsxs)(react_1.Flex, { align: "center", gap: "9px", overflow: "hidden", flex: "1", children: [(0, jsx_runtime_1.jsx)(react_1.Icon, { as: sub.icon, fontSize: "0.95rem", flexShrink: 0, color: isSubActive ? activeAccent.icon : theme.colors.sidebar.mutedIcon, _groupHover: isSubActive ? undefined : { color: theme.colors.white }, transition: "color 0.12s" }), (0, jsx_runtime_1.jsx)(TextTruncation_1.default, { fontSize: "12.5px", fontWeight: isSubActive ? 600 : 500, flex: 1, color: isSubActive ? activeAccent.label : theme.colors.white, _groupHover: isSubActive ? undefined : { color: theme.colors.white }, children: sub.title })] }), sub.locked ? ((0, jsx_runtime_1.jsx)(react_1.Icon, { as: lucide_react_1.LockKeyhole, fontSize: "md", color: theme.colors.sidebar.mutedIcon })) : (() => {
55
+ }, opacity: isSubBlocked ? 0.5 : 1, pointerEvents: isSubBlocked ? "none" : "auto", transition: "background 0.12s", children: [(0, jsx_runtime_1.jsxs)(react_1.Flex, { align: "center", gap: "9px", overflow: "hidden", flex: "1", children: [(0, jsx_runtime_1.jsx)(react_1.Icon, { as: sub.icon, fontSize: sidebarScale_1.SIDEBAR_ROW.iconSize, flexShrink: 0, color: isSubActive ? activeAccent.icon : theme.colors.sidebar.mutedIcon, _groupHover: isSubActive ? undefined : { color: theme.colors.white }, transition: "color 0.12s" }), (0, jsx_runtime_1.jsx)(TextTruncation_1.default, { fontSize: sidebarScale_1.SIDEBAR_ROW.fontSize, fontWeight: isSubActive ? 600 : 500, flex: 1, color: isSubActive ? activeAccent.label : theme.colors.white, _groupHover: isSubActive ? undefined : { color: theme.colors.white }, children: sub.title })] }), sub.locked ? ((0, jsx_runtime_1.jsx)(react_1.Icon, { as: lucide_react_1.LockKeyhole, fontSize: "md", color: theme.colors.sidebar.mutedIcon })) : (() => {
55
56
  var _a, _b, _c, _d;
56
57
  const cfg = typeof sub.badge === "object" && sub.badge !== null
57
58
  ? sub.badge
@@ -0,0 +1,15 @@
1
+ /** One type and row scale for the whole sidebar — rail, submenu, flyout, secondary bar and chrome. */
2
+ export declare const SIDEBAR_ROW: {
3
+ readonly height: "32px";
4
+ /** Rail row in the mobile overlay — the WCAG 2.5.5 touch target. */
5
+ readonly overlayHeight: "44px";
6
+ readonly subHeight: "28px";
7
+ readonly fontSize: "13px";
8
+ readonly iconSize: "1rem";
9
+ };
10
+ /** Header/footer text around the rows; every row itself uses SIDEBAR_ROW.fontSize. */
11
+ export declare const SIDEBAR_CHROME: {
12
+ readonly titleFontSize: "12.5px";
13
+ readonly labelFontSize: "11.5px";
14
+ readonly metaFontSize: "10px";
15
+ };
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SIDEBAR_CHROME = exports.SIDEBAR_ROW = void 0;
4
+ /** One type and row scale for the whole sidebar — rail, submenu, flyout, secondary bar and chrome. */
5
+ exports.SIDEBAR_ROW = {
6
+ height: "32px",
7
+ /** Rail row in the mobile overlay — the WCAG 2.5.5 touch target. */
8
+ overlayHeight: "44px",
9
+ subHeight: "28px",
10
+ fontSize: "13px",
11
+ iconSize: "1rem",
12
+ };
13
+ /** Header/footer text around the rows; every row itself uses SIDEBAR_ROW.fontSize. */
14
+ exports.SIDEBAR_CHROME = {
15
+ titleFontSize: "12.5px",
16
+ labelFontSize: "11.5px",
17
+ metaFontSize: "10px",
18
+ };
@@ -1,3 +1,3 @@
1
1
  import { SwitchProps } from "./SwitchProps";
2
- /** @deprecated Use `SegmentedControl` — Switch now renders it at a fixed 12.5rem width. */
3
- export default function Switch({ leftText, rightText, leftIcon, rightIcon, onSwitchToggle, switchActive, "aria-label": ariaLabel, }: SwitchProps): import("react/jsx-runtime").JSX.Element;
2
+ /** @deprecated Use `SegmentedControl` — Switch renders it at 12.5rem, growing when the labels need it. */
3
+ export default function Switch({ leftText, rightText, leftIcon, rightIcon, onSwitchToggle, switchActive, surface, "aria-label": ariaLabel, }: SwitchProps): import("react/jsx-runtime").JSX.Element;
@@ -7,11 +7,11 @@ exports.default = Switch;
7
7
  const jsx_runtime_1 = require("react/jsx-runtime");
8
8
  const react_1 = require("@chakra-ui/react");
9
9
  const SegmentedControl_1 = __importDefault(require("../SegmentedControl/SegmentedControl"));
10
- /** @deprecated Use `SegmentedControl` — Switch now renders it at a fixed 12.5rem width. */
11
- function Switch({ leftText, rightText, leftIcon, rightIcon, onSwitchToggle, switchActive, "aria-label": ariaLabel, }) {
10
+ /** @deprecated Use `SegmentedControl` — Switch renders it at 12.5rem, growing when the labels need it. */
11
+ function Switch({ leftText, rightText, leftIcon, rightIcon, onSwitchToggle, switchActive, surface, "aria-label": ariaLabel, }) {
12
12
  const options = [
13
13
  { value: "left", label: leftText, icon: leftIcon },
14
14
  { value: "right", label: rightText, icon: rightIcon },
15
15
  ];
16
- return ((0, jsx_runtime_1.jsx)(react_1.Box, { w: "12.5rem", children: (0, jsx_runtime_1.jsx)(SegmentedControl_1.default, { options: options, value: switchActive, onChange: onSwitchToggle, variant: "brandSlide", isFullWidth: true, "aria-label": ariaLabel !== null && ariaLabel !== void 0 ? ariaLabel : `${leftText} or ${rightText}` }) }));
16
+ return ((0, jsx_runtime_1.jsx)(react_1.Box, { w: "fit-content", minW: "12.5rem", children: (0, jsx_runtime_1.jsx)(SegmentedControl_1.default, { options: options, value: switchActive, onChange: onSwitchToggle, variant: "brandSlide", surface: surface, isFullWidth: true, "aria-label": ariaLabel !== null && ariaLabel !== void 0 ? ariaLabel : `${leftText} or ${rightText}` }) }));
17
17
  }
@@ -8,6 +8,8 @@ export type SwitchProps = {
8
8
  onSwitchToggle: (value: "left" | "right") => void;
9
9
  /** Controlled selected side; the pill only moves when this changes. */
10
10
  switchActive: "left" | "right";
11
+ /** Background this sits on. Optional: the track is opaque on any backdrop; pass it only to aim the plate's hairline edge at the real backdrop. */
12
+ surface?: string;
11
13
  /** Names the radiogroup; pass it, as there is no visible group label. */
12
14
  "aria-label"?: string;
13
15
  };
@@ -2,7 +2,7 @@ import React from "react";
2
2
  import { TableProps } from "../TableProps";
3
3
  type PaginationProps = Pick<TableProps, "paginationSelectOptions"> & {
4
4
  paginationText: string;
5
- handlePageSizeChange: (event: React.ChangeEvent<HTMLSelectElement>) => void;
5
+ handlePageSizeChange: (size: number) => void;
6
6
  rowsPerPage: number;
7
7
  currentPage: number;
8
8
  pages: number;