pixelize-design-library 2.4.2-beta.60 → 2.4.2-beta.61
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 +38 -10
- package/COMPONENT-GOTCHAS.md +41 -4
- package/DESIGN-GUIDE.md +9 -1
- package/dist/Components/NavLauncher/LauncherTabs.d.ts +18 -0
- package/dist/Components/NavLauncher/LauncherTabs.js +64 -0
- package/dist/Components/NavLauncher/NavLauncher.d.ts +1 -1
- package/dist/Components/NavLauncher/NavLauncher.js +203 -53
- package/dist/Components/NavLauncher/NavLauncherProps.d.ts +23 -4
- package/dist/Components/NavLauncher/NewTabLink.d.ts +2 -2
- package/dist/Components/NavLauncher/NewTabLink.js +7 -3
- package/dist/Components/NavLauncher/launcherParts.d.ts +4 -1
- package/dist/Components/NavLauncher/launcherParts.js +16 -8
- package/dist/Components/NavLauncher/resultNavigation.d.ts +3 -0
- package/dist/Components/NavLauncher/resultNavigation.js +65 -0
- package/dist/Components/NavLauncher/revealStyles.d.ts +1 -1
- package/dist/Components/NavLauncher/revealStyles.js +2 -2
- package/dist/Components/NavigationBar/NavigationBar.js +2 -1
- package/dist/Components/NavigationBar/NavigationBarProps.d.ts +1 -0
- package/dist/Components/OrgSwitcher/OrgSwitcher.js +18 -6
- package/dist/Components/OrgSwitcher/OrgSwitcherProps.d.ts +4 -0
- package/dist/esm/Components/NavLauncher/LauncherTabs.js +58 -0
- package/dist/esm/Components/NavLauncher/NavLauncher.js +204 -54
- package/dist/esm/Components/NavLauncher/NewTabLink.js +4 -3
- package/dist/esm/Components/NavLauncher/launcherParts.js +15 -8
- package/dist/esm/Components/NavLauncher/resultNavigation.js +61 -0
- package/dist/esm/Components/NavLauncher/revealStyles.js +2 -2
- package/dist/esm/Components/NavigationBar/NavigationBar.js +2 -1
- package/dist/esm/Components/OrgSwitcher/OrgSwitcher.js +16 -7
- package/dist/index.d.ts +1 -0
- package/package.json +1 -1
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.useRowHover = exports.stretchedLink = exports.useRowFocus = exports.titleInset = exports.activeRowSurface = exports.activeRowStyle = exports.ROW_CONTAINER = exports.WIDE_ROW = exports.isPlainClick = exports.ITEM_SELECTOR = void 0;
|
|
6
|
+
exports.useRowHover = exports.stretchedLink = exports.useRowFocus = exports.titleInset = exports.activeRowSurface = exports.activeRowStyle = exports.ROW_CONTAINER = exports.WIDE_ROW = exports.isPlainClick = exports.useTouchDensity = exports.TouchDensity = exports.ITEM_SELECTOR = void 0;
|
|
7
7
|
exports.CountBadge = CountBadge;
|
|
8
8
|
exports.NewTag = NewTag;
|
|
9
9
|
exports.SectionHeader = SectionHeader;
|
|
@@ -33,6 +33,10 @@ const NewTabLink_1 = __importDefault(require("./NewTabLink"));
|
|
|
33
33
|
const PinToggle_1 = __importDefault(require("./PinToggle"));
|
|
34
34
|
const revealStyles_1 = require("./revealStyles");
|
|
35
35
|
exports.ITEM_SELECTOR = "[data-launcher-item]";
|
|
36
|
+
const TouchDensityContext = (0, react_2.createContext)(false);
|
|
37
|
+
exports.TouchDensity = TouchDensityContext.Provider;
|
|
38
|
+
const useTouchDensity = () => (0, react_2.useContext)(TouchDensityContext);
|
|
39
|
+
exports.useTouchDensity = useTouchDensity;
|
|
36
40
|
const isPlainClick = (event) => event.button === 0 &&
|
|
37
41
|
!event.metaKey &&
|
|
38
42
|
!event.ctrlKey &&
|
|
@@ -138,6 +142,7 @@ function Highlight({ text, query }) {
|
|
|
138
142
|
}
|
|
139
143
|
function RowActions({ children }) {
|
|
140
144
|
const { colors } = (0, useCustomTheme_1.useCustomTheme)();
|
|
145
|
+
const isTouch = (0, exports.useTouchDensity)();
|
|
141
146
|
const revealed = REVEALED.replace(/ &/g, " > &");
|
|
142
147
|
return ((0, jsx_runtime_1.jsx)(react_1.Flex, { sx: {
|
|
143
148
|
[NARROW_ROW]: {
|
|
@@ -146,7 +151,7 @@ function RowActions({ children }) {
|
|
|
146
151
|
borderRadius: "6px",
|
|
147
152
|
},
|
|
148
153
|
},
|
|
149
|
-
}, position: "absolute", top: "7px", right: "4px", h: "19px", align: "center", gap: "2px", zIndex: 1, children: children }));
|
|
154
|
+
}, position: "absolute", top: isTouch ? "12px" : "7px", right: "4px", h: "19px", align: "center", gap: "2px", zIndex: 1, children: children }));
|
|
150
155
|
}
|
|
151
156
|
function RowTip({ text }) {
|
|
152
157
|
const { colors } = (0, useCustomTheme_1.useCustomTheme)();
|
|
@@ -157,19 +162,21 @@ function ModuleRow({ module, keyScreens, isPinned, onTogglePin, pinId, labels, l
|
|
|
157
162
|
const hover = (0, exports.useRowHover)();
|
|
158
163
|
const focus = (0, exports.useRowFocus)();
|
|
159
164
|
const ring = (0, focusRing_styles_1.focusVisibleStyles)(colors);
|
|
165
|
+
const isTouch = (0, exports.useTouchDensity)();
|
|
160
166
|
const base = typeof module.badge === "number" || module.badge ? 24 : 0;
|
|
161
167
|
const open = base + (onTogglePin ? 46 : 24);
|
|
162
|
-
return ((0, jsx_runtime_1.jsxs)(react_1.Flex, { "data-group": true, "data-nav-cell": true, position: "relative", align: "flex-start", gap: "10px", minH: "34px", pl: "8px", pr: "4px", pt: "7px", pb: "5px", borderRadius: "8px", transition: (0, motion_1.transitionFor)(["background-color"]), _hover: hover._hover, _focusWithin: hover._focusWithin, sx: { ...focus.sx, ...exports.ROW_CONTAINER }, children: [(0, jsx_runtime_1.jsx)(RowIcon, { icon: module.icon, size: 16, mt: "2px" }), (0, jsx_runtime_1.jsxs)(react_1.Flex, { direction: "column", flex: 1, minW: 0, children: [(0, jsx_runtime_1.jsxs)(react_1.Flex, { align: "center", gap: "6px", h: "19px", minW: 0, sx: (0, exports.titleInset)(base, open), children: [(0, jsx_runtime_1.jsx)(OverflowToolTip_1.default, { label: module.label, placement: "top-start", children: (0, jsx_runtime_1.jsx)(react_1.Box, { as: link.linkAs, href: module.href, "data-launcher-item": true, ...focus.primary, "data-pin-id": onTogglePin ? pinId : undefined, onClick: link.onPlainClick, minW: 0, fontSize: "13.5px", fontWeight: 500, color: colors.text[900], noOfLines: 1, borderRadius: "sm", sx: (0, exports.stretchedLink)("8px"), children: module.label }) }), module.isNew ? (0, jsx_runtime_1.jsx)(NewTag, { label: labels.newBadge }) : null] }), keyScreens.length ? ((0, jsx_runtime_1.jsx)(OverflowToolTip_1.default, { label: keyScreens.map((screen) => screen.label).join(" · "), placement: "bottom-start", children: (0, jsx_runtime_1.jsx)(react_1.Box, { role: "group", "aria-label": `${module.label} ${labels.screens}`, position: "relative", zIndex: 1, w: "fit-content", maxW: "100%", fontSize: "11.5px", lineHeight: "15px", color: colors.textMuted, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis", children: keyScreens.map((screen, i) => ((0, jsx_runtime_1.jsxs)(react_2.Fragment, { children: [i > 0 ? ((0, jsx_runtime_1.jsx)(react_1.Box, { as: "span", "aria-hidden": true, mx: "5px", opacity: 0.7, children: "\u00B7" })) : null, (0, jsx_runtime_1.jsx)(react_1.Box, { as: link.linkAs, href: screen.href, "data-launcher-item": true, onClick: link.onPlainClick, color: "inherit", borderRadius: "sm", position: "relative", zIndex: 1, _hover: {
|
|
168
|
+
return ((0, jsx_runtime_1.jsxs)(react_1.Flex, { "data-group": true, "data-nav-cell": true, position: "relative", align: "flex-start", gap: "10px", minH: isTouch ? "44px" : "34px", pl: "8px", pr: "4px", pt: isTouch ? "12px" : "7px", pb: isTouch ? "8px" : "5px", borderRadius: "8px", transition: (0, motion_1.transitionFor)(["background-color"]), _hover: hover._hover, _focusWithin: hover._focusWithin, sx: { ...focus.sx, ...exports.ROW_CONTAINER }, children: [(0, jsx_runtime_1.jsx)(RowIcon, { icon: module.icon, size: 16, mt: "2px" }), (0, jsx_runtime_1.jsxs)(react_1.Flex, { direction: "column", flex: 1, minW: 0, children: [(0, jsx_runtime_1.jsxs)(react_1.Flex, { align: "center", gap: "6px", h: "19px", minW: 0, sx: (0, exports.titleInset)(base, open), children: [(0, jsx_runtime_1.jsx)(OverflowToolTip_1.default, { label: module.label, placement: "top-start", children: (0, jsx_runtime_1.jsx)(react_1.Box, { as: link.linkAs, href: module.href, "data-launcher-item": true, ...focus.primary, "data-pin-id": onTogglePin ? pinId : undefined, onClick: link.onPlainClick, minW: 0, fontSize: "13.5px", fontWeight: 500, color: colors.text[900], noOfLines: 1, borderRadius: "sm", sx: (0, exports.stretchedLink)("8px"), children: module.label }) }), module.isNew ? (0, jsx_runtime_1.jsx)(NewTag, { label: labels.newBadge }) : null] }), keyScreens.length ? ((0, jsx_runtime_1.jsx)(OverflowToolTip_1.default, { label: keyScreens.map((screen) => screen.label).join(" · "), placement: "bottom-start", children: (0, jsx_runtime_1.jsx)(react_1.Box, { role: "group", "aria-label": `${module.label} ${labels.screens}`, position: "relative", zIndex: 1, w: "fit-content", maxW: "100%", fontSize: "11.5px", lineHeight: "15px", color: colors.textMuted, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis", children: keyScreens.map((screen, i) => ((0, jsx_runtime_1.jsxs)(react_2.Fragment, { children: [i > 0 ? ((0, jsx_runtime_1.jsx)(react_1.Box, { as: "span", "aria-hidden": true, mx: "5px", opacity: 0.7, children: "\u00B7" })) : null, (0, jsx_runtime_1.jsx)(react_1.Box, { as: link.linkAs, href: screen.href, "data-launcher-item": true, onClick: link.onPlainClick, color: "inherit", borderRadius: "sm", position: "relative", zIndex: 1, _hover: {
|
|
163
169
|
textDecoration: "underline",
|
|
164
170
|
textUnderlineOffset: "2px",
|
|
165
|
-
}, sx: ring, children: screen.label })] }, screen.id))) }) })) : null] }), (0, jsx_runtime_1.jsxs)(RowActions, { children: [(0, jsx_runtime_1.jsx)(CountBadge, { value: module.badge }), onTogglePin ? ((0, jsx_runtime_1.jsx)(PinToggle_1.default, { isPinned: isPinned, label: isPinned ? labels.unpin(module.label) : labels.pin(module.label), title: "", onToggle: onTogglePin })) : null, (0, jsx_runtime_1.jsx)(NewTabLink_1.default, { href: module.href, label: labels.openInNewTab(module.label), linkAs: link.linkAs })] }), onTogglePin ? ((0, jsx_runtime_1.jsx)(RowTip, { text: isPinned ? labels.unpinTip : labels.pinTip })) : null] }));
|
|
171
|
+
}, sx: ring, children: screen.label })] }, screen.id))) }) })) : null] }), (0, jsx_runtime_1.jsxs)(RowActions, { children: [(0, jsx_runtime_1.jsx)(CountBadge, { value: module.badge }), onTogglePin ? ((0, jsx_runtime_1.jsx)(PinToggle_1.default, { isPinned: isPinned, label: isPinned ? labels.unpin(module.label) : labels.pin(module.label), title: "", onToggle: onTogglePin })) : null, (0, jsx_runtime_1.jsx)(NewTabLink_1.default, { href: module.href, label: labels.openInNewTab(module.label), tip: labels.newTabTip, linkAs: link.linkAs })] }), onTogglePin ? ((0, jsx_runtime_1.jsx)(RowTip, { text: isPinned ? labels.unpinTip : labels.pinTip })) : null] }));
|
|
166
172
|
}
|
|
167
173
|
function RailRow({ screen, module, link, isStrong = false, trailing, pinId, }) {
|
|
168
174
|
var _a;
|
|
169
175
|
const { colors } = (0, useCustomTheme_1.useCustomTheme)();
|
|
170
176
|
const hover = (0, exports.useRowHover)();
|
|
171
177
|
const focus = (0, exports.useRowFocus)();
|
|
172
|
-
|
|
178
|
+
const isTouch = (0, exports.useTouchDensity)();
|
|
179
|
+
return ((0, jsx_runtime_1.jsxs)(react_1.Flex, { "data-group": true, position: "relative", align: "center", gap: "10px", h: isTouch ? "44px" : "32px", pl: "8px", pr: "4px", borderRadius: "8px", transition: (0, motion_1.transitionFor)(["background-color"]), _hover: hover._hover, _focusWithin: hover._focusWithin, sx: focus.sx, children: [(0, jsx_runtime_1.jsx)(RowIcon, { icon: (_a = screen.icon) !== null && _a !== void 0 ? _a : module.icon, size: 15 }), (0, jsx_runtime_1.jsx)(OverflowToolTip_1.default, { label: screen.label, placement: "top-start", children: (0, jsx_runtime_1.jsx)(react_1.Box, { as: link.linkAs, href: screen.href, "data-launcher-item": true, ...focus.primary, "data-pin-id": pinId, onClick: link.onPlainClick, flex: 1, minW: 0, fontSize: "13px", fontWeight: isStrong ? 500 : 400, color: colors.text[900], noOfLines: 1, borderRadius: "sm", sx: (0, exports.stretchedLink)("8px"), children: screen.label }) }), (0, jsx_runtime_1.jsx)(react_1.Flex, { position: "relative", zIndex: 1, align: "center", gap: "2px", children: trailing })] }));
|
|
173
180
|
}
|
|
174
181
|
function PinTextButton({ label, text, onToggle }) {
|
|
175
182
|
const { colors } = (0, useCustomTheme_1.useCustomTheme)();
|
|
@@ -184,13 +191,14 @@ function PinnedTile({ screen, module, link, labels, onTogglePin, }) {
|
|
|
184
191
|
const { colors } = (0, useCustomTheme_1.useCustomTheme)();
|
|
185
192
|
const Icon = (_a = screen.icon) !== null && _a !== void 0 ? _a : module.icon;
|
|
186
193
|
const focus = (0, exports.useRowFocus)(true);
|
|
187
|
-
|
|
194
|
+
const isTouch = (0, exports.useTouchDensity)();
|
|
195
|
+
return ((0, jsx_runtime_1.jsxs)(react_1.Flex, { "data-group": true, "data-nav-cell": true, position: "relative", align: "center", gap: "8px", h: isTouch ? "44px" : "36px", pl: "9px", pr: "4px", borderRadius: "9px", borderWidth: "1px", borderColor: colors.boxborder[200], bg: colors.surfaceRaised, transition: (0, motion_1.transitionFor)(["border-color", "background-color"]), _hover: { borderColor: colors.gray[300] }, sx: focus.sx, children: [Icon ? ((0, jsx_runtime_1.jsx)(react_1.Box, { as: "span", display: "inline-flex", flexShrink: 0, color: colors.accentText, children: (0, jsx_runtime_1.jsx)(Icon, { size: 15, strokeWidth: 1.8, "aria-hidden": true }) })) : null, (0, jsx_runtime_1.jsx)(OverflowToolTip_1.default, { label: screen.label, placement: "top-start", children: (0, jsx_runtime_1.jsx)(react_1.Box, { as: link.linkAs, href: screen.href, "data-launcher-item": true, ...focus.primary, "data-pin-id": onTogglePin ? screen.id : undefined, onClick: link.onPlainClick, flex: 1, minW: 0, fontSize: "13px", fontWeight: 500, color: colors.text[900], noOfLines: 1, borderRadius: "sm", sx: (0, exports.stretchedLink)("9px"), children: screen.label }) }), (0, jsx_runtime_1.jsx)(CountBadge, { value: screen.badge, size: "tile" }), onTogglePin ? ((0, jsx_runtime_1.jsx)(react_1.Box, { position: "relative", zIndex: 1, flexShrink: 0, w: "0", overflow: "hidden", transition: (0, motion_1.transitionFor)(["width"]), _groupHover: { w: "22px" }, _groupFocusWithin: { w: "22px" }, children: (0, jsx_runtime_1.jsx)(PinToggle_1.default, { isPinned: true, size: 12, label: labels.unpin(screen.label), title: labels.unpinTip, onToggle: onTogglePin }) })) : null] }));
|
|
188
196
|
}
|
|
189
|
-
function AppsSection({ apps, hues, currentAppId, heading, onSelect, }) {
|
|
197
|
+
function AppsSection({ apps, hues, currentAppId, heading, hideHeading = false, onSelect, }) {
|
|
190
198
|
const { colors } = (0, useCustomTheme_1.useCustomTheme)();
|
|
191
199
|
const rows = (0, rowStates_1.listRowBackgrounds)(colors);
|
|
192
200
|
const rowRing = (0, exports.activeRowSurface)(colors);
|
|
193
|
-
return ((0, jsx_runtime_1.jsxs)(react_1.Box, { children: [(0, jsx_runtime_1.jsx)(SectionHeader, { label: heading, isRail: true, hasCount: false }), (0, jsx_runtime_1.jsx)(react_1.Box, { as: "ul", listStyleType: "none", m: 0, p: 0, "aria-label": heading, children: apps.map((app, index) => {
|
|
201
|
+
return ((0, jsx_runtime_1.jsxs)(react_1.Box, { children: [hideHeading ? null : (0, jsx_runtime_1.jsx)(SectionHeader, { label: heading, isRail: true, hasCount: false }), (0, jsx_runtime_1.jsx)(react_1.Box, { as: "ul", listStyleType: "none", m: 0, p: 0, "aria-label": heading, children: apps.map((app, index) => {
|
|
194
202
|
var _a;
|
|
195
203
|
const isCurrent = app.id === currentAppId;
|
|
196
204
|
const interactive = !isCurrent && !app.locked;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export type ResultKey = "ArrowUp" | "ArrowDown" | "ArrowLeft" | "ArrowRight" | "Home" | "End" | "PageUp" | "PageDown";
|
|
2
|
+
/** Next flat result index for a key, following the visual grid: rows by `columns` inside a group, reading order across columns. */
|
|
3
|
+
export declare const moveResult: (sizes: readonly number[], columns: number, index: number, key: ResultKey, pageRows?: number) => number;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.moveResult = void 0;
|
|
4
|
+
const locate = (sizes, index) => {
|
|
5
|
+
let start = 0;
|
|
6
|
+
for (let group = 0; group < sizes.length; group += 1) {
|
|
7
|
+
if (index < start + sizes[group])
|
|
8
|
+
return { group, pos: index - start, start };
|
|
9
|
+
start += sizes[group];
|
|
10
|
+
}
|
|
11
|
+
return {
|
|
12
|
+
group: sizes.length - 1,
|
|
13
|
+
pos: 0,
|
|
14
|
+
start: start - sizes[sizes.length - 1],
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
const startOf = (sizes, group) => sizes.slice(0, group).reduce((sum, size) => sum + size, 0);
|
|
18
|
+
const stepVertical = (sizes, columns, index, down, wrap) => {
|
|
19
|
+
const { group, pos, start } = locate(sizes, index);
|
|
20
|
+
const size = sizes[group];
|
|
21
|
+
const column = pos % columns;
|
|
22
|
+
if (down) {
|
|
23
|
+
if (pos + columns < size)
|
|
24
|
+
return index + columns;
|
|
25
|
+
if (Math.floor(pos / columns) < Math.floor((size - 1) / columns))
|
|
26
|
+
return start + size - 1;
|
|
27
|
+
const next = group + 1 < sizes.length ? group + 1 : wrap ? 0 : -1;
|
|
28
|
+
if (next < 0)
|
|
29
|
+
return index;
|
|
30
|
+
return startOf(sizes, next) + Math.min(column, sizes[next] - 1);
|
|
31
|
+
}
|
|
32
|
+
if (pos - columns >= 0)
|
|
33
|
+
return index - columns;
|
|
34
|
+
const prev = group > 0 ? group - 1 : wrap ? sizes.length - 1 : -1;
|
|
35
|
+
if (prev < 0)
|
|
36
|
+
return index;
|
|
37
|
+
const lastRow = Math.floor((sizes[prev] - 1) / columns);
|
|
38
|
+
return (startOf(sizes, prev) + Math.min(sizes[prev] - 1, lastRow * columns + column));
|
|
39
|
+
};
|
|
40
|
+
/** Next flat result index for a key, following the visual grid: rows by `columns` inside a group, reading order across columns. */
|
|
41
|
+
const moveResult = (sizes, columns, index, key, pageRows = 1) => {
|
|
42
|
+
const total = sizes.reduce((sum, size) => sum + size, 0);
|
|
43
|
+
if (total === 0)
|
|
44
|
+
return 0;
|
|
45
|
+
switch (key) {
|
|
46
|
+
case "ArrowDown":
|
|
47
|
+
case "ArrowUp":
|
|
48
|
+
return stepVertical(sizes, columns, index, key === "ArrowDown", true);
|
|
49
|
+
case "ArrowRight":
|
|
50
|
+
return Math.min(total - 1, index + 1);
|
|
51
|
+
case "ArrowLeft":
|
|
52
|
+
return Math.max(0, index - 1);
|
|
53
|
+
case "Home":
|
|
54
|
+
return 0;
|
|
55
|
+
case "End":
|
|
56
|
+
return total - 1;
|
|
57
|
+
default: {
|
|
58
|
+
let next = index;
|
|
59
|
+
for (let i = 0; i < pageRows; i += 1)
|
|
60
|
+
next = stepVertical(sizes, columns, next, key === "PageDown", false);
|
|
61
|
+
return next;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
exports.moveResult = moveResult;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { SystemStyleObject } from "@chakra-ui/react";
|
|
2
2
|
import type { PaletteProps } from "../../Theme/tokens/types";
|
|
3
|
-
/** Shows a row affordance on row hover, row focus-within or its own keyboard focus, and always on touch. */
|
|
3
|
+
/** Shows a row affordance on row hover, row focus-within or its own keyboard focus, and always on touch, where it also grows to a 32px hit area. */
|
|
4
4
|
export declare const revealStyles: (colors: PaletteProps) => SystemStyleObject;
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.revealStyles = void 0;
|
|
4
4
|
const focusRing_styles_1 = require("../../Theme/chakra/focusRing.styles");
|
|
5
5
|
const motion_1 = require("../../Theme/chakra/motion");
|
|
6
|
-
/** Shows a row affordance on row hover, row focus-within or its own keyboard focus, and always on touch. */
|
|
6
|
+
/** Shows a row affordance on row hover, row focus-within or its own keyboard focus, and always on touch, where it also grows to a 32px hit area. */
|
|
7
7
|
const revealStyles = (colors) => {
|
|
8
8
|
const ring = (0, focusRing_styles_1.focusVisibleStyles)(colors);
|
|
9
9
|
return {
|
|
@@ -12,7 +12,7 @@ const revealStyles = (colors) => {
|
|
|
12
12
|
_groupHover: { opacity: 1 },
|
|
13
13
|
_groupFocusWithin: { opacity: 1 },
|
|
14
14
|
"[data-reveal=true] &": { opacity: 1 },
|
|
15
|
-
"@media (hover: none)": { opacity: 1 },
|
|
15
|
+
"@media (hover: none)": { opacity: 1, minWidth: "32px", width: "32px", height: "32px" },
|
|
16
16
|
...(0, motion_1.reducedMotionSx)(),
|
|
17
17
|
};
|
|
18
18
|
};
|
|
@@ -12,6 +12,7 @@ const accentText_1 = require("../../Theme/tokens/builders/accentText");
|
|
|
12
12
|
const outlineRung_1 = require("../../Theme/tokens/builders/outlineRung");
|
|
13
13
|
const rowStates_1 = require("../../Theme/tokens/builders/rowStates");
|
|
14
14
|
const statusTone_1 = require("../../Theme/tokens/builders/statusTone");
|
|
15
|
+
const ToolTip_1 = __importDefault(require("../ToolTip/ToolTip"));
|
|
15
16
|
const PersonChip_1 = __importDefault(require("../PersonChip/PersonChip"));
|
|
16
17
|
const lucide_react_1 = require("lucide-react");
|
|
17
18
|
// Roomy enough to hover without aiming: the glyph is only 1.25rem.
|
|
@@ -52,7 +53,7 @@ function NavBar({ userAvathar, userName, userRole, navMenu, moreIcon, handleNavO
|
|
|
52
53
|
_focus: { bg: menuHoverBg },
|
|
53
54
|
_active: { bg: rowBackgrounds.selectedActive },
|
|
54
55
|
};
|
|
55
|
-
return ((0, jsx_runtime_1.jsx)(react_1.Box, { bg: theme.colors.backgroundColor.light, px: 4, borderBottom: "1px solid", borderColor: theme.colors.boxborder[200], children: (0, jsx_runtime_1.jsxs)(react_1.Flex, { h: 16, alignItems: "center", justifyContent: "space-between", children: [(0, jsx_runtime_1.jsxs)(react_1.Box, { display: "flex", gap: 1.5, alignItems: "center", children: [(0, jsx_runtime_1.jsx)(react_1.Box, { as: "button", type: "button", onClick: () => onSideBarToggole === null || onSideBarToggole === void 0 ? void 0 : onSideBarToggole(), onMouseEnter: onSideBarPeek, onFocus: onSideBarPeek, "aria-label": sideBarToggole ? "Close navigation menu" : "Open navigation menu", "aria-expanded": !!sideBarToggole, ...iconButtonStyle, display: forceSideBarToggle ? "flex" : { base: "flex", lg: "none" }, w: SIDEBAR_TOGGLE_HIT, h: SIDEBAR_TOGGLE_HIT, children: sideBarToggole ? ((0, jsx_runtime_1.jsx)(lucide_react_1.PanelLeftClose, { size: "1.25rem" })) : ((0, jsx_runtime_1.jsx)(lucide_react_1.PanelRightClose, { size: "1.25rem" })) }), (navigationBarText === null || navigationBarText === void 0 ? void 0 : navigationBarText.onIconClick) && ((0, jsx_runtime_1.jsx)(react_1.Box, { ...iconButtonStyle, as: "button", type: "button", "aria-label": "Go back", display: "flex", onClick: () => { var _a; return (_a = navigationBarText === null || navigationBarText === void 0 ? void 0 : navigationBarText.onIconClick) === null || _a === void 0 ? void 0 : _a.call(navigationBarText); }, children: (0, jsx_runtime_1.jsx)(lucide_react_1.CircleArrowLeft, { size: "1.25rem", color: theme.colors.text[500] }) })), leading && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [leading, (0, jsx_runtime_1.jsx)(react_1.Box, { as: "span", "aria-hidden": "true", mx: 2, w: "1px", h: "1.625rem", bg: theme.colors.boxborder[200] })] })), (navigationBarText === null || navigationBarText === void 0 ? void 0 : navigationBarText.text) && ((0, jsx_runtime_1.jsx)(react_1.Text, { color: (0, accentText_1.accentTextOnCanvas)(theme.colors.secondary, theme.colors.backgroundColor.light), fontSize: "1.25rem", fontWeight: 600, fontFamily: "open-sans, sans-serif", letterSpacing: "-0.013rem", children: navigationBarText === null || navigationBarText === void 0 ? void 0 : navigationBarText.text }))] }), (0, jsx_runtime_1.jsx)(react_1.Flex, { minW: 0, flexShrink: 1, children: (0, jsx_runtime_1.jsxs)(react_1.Stack, { direction: "row", alignItems: "center", spacing: 4, minW: 0, children: [moreIcon && ((0, jsx_runtime_1.jsx)(react_1.Box, { display: "flex", alignItems: "center", minW: 0, children: moreIcon })), (0, jsx_runtime_1.jsxs)(react_1.Menu, { children: [(0, jsx_runtime_1.jsx)(react_1.MenuButton, { as: react_1.Button, rounded: "full", variant: "link", cursor: "pointer", minW: 0, flexShrink: 0, children: (0, jsx_runtime_1.jsx)(Avatar_1.default, { size: "sm", name: userName, src: userAvathar }) }), (0, jsx_runtime_1.jsx)(react_1.MenuList, { alignItems: "center", zIndex: 5, p: 0, py: "0.375rem",
|
|
56
|
+
return ((0, jsx_runtime_1.jsx)(react_1.Box, { bg: theme.colors.backgroundColor.light, px: 4, borderBottom: "1px solid", borderColor: theme.colors.boxborder[200], children: (0, jsx_runtime_1.jsxs)(react_1.Flex, { h: 16, alignItems: "center", justifyContent: "space-between", gap: 2, children: [(0, jsx_runtime_1.jsxs)(react_1.Box, { display: "flex", gap: 1.5, alignItems: "center", flex: "1 1 0%", children: [(0, jsx_runtime_1.jsx)(react_1.Box, { as: "button", type: "button", onClick: () => onSideBarToggole === null || onSideBarToggole === void 0 ? void 0 : onSideBarToggole(), onMouseEnter: onSideBarPeek, onFocus: onSideBarPeek, "aria-label": sideBarToggole ? "Close navigation menu" : "Open navigation menu", "aria-expanded": !!sideBarToggole, ...iconButtonStyle, flexShrink: 0, display: forceSideBarToggle ? "flex" : { base: "flex", lg: "none" }, w: SIDEBAR_TOGGLE_HIT, h: SIDEBAR_TOGGLE_HIT, children: sideBarToggole ? ((0, jsx_runtime_1.jsx)(lucide_react_1.PanelLeftClose, { size: "1.25rem" })) : ((0, jsx_runtime_1.jsx)(lucide_react_1.PanelRightClose, { size: "1.25rem" })) }), (navigationBarText === null || navigationBarText === void 0 ? void 0 : navigationBarText.onIconClick) && ((0, jsx_runtime_1.jsx)(react_1.Box, { ...iconButtonStyle, as: "button", type: "button", "aria-label": "Go back", display: "flex", flexShrink: 0, onClick: () => { var _a; return (_a = navigationBarText === null || navigationBarText === void 0 ? void 0 : navigationBarText.onIconClick) === null || _a === void 0 ? void 0 : _a.call(navigationBarText); }, children: (0, jsx_runtime_1.jsx)(lucide_react_1.CircleArrowLeft, { size: "1.25rem", color: theme.colors.text[500] }) })), leading && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [leading, (0, jsx_runtime_1.jsx)(react_1.Box, { as: "span", "aria-hidden": "true", mx: 2, w: "1px", h: "1.625rem", flexShrink: 0, bg: theme.colors.boxborder[200] })] })), (navigationBarText === null || navigationBarText === void 0 ? void 0 : navigationBarText.text) && ((0, jsx_runtime_1.jsx)(ToolTip_1.default, { label: typeof navigationBarText.text === "string" ? navigationBarText.text : "", overflowOnly: true, placement: "bottom", children: (0, jsx_runtime_1.jsx)(react_1.Text, { flex: "1 1 0%", w: 0, minW: 0, isTruncated: true, color: (0, accentText_1.accentTextOnCanvas)(theme.colors.secondary, theme.colors.backgroundColor.light), fontSize: "1.25rem", fontWeight: 600, fontFamily: "open-sans, sans-serif", letterSpacing: "-0.013rem", children: navigationBarText === null || navigationBarText === void 0 ? void 0 : navigationBarText.text }) }))] }), (0, jsx_runtime_1.jsx)(react_1.Flex, { minW: 0, flexShrink: 1, children: (0, jsx_runtime_1.jsxs)(react_1.Stack, { direction: "row", alignItems: "center", spacing: 4, minW: 0, children: [moreIcon && ((0, jsx_runtime_1.jsx)(react_1.Box, { display: "flex", alignItems: "center", minW: 0, sx: { "& > *": { minW: 0 } }, children: moreIcon })), (0, jsx_runtime_1.jsxs)(react_1.Menu, { children: [(0, jsx_runtime_1.jsx)(react_1.MenuButton, { as: react_1.Button, rounded: "full", variant: "link", cursor: "pointer", minW: 0, flexShrink: 0, children: (0, jsx_runtime_1.jsx)(Avatar_1.default, { size: "sm", name: userName, src: userAvathar }) }), (0, jsx_runtime_1.jsx)(react_1.MenuList, { alignItems: "center", zIndex: 5, p: 0, py: "0.375rem",
|
|
56
57
|
// Without a cap one long title stretches the whole dropdown; titles truncate instead.
|
|
57
58
|
maxW: "18rem", bg: theme.colors.surfaceRaised,
|
|
58
59
|
// NOTE: Chakra's MenuItem inherits --menu-bg hardcoded to #fff via dead _dark — set it or items stay white.
|
|
@@ -6,6 +6,7 @@ export type NavbarProps = {
|
|
|
6
6
|
userName: string;
|
|
7
7
|
userRole?: string;
|
|
8
8
|
navMenu: MenuProps[];
|
|
9
|
+
/** Right-cluster slot before the avatar (org switcher, bell, launcher trigger). Its child may shrink; give icon buttons `flexShrink={0}`. */
|
|
9
10
|
moreIcon?: ReactNode;
|
|
10
11
|
handleNavOnClick: (url: string) => void;
|
|
11
12
|
handleLogout: () => void;
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
4
7
|
const react_1 = require("react");
|
|
@@ -10,12 +13,15 @@ const chartColorsFromTheme_1 = require("../../Theme/tokens/builders/chartColorsF
|
|
|
10
13
|
const outlineRung_1 = require("../../Theme/tokens/builders/outlineRung");
|
|
11
14
|
const rowStates_1 = require("../../Theme/tokens/builders/rowStates");
|
|
12
15
|
const useExclusiveOverlay_1 = require("../../Hooks/useExclusiveOverlay");
|
|
16
|
+
const useMatchMedia_1 = require("../../Hooks/useMatchMedia");
|
|
17
|
+
const ToolTip_1 = __importDefault(require("../ToolTip/ToolTip"));
|
|
13
18
|
const OrgSwitcherProps_1 = require("./OrgSwitcherProps");
|
|
14
19
|
const sizeMap = {
|
|
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 },
|
|
20
|
+
sm: { h: "32px", avatarH: "32px", avatar: "22px", font: "0.8rem", sub: "0.65rem", px: 2 },
|
|
21
|
+
md: { h: "40px", avatarH: "36px", avatar: "28px", font: "0.9rem", sub: "0.7rem", px: 3 },
|
|
22
|
+
lg: { h: "48px", avatarH: "48px", avatar: "34px", font: "1rem", sub: "0.78rem", px: 4 },
|
|
18
23
|
};
|
|
24
|
+
const MD_QUERY = "(min-width: 48em)";
|
|
19
25
|
const Avatar = ({ org, boxSize, fontSize, }) => {
|
|
20
26
|
const { colors } = (0, useCustomTheme_1.useCustomTheme)();
|
|
21
27
|
if (org.logoUrl) {
|
|
@@ -24,9 +30,11 @@ const Avatar = ({ org, boxSize, fontSize, }) => {
|
|
|
24
30
|
const fill = (0, OrgSwitcherProps_1.avatarColor)(org.name, (0, chartColorsFromTheme_1.chartMode)(colors));
|
|
25
31
|
return ((0, jsx_runtime_1.jsx)(react_2.Flex, { align: "center", justify: "center", boxSize: boxSize, borderRadius: "lg", flexShrink: 0, bg: fill, color: (0, accentText_1.onFilled)(fill, colors.white, colors.black), fontSize: fontSize, fontWeight: 700, children: (0, OrgSwitcherProps_1.orgInitial)(org.name) }));
|
|
26
32
|
};
|
|
27
|
-
const OrgSwitcher = ({ organizations, value, onChange, isLoading = false, isSearchable, searchThreshold = 6, triggerVariant = "ghost", size = "md", maxWidth = "200px", menuMinWidth = "280px", placeholder = "Select organization", ariaLabel = "Switch organization", showRole = true, }) => {
|
|
28
|
-
var _a;
|
|
33
|
+
const OrgSwitcher = ({ organizations, value, onChange, isLoading = false, isSearchable, searchThreshold = 6, triggerVariant = "ghost", size = "md", maxWidth = "200px", menuMinWidth = "280px", placeholder = "Select organization", ariaLabel = "Switch organization", showRole = true, display = "full", }) => {
|
|
34
|
+
var _a, _b;
|
|
29
35
|
const theme = (0, useCustomTheme_1.useCustomTheme)();
|
|
36
|
+
const isMd = (0, useMatchMedia_1.useMatchMedia)(MD_QUERY, true);
|
|
37
|
+
const avatarOnly = display === "avatar" || (display === "auto" && !isMd);
|
|
30
38
|
const rowBackgrounds = (0, react_1.useMemo)(() => (0, rowStates_1.listRowBackgrounds)(theme.colors), [theme.colors]);
|
|
31
39
|
const s = sizeMap[size];
|
|
32
40
|
const { isOpen, onOpen, onClose } = (0, react_2.useDisclosure)();
|
|
@@ -87,10 +95,14 @@ const OrgSwitcher = ({ organizations, value, onChange, isLoading = false, isSear
|
|
|
87
95
|
if (org.id !== value)
|
|
88
96
|
onChange(org.id, org);
|
|
89
97
|
};
|
|
98
|
+
const avatarNode = selected ? ((0, jsx_runtime_1.jsx)(Avatar, { org: selected, boxSize: s.avatar, fontSize: s.sub })) : ((0, jsx_runtime_1.jsx)(react_2.Flex, { align: "center", justify: "center", boxSize: s.avatar, borderRadius: "lg", bg: theme.colors.gray[100], color: (0, accentText_1.accentTextOnCanvas)(theme.colors.gray, theme.colors.gray[100]), flexShrink: 0, children: (0, jsx_runtime_1.jsx)(lucide_react_1.Building2, { size: 14 }) }));
|
|
99
|
+
const labelGap = s.px === 2 ? 8 : 10;
|
|
100
|
+
const squeezedWidth = `calc(${s.px * 8 + labelGap * 2 + 16}px + ${s.avatar})`;
|
|
101
|
+
const trigger = ((0, jsx_runtime_1.jsxs)(react_2.Flex, { as: "button", type: "button", "aria-label": avatarOnly && selected ? `${ariaLabel}, ${selected.name}` : ariaLabel, align: "center", justify: avatarOnly ? "center" : undefined, gap: avatarOnly ? "4px" : `${labelGap}px`, h: avatarOnly ? s.avatarH : s.h, px: avatarOnly ? "6px" : s.px, minW: avatarOnly ? undefined : squeezedWidth, flexShrink: avatarOnly ? 0 : 1, borderRadius: "lg", cursor: isLoading ? "default" : "pointer", opacity: isLoading ? 0.6 : 1, pointerEvents: isLoading ? "none" : "auto", transition: "background 0.15s ease", _hover: { bg: triggerVariant === "ghost" ? triggerHoverBg : undefined }, ...triggerStyles, children: [avatarNode, !avatarOnly && ((0, jsx_runtime_1.jsx)(react_2.Text, { fontSize: s.font, fontWeight: 600, color: theme.colors.gray[700], maxW: maxWidth, minW: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", textAlign: "left", children: (_a = selected === null || selected === void 0 ? void 0 : selected.name) !== null && _a !== void 0 ? _a : placeholder })), isLoading ? ((0, jsx_runtime_1.jsx)(react_2.Spinner, { size: "xs", thickness: "1.5px", color: theme.colors.accentText, flexShrink: 0 })) : avatarOnly ? ((0, jsx_runtime_1.jsx)(react_2.Box, { as: lucide_react_1.ChevronDown, size: 12, color: theme.colors.textMuted, flexShrink: 0, "aria-hidden": "true" })) : ((0, jsx_runtime_1.jsx)(react_2.Box, { as: lucide_react_1.ChevronsUpDown, size: 16, color: theme.colors.textMuted, flexShrink: 0 }))] }));
|
|
90
102
|
return ((0, jsx_runtime_1.jsxs)(react_2.Popover, { isOpen: isOpen, onOpen: handlePopoverOpen, onClose: () => {
|
|
91
103
|
onClose();
|
|
92
104
|
setQuery("");
|
|
93
|
-
}, placement: "bottom-start", initialFocusRef: showSearch ? searchRef : firstOptionRef, isLazy: true, children: [(0, jsx_runtime_1.jsx)(
|
|
105
|
+
}, placement: "bottom-start", initialFocusRef: showSearch ? searchRef : firstOptionRef, isLazy: true, children: [avatarOnly ? ((0, jsx_runtime_1.jsx)(ToolTip_1.default, { label: (_b = selected === null || selected === void 0 ? void 0 : selected.name) !== null && _b !== void 0 ? _b : placeholder, placement: "bottom", isDisabled: isOpen, children: (0, jsx_runtime_1.jsx)(react_2.Box, { as: "span", display: "inline-flex", flexShrink: 0, children: (0, jsx_runtime_1.jsx)(react_2.PopoverTrigger, { children: trigger }) }) })) : ((0, jsx_runtime_1.jsx)(react_2.PopoverTrigger, { children: trigger })), (0, jsx_runtime_1.jsx)(react_2.PopoverContent, { minW: menuMinWidth, maxW: "calc(100vw - 32px)", w: "auto",
|
|
94
106
|
// NOTE: Chakra's --popper-bg is hardcoded white via dead _dark — without an explicit bg the panel stayed white.
|
|
95
107
|
bg: theme.colors.surfaceRaised, borderRadius: "xl", overflow: "hidden", boxShadow: `0 10px 30px ${theme.colors.boxShadow.default}`, _focus: { outline: "none", boxShadow: `0 10px 30px ${theme.colors.boxShadow.default}` }, children: (0, jsx_runtime_1.jsxs)(react_2.PopoverBody, { p: 0, children: [showSearch && ((0, jsx_runtime_1.jsx)(react_2.Box, { p: 2, borderBottom: "1px solid", borderColor: theme.colors.gray[100], children: (0, jsx_runtime_1.jsxs)(react_2.InputGroup, { size: "sm", children: [(0, jsx_runtime_1.jsx)(react_2.InputLeftElement, { pointerEvents: "none", children: (0, jsx_runtime_1.jsx)(lucide_react_1.Search, { size: 15, color: theme.colors.textMuted }) }), (0, jsx_runtime_1.jsx)(react_2.Input, { ref: searchRef, placeholder: "Search organizations", value: query, onChange: (e) => setQuery(e.target.value), onKeyDown: (e) => {
|
|
96
108
|
if (e.key === "ArrowDown" && filtered.length > 0) {
|
|
@@ -11,6 +11,8 @@ export interface OrgOption {
|
|
|
11
11
|
}
|
|
12
12
|
/** Trigger size; looked up in a fixed sizeMap for height, avatar and font sizing. */
|
|
13
13
|
export type OrgSwitcherSize = "sm" | "md" | "lg";
|
|
14
|
+
/** Trigger layout: avatar + name + chevron ("full"), avatar + chevron only ("avatar"), or "auto" to switch at the `md` breakpoint. */
|
|
15
|
+
export type OrgSwitcherDisplay = "full" | "avatar" | "auto";
|
|
14
16
|
/** Session-scoped org switcher (trigger+popover) — not an admin screen; see OrganizationDetails for create/rename/delete/default. Closed prop list, no ...rest/ref on the trigger button. */
|
|
15
17
|
export interface OrgSwitcherProps {
|
|
16
18
|
/** Organizations to choose from. */
|
|
@@ -39,6 +41,8 @@ export interface OrgSwitcherProps {
|
|
|
39
41
|
ariaLabel?: string;
|
|
40
42
|
/** Show the role subtitle inside the dropdown rows. Default true. */
|
|
41
43
|
showRole?: boolean;
|
|
44
|
+
/** "avatar" shows only the org avatar and a small chevron, name moves to the accessible name and a tooltip; "auto" is avatar below `md`, full from `md` up. Default "full". */
|
|
45
|
+
display?: OrgSwitcherDisplay;
|
|
42
46
|
}
|
|
43
47
|
export declare const AVATAR_COLORS: readonly string[];
|
|
44
48
|
/** Chart hues are tuned to sit apart from each other, not to carry a label. */
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Box, Flex } from "@chakra-ui/react";
|
|
3
|
+
import { useRef } from "react";
|
|
4
|
+
import { focusVisibleStyles } from "../../Theme/chakra/focusRing.styles.js";
|
|
5
|
+
import { transitionFor } from "../../Theme/tokens/primitives/motion.js";
|
|
6
|
+
import { useCustomTheme } from "../../Theme/useCustomTheme.js";
|
|
7
|
+
export const tabId = (base, id) => `${base}-tab-${id}`;
|
|
8
|
+
export const panelId = (base) => `${base}-panel`;
|
|
9
|
+
export function LauncherTabs({ tabs, selected, onSelect, idBase, label, onLeaveUp, onLeaveDown, }) {
|
|
10
|
+
const { colors } = useCustomTheme();
|
|
11
|
+
const refs = useRef(new Map());
|
|
12
|
+
const ring = focusVisibleStyles(colors);
|
|
13
|
+
const choose = (index) => {
|
|
14
|
+
var _a;
|
|
15
|
+
const next = tabs[(index + tabs.length) % tabs.length];
|
|
16
|
+
onSelect(next.id);
|
|
17
|
+
(_a = refs.current.get(next.id)) === null || _a === void 0 ? void 0 : _a.focus();
|
|
18
|
+
};
|
|
19
|
+
const onKeyDown = (event) => {
|
|
20
|
+
if (event.altKey || event.ctrlKey || event.metaKey)
|
|
21
|
+
return;
|
|
22
|
+
const current = tabs.findIndex((tab) => tab.id === selected);
|
|
23
|
+
const handlers = {
|
|
24
|
+
ArrowRight: () => choose(current + 1),
|
|
25
|
+
ArrowLeft: () => choose(current - 1),
|
|
26
|
+
Home: () => choose(0),
|
|
27
|
+
End: () => choose(tabs.length - 1),
|
|
28
|
+
ArrowUp: onLeaveUp,
|
|
29
|
+
ArrowDown: onLeaveDown,
|
|
30
|
+
};
|
|
31
|
+
const handle = handlers[event.key];
|
|
32
|
+
if (!handle)
|
|
33
|
+
return;
|
|
34
|
+
event.preventDefault();
|
|
35
|
+
event.stopPropagation();
|
|
36
|
+
handle();
|
|
37
|
+
};
|
|
38
|
+
return (_jsx(Flex, { role: "tablist", "aria-label": label, "aria-orientation": "horizontal", flexShrink: 0, px: { base: "10px", md: "16px" }, gap: { base: 0, md: "4px" }, borderBottomWidth: "1px", borderColor: colors.boxborder[200], bg: colors.surfaceRaised, onKeyDown: onKeyDown, children: tabs.map((tab) => {
|
|
39
|
+
const isSelected = tab.id === selected;
|
|
40
|
+
return (_jsx(Box, { as: "button", type: "button", role: "tab", id: tabId(idBase, tab.id), ref: (node) => {
|
|
41
|
+
if (node)
|
|
42
|
+
refs.current.set(tab.id, node);
|
|
43
|
+
else
|
|
44
|
+
refs.current.delete(tab.id);
|
|
45
|
+
}, "aria-selected": isSelected, "aria-controls": isSelected ? panelId(idBase) : undefined, tabIndex: isSelected ? 0 : -1, onClick: () => onSelect(tab.id), position: "relative", flex: { base: 1, md: "none" }, minW: { md: "112px" }, h: "46px", px: { base: "6px", md: "14px" }, whiteSpace: "nowrap", fontSize: "14px", fontWeight: isSelected ? 600 : 500, color: isSelected ? colors.accentText : colors.textMuted, transition: transitionFor(["color"]), _hover: {
|
|
46
|
+
color: isSelected ? colors.accentText : colors.text[900],
|
|
47
|
+
}, _after: {
|
|
48
|
+
content: '""',
|
|
49
|
+
position: "absolute",
|
|
50
|
+
left: "10px",
|
|
51
|
+
right: "10px",
|
|
52
|
+
bottom: "-1px",
|
|
53
|
+
h: "2px",
|
|
54
|
+
borderRadius: "2px 2px 0 0",
|
|
55
|
+
bg: isSelected ? colors.primary[500] : "transparent",
|
|
56
|
+
}, sx: { ...ring, borderRadius: "8px" }, children: tab.label }, tab.id));
|
|
57
|
+
}) }));
|
|
58
|
+
}
|