pixelize-design-library 2.4.2-beta.53 → 2.4.2-beta.55
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 +43 -0
- package/COMPONENT-GOTCHAS.md +57 -4
- package/DESIGN-GUIDE.md +8 -6
- package/dist/Components/AppSwitcher/AppSwitcher.js +1 -2
- package/dist/Components/Button/Button.styles.js +1 -1
- package/dist/Components/Button/ButtonProps.d.ts +1 -1
- package/dist/Components/Common/fieldStyles.d.ts +1 -1
- package/dist/Components/Common/fieldStyles.js +1 -1
- package/dist/Components/DatePicker/DatePickerProps.d.ts +1 -1
- package/dist/Components/Dropdown/DropDown.js +4 -4
- package/dist/Components/Dropdown/DropdownProps.d.ts +1 -1
- package/dist/Components/Input/PhoneNumberInputProps.d.ts +1 -1
- package/dist/Components/MultiSelect/MultiSelectProps.d.ts +1 -1
- package/dist/Components/NotificationBell/NotificationBellProps.d.ts +1 -1
- package/dist/Components/OrgSwitcher/OrgSwitcher.js +3 -4
- package/dist/Components/PinInput/PinInputProps.d.ts +1 -1
- package/dist/Components/RangeSlider/RangeSliderProps.d.ts +1 -1
- package/dist/Components/RangeSlider/rangeSliderSize.d.ts +1 -1
- package/dist/Components/RangeSlider/rangeSliderSize.js +1 -1
- package/dist/Components/Search/SearchProps.d.ts +1 -1
- package/dist/Components/SearchSelect/SearchSelectProps.d.ts +1 -1
- package/dist/Components/SegmentedControl/SegmentedControl.js +1 -1
- package/dist/Components/SegmentedControl/SegmentedControlProps.d.ts +1 -1
- package/dist/Components/Select/SelectProps.d.ts +1 -1
- package/dist/Components/SelectSearch/SelectSearchProps.d.ts +1 -1
- package/dist/Components/SelectV2/SelectV2Props.d.ts +1 -1
- package/dist/Components/SideBar/SecondaryBar.js +4 -2
- package/dist/Components/SideBar/SideBar.js +14 -8
- package/dist/Components/SideBar/components/MenuItemBox.js +9 -5
- package/dist/Components/SideBar/components/MenuPopoverContent.js +5 -3
- package/dist/Components/SideBar/components/OtherApps.js +1 -1
- package/dist/Components/Table/Table.js +16 -4
- package/dist/Components/Table/TableProps.d.ts +1 -1
- package/dist/Components/Table/components/rowMetrics.d.ts +1 -0
- package/dist/Components/Table/components/rowMetrics.js +2 -1
- package/dist/Components/Tabs/TabsProps.d.ts +1 -1
- package/dist/Components/Tabs/components/Tab.js +1 -1
- package/dist/Components/Toggle/TableToggle.js +1 -1
- package/dist/Constants/Sidebar.js +3 -3
- package/dist/Theme/tokens/builders/sidebarAccent.js +4 -2
- package/dist/Theme/tokens/primitives/controlSizes.d.ts +2 -1
- package/dist/Theme/tokens/primitives/controlSizes.js +10 -4
- package/dist/Theme/tokens/primitives/optionRowSizes.js +6 -6
- package/dist/esm/Components/AppSwitcher/AppSwitcher.js +1 -2
- package/dist/esm/Components/Button/Button.styles.js +2 -2
- package/dist/esm/Components/Common/fieldStyles.js +1 -1
- package/dist/esm/Components/Dropdown/DropDown.js +5 -5
- package/dist/esm/Components/OrgSwitcher/OrgSwitcher.js +3 -4
- package/dist/esm/Components/RangeSlider/rangeSliderSize.js +1 -1
- package/dist/esm/Components/SegmentedControl/SegmentedControl.js +2 -2
- package/dist/esm/Components/SideBar/SecondaryBar.js +6 -4
- package/dist/esm/Components/SideBar/SideBar.js +14 -8
- package/dist/esm/Components/SideBar/components/MenuItemBox.js +9 -5
- package/dist/esm/Components/SideBar/components/MenuPopoverContent.js +6 -4
- package/dist/esm/Components/SideBar/components/OtherApps.js +1 -1
- package/dist/esm/Components/Table/Table.js +17 -5
- package/dist/esm/Components/Table/components/rowMetrics.js +1 -0
- package/dist/esm/Components/Tabs/components/Tab.js +2 -2
- package/dist/esm/Components/Toggle/TableToggle.js +2 -2
- package/dist/esm/Constants/Sidebar.js +3 -3
- package/dist/esm/Theme/tokens/builders/sidebarAccent.js +5 -3
- package/dist/esm/Theme/tokens/primitives/controlSizes.js +9 -3
- package/dist/esm/Theme/tokens/primitives/optionRowSizes.js +6 -6
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -81,6 +81,49 @@ next major.
|
|
|
81
81
|
|
|
82
82
|
### Fixed
|
|
83
83
|
|
|
84
|
+
- **Control-size regression: field and button heights are two scales again, not one.** A
|
|
85
|
+
form-field-only bump had leaked into `Button`, `SegmentedControl`, `Tabs`, `TableToggle` and
|
|
86
|
+
`Dropdown`'s trigger through one shared token. `CONTROL_SIZES` (fields/selects: xs 24 · sm 38 ·
|
|
87
|
+
md 40 · lg 48) and `BUTTON_SIZES` (buttons and every button-like trigger: xs 24 · sm 32 · md 40 ·
|
|
88
|
+
lg 48, back to pre-regression) are now separate exports, gated by
|
|
89
|
+
`Common/sizeScaleOwnership.test.ts` so they can't silently merge again. `OPTION_ROW_SIZES`
|
|
90
|
+
(dropdown/select/menu row heights) is reverted to xs 24 · sm 30 · md 34 · lg 40; `OrgSwitcher`/
|
|
91
|
+
`AppSwitcher` are back on their own hardcoded literal sizes, not a shared token.
|
|
92
|
+
- **`SideBar`'s nav scrollbar thumb was the brand `primary` color.** Every other scrollbar in the
|
|
93
|
+
library reads a neutral chrome token; the sidebar's hand-rolled CSS (`Constants/Sidebar.ts`) was
|
|
94
|
+
the one place still reaching for `primary[500]`/`primary[700]`. It now reads
|
|
95
|
+
`sidebar.mutedIcon`/`mutedLabel` — contrast-resolved against the rail, not brand-colored.
|
|
96
|
+
- **`SideBar` follow-up UI audit — six more fixes, no behavior/prop changes.** `SecondaryBar`'s own
|
|
97
|
+
scroll panel had no scrollbar styling (fell through to the page's default) and a hardcoded,
|
|
98
|
+
collision-prone id — now matches `SideBar`'s own generated-id + `cssForScrollBar` pattern. The
|
|
99
|
+
collapsed-rail badge dot (`red[400]`) is now `sidebar.semanticText.error`, so it stays legible in
|
|
100
|
+
both modes instead of drifting. Six `whiteAlpha.100` hover/rest fills (header collapse button,
|
|
101
|
+
Add New, user footer, inline submenu row, app switcher cell, `SecondaryBar`'s collapse toggle)
|
|
102
|
+
were below the sidebar's own perceptible-step floor — bumped to `.200`, matching every other row.
|
|
103
|
+
The collapsed-flyout submenu showed Chakra's built-in "?" glyph for a sub-item with no `icon`; it
|
|
104
|
+
now draws the same dot the always-visible inline submenu already used. Hovering an *active* flyout
|
|
105
|
+
row got lighter-then-darker instead of lighter-then-lighter — fixed to the same `.300`→`.400` step
|
|
106
|
+
every other active row uses. The default (no `logo`/`avatarUrl`) header logo tile and footer
|
|
107
|
+
avatar initials painted a raw `primary` fill that measured ~1:1 against the rail — invisible — on
|
|
108
|
+
zinc, skyline and storefront; both now use the same rail-safe surface/ink pairing the active-row
|
|
109
|
+
accent already resolves against.
|
|
110
|
+
- **`SideBar` audit round 2 — muted-chrome contrast, inline-submenu consistency, demo previews.**
|
|
111
|
+
`sidebar.mutedIcon`/`mutedLabel` cleared AA against the bare rail and `elevated` but not against
|
|
112
|
+
a whiteAlpha hover/active overlay on top of either — now resolved with `settleAcross` against
|
|
113
|
+
both surfaces at once, gated by new `paletteContrast.test.ts` cases across 9 brands x 2 modes.
|
|
114
|
+
The expanded rail's always-visible inline submenu (`MenuItemBox.tsx`) now matches the
|
|
115
|
+
fill+accent-bar+`activeAccent.label` pattern the top-level row and the collapsed-flyout submenu
|
|
116
|
+
already use for an active item, instead of only swapping label color. Demo-only: the playground's
|
|
117
|
+
docked-sidebar previews (`src/Pages/demo.sidebar.tsx`) rendered blank below the `lg` breakpoint
|
|
118
|
+
because `SideBar` reads the real `window` width, not the preview box's — now shows a
|
|
119
|
+
"widen the window" fallback there instead; the secondary-bar demo's panel was also widened so its
|
|
120
|
+
drill-down chevron isn't clipped.
|
|
121
|
+
- **`Table` clipped its last row(s) whenever a cell wrapped to more than one line.** The container
|
|
122
|
+
height was computed as `rows × density height + header`, assuming every row is exactly one line —
|
|
123
|
+
wrapped text (long values, multi-column data) rendered taller than that, and the box clipped it
|
|
124
|
+
behind a scrollbar even with empty space left on the page. Tables at or under the row-count cap
|
|
125
|
+
(`maxVisibleRows`, default 10) now grow to fit their real content instead; larger lists keep the
|
|
126
|
+
exact capped/scrolling height and virtualize as before, so nothing changes for big record counts.
|
|
84
127
|
- **Icons beside a field are centred at every size and height.** A lone right-hand icon in
|
|
85
128
|
`TextInput` (an `inputRightIcon`, the clear button or the password toggle) sat flush against the
|
|
86
129
|
border while the left one was inset; both now mirror at 6/9/12/15px. `SelectSearch`'s `rightIcon`
|
package/COMPONENT-GOTCHAS.md
CHANGED
|
@@ -312,7 +312,7 @@ not enough when the overlay sits inside a transition wrapper — the wrapper kee
|
|
|
312
312
|
|
|
313
313
|
| Component | beta.43 → beta.44 | Restore the old look |
|
|
314
314
|
| --- | --- | --- |
|
|
315
|
-
| Fields, selects, buttons (`Button`, `TextInput`, `InputTextArea`, `NumberInput`, DatePicker family, `Select`, `SelectV2`, `SearchSelect`, `SelectSearch`, `Search`, `Dropdown`, `SegmentedControl`) | Default size `md` → `sm` (38px). One scale for all: xs
|
|
315
|
+
| Fields, selects, buttons (`Button`, `TextInput`, `InputTextArea`, `NumberInput`, DatePicker family, `Select`, `SelectV2`, `SearchSelect`, `SelectSearch`, `Search`, `Dropdown`, `SegmentedControl`) | Default size `md` → `sm` (38px). One scale for all: xs 24 / sm 38 / md 40 / lg 48 — the same height in every field, select and button. `TimePicker` has no `size` (fixed `sm`); `SegmentedControl` has no `xs`. **Since decoupled** — fields/selects now read `CONTROL_SIZES` (unchanged: xs 24 / sm 38 / md 40 / lg 48), `Button`/`SegmentedControl`/`Tabs`/`TableToggle`/`Dropdown`'s trigger read the separate `BUTTON_SIZES` (xs 24 / sm 32 / md 40 / lg 48, back to pre-regression) — see the gotcha below | `size="md"` |
|
|
316
316
|
| `Button` | Text one step smaller (sm 14→13px, md 16→14, lg 18→16). Busy = spinner only, width kept (was "Loading" + spinner). Outline: 1px border, hover is a tint, not a fill | `loadingText="Loading"` |
|
|
317
317
|
| `Tag` | `solid`/`md` → `subtle`/`sm`. Hover + pointer only with `onTagClick`; `maxW` truncates with the full text as a title. Exact heights 20/24/28/32, weight 500, 1px inset ring (never adds height); subtle is a light tint with ink ≥ 6.5:1 | `variant="solid" size="md"` |
|
|
318
318
|
| `resolveSoftTone` | `bg`/`border` are now translucent (alpha hex) — composite onto the surface before `contrastRatio`; optional 3rd `surface` arg; adds `hoverBg`/`activeBg`. Badge/Alert/Toaster/EmptyState follow | — |
|
|
@@ -359,7 +359,7 @@ not enough when the overlay sits inside a transition wrapper — the wrapper kee
|
|
|
359
359
|
| `Tag` | Label line-height 1.45 so descenders (`p`, `g`, `y`) are no longer clipped by the ellipsis overflow | — |
|
|
360
360
|
| `Toaster` | `error` toasts announce assertively (`role="alert"`); status icons have a text equivalent | — |
|
|
361
361
|
| `FeedbackForm` | Built on `TextInput`/`InputTextArea`/`RadioButtonGroup`; required fields show `*` in the label | — |
|
|
362
|
-
| `PinInput` | `size` now works (square cells
|
|
362
|
+
| `PinInput` | `size` now works (square cells 24 / 38 / 40 / 48, default `sm`) — it was silently ignored | `size="md"` |
|
|
363
363
|
| `Tag` | New `leadingIcon` (decorative, before the label) and `isDisabled` (sets `aria-disabled` + native `disabled` on the clickable/remove buttons, so they leave the tab order — not just dimmed) | — |
|
|
364
364
|
| `ToolTip` | Defaults a Popper `preventOverflow` padding of 8px, so a bubble near the right edge no longer overhangs by a subpixel and raises page scrollbars. A caller-supplied `preventOverflow` modifier still wins | pass your own `modifiers` |
|
|
365
365
|
| `Table` / `KanbanBoard` | Column sort buttons and draggable cards now show the library focus ring on keyboard focus (was an opacity flicker / the browser default outline). Kanban card wrappers render as Chakra `Box`; keyboard drag (Space, arrows, Space) is unchanged | — |
|
|
@@ -388,6 +388,26 @@ differ — this is a rewrite of the call site, not a rename.
|
|
|
388
388
|
`RangeSlider`, `Spinner`, `Tab`, `TabList`, `TabPanel`, `TabPanels`, `Tabs`. They now point at the
|
|
389
389
|
library's own themed component rather than the Chakra passthrough.
|
|
390
390
|
|
|
391
|
+
### `CONTROL_SIZES` (fields) and `BUTTON_SIZES` (buttons) are separate scales — changing one never changes the other
|
|
392
|
+
|
|
393
|
+
Fields/selects (`TextInput`, `Select`, `MultiSelect`, `SearchSelect`, `NumberInput`, `PinInput`, the
|
|
394
|
+
`DatePicker` family, …) read `CONTROL_SIZES` — xs 24 · sm 38 · md 40 · lg 48. `Button` and every
|
|
395
|
+
button-like trigger (`SegmentedControl`, `Tabs`, `TableToggle`, `Dropdown`'s trigger) read the
|
|
396
|
+
separate `BUTTON_SIZES` — xs 24 · sm 32 · md 40 · lg 48. They used to share one token, which is what
|
|
397
|
+
let a field-only size bump leak into buttons — the split is now gate-tested
|
|
398
|
+
(`Common/sizeScaleOwnership.test.ts`).
|
|
399
|
+
|
|
400
|
+
**Apply:** a PR that "just" bumps a form-field size should never touch `Button.styles.ts`,
|
|
401
|
+
`SegmentedControl`, `Tab`, `TableToggle` or `Dropdown` — if it does, it's reading the wrong token.
|
|
402
|
+
|
|
403
|
+
### `controlSizeStyles()`'s `minH` silently overrides a smaller `h` override
|
|
404
|
+
|
|
405
|
+
`fieldStyles.ts`'s `controlSizeStyles()` sets both `h` and `minH` to the same token value. A caller
|
|
406
|
+
overriding only `h` with a smaller literal compiles and renders, but the inherited `minH` still
|
|
407
|
+
wins, so the field stays at the token height.
|
|
408
|
+
|
|
409
|
+
**Apply:** override both `h` and `minH` together, or don't override either.
|
|
410
|
+
|
|
391
411
|
### `Tag`'s `onIconClick` renders nothing without `icon` — the remove button silently never appears
|
|
392
412
|
|
|
393
413
|
`onIconClick` only turns `icon` into a remove button; it has no effect on its own (`Tag.tsx`
|
|
@@ -1411,12 +1431,45 @@ properties first, or doesn't support the pseudo-elements at all, fell back to th
|
|
|
1411
1431
|
scrollbar: a plain bar with no relation to the dark sidebar theme, showing up the moment a nav list
|
|
1412
1432
|
(enough sections/items) overflowed the viewport. Fixed by switching to the already-written
|
|
1413
1433
|
`cssForScrollBar(theme)` (same file), which sets `scrollbarWidth`/`scrollbarColor` **and** the
|
|
1414
|
-
webkit pseudo-elements, themed to `sidebar.background[500]` / `
|
|
1415
|
-
`FlexCss` is removed — `cssForScrollBar` is now the only scrollbar treatment
|
|
1434
|
+
webkit pseudo-elements, themed to `sidebar.background[500]` / `sidebar.mutedIcon`/`mutedLabel`,
|
|
1435
|
+
hidden until hover. `FlexCss` is removed — `cssForScrollBar` is now the only scrollbar treatment
|
|
1436
|
+
the SideBar uses. (2026-09-29: the thumb was briefly brand `primary[500]`/`[700]` — since fixed to
|
|
1437
|
+
the neutral tokens shown above; `SecondaryBar`'s own scroll panel got the same styling and a
|
|
1438
|
+
duplicate-id fix in the same pass.)
|
|
1416
1439
|
|
|
1417
1440
|
**Apply:** nothing to do. If a nav list is long enough to scroll, the bar now stays invisible until
|
|
1418
1441
|
hovered, in the sidebar's own colors, on every engine — not just Chromium.
|
|
1419
1442
|
|
|
1443
|
+
### `SideBar` contrast pass — badge dot, hover fills, missing-icon fallback, default avatar/logo (2026-09-29) — fixed
|
|
1444
|
+
|
|
1445
|
+
A themed-UI audit found six real defects, none of them behavior changes: the collapsed-rail
|
|
1446
|
+
notification dot (`red[400]`) is now `sidebar.semanticText.error`, which stays legible against the
|
|
1447
|
+
rail in both modes instead of drifting; six `whiteAlpha.100` hover/rest fills that sat below the
|
|
1448
|
+
sidebar's own perceptible-step floor are now `whiteAlpha.200`, matching every other row's hover;
|
|
1449
|
+
the collapsed-flyout submenu (`MenuPopoverContent`) no longer shows Chakra's built-in "?" glyph for
|
|
1450
|
+
a sub-item with no `icon` — it draws the same small dot the always-visible inline submenu already
|
|
1451
|
+
used; hovering an *active* flyout row no longer gets visibly lighter-then-darker (it now steps
|
|
1452
|
+
`.300` -> `.400`, like every other active row); and the default (no `logo`/`avatarUrl`) header logo
|
|
1453
|
+
tile and footer avatar initials no longer paint a raw `primary` fill, which was within ~1:1 of the
|
|
1454
|
+
rail — invisible — on zinc, skyline and storefront.
|
|
1455
|
+
|
|
1456
|
+
**Apply:** nothing to do — same props, same markup, visuals only. If you rendered a `SideBar` or
|
|
1457
|
+
`SecondaryBar` with a screenshot baseline captured before 2026-09-29, expect the badge dot color,
|
|
1458
|
+
some hover states, and the default logo/avatar tile to look different.
|
|
1459
|
+
|
|
1460
|
+
### `SideBar` contrast pass round 2 — muted icon/label under a hover fill, inline-submenu state (2026-09-29) — fixed
|
|
1461
|
+
|
|
1462
|
+
A follow-up audit found `sidebar.mutedIcon`/`mutedLabel` could dip under WCAG AA when sitting on
|
|
1463
|
+
top of an active or hovered row (the whiteAlpha overlay steps), even though the same token cleared
|
|
1464
|
+
AA against the bare rail — the token was never resolved against that combined surface. Also, the
|
|
1465
|
+
expanded rail's always-visible inline submenu only swapped an active row's label to white with no
|
|
1466
|
+
fill or accent bar, unlike every other active row in the family (top-level rows, the
|
|
1467
|
+
collapsed-flyout submenu). Both fixed with no prop or markup changes.
|
|
1468
|
+
|
|
1469
|
+
**Apply:** nothing to do — same props, visuals only. Expect a muted icon/label under a hover/active
|
|
1470
|
+
row to read slightly lighter than before on some brands, and an active inline-submenu item to now
|
|
1471
|
+
show a fill and left accent bar matching the rest of the sidebar's active-row styling.
|
|
1472
|
+
|
|
1420
1473
|
### `KanbanBoard`'s `permissions.isViewable: false` hides everything, including header actions
|
|
1421
1474
|
|
|
1422
1475
|
Not just the columns — the select/edit/create header bar disappears too, since the whole component
|
package/DESIGN-GUIDE.md
CHANGED
|
@@ -87,12 +87,14 @@ stay light in dark mode.
|
|
|
87
87
|
`secondary` and `tertiary` render as the same hex on most brands (see `COMPONENT-GOTCHAS.md`) —
|
|
88
88
|
don't lean on that pair to distinguish two categories; reach for a utility scheme instead.
|
|
89
89
|
|
|
90
|
-
## 5. Controls —
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
`
|
|
95
|
-
|
|
90
|
+
## 5. Controls — two scales, `sm` by default
|
|
91
|
+
|
|
92
|
+
Fields (`TextInput`, `InputTextArea`, `NumberInput`, `Select`, `Search`, `RangeSlider`, the
|
|
93
|
+
`DatePicker` family) sit on `CONTROL_SIZES` — `xs` 24px · `sm` 38px · `md` 40px · `lg` 48px.
|
|
94
|
+
`Button` and every button-like trigger (`SegmentedControl`, `Tabs`, `TableToggle`, `Dropdown`)
|
|
95
|
+
sit on the separate `BUTTON_SIZES` scale — `xs` 24px · `sm` 32px · `md` 40px · `lg` 48px. Both
|
|
96
|
+
**default to `sm`**, so on a desktop page **don't pass `size`**. They line up at `md`/`lg`; at
|
|
97
|
+
`sm` a button reads 6px shorter than the field beside it.
|
|
96
98
|
|
|
97
99
|
| Button role | Props |
|
|
98
100
|
| --- | --- |
|
|
@@ -46,10 +46,9 @@ const useExclusiveOverlay_1 = require("../../Hooks/useExclusiveOverlay");
|
|
|
46
46
|
const AppMark_1 = __importStar(require("./AppMark"));
|
|
47
47
|
const AppSwitcherProps_1 = require("./AppSwitcherProps");
|
|
48
48
|
const useAppSwitcherShortcut_1 = require("./useAppSwitcherShortcut");
|
|
49
|
-
const controlSizes_1 = require("../../Theme/tokens/primitives/controlSizes");
|
|
50
49
|
const COLUMNS = 2;
|
|
51
50
|
const HEADING = "Your apps";
|
|
52
|
-
const s = { trigger:
|
|
51
|
+
const s = { trigger: "36px", mark: "32px", icon: 17, name: "0.875rem", sub: "0.75rem", row: "52px" };
|
|
53
52
|
const warned = new Set();
|
|
54
53
|
const warnOnce = (key, message) => {
|
|
55
54
|
if (process.env.NODE_ENV === "production" || warned.has(key))
|
|
@@ -8,7 +8,7 @@ const focusRing_styles_1 = require("../../Theme/chakra/focusRing.styles");
|
|
|
8
8
|
const motion_1 = require("../../Theme/chakra/motion");
|
|
9
9
|
const primitives_1 = require("../../Theme/tokens/primitives");
|
|
10
10
|
const controlSize = (size) => {
|
|
11
|
-
const { height, fontSize, paddingX } = primitives_1.
|
|
11
|
+
const { height, fontSize, paddingX } = primitives_1.BUTTON_SIZES[size];
|
|
12
12
|
return { h: height, minW: height, fontSize, px: paddingX };
|
|
13
13
|
};
|
|
14
14
|
// NOTE: [500] alone measures ~4.2 on a dark canvas — resolved per-mode so outline/ghost/link text stays readable.
|
|
@@ -11,7 +11,7 @@ export type ButtonProps = LayoutProps & DataAttributes & Pick<ChakraButtonProps,
|
|
|
11
11
|
loadingText?: string;
|
|
12
12
|
/** Defaults to "fit-content", not 100%; the w alias only applies when width is unset — width wins if both are passed. */
|
|
13
13
|
width?: string | number;
|
|
14
|
-
/** Control height xs
|
|
14
|
+
/** Control height xs 24 · sm 32 · md 40 · lg 48 (xl 56); defaults to "sm" via the theme, so a ButtonGroup size still applies. */
|
|
15
15
|
size?: "lg" | "md" | "sm" | "xs" | "xl";
|
|
16
16
|
/** Defaults to "solid"; "gradient" paints the theme's fixed brand gradient. */
|
|
17
17
|
variant?: "solid" | "outline" | "ghost" | "link" | "unstyled" | "gradient";
|
|
@@ -5,7 +5,7 @@ import { type ControlSize } from "../../Theme/tokens/primitives/controlSizes";
|
|
|
5
5
|
export declare const FIELD_RADIUS = "lg";
|
|
6
6
|
export declare const FIELD_BORDER_WIDTH = "1px";
|
|
7
7
|
export declare const FIELD_TRANSITION: string;
|
|
8
|
-
/** Chakra `h`/`fontSize`/`px` for a
|
|
8
|
+
/** Chakra `h`/`fontSize`/`px` for a field or select of this size. */
|
|
9
9
|
export declare const controlSizeStyles: (size: ControlSize) => {
|
|
10
10
|
h: string;
|
|
11
11
|
minH: string;
|
|
@@ -9,7 +9,7 @@ const focusRing_styles_1 = require("../../Theme/chakra/focusRing.styles");
|
|
|
9
9
|
exports.FIELD_RADIUS = "lg";
|
|
10
10
|
exports.FIELD_BORDER_WIDTH = "1px";
|
|
11
11
|
exports.FIELD_TRANSITION = (0, motion_1.transitionFor)(["border-color", "box-shadow", "background-color"]);
|
|
12
|
-
/** Chakra `h`/`fontSize`/`px` for a
|
|
12
|
+
/** Chakra `h`/`fontSize`/`px` for a field or select of this size. */
|
|
13
13
|
const controlSizeStyles = (size) => {
|
|
14
14
|
const spec = controlSizes_1.CONTROL_SIZES[size];
|
|
15
15
|
return { h: spec.height, minH: spec.height, fontSize: spec.fontSize, px: spec.paddingX };
|
|
@@ -44,7 +44,7 @@ export type BaseDatePickerProps = {
|
|
|
44
44
|
width?: string | number;
|
|
45
45
|
/** Blocks today in the calendar and in typed input; the single picker preselects tomorrow instead. */
|
|
46
46
|
disableToday?: boolean;
|
|
47
|
-
/** Control-scale height: xs
|
|
47
|
+
/** Control-scale height: xs 24 · sm 38 · md 40 · lg 48px (default `sm`, like TextInput); also scales the calendar/clock icon. */
|
|
48
48
|
size?: "xs" | "sm" | "md" | "lg";
|
|
49
49
|
};
|
|
50
50
|
/** Single-date variant, Date API (default) — `isRange` must be false or omitted; this is the discriminant the DatePickerProps union switches on. */
|
|
@@ -17,10 +17,10 @@ const motion_2 = require("../../Theme/chakra/motion");
|
|
|
17
17
|
const focusRing_styles_1 = require("../../Theme/chakra/focusRing.styles");
|
|
18
18
|
const MotionBox = (0, framer_motion_1.motion)((0, react_1.forwardRef)((props, ref) => ((0, jsx_runtime_1.jsx)(react_2.Box, { ref: ref, ...props }))));
|
|
19
19
|
const SIZE_MAP = {
|
|
20
|
-
xs: { btn: "xs", img: "1rem", chevron: controlSizes_1.
|
|
21
|
-
sm: { btn: "sm", img: "1rem", chevron: controlSizes_1.
|
|
22
|
-
md: { btn: "md", img: "1.125rem", chevron: controlSizes_1.
|
|
23
|
-
lg: { btn: "lg", img: "1.25rem", chevron: controlSizes_1.
|
|
20
|
+
xs: { btn: "xs", img: "1rem", chevron: controlSizes_1.BUTTON_SIZES.xs.iconSize, minW: "8rem", gap: 1.5, rowSize: "xs" },
|
|
21
|
+
sm: { btn: "sm", img: "1rem", chevron: controlSizes_1.BUTTON_SIZES.sm.iconSize, minW: "9rem", gap: 2, rowSize: "sm" },
|
|
22
|
+
md: { btn: "md", img: "1.125rem", chevron: controlSizes_1.BUTTON_SIZES.md.iconSize, minW: "11rem", gap: 2, rowSize: "md" },
|
|
23
|
+
lg: { btn: "lg", img: "1.25rem", chevron: controlSizes_1.BUTTON_SIZES.lg.iconSize, minW: "12rem", gap: 2.5, rowSize: "lg" },
|
|
24
24
|
xl: { btn: "lg", img: "1.4rem", chevron: 20, minW: "13rem", gap: 3, rowSize: "lg" },
|
|
25
25
|
};
|
|
26
26
|
const TRIGGER_TRANSITION = (0, motion_1.transitionFor)(["background-color", "border-color", "color", "box-shadow"]);
|
|
@@ -28,7 +28,7 @@ export type DropdownProps = {
|
|
|
28
28
|
LabelStyle?: React.CSSProperties;
|
|
29
29
|
/** Inline style on each row's `image` icon; ignored for options without one. */
|
|
30
30
|
ImageStyle?: React.CSSProperties;
|
|
31
|
-
/** Trigger
|
|
31
|
+
/** Trigger on the button scale, menu rows on the option-row scale; defaults to `sm`. `xl` renders an `lg` trigger. */
|
|
32
32
|
size?: "xs" | "sm" | "md" | "lg" | "xl";
|
|
33
33
|
/** @deprecated Use `size` instead. Kept for backward compatibility. */
|
|
34
34
|
optionsSize?: "sm" | "md" | "lg";
|
|
@@ -10,7 +10,7 @@ export type PhoneNumberInputProps = {
|
|
|
10
10
|
label?: string;
|
|
11
11
|
/** Falls back to an auto-generated id (shared with `inputId` when that's omitted too), so the label is always bound. */
|
|
12
12
|
id?: string;
|
|
13
|
-
/** Control-scale height:
|
|
13
|
+
/** Control-scale height: xs 24 · sm 38 · md 40 · lg 48px. Defaults to "sm", like TextInput, so it lines up in a form. */
|
|
14
14
|
size?: string;
|
|
15
15
|
value?: string;
|
|
16
16
|
codeValueReturn?: boolean;
|
|
@@ -18,7 +18,7 @@ export type MultiSelectProps = {
|
|
|
18
18
|
addOnBlur?: boolean;
|
|
19
19
|
/** Marks the field invalid (`aria-invalid` + error border) and swaps `helperText` for `errorMessage`; a rejected email sets this internally too. */
|
|
20
20
|
error?: boolean;
|
|
21
|
-
/** Height on the
|
|
21
|
+
/** Height on the field control scale (xs 24 · sm 38 · md 40 · lg 48px). Defaults to `sm`. */
|
|
22
22
|
size?: "xs" | "sm" | "md" | "lg";
|
|
23
23
|
inputStyle?: object;
|
|
24
24
|
/** Rendered only while `error` is true; a rejected email's internal "Invalid email address" text wins over this until the input changes. */
|
|
@@ -4,7 +4,7 @@ import type { Tone } from "../../Theme/tokens/builders/tone";
|
|
|
4
4
|
import type { DaySectionLabels } from "./notificationHelpers";
|
|
5
5
|
/** Shared tone vocabulary for the badge, row tile and zone/filter buttons — an alias of the theme's Tone. */
|
|
6
6
|
export type NotificationTone = Tone;
|
|
7
|
-
/**
|
|
7
|
+
/** Button size scale for the bell trigger. */
|
|
8
8
|
export type NotificationBellSize = "xs" | "sm" | "md" | "lg";
|
|
9
9
|
/** Bell trigger with the three-state badge (capped count -> dot -> nothing); renders no panel itself. */
|
|
10
10
|
export interface NotificationBellProps {
|
|
@@ -11,11 +11,10 @@ const outlineRung_1 = require("../../Theme/tokens/builders/outlineRung");
|
|
|
11
11
|
const rowStates_1 = require("../../Theme/tokens/builders/rowStates");
|
|
12
12
|
const useExclusiveOverlay_1 = require("../../Hooks/useExclusiveOverlay");
|
|
13
13
|
const OrgSwitcherProps_1 = require("./OrgSwitcherProps");
|
|
14
|
-
const controlSizes_1 = require("../../Theme/tokens/primitives/controlSizes");
|
|
15
14
|
const sizeMap = {
|
|
16
|
-
sm: { h:
|
|
17
|
-
md: { h:
|
|
18
|
-
lg: { h:
|
|
15
|
+
sm: { h: "32px", avatar: "22px", font: "0.8rem", sub: "0.65rem", px: 2 },
|
|
16
|
+
md: { h: "40px", avatar: "28px", font: "0.9rem", sub: "0.7rem", px: 3 },
|
|
17
|
+
lg: { h: "48px", avatar: "34px", font: "1rem", sub: "0.78rem", px: 4 },
|
|
19
18
|
};
|
|
20
19
|
const Avatar = ({ org, boxSize, fontSize, }) => {
|
|
21
20
|
const { colors } = (0, useCustomTheme_1.useCustomTheme)();
|
|
@@ -2,7 +2,7 @@ import { PinInputProps } from "@chakra-ui/react";
|
|
|
2
2
|
/** The only pin/OTP component exported from the package. */
|
|
3
3
|
export type ChakraPinInputProps = Pick<PinInputProps, "otp" | "mask" | "defaultValue" | "placeholder" | "manageFocus" | "errorBorderColor" | "focusBorderColor" | "onChange" | "onComplete"> & {
|
|
4
4
|
type?: "alphanumeric" | "number";
|
|
5
|
-
/** Square cell size, aligned to CONTROL_SIZES heights (xs
|
|
5
|
+
/** Square cell size, aligned to CONTROL_SIZES heights (xs 24 · sm 38 · md 40 · lg 48). Defaults to "sm". */
|
|
6
6
|
size?: "xs" | "sm" | "md" | "lg";
|
|
7
7
|
variant?: "flushed" | "outline" | "filled" | "unstyled";
|
|
8
8
|
color?: "gray" | "red" | "orange" | "yellow" | "green" | "teal" | "blue" | "cyan" | "purple" | "pink" | "whiteAlpha" | "blackAlpha" | "primary";
|
|
@@ -23,7 +23,7 @@ interface RangeSliderSharedProps {
|
|
|
23
23
|
scale?: SliderScale;
|
|
24
24
|
/** Formats a raw value for display — value labels, tooltip and aria-valuetext. Defaults to String. */
|
|
25
25
|
formatValue?: (value: number) => string;
|
|
26
|
-
/** Track thickness and thumb size,
|
|
26
|
+
/** Track thickness and thumb size, keyed by ControlSize name — its own values, not the field or button scale. Defaults to "sm". */
|
|
27
27
|
size?: ControlSize;
|
|
28
28
|
/** Heading shown above the track. Pass "" to render none. Defaults to "Range". */
|
|
29
29
|
label?: string;
|
|
@@ -3,5 +3,5 @@ export type RangeSliderSizeSpec = {
|
|
|
3
3
|
trackHeight: string;
|
|
4
4
|
thumbSize: string;
|
|
5
5
|
};
|
|
6
|
-
/** Track thickness and thumb diameter for a size,
|
|
6
|
+
/** Track thickness and thumb diameter for a size — its own values, keyed by the same size names. */
|
|
7
7
|
export declare const rangeSliderSize: (size: ControlSize) => RangeSliderSizeSpec;
|
|
@@ -7,6 +7,6 @@ const RANGE_SLIDER_SIZES = {
|
|
|
7
7
|
md: { trackHeight: "4px", thumbSize: "1.25rem" },
|
|
8
8
|
lg: { trackHeight: "5px", thumbSize: "1.5rem" },
|
|
9
9
|
};
|
|
10
|
-
/** Track thickness and thumb diameter for a size,
|
|
10
|
+
/** Track thickness and thumb diameter for a size — its own values, keyed by the same size names. */
|
|
11
11
|
const rangeSliderSize = (size) => RANGE_SLIDER_SIZES[size];
|
|
12
12
|
exports.rangeSliderSize = rangeSliderSize;
|
|
@@ -15,7 +15,7 @@ export type SearchProps = {
|
|
|
15
15
|
onClear?: () => void;
|
|
16
16
|
/** @deprecated Use `onClear` — same behaviour, consistent casing. */
|
|
17
17
|
onclose?: () => void;
|
|
18
|
-
/** Height on the
|
|
18
|
+
/** Height on the field control scale (xs 24 · sm 38 · md 40 · lg 48px). Defaults to `sm`. */
|
|
19
19
|
size?: ControlSize;
|
|
20
20
|
name?: string;
|
|
21
21
|
/** Disables the input and hides the clear button; the hotkey still focuses it. */
|
|
@@ -38,7 +38,7 @@ export type SearchSelectProps = {
|
|
|
38
38
|
width?: string | number;
|
|
39
39
|
/** Only sets the insideSelect segment's height, not the main field's — that's driven by `size`. */
|
|
40
40
|
height?: string | number;
|
|
41
|
-
/** Height on the
|
|
41
|
+
/** Height on the field control scale (xs 24 · sm 38 · md 40 · lg 48px). Defaults to `sm`. */
|
|
42
42
|
size?: "xs" | "sm" | "md" | "lg";
|
|
43
43
|
/** Blocks opening, typing, chip removal and clearing; renders the shared disabled field look. */
|
|
44
44
|
isDisabled?: boolean;
|
|
@@ -27,7 +27,7 @@ const formatCount = (count) => (count > MAX_COUNT ? `${MAX_COUNT}+` : `${count}`
|
|
|
27
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). */
|
|
28
28
|
function SegmentedControl({ options, value, onChange, size = "sm", isFullWidth = false, variant = "default", surface, "aria-label": ariaLabel, }) {
|
|
29
29
|
const { colors, radii } = (0, useCustomTheme_1.useCustomTheme)();
|
|
30
|
-
const control = controlSizes_1.
|
|
30
|
+
const control = controlSizes_1.BUTTON_SIZES[size];
|
|
31
31
|
const isBrandSlide = variant === "brandSlide";
|
|
32
32
|
const isUnderlineSlide = variant === "underlineSlide";
|
|
33
33
|
const hasIndicator = isBrandSlide || isUnderlineSlide;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ControlSize } from "../../Theme/tokens/primitives/controlSizes";
|
|
2
|
-
/** Whole-track height on the
|
|
2
|
+
/** Whole-track height on the button control scale (sm 32 · md 40 · lg 48px); defaults to "sm". */
|
|
3
3
|
export type SegmentedControlSize = Exclude<ControlSize, "xs">;
|
|
4
4
|
/** brandSlide = primary view switcher; underlineSlide = dense toolbar; default = plain buttons. */
|
|
5
5
|
export type SegmentedControlVariant = "default" | "brandSlide" | "underlineSlide";
|
|
@@ -24,7 +24,7 @@ type SelectCommonProps = {
|
|
|
24
24
|
label?: string;
|
|
25
25
|
/** Native: the built-in placeholder `<option>`. Popup: trigger text when nothing is selected. Defaults to "Select Option". */
|
|
26
26
|
placeholder?: string;
|
|
27
|
-
/** Height on the
|
|
27
|
+
/** Height on the field control scale (xs 24 · sm 38 · md 40 · lg 48px). Defaults to `sm`. */
|
|
28
28
|
size?: ControlSize;
|
|
29
29
|
/** Applied to the wrapping FormControl. */
|
|
30
30
|
width?: string | number;
|
|
@@ -49,7 +49,7 @@ export type SelectSearchProps = {
|
|
|
49
49
|
errorMessage?: string | undefined;
|
|
50
50
|
/** Hint under the field; replaced by `errorMessage` while `error` is true. */
|
|
51
51
|
helperText?: string;
|
|
52
|
-
/** Height on the
|
|
52
|
+
/** Height on the field control scale (xs 24 · sm 38 · md 40 · lg 48px). Defaults to `sm`. */
|
|
53
53
|
size?: ControlSize;
|
|
54
54
|
/** Shows a sticky "Add New"-style footer row in the popup; required for all Bottom* props. */
|
|
55
55
|
isBottomIcon?: boolean | undefined;
|
|
@@ -33,7 +33,7 @@ type SelectV2CommonProps = {
|
|
|
33
33
|
isReadOnly?: boolean;
|
|
34
34
|
/** Label asterisk + `aria-required` only; never blocks an empty submit. */
|
|
35
35
|
isRequired?: boolean;
|
|
36
|
-
/**
|
|
36
|
+
/** Field control scale (xs 24 · sm 38 · md 40 · lg 48px). Defaults to `sm`. */
|
|
37
37
|
size?: ControlSize;
|
|
38
38
|
/** Shows a type-ahead filter input at the top of the popup. Defaults to true. */
|
|
39
39
|
isSearchable?: boolean;
|
|
@@ -14,6 +14,7 @@ const lucide_react_1 = require("lucide-react");
|
|
|
14
14
|
const OverflowTooltipText_1 = __importDefault(require("./components/OverflowTooltipText"));
|
|
15
15
|
const ToolTip_1 = __importDefault(require("../ToolTip/ToolTip"));
|
|
16
16
|
const Sidebar_1 = require("../../Constants/Sidebar");
|
|
17
|
+
const sidebarId_1 = require("./sidebarId");
|
|
17
18
|
const tone_1 = require("../../Theme/tokens/builders/tone");
|
|
18
19
|
const sidebarAccent_1 = require("../../Theme/tokens/builders/sidebarAccent");
|
|
19
20
|
const paletteFromTheme_1 = require("../../Theme/chakra/paletteFromTheme");
|
|
@@ -47,7 +48,7 @@ const CollapsedItem = ({ item, isActive, itemFontSize, onItemClick }) => {
|
|
|
47
48
|
e.preventDefault();
|
|
48
49
|
if (!(0, menuDisabled_1.menuDisabled)(item))
|
|
49
50
|
onItemClick === null || onItemClick === void 0 ? void 0 : onItemClick(item);
|
|
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.
|
|
51
|
+
}, 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.sidebar.semanticText.error }))] }) }) }), (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 }))] }) }) }) })] }));
|
|
51
52
|
};
|
|
52
53
|
const ExpandedItem = ({ item, isActive, itemFontSize, onItemClick }) => {
|
|
53
54
|
var _a;
|
|
@@ -65,9 +66,10 @@ const ExpandedItem = ({ item, isActive, itemFontSize, onItemClick }) => {
|
|
|
65
66
|
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, }) => {
|
|
66
67
|
const theme = (0, useCustomTheme_1.useCustomTheme)();
|
|
67
68
|
const activeAccent = (0, sidebarAccentColors_1.getSidebarActiveAccent)(theme.colors);
|
|
69
|
+
const scrollContainerId = (0, sidebarId_1.sanitizeId)((0, react_1.useId)());
|
|
68
70
|
const [collapsed, setCollapsed] = (0, react_1.useState)(defaultCollapsed);
|
|
69
71
|
const width = collapsed ? collapsedWidth : expandedWidth;
|
|
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.
|
|
72
|
+
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.200" }, 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: scrollContainerId, flex: "1", minH: 0, overflowY: "auto", overflowX: "hidden", py: 2, px: "6px", sx: (0, Sidebar_1.cssForScrollBar)(theme), children: items.map((item) => {
|
|
71
73
|
var _a;
|
|
72
74
|
const isActive = String(selected) === String(item.id) ||
|
|
73
75
|
String(selected) === String(item.title);
|
|
@@ -8,7 +8,6 @@ const jsx_runtime_1 = require("react/jsx-runtime");
|
|
|
8
8
|
const react_1 = require("react");
|
|
9
9
|
const react_2 = require("@chakra-ui/react");
|
|
10
10
|
const useCustomTheme_1 = require("../../Theme/useCustomTheme");
|
|
11
|
-
const filledSurface_1 = require("../../Theme/tokens/builders/filledSurface");
|
|
12
11
|
const sidebarAccentColors_1 = require("./sidebarAccentColors");
|
|
13
12
|
const sidebarId_1 = require("./sidebarId");
|
|
14
13
|
const Sidebar_1 = require("../../Constants/Sidebar");
|
|
@@ -36,13 +35,18 @@ const sidebarScale_1 = require("./sidebarScale");
|
|
|
36
35
|
const viewportHeight_1 = require("../../Theme/tokens/builders/viewportHeight");
|
|
37
36
|
const SidebarHeader = ({ logo, companyName, companySubtitle, toggle, isLoading, onToggle, overlay, onClose, }) => {
|
|
38
37
|
const theme = (0, useCustomTheme_1.useCustomTheme)();
|
|
38
|
+
const activeAccent = (0, sidebarAccentColors_1.getSidebarActiveAccent)(theme.colors);
|
|
39
39
|
if (isLoading) {
|
|
40
40
|
return ((0, jsx_runtime_1.jsx)(react_2.Box, { w: "100%", px: toggle ? 2 : 4, py: 2, h: Sidebar_1.HEADER_HEIGHT, display: "flex", alignItems: "center", flexShrink: 0, children: toggle ? ((0, jsx_runtime_1.jsx)(react_2.Flex, { align: "center", gap: 4, justifyContent: "center", w: "100%", children: (0, jsx_runtime_1.jsx)(react_2.Skeleton, { w: "28px", h: "28px", borderRadius: "lg", startColor: theme.colors.sidebar.background[400], endColor: theme.colors.sidebar.background[300] }) })) : ((0, jsx_runtime_1.jsxs)(react_2.Flex, { align: "center", gap: 3, w: "100%", children: [(0, jsx_runtime_1.jsx)(react_2.Skeleton, { w: "28px", h: "28px", borderRadius: "lg", startColor: theme.colors.sidebar.background[400], endColor: theme.colors.sidebar.background[300] }), (0, jsx_runtime_1.jsx)(react_2.Skeleton, { h: "1.25rem", w: "60%", borderRadius: "lg", startColor: theme.colors.sidebar.background[400], endColor: theme.colors.sidebar.background[300] })] })) }));
|
|
41
41
|
}
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
42
|
+
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
|
|
43
|
+
// Rail-safe pairing, not a raw primary fill: primary[500] equals the rail itself on
|
|
44
|
+
// some brands (zinc), making the tile disappear. See THEME-CONTRACT.md sidebar rules.
|
|
45
|
+
, {
|
|
46
|
+
// Rail-safe pairing, not a raw primary fill: primary[500] equals the rail itself on
|
|
47
|
+
// some brands (zinc), making the tile disappear. See THEME-CONTRACT.md sidebar rules.
|
|
48
|
+
bg: theme.colors.sidebar.activeBg, color: activeAccent.label, 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, {}) }));
|
|
49
|
+
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.200", display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0, position: "relative", _hover: { bg: "whiteAlpha.300" }, transition: "background 0.15s", sx: {
|
|
46
50
|
"&::after": {
|
|
47
51
|
content: '""',
|
|
48
52
|
position: "absolute",
|
|
@@ -61,7 +65,7 @@ const SkeletonMenuRow = ({ toggle }) => {
|
|
|
61
65
|
const AddNewButton = ({ toggle, onClick, overlay }) => {
|
|
62
66
|
const theme = (0, useCustomTheme_1.useCustomTheme)();
|
|
63
67
|
const activeAccent = (0, sidebarAccentColors_1.getSidebarActiveAccent)(theme.colors);
|
|
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.
|
|
68
|
+
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.200" }, 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" }))] }));
|
|
65
69
|
};
|
|
66
70
|
const deriveInitials = (user) => {
|
|
67
71
|
if (user.initials)
|
|
@@ -76,8 +80,10 @@ const deriveInitials = (user) => {
|
|
|
76
80
|
const UserFooter = ({ user, toggle, overlay }) => {
|
|
77
81
|
const theme = (0, useCustomTheme_1.useCustomTheme)();
|
|
78
82
|
const activeAccent = (0, sidebarAccentColors_1.getSidebarActiveAccent)(theme.colors);
|
|
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",
|
|
80
|
-
|
|
83
|
+
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",
|
|
84
|
+
// Same rail-safe pairing as the logo tile — primary.opacity[32] was invisible on zinc/skyline.
|
|
85
|
+
bg: theme.colors.sidebar.activeBg, color: activeAccent.label, display: "flex", alignItems: "center", justifyContent: "center", fontSize: sidebarScale_1.SIDEBAR_CHROME.metaFontSize, fontWeight: 600, flexShrink: 0, children: deriveInitials(user) }));
|
|
86
|
+
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.200" }, 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 })] }) }));
|
|
81
87
|
};
|
|
82
88
|
// Footer "cell" — one segment of the Collapse | Hide/Show control.
|
|
83
89
|
const ControlCell = ({ onClick, ariaLabel, label, accent, children }) => {
|