pixelize-design-library 2.4.2-beta.62 → 2.4.2-beta.64
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 +122 -2
- package/COMPONENT-GOTCHAS.md +51 -9
- package/DESIGN-GUIDE.md +13 -5
- package/dist/Components/Button/Button.styles.js +58 -23
- package/dist/Components/Card/CardProps.d.ts +2 -2
- package/dist/Components/ConfirmDialog/ConfirmDialog.js +2 -1
- package/dist/Components/CustomModulesTable/CustomModulesTable.js +6 -4
- package/dist/Components/CustomModulesTable/EditModuleModal.js +2 -1
- package/dist/Components/DatePicker/RangeDatePicker.js +2 -1
- package/dist/Components/DatePicker/SingleDatePicker.js +2 -1
- package/dist/Components/DatePicker/TimeOnlyPicker.js +2 -1
- package/dist/Components/DatePicker/dayStates.js +2 -1
- package/dist/Components/Drawer/Drawer.js +2 -1
- package/dist/Components/Dropdown/DropDown.js +4 -10
- package/dist/Components/FilePreview/FilePreview.js +2 -1
- package/dist/Components/FileUpload/FileUpload.js +9 -2
- package/dist/Components/FileUploader/FileUploader.js +4 -0
- package/dist/Components/FileUploader/FileUploaderProps.d.ts +1 -1
- package/dist/Components/FilterSidebar/FilterSidebar.js +7 -4
- package/dist/Components/Input/TextInput.styles.js +10 -6
- package/dist/Components/KanbanBoard/AccountCard.js +4 -2
- package/dist/Components/KanbanBoard/KanbanBoard.js +6 -5
- package/dist/Components/NavigationBar/NavigationBar.js +5 -3
- package/dist/Components/Notification/Notification.js +4 -3
- package/dist/Components/NotificationBell/NotificationPanel.js +4 -3
- package/dist/Components/OrgSwitcher/OrgSwitcher.js +2 -4
- package/dist/Components/OrganizationDetails/CreateOrgModal.js +2 -1
- package/dist/Components/OrganizationDetails/OrganizationDetails.js +5 -3
- package/dist/Components/ProfilePhotoViewer/ProfilePhotoViewer.js +12 -7
- package/dist/Components/ScrollToTop/ScrollToTop.js +4 -3
- package/dist/Components/SearchSelect/SearchSelect.js +44 -35
- package/dist/Components/SearchSelect/searchSelectNav.d.ts +13 -0
- package/dist/Components/SearchSelect/searchSelectNav.js +40 -0
- package/dist/Components/Select/SelectPopup.js +3 -4
- package/dist/Components/Select/optionRowInk.d.ts +12 -0
- package/dist/Components/Select/optionRowInk.js +10 -1
- package/dist/Components/SelectSearch/SelectSearch.js +3 -11
- package/dist/Components/SettingRow/SettingRow.js +2 -1
- package/dist/Components/SettingRow/SettingsSection.js +2 -1
- package/dist/Components/SideBar/SecondaryBar.js +4 -3
- package/dist/Components/SideBar/SideBar.js +16 -13
- package/dist/Components/SideBar/SideBarProps.d.ts +1 -1
- package/dist/Components/SideBar/components/MenuItemBox.js +7 -4
- package/dist/Components/SideBar/components/MenuPopoverContent.js +2 -1
- package/dist/Components/SideBar/components/OtherApps.js +2 -1
- package/dist/Components/SideBar/components/PinnedSection.js +7 -4
- package/dist/Components/SideBar/sidebarMotion.d.ts +2 -0
- package/dist/Components/SideBar/sidebarMotion.js +6 -0
- package/dist/Components/SignInActivityTable/SignInActivityTable.js +6 -4
- package/dist/Components/StageProgress/StageItem.js +5 -2
- package/dist/Components/StageProgress/StepperStage.js +2 -2
- package/dist/Components/StatCard/StatCard.js +2 -1
- package/dist/Components/Table/Table.js +9 -4
- package/dist/Components/Table/TableProps.d.ts +1 -1
- package/dist/Components/Table/components/TableActions.js +3 -2
- package/dist/Components/Table/components/TableBody.js +9 -1
- package/dist/Components/Table/components/TableHeader.js +7 -2
- package/dist/Components/Table/components/TableLoading.d.ts +4 -1
- package/dist/Components/Table/components/TableLoading.js +6 -5
- package/dist/Components/Table/filters/CompactSelect.js +3 -11
- package/dist/Components/Table/settings/TableSettings.js +7 -2
- package/dist/Components/Table/variants/TableVariantContext.d.ts +1 -1
- package/dist/Components/Table/variants/TableVariantContext.js +3 -3
- package/dist/Components/Table/variants/classic.js +3 -2
- package/dist/Components/Timeline/Timeline.js +11 -4
- package/dist/Components/Toaster/Toaster.js +19 -8
- package/dist/Components/Toggle/TableToggle.js +5 -2
- package/dist/Components/UserDetails/AddUserModal.js +2 -1
- package/dist/Components/UserDetails/ChangeRoleModal.js +2 -1
- package/dist/Components/UserDetails/UserDetails.js +3 -1
- package/dist/Components/WorkspaceWindow/WorkspaceTrayPreview.js +4 -0
- package/dist/Components/WorkspaceWindow/WorkspaceWindow.d.ts +2 -2
- package/dist/Components/WorkspaceWindow/WorkspaceWindow.js +25 -18
- package/dist/Components/WorkspaceWindow/WorkspaceWindowProps.d.ts +38 -2
- package/dist/Theme/chakra/Card.styles.d.ts +7 -1
- package/dist/Theme/chakra/Card.styles.js +4 -1
- package/dist/Theme/chakra/Menu.styles.d.ts +11 -5
- package/dist/Theme/chakra/Menu.styles.js +10 -0
- package/dist/Theme/chakra/Popover.styles.d.ts +2 -11
- package/dist/Theme/chakra/Popover.styles.js +2 -0
- package/dist/Theme/chakra/common.web.d.ts +4 -0
- package/dist/Theme/chakra/componentStyles.d.ts +19 -3
- package/dist/Theme/chakra/componentStyles.js +12 -8
- package/dist/Theme/chakra/motion.d.ts +1 -0
- package/dist/Theme/chakra/motion.js +2 -1
- package/dist/Theme/chakra/overlay.styles.d.ts +5 -0
- package/dist/Theme/chakra/overlay.styles.js +4 -1
- package/dist/Theme/themeProps.d.ts +4 -0
- package/dist/Theme/tokens/brands/index.d.ts +1 -0
- package/dist/Theme/tokens/brands/index.js +17 -1
- package/dist/Theme/tokens/brands/radiant/palette.light.js +15 -0
- package/dist/Theme/tokens/brands/rosewood/palette.light.js +10 -10
- package/dist/Theme/tokens/brands/zinc/palette.dark.d.ts +7 -29
- package/dist/Theme/tokens/brands/zinc/palette.dark.js +3 -35
- package/dist/Theme/tokens/builders/accentText.d.ts +2 -0
- package/dist/Theme/tokens/builders/accentText.js +7 -1
- package/dist/Theme/tokens/builders/buildDarkPalette.d.ts +6 -1
- package/dist/Theme/tokens/builders/buildDarkPalette.js +37 -8
- package/dist/Theme/tokens/builders/filledSurface.d.ts +5 -1
- package/dist/Theme/tokens/builders/filledSurface.js +17 -4
- package/dist/Theme/tokens/builders/mutedText.d.ts +1 -1
- package/dist/Theme/tokens/builders/mutedText.js +13 -3
- package/dist/Theme/tokens/builders/planeStep.d.ts +5 -0
- package/dist/Theme/tokens/builders/planeStep.js +21 -0
- package/dist/Theme/tokens/builders/planes.d.ts +4 -0
- package/dist/Theme/tokens/builders/planes.js +33 -0
- package/dist/Theme/tokens/builders/skeletonShimmer.d.ts +9 -0
- package/dist/Theme/tokens/builders/skeletonShimmer.js +25 -0
- package/dist/Theme/tokens/builders/surfaceRaised.d.ts +3 -1
- package/dist/Theme/tokens/builders/surfaceRaised.js +18 -8
- package/dist/Theme/tokens/builders/surfaceRungs.js +3 -1
- package/dist/Theme/tokens/primitives/index.d.ts +2 -2
- package/dist/Theme/tokens/primitives/index.js +4 -1
- package/dist/Theme/tokens/primitives/motion.d.ts +1 -0
- package/dist/Theme/tokens/primitives/motion.js +2 -1
- package/dist/Theme/tokens/primitives/shadows.d.ts +16 -0
- package/dist/Theme/tokens/primitives/shadows.js +56 -6
- package/dist/Theme/tokens/primitives/typography.js +1 -1
- package/dist/Utils/table.js +2 -2
- package/dist/esm/Components/Button/Button.styles.js +62 -27
- package/dist/esm/Components/ConfirmDialog/ConfirmDialog.js +2 -1
- package/dist/esm/Components/CustomModulesTable/CustomModulesTable.js +6 -4
- package/dist/esm/Components/CustomModulesTable/EditModuleModal.js +2 -1
- package/dist/esm/Components/DatePicker/RangeDatePicker.js +2 -1
- package/dist/esm/Components/DatePicker/SingleDatePicker.js +2 -1
- package/dist/esm/Components/DatePicker/TimeOnlyPicker.js +2 -1
- package/dist/esm/Components/DatePicker/dayStates.js +2 -1
- package/dist/esm/Components/Drawer/Drawer.js +2 -1
- package/dist/esm/Components/Dropdown/DropDown.js +4 -10
- package/dist/esm/Components/FilePreview/FilePreview.js +3 -2
- package/dist/esm/Components/FileUpload/FileUpload.js +10 -3
- package/dist/esm/Components/FileUploader/FileUploader.js +4 -0
- package/dist/esm/Components/FilterSidebar/FilterSidebar.js +7 -4
- package/dist/esm/Components/Input/TextInput.styles.js +10 -6
- package/dist/esm/Components/KanbanBoard/AccountCard.js +4 -2
- package/dist/esm/Components/KanbanBoard/KanbanBoard.js +6 -5
- package/dist/esm/Components/NavigationBar/NavigationBar.js +5 -3
- package/dist/esm/Components/Notification/Notification.js +4 -3
- package/dist/esm/Components/NotificationBell/NotificationPanel.js +4 -3
- package/dist/esm/Components/OrgSwitcher/OrgSwitcher.js +2 -4
- package/dist/esm/Components/OrganizationDetails/CreateOrgModal.js +2 -1
- package/dist/esm/Components/OrganizationDetails/OrganizationDetails.js +5 -3
- package/dist/esm/Components/ProfilePhotoViewer/ProfilePhotoViewer.js +13 -8
- package/dist/esm/Components/ScrollToTop/ScrollToTop.js +5 -4
- package/dist/esm/Components/SearchSelect/SearchSelect.js +46 -37
- package/dist/esm/Components/SearchSelect/searchSelectNav.js +32 -0
- package/dist/esm/Components/Select/SelectPopup.js +4 -5
- package/dist/esm/Components/Select/optionRowInk.js +7 -0
- package/dist/esm/Components/SelectSearch/SelectSearch.js +4 -12
- package/dist/esm/Components/SettingRow/SettingRow.js +2 -1
- package/dist/esm/Components/SettingRow/SettingsSection.js +2 -1
- package/dist/esm/Components/SideBar/SecondaryBar.js +4 -3
- package/dist/esm/Components/SideBar/SideBar.js +17 -14
- package/dist/esm/Components/SideBar/components/MenuItemBox.js +7 -4
- package/dist/esm/Components/SideBar/components/MenuPopoverContent.js +2 -1
- package/dist/esm/Components/SideBar/components/OtherApps.js +2 -1
- package/dist/esm/Components/SideBar/components/PinnedSection.js +7 -4
- package/dist/esm/Components/SideBar/sidebarMotion.js +3 -0
- package/dist/esm/Components/SignInActivityTable/SignInActivityTable.js +6 -4
- package/dist/esm/Components/StageProgress/StageItem.js +5 -2
- package/dist/esm/Components/StageProgress/StepperStage.js +2 -2
- package/dist/esm/Components/StatCard/StatCard.js +2 -1
- package/dist/esm/Components/Table/Table.js +12 -7
- package/dist/esm/Components/Table/components/TableActions.js +3 -2
- package/dist/esm/Components/Table/components/TableBody.js +10 -2
- package/dist/esm/Components/Table/components/TableHeader.js +9 -4
- package/dist/esm/Components/Table/components/TableLoading.js +5 -4
- package/dist/esm/Components/Table/filters/CompactSelect.js +4 -12
- package/dist/esm/Components/Table/settings/TableSettings.js +8 -3
- package/dist/esm/Components/Table/variants/TableVariantContext.js +3 -3
- package/dist/esm/Components/Table/variants/classic.js +3 -2
- package/dist/esm/Components/Timeline/Timeline.js +11 -4
- package/dist/esm/Components/Toaster/Toaster.js +20 -9
- package/dist/esm/Components/Toggle/TableToggle.js +5 -2
- package/dist/esm/Components/UserDetails/AddUserModal.js +2 -1
- package/dist/esm/Components/UserDetails/ChangeRoleModal.js +2 -1
- package/dist/esm/Components/UserDetails/UserDetails.js +3 -1
- package/dist/esm/Components/WorkspaceWindow/WorkspaceTrayPreview.js +4 -0
- package/dist/esm/Components/WorkspaceWindow/WorkspaceWindow.js +26 -19
- package/dist/esm/Theme/chakra/Card.styles.js +4 -1
- package/dist/esm/Theme/chakra/Menu.styles.js +10 -0
- package/dist/esm/Theme/chakra/Popover.styles.js +2 -0
- package/dist/esm/Theme/chakra/componentStyles.js +12 -8
- package/dist/esm/Theme/chakra/motion.js +1 -0
- package/dist/esm/Theme/chakra/overlay.styles.js +3 -0
- package/dist/esm/Theme/tokens/brands/index.js +16 -0
- package/dist/esm/Theme/tokens/brands/radiant/palette.light.js +15 -0
- package/dist/esm/Theme/tokens/brands/rosewood/palette.light.js +10 -10
- package/dist/esm/Theme/tokens/brands/zinc/palette.dark.js +3 -35
- package/dist/esm/Theme/tokens/builders/accentText.js +5 -0
- package/dist/esm/Theme/tokens/builders/buildDarkPalette.js +38 -9
- package/dist/esm/Theme/tokens/builders/filledSurface.js +18 -5
- package/dist/esm/Theme/tokens/builders/mutedText.js +12 -2
- package/dist/esm/Theme/tokens/builders/planeStep.js +14 -0
- package/dist/esm/Theme/tokens/builders/planes.js +28 -0
- package/dist/esm/Theme/tokens/builders/skeletonShimmer.js +21 -0
- package/dist/esm/Theme/tokens/builders/surfaceRaised.js +16 -7
- package/dist/esm/Theme/tokens/builders/surfaceRungs.js +3 -1
- package/dist/esm/Theme/tokens/primitives/index.js +1 -1
- package/dist/esm/Theme/tokens/primitives/motion.js +1 -0
- package/dist/esm/Theme/tokens/primitives/shadows.js +54 -5
- package/dist/esm/Theme/tokens/primitives/typography.js +1 -1
- package/dist/esm/Utils/table.js +2 -2
- package/dist/esm/index.js +4 -3
- package/dist/index.d.ts +5 -4
- package/dist/index.js +15 -6
- package/package.json +1 -1
|
@@ -5,13 +5,17 @@ import { motion } from "framer-motion";
|
|
|
5
5
|
import ManageColumns from "./ManageColumns.js";
|
|
6
6
|
import Button from "../../Button/Button.js";
|
|
7
7
|
import { useCustomTheme } from "../../../Theme/useCustomTheme.js";
|
|
8
|
+
import { raisedRule } from "../../../Theme/tokens/builders/surfaceRaised.js";
|
|
8
9
|
import { scrollbarStyles } from "../../../Theme/tokens/builders/scrollbar.js";
|
|
9
10
|
import { columnLabelText } from "../columnLabel.js";
|
|
10
11
|
import { Settings, Check } from "lucide-react";
|
|
11
12
|
import ToolTip from "../../ToolTip/ToolTip.js";
|
|
12
13
|
import { listRowBackgrounds } from "../../../Theme/tokens/builders/rowStates.js";
|
|
13
|
-
import { transitionFor } from "../../../Theme/tokens/primitives/motion.js";
|
|
14
|
+
import { motionTransition, transitionFor } from "../../../Theme/tokens/primitives/motion.js";
|
|
15
|
+
import { usePrefersReducedMotion } from "../../../Theme/chakra/motion.js";
|
|
14
16
|
const MotionModalContent = motion(ModalContent);
|
|
17
|
+
const SHEET_ENTER = motionTransition("enter", "out");
|
|
18
|
+
const SHEET_EXIT = motionTransition("exit", "in");
|
|
15
19
|
const DENSITY_OPTIONS = [
|
|
16
20
|
{ value: "compact", label: "Compact", desc: "Tight rows — fit more data on screen" },
|
|
17
21
|
{ value: "normal", label: "Normal", desc: "Balanced default spacing" },
|
|
@@ -19,6 +23,7 @@ const DENSITY_OPTIONS = [
|
|
|
19
23
|
];
|
|
20
24
|
const TableSettings = ({ columns, onSave, density = "normal", onDensityChange, groupBy, }) => {
|
|
21
25
|
const theme = useCustomTheme();
|
|
26
|
+
const sheetOffset = usePrefersReducedMotion() ? 0 : "-100%";
|
|
22
27
|
const rowBackgrounds = useMemo(() => listRowBackgrounds(theme.colors), [theme.colors]);
|
|
23
28
|
const childInputMethodsRef = useRef({});
|
|
24
29
|
const [settingsOpen, setSettingsOpen] = useState(false);
|
|
@@ -52,7 +57,7 @@ const TableSettings = ({ columns, onSave, density = "normal", onDensityChange, g
|
|
|
52
57
|
return (_jsxs(Box, { children: [_jsx(ToolTip, { label: "Table Settings", placement: "top", children: _jsx(IconButton, { "aria-label": "Table settings", icon: _jsx(Settings, { size: "1.25rem" }), onClick: handleOpen, variant: "unstyled", minW: "auto", h: "auto", display: "flex", justifyContent: "flex-end", cursor: "pointer", transition: transitionFor(["color", "transform"], "base"), color: theme.colors.text[500], _hover: {
|
|
53
58
|
transform: "scale(1.1)",
|
|
54
59
|
color: theme.colors.accentText
|
|
55
|
-
} }) }), _jsxs(Modal, { isOpen: settingsOpen, onClose: () => setSettingsOpen(false), size: { base: "full", md: "md" }, children: [_jsx(ModalOverlay, {}), _jsxs(MotionModalContent, { mt: "0", top: "0", left: { base: 0, md: "auto" }, right: { base: 0, md: "auto" }, position: "absolute", borderTopRadius: "none", initial: { y:
|
|
60
|
+
} }) }), _jsxs(Modal, { isOpen: settingsOpen, onClose: () => setSettingsOpen(false), size: { base: "full", md: "md" }, children: [_jsx(ModalOverlay, {}), _jsxs(MotionModalContent, { mt: "0", top: "0", left: { base: 0, md: "auto" }, right: { base: 0, md: "auto" }, position: "absolute", borderTopRadius: "none", initial: { y: sheetOffset, opacity: 0 }, animate: { y: 0, opacity: 1 }, exit: { y: sheetOffset, opacity: 0, transition: SHEET_EXIT }, transition: SHEET_ENTER, padding: "0", minW: { base: "auto", md: "620px" }, minH: { base: "auto", md: "520px" }, maxH: "90vh", display: "flex", flexDirection: "column", bg: theme.colors.surfaceRaised, overflow: "hidden", children: [_jsx(ModalCloseButton, { top: 3, right: 3, zIndex: 2 }), _jsxs(Tabs, { index: selectedIndex, onChange: setSelectedIndex, variant: "unstyled", display: "flex", flexDirection: "column", flex: "1", minH: 0, children: [_jsxs(Box, { pt: 4, px: 4, children: [_jsx(Text, { fontWeight: 600, fontSize: "md", mb: 3, children: "Table Settings" }), _jsxs(TabList, { gap: 0, borderBottom: "1px solid", borderColor: raisedRule(theme.colors), children: [_jsx(Tab, { ...tabStyle, children: "Density" }), _jsx(Tab, { ...tabStyle, children: "Manage Columns" }), _jsx(Tab, { ...tabStyle, children: "Group" })] })] }), _jsx(ModalBody, { px: 4, py: 3, flex: "1", overflowY: "auto", sx: scrollbarStyles(theme.colors), children: _jsxs(TabPanels, { children: [_jsx(TabPanel, { px: 0, py: 1, children: _jsx(Flex, { direction: "column", gap: 2, children: DENSITY_OPTIONS.map((opt) => {
|
|
56
61
|
const selected = density === opt.value;
|
|
57
62
|
return (_jsxs(Flex, { as: "button", type: "button", align: "center", gap: 3, px: 3, py: 2.5, borderRadius: "lg", border: "1px solid", borderColor: selected ? theme.colors.accentText : theme.colors.boxborder[200], bg: selected ? rowBackgrounds.selected : theme.colors.transparent, transition: transitionFor(["background-color", "border-color"]), _hover: { borderColor: theme.colors.accentText }, onClick: () => onDensityChange === null || onDensityChange === void 0 ? void 0 : onDensityChange(opt.value), children: [_jsx(Box, { boxSize: "1.1rem", borderRadius: "full", border: "2px solid", borderColor: selected ? theme.colors.accentText : theme.colors.boxborder[500], display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0, children: selected && _jsx(Check, { size: 11, color: theme.colors.accentText, strokeWidth: 3 }) }), _jsxs(Box, { textAlign: "left", children: [_jsx(Text, { fontSize: "13px", fontWeight: 600, color: theme.colors.text[700], children: opt.label }), _jsx(Text, { fontSize: "11px", color: theme.colors.textMuted, children: opt.desc })] })] }, opt.value));
|
|
58
63
|
}) }) }), _jsx(TabPanel, { px: 0, py: 0, children: _jsx(Box, { sx: {
|
|
@@ -73,6 +78,6 @@ const TableSettings = ({ columns, onSave, density = "normal", onDensityChange, g
|
|
|
73
78
|
var _a;
|
|
74
79
|
const selected = selectedGroup === opt.id;
|
|
75
80
|
return (_jsxs(Flex, { as: "button", type: "button", align: "center", gap: 3, px: 3, py: 2.5, borderRadius: "lg", border: "1px solid", borderColor: selected ? theme.colors.accentText : theme.colors.boxborder[200], bg: selected ? rowBackgrounds.selected : theme.colors.transparent, transition: transitionFor(["background-color", "border-color"]), _hover: { borderColor: theme.colors.accentText }, onClick: () => setSelectedGroup(opt.id), children: [_jsx(Box, { boxSize: "1.1rem", borderRadius: "full", border: "2px solid", borderColor: selected ? theme.colors.accentText : theme.colors.boxborder[500], display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0, children: selected && _jsx(Check, { size: 11, color: theme.colors.accentText, strokeWidth: 3 }) }), _jsx(Text, { fontSize: "13px", fontWeight: 600, color: theme.colors.text[700], textAlign: "left", children: opt.label })] }, String((_a = opt.id) !== null && _a !== void 0 ? _a : "__none__")));
|
|
76
|
-
}) })] })] }) })] }), _jsxs(ModalFooter, { gap: "0.5rem", borderTop: "1px solid", borderColor: theme.colors
|
|
81
|
+
}) })] })] }) })] }), _jsxs(ModalFooter, { gap: "0.5rem", borderTop: "1px solid", borderColor: raisedRule(theme.colors), pt: 3, pb: 3, px: 4, children: [_jsx(Button, { label: "Close", size: "sm", onClick: () => setSettingsOpen(false), variant: "outline", colorScheme: "red" }), _jsx(Button, { label: "Save", size: "sm", onClick: handleSave })] })] })] })] }));
|
|
77
82
|
};
|
|
78
83
|
export default TableSettings;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { createContext, useContext, useMemo } from "react";
|
|
2
2
|
import { useCustomTheme } from "../../../Theme/useCustomTheme.js";
|
|
3
3
|
import { isDarkCanvas } from "../../../Theme/tokens/builders/accentText.js";
|
|
4
|
-
import {
|
|
4
|
+
import { studioPreset } from "./studio.js";
|
|
5
5
|
const TableVariantContext = createContext(null);
|
|
6
6
|
export const TableVariantProvider = TableVariantContext.Provider;
|
|
7
|
-
/** No provider means the
|
|
7
|
+
/** No provider means the default variant — studio, the same preset `Table` falls back to. */
|
|
8
8
|
export function useTableVariant() {
|
|
9
9
|
const provided = useContext(TableVariantContext);
|
|
10
10
|
const theme = useCustomTheme();
|
|
11
11
|
const isDark = isDarkCanvas(theme.colors.backgroundColor.main);
|
|
12
|
-
return useMemo(() => provided !== null && provided !== void 0 ? provided :
|
|
12
|
+
return useMemo(() => provided !== null && provided !== void 0 ? provided : studioPreset(theme.colors, isDark), [provided, theme.colors, isDark]);
|
|
13
13
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { accentTextOnCanvas } from "../../../Theme/tokens/builders/accentText.js";
|
|
2
|
+
import { cardRule } from "../../../Theme/tokens/builders/planeStep.js";
|
|
2
3
|
import { getTableRowHoverStyle } from "../components/tableRowHoverStyle.js";
|
|
3
4
|
import { stripeFill } from "./stripe.js";
|
|
4
5
|
/**
|
|
@@ -16,14 +17,14 @@ export const classicPreset = (colors, isDark) => {
|
|
|
16
17
|
textTransform: "capitalize",
|
|
17
18
|
letterSpacing: "normal",
|
|
18
19
|
height: "45px",
|
|
19
|
-
ruleColor: colors
|
|
20
|
+
ruleColor: cardRule(colors),
|
|
20
21
|
showColumnRule: true,
|
|
21
22
|
actions: "always",
|
|
22
23
|
},
|
|
23
24
|
row: {
|
|
24
25
|
hoverBg: getTableRowHoverStyle(colors, isDark).backgroundColor,
|
|
25
26
|
hoverScope: "cell",
|
|
26
|
-
ruleColor: colors
|
|
27
|
+
ruleColor: cardRule(colors),
|
|
27
28
|
frozenRuleColor: colors.boxborder[300],
|
|
28
29
|
selectedBg: colors.primary.opacity[16],
|
|
29
30
|
selectedBarColor: colors.primary[500],
|
|
@@ -4,6 +4,7 @@ import { ArrowRight, FileText, IndianRupee, Paperclip, Pencil, PencilLine, Plus,
|
|
|
4
4
|
import React from "react";
|
|
5
5
|
import { useCustomTheme } from "../../Theme/useCustomTheme.js";
|
|
6
6
|
import { accentTextOnCanvas } from "../../Theme/tokens/builders/accentText.js";
|
|
7
|
+
import { bandOn } from "../../Theme/tokens/builders/planeStep.js";
|
|
7
8
|
import { AA_NON_TEXT, liftToContrast } from "../../Theme/tokens/builders/outlineRung.js";
|
|
8
9
|
import { transitionFor } from "../../Theme/tokens/primitives/motion.js";
|
|
9
10
|
import { BORDER_WIDTHS } from "../../Theme/tokens/primitives/borderWidths.js";
|
|
@@ -152,12 +153,14 @@ const NoteItem = React.memo(function NoteItem({ note, event, index, colors, acti
|
|
|
152
153
|
var _a, _b;
|
|
153
154
|
const isEditing = activeEditNoteId === note.log_note_id;
|
|
154
155
|
const isDeleting = deletingNoteId != null && deletingNoteId === note.log_note_id;
|
|
156
|
+
const noteChip = bandOn(colors.primary[50], colors.gray[50]);
|
|
157
|
+
const noteChipInk = accentTextOnCanvas(colors.primary, noteChip);
|
|
155
158
|
if (isEditing) {
|
|
156
159
|
return (_jsx(Box, { children: _jsx(NoteTextArea, { isEditable: true, value: (_a = note.note) !== null && _a !== void 0 ? _a : "", title: (_b = note.title) !== null && _b !== void 0 ? _b : "", saveButtonLoading: editNoteLoading, handleSubmit: (n, t, f) => onEditNote === null || onEditNote === void 0 ? void 0 : onEditNote(note.log_note_id, n, t, f, event, index), handleCancel: () => setActiveEditNoteId(null) }) }));
|
|
157
160
|
}
|
|
158
161
|
return (_jsxs(Box, { position: "relative", zIndex: 1, bg: colors.gray[50], border: `${BORDER_WIDTHS.hairline} solid ${colors.boxborder[200]}`, borderRadius: "lg", px: 2.5, py: 2, opacity: isDeleting ? 0.6 : 1, _hover: { ".timeline-note-actions": { opacity: 1 } }, _focusWithin: { ".timeline-note-actions": { opacity: 1 } }, children: [_jsxs(Flex, { align: "center", gap: 1.5, mb: note.note ? 1 : 0, children: [_jsx(Box, { as: "span", color: accentTextOnCanvas(colors.primary, colors.gray[50]), display: "inline-flex", children: _jsx(StickyNote, { size: 12 }) }), note.title && (_jsx(Text, { fontSize: fontSizes["xs-minus"], fontWeight: 700, color: colors.text[800], noOfLines: 1, children: note.title })), (onEditNote || onDeleteNote) && (_jsx(Flex, { className: "timeline-note-actions", align: "center", gap: 0.5, ml: "auto", flexShrink: 0, opacity: isDeleting ? 1 : 0, transition: REVEAL_TRANSITION, sx: reducedMotionSx(), children: isDeleting ? (_jsx(Spinner, { size: "xs", color: colors.textMuted })) : (_jsxs(_Fragment, { children: [onEditNote && (_jsx(Tooltip, { label: "Edit", placement: "top", hasArrow: true, children: _jsx(Box, { as: "button", type: "button", "aria-label": "Edit note", sx: focusVisibleStyles(colors), display: "inline-flex", alignItems: "center", justifyContent: "center", p: 1, borderRadius: "md", color: colors.textMuted, bg: "transparent", cursor: "pointer", _hover: {
|
|
159
|
-
bg:
|
|
160
|
-
color:
|
|
162
|
+
bg: noteChip,
|
|
163
|
+
color: noteChipInk,
|
|
161
164
|
}, onClick: (e) => {
|
|
162
165
|
e.stopPropagation();
|
|
163
166
|
setActiveEditNoteId(note.log_note_id);
|
|
@@ -167,7 +170,7 @@ const NoteItem = React.memo(function NoteItem({ note, event, index, colors, acti
|
|
|
167
170
|
}, onClick: (e) => {
|
|
168
171
|
e.stopPropagation();
|
|
169
172
|
onDeleteNote === null || onDeleteNote === void 0 ? void 0 : onDeleteNote(note.log_note_id, event, index);
|
|
170
|
-
}, children: _jsx(Trash2, { size: 12 }) }) }))] })) }))] }), note.note && (_jsx(Text, { fontSize: fontSizes["xs-minus"], color: colors.text[700], whiteSpace: "pre-wrap", children: note.note })), note.attachments && note.attachments.length > 0 && (_jsx(Flex, { wrap: "wrap", gap: 1.5, mt: 1.5, children: note.attachments.map((att, attIndex) => (_jsxs(Flex, { as: "a", href: att.url, target: "_blank", rel: "noopener noreferrer", onClick: (e) => e.stopPropagation(), align: "center", gap: 1, px: 1.5, py: 0.5, borderRadius: "full", bg:
|
|
173
|
+
}, children: _jsx(Trash2, { size: 12 }) }) }))] })) }))] }), note.note && (_jsx(Text, { fontSize: fontSizes["xs-minus"], color: colors.text[700], whiteSpace: "pre-wrap", children: note.note })), note.attachments && note.attachments.length > 0 && (_jsx(Flex, { wrap: "wrap", gap: 1.5, mt: 1.5, children: note.attachments.map((att, attIndex) => (_jsxs(Flex, { as: "a", href: att.url, target: "_blank", rel: "noopener noreferrer", onClick: (e) => e.stopPropagation(), align: "center", gap: 1, px: 1.5, py: 0.5, borderRadius: "full", bg: noteChip, color: noteChipInk, fontSize: MIN_TEXT, maxW: "100%", _hover: { bg: colors.primary[100] }, children: [_jsx(Paperclip, { size: 10 }), _jsx(Box, { as: "span", noOfLines: 1, maxW: "9rem", children: att.name || "attachment" })] }, attIndex))) })), (note.created_by || note.created_at) && (_jsxs(Text, { fontSize: MIN_TEXT, color: colors.textMuted, mt: 1, children: [note.created_by ? formatName(note.created_by) : "", note.created_by && note.created_at ? " · " : "", note.created_at ? formatTimestamp(note.created_at, "time") : ""] }))] }));
|
|
171
174
|
});
|
|
172
175
|
// The colored event card (shared by both the desktop "tree" and mobile rail).
|
|
173
176
|
// `accent` decides which edge carries the colored bar (pointing toward the spine).
|
|
@@ -177,6 +180,7 @@ const EventCard = React.memo(function EventCard({ event, index, accent, colors,
|
|
|
177
180
|
const changes = useMemo(() => parseChanges(event.changes), [event.changes]);
|
|
178
181
|
const clickable = typeof onEventClick === "function";
|
|
179
182
|
const actor = formatName(event.action_by);
|
|
183
|
+
const addNoteHover = bandOn(colors.primary[50], colors.background[50]);
|
|
180
184
|
return (_jsxs(Box, { _hover: { ".timeline-add-note": { opacity: 1 } }, _focusWithin: { ".timeline-add-note": { opacity: 1 } }, children: [_jsxs(Box, { position: "relative", zIndex: 1, bg: colors.background[50], border: `${BORDER_WIDTHS.hairline} solid ${colors.boxborder[200]}`, borderInlineStartWidth: accent === "left" ? "0.1875rem" : undefined, borderInlineEndWidth: accent === "right" ? "0.1875rem" : undefined, borderInlineStartColor: accent === "left" ? scale[400] : undefined, borderInlineEndColor: accent === "right" ? scale[400] : undefined, borderRadius: "xl", px: 3.5, py: 2.5, ...(clickable && {
|
|
181
185
|
transition: CARD_TRANSITION,
|
|
182
186
|
_hover: {
|
|
@@ -189,7 +193,10 @@ const EventCard = React.memo(function EventCard({ event, index, accent, colors,
|
|
|
189
193
|
e.stopPropagation();
|
|
190
194
|
setActiveNoteEventIndex(isActiveNote ? null : index);
|
|
191
195
|
}, position: "relative", zIndex: 1, opacity: isActiveNote ? 1 : 0, transition: REVEAL_TRANSITION, sx: { ...focusVisibleStyles(colors), ...reducedMotionSx() }, px: 2, py: 1, borderRadius: "md", fontSize: fontSizes.xs, fontWeight: 600, color: accentTextOnCanvas(colors.primary, colors.background[50]), bg: "transparent", cursor: "pointer", _hover: {
|
|
192
|
-
bg:
|
|
196
|
+
bg: addNoteHover,
|
|
197
|
+
color: addNoteHover === colors.primary[50]
|
|
198
|
+
? undefined
|
|
199
|
+
: accentTextOnCanvas(colors.primary, addNoteHover),
|
|
193
200
|
}, children: isActiveNote ? "Hide note" : "Add note" }))] }), event.notes && event.notes.length > 0 && (_jsx(Flex, { direction: "column", gap: 2, mt: 2, pt: 2, borderTop: `${BORDER_WIDTHS.hairline} solid ${colors.boxborder[200]}`, children: event.notes.map((note, noteIndex) => {
|
|
194
201
|
var _a;
|
|
195
202
|
return (_jsx(NoteItem, { note: note, event: event, index: index, colors: colors, activeEditNoteId: activeEditNoteId, setActiveEditNoteId: setActiveEditNoteId, editNoteLoading: editNoteLoading, deletingNoteId: deletingNoteId, onEditNote: onEditNote, onDeleteNote: onDeleteNote }, (_a = note.log_note_id) !== null && _a !== void 0 ? _a : noteIndex));
|
|
@@ -7,9 +7,10 @@ import { CheckCircle2, AlertTriangle, Info, XCircle, } from "lucide-react";
|
|
|
7
7
|
import Spinner from "../Spinner/Spinner.js";
|
|
8
8
|
import { toastDuration } from "./toastDuration.js";
|
|
9
9
|
import { REDUCED_MOTION_QUERY, reducedMotionSx } from "../../Theme/chakra/motion.js";
|
|
10
|
-
import { transitionFor } from "../../Theme/tokens/primitives/motion.js";
|
|
10
|
+
import { motionTransition, transitionFor } from "../../Theme/tokens/primitives/motion.js";
|
|
11
11
|
import { useCustomTheme } from "../../Theme/useCustomTheme.js";
|
|
12
12
|
import { resolveSoftTone } from "../../Theme/tokens/builders/tone.js";
|
|
13
|
+
import { compositeOver } from "../../Theme/tokens/builders/color.js";
|
|
13
14
|
const ToasterContext = createContext(undefined);
|
|
14
15
|
const shrink = keyframes `
|
|
15
16
|
from { transform: scaleX(1); }
|
|
@@ -17,11 +18,13 @@ const shrink = keyframes `
|
|
|
17
18
|
`;
|
|
18
19
|
// One-shot ring pulse on the status icon — a subtle "just happened" beat.
|
|
19
20
|
const iconPulse = keyframes `
|
|
20
|
-
0% {
|
|
21
|
-
70% {
|
|
22
|
-
100% {
|
|
21
|
+
0% { transform: scale(1); opacity: 1; }
|
|
22
|
+
70% { transform: scale(1.5); opacity: 0; }
|
|
23
|
+
100% { transform: scale(1.5); opacity: 0; }
|
|
23
24
|
`;
|
|
24
25
|
const MotionBox = motion(Box);
|
|
26
|
+
const TOAST_ENTER = motionTransition("enter", "out");
|
|
27
|
+
const TOAST_EXIT = motionTransition("exit", "in");
|
|
25
28
|
// Presentational toast card — owns hover state so auto-dismiss pauses while the pointer is over it.
|
|
26
29
|
function ToastCard({ onClose, title, description, actions, isClosable, duration, meta, colors: c, isUrgent, }) {
|
|
27
30
|
const [paused, setPaused] = useState(false);
|
|
@@ -33,15 +36,23 @@ function ToastCard({ onClose, title, description, actions, isClosable, duration,
|
|
|
33
36
|
, {
|
|
34
37
|
// The single live-region root: an explicit aria-live here, on the card's own
|
|
35
38
|
// root, keeps errors from being announced a second time by a duplicate wrapper.
|
|
36
|
-
role: isUrgent ? "alert" : undefined, "aria-live": isUrgent ? "assertive" : undefined, initial: { opacity: 0, x: 24 }, animate: { opacity: 1, x: 0 }, exit: { opacity: 0, x: 24
|
|
39
|
+
role: isUrgent ? "alert" : undefined, "aria-live": isUrgent ? "assertive" : undefined, initial: { opacity: 0, x: 24 }, animate: { opacity: 1, x: 0 }, exit: { opacity: 0, x: 24, transition: TOAST_EXIT }, transition: TOAST_ENTER, onHoverStart: () => setPaused(true), onHoverEnd: () => setPaused(false), position: "relative", bg: c.surfaceRaised, border: `0.0625rem solid ${c.boxborder[200]}`, boxShadow: "md", borderRadius: "xl", overflow: "hidden", minW: "22.5rem", maxW: "26rem", sx: {
|
|
37
40
|
isolation: "isolate",
|
|
38
41
|
transition: transitionFor(["box-shadow"]),
|
|
39
42
|
_hover: { boxShadow: "lg" },
|
|
40
43
|
...reducedMotionSx(),
|
|
41
|
-
}, children: [_jsxs(Flex, { p: 3.5, gap: 3, align: actions ? "flex-start" : "center", children: [_jsx(Flex, { align: "center", justify: "center", boxSize: "2rem", minW: "2rem", borderRadius: "full", bg: tone.bg, color: tone.fg, sx: {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
44
|
+
}, children: [_jsxs(Flex, { p: 3.5, gap: 3, align: actions ? "flex-start" : "center", children: [_jsx(Flex, { align: "center", justify: "center", boxSize: "2rem", minW: "2rem", borderRadius: "full", position: "relative", bg: compositeOver(tone.bg, c.surfaceRaised), color: tone.fg, sx: {
|
|
45
|
+
"&::after": {
|
|
46
|
+
content: '""',
|
|
47
|
+
position: "absolute",
|
|
48
|
+
inset: 0,
|
|
49
|
+
borderRadius: "full",
|
|
50
|
+
bg: tone.border,
|
|
51
|
+
zIndex: -1,
|
|
52
|
+
opacity: 0,
|
|
53
|
+
animation: `${iconPulse} 900ms ease-out 1`,
|
|
54
|
+
...reducedMotionSx(),
|
|
55
|
+
},
|
|
45
56
|
}, children: meta.icon }), _jsxs(VisuallyHidden, { children: [meta.label, ":"] }), _jsxs(Box, { flex: "1", minW: 0, children: [title && (_jsx(Text, { fontWeight: 600, fontSize: "0.875rem", lineHeight: "1.3", color: c.text[800], children: title })), description && (_jsx(Text, { fontSize: "0.8125rem", lineHeight: "1.45", color: c.textMuted, mt: title ? "0.125rem" : 0, children: description })), actions && (_jsx(Flex, { gap: 2, mt: 2.5, align: "center", wrap: "wrap", children: actions(onClose) }))] }), isClosable && (_jsx(CloseButton, { onClick: onClose, size: "sm", color: c.textMuted, borderRadius: "md", alignSelf: "flex-start", _hover: {
|
|
46
57
|
bg: c.gray[100],
|
|
47
58
|
color: c.text[700],
|
|
@@ -8,9 +8,12 @@ import ToolTip from "../ToolTip/ToolTip.js";
|
|
|
8
8
|
import { useSlidingPill } from "../SegmentedControl/useSlidingPill.js";
|
|
9
9
|
import { BUTTON_SIZES } from "../../Theme/tokens/primitives/controlSizes.js";
|
|
10
10
|
import { BORDER_WIDTHS } from "../../Theme/tokens/primitives/borderWidths.js";
|
|
11
|
+
import { transitionFor } from "../../Theme/tokens/primitives/motion.js";
|
|
11
12
|
const MODES = ["grid", "list"];
|
|
12
13
|
const TRACK_HEIGHT = BUTTON_SIZES.sm.height;
|
|
13
14
|
const SEGMENT_HEIGHT = `calc(${TRACK_HEIGHT} - 0.25rem)`;
|
|
15
|
+
const INK_TRANSITION = transitionFor(["color"], "base");
|
|
16
|
+
const PILL_TRANSITION = transitionFor(["transform", "width"], "base", "out");
|
|
14
17
|
/** Two icon-only IconButtons (Grid/List), aria-pressed marks the active one; shares variant with SegmentedControl (see MODULE.md). */
|
|
15
18
|
const TableToggle = ({ value, onChange, variant = "default" }) => {
|
|
16
19
|
const theme = useCustomTheme();
|
|
@@ -71,10 +74,10 @@ const TableToggle = ({ value, onChange, variant = "default" }) => {
|
|
|
71
74
|
? colors.accentText
|
|
72
75
|
: hoverInk,
|
|
73
76
|
},
|
|
74
|
-
transition:
|
|
77
|
+
transition: INK_TRANSITION,
|
|
75
78
|
}),
|
|
76
79
|
};
|
|
77
|
-
return (_jsxs(Box, { ref: trackRef, ...styles.container, children: [isBrandSlide && pill && (_jsx(Box, { "aria-hidden": "true", position: "absolute", top: "0.125rem", left: 0, h: SEGMENT_HEIGHT, w: `${pill.width}px`, borderRadius: "lg", bg: brandFill.fill, boxShadow: `0 0.125rem 0.5rem ${colors.boxShadow.primary}`, transform: `translateX(${pill.left}px)`, transition:
|
|
80
|
+
return (_jsxs(Box, { ref: trackRef, ...styles.container, children: [isBrandSlide && pill && (_jsx(Box, { "aria-hidden": "true", position: "absolute", top: "0.125rem", left: 0, h: SEGMENT_HEIGHT, w: `${pill.width}px`, borderRadius: "lg", bg: brandFill.fill, boxShadow: `0 0.125rem 0.5rem ${colors.boxShadow.primary}`, transform: `translateX(${pill.left}px)`, transition: PILL_TRANSITION })), isUnderlineSlide && pill && (_jsx(Box, { "aria-hidden": "true", position: "absolute", bottom: `-${BORDER_WIDTHS.hairline}`, left: 0, h: "0.125rem", w: `${pill.width}px`, borderRadius: "full", bg: colors.primary[500], transform: `translateX(${pill.left}px)`, transition: PILL_TRANSITION })), _jsx(ToolTip, { label: "Grid View", placement: "top", fontSize: "xs", hasArrow: true, children: _jsx(IconButton, { ref: (node) => {
|
|
78
81
|
refs.current[0] = node;
|
|
79
82
|
}, "aria-label": "Grid View", "aria-pressed": value === "grid", icon: _jsx(Table2, { size: "1.25rem" }), variant: "ghost", onClick: () => onChange("grid"), ...styles.button("grid") }) }), _jsx(ToolTip, { label: "List View", placement: "top", fontSize: "xs", hasArrow: true, children: _jsx(IconButton, { ref: (node) => {
|
|
80
83
|
refs.current[1] = node;
|
|
@@ -2,6 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { useEffect, useState } from "react";
|
|
3
3
|
import { Modal, ModalOverlay, ModalContent, ModalHeader, ModalCloseButton, ModalBody, ModalFooter, FormControl, VStack, } from "@chakra-ui/react";
|
|
4
4
|
import { useCustomTheme } from "../../Theme/useCustomTheme.js";
|
|
5
|
+
import { raisedRule } from "../../Theme/tokens/builders/surfaceRaised.js";
|
|
5
6
|
import Button from "../Button/Button.js";
|
|
6
7
|
import TextInput from "../Input/TextInput.js";
|
|
7
8
|
import SearchSelect from "../SearchSelect/SearchSelect.js";
|
|
@@ -75,7 +76,7 @@ const AddUserModal = ({ isOpen, onClose, roleOptions, isLoading, onSubmit, onAdd
|
|
|
75
76
|
type: "email",
|
|
76
77
|
},
|
|
77
78
|
];
|
|
78
|
-
return (_jsxs(Modal, { isOpen: isOpen, onClose: onClose, trapFocus: false, isCentered: true, children: [_jsx(ModalOverlay, { backdropFilter: "blur(4px)" }), _jsxs(ModalContent, { bg: colors.surfaceRaised, borderRadius: "xl", overflow: "hidden", children: [_jsxs(ModalHeader, { borderBottom: "1px solid", borderColor: colors
|
|
79
|
+
return (_jsxs(Modal, { isOpen: isOpen, onClose: onClose, trapFocus: false, isCentered: true, children: [_jsx(ModalOverlay, { backdropFilter: "blur(4px)" }), _jsxs(ModalContent, { bg: colors.surfaceRaised, borderRadius: "xl", overflow: "hidden", children: [_jsxs(ModalHeader, { borderBottom: "1px solid", borderColor: raisedRule(colors), children: [labels.addNewUser, upgradeNotice] }), _jsx(ModalCloseButton, {}), _jsx(ModalBody, { py: 5, children: _jsxs(VStack, { spacing: 4, align: "stretch", children: [textFields.map((field) => (_jsx(FormControl, { isInvalid: !!errors[field.id], children: _jsx(TextInput, { id: field.id, name: field.id, type: field.type, label: field.label, placeholder: field.placeholder, value: values[field.id], onChange: handleChange(field.id), isRequired: true, error: !!errors[field.id], errorMessage: errors[field.id], width: "100%" }) }, field.id))), _jsx(FormControl, { isInvalid: !!errors.role, isRequired: true, children: _jsx(SearchSelect, { label: labels.role, options: roleOptions.map((item) => ({
|
|
79
80
|
id: item.id,
|
|
80
81
|
label: item.label,
|
|
81
82
|
})), value: (_a = values.role) !== null && _a !== void 0 ? _a : undefined, onSelect: (option) => {
|
|
@@ -2,6 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { useEffect, useState } from "react";
|
|
3
3
|
import { Modal, ModalOverlay, ModalContent, ModalHeader, ModalCloseButton, ModalBody, ModalFooter, FormControl, VStack, } from "@chakra-ui/react";
|
|
4
4
|
import { useCustomTheme } from "../../Theme/useCustomTheme.js";
|
|
5
|
+
import { raisedRule } from "../../Theme/tokens/builders/surfaceRaised.js";
|
|
5
6
|
import Button from "../Button/Button.js";
|
|
6
7
|
import TextInput from "../Input/TextInput.js";
|
|
7
8
|
import SearchSelect from "../SearchSelect/SearchSelect.js";
|
|
@@ -31,7 +32,7 @@ const ChangeRoleModal = ({ isOpen, onClose, userId, email, currentRole, roleOpti
|
|
|
31
32
|
return;
|
|
32
33
|
await (onSubmit === null || onSubmit === void 0 ? void 0 : onSubmit({ userId, roleId: selectedRole.id }));
|
|
33
34
|
};
|
|
34
|
-
return (_jsxs(Modal, { isOpen: isOpen, onClose: onClose, trapFocus: false, isCentered: true, children: [_jsx(ModalOverlay, { backdropFilter: "blur(4px)" }), _jsxs(ModalContent, { bg: colors.surfaceRaised, borderRadius: "xl", overflow: "hidden", children: [_jsx(ModalHeader, { borderBottom: "1px solid", borderColor: colors
|
|
35
|
+
return (_jsxs(Modal, { isOpen: isOpen, onClose: onClose, trapFocus: false, isCentered: true, children: [_jsx(ModalOverlay, { backdropFilter: "blur(4px)" }), _jsxs(ModalContent, { bg: colors.surfaceRaised, borderRadius: "xl", overflow: "hidden", children: [_jsx(ModalHeader, { borderBottom: "1px solid", borderColor: raisedRule(colors), children: labels.changeRoleTitle }), _jsx(ModalCloseButton, {}), _jsx(ModalBody, { py: 5, children: _jsxs(VStack, { spacing: 4, align: "stretch", children: [_jsx(TextInput, { label: labels.email, value: email !== null && email !== void 0 ? email : "", isDisabled: true, width: "100%" }), _jsx(FormControl, { isInvalid: !!error, isRequired: true, children: _jsx(SearchSelect, { label: labels.role, options: roleOptions.map((item) => ({
|
|
35
36
|
id: item.id,
|
|
36
37
|
label: item.label,
|
|
37
38
|
})), value: selectedRole !== null && selectedRole !== void 0 ? selectedRole : undefined, onSelect: (option) => {
|
|
@@ -6,6 +6,7 @@ import { ChevronLeft, RefreshCw, Send, Shield, Trash2, UserPlus, Users, UserRoun
|
|
|
6
6
|
import { useCustomTheme } from "../../Theme/useCustomTheme.js";
|
|
7
7
|
import { resolveHoverTint } from "../../Theme/tokens/builders/outlineRung.js";
|
|
8
8
|
import { accentTextOnCanvas } from "../../Theme/tokens/builders/accentText.js";
|
|
9
|
+
import { bandOn } from "../../Theme/tokens/builders/planeStep.js";
|
|
9
10
|
import { listRowBackgrounds } from "../../Theme/tokens/builders/rowStates.js";
|
|
10
11
|
import { focusVisibleRing } from "../../Theme/chakra/focusRing.styles.js";
|
|
11
12
|
import EmptyState from "../EmptyState/EmptyState.js";
|
|
@@ -60,6 +61,7 @@ const UserDetails = ({ users, selectedUser, selectedUserId, roleOptions = [], ca
|
|
|
60
61
|
const [actionUserId, setActionUserId] = useState(null);
|
|
61
62
|
const border = colors.boxborder[200];
|
|
62
63
|
const surface = colors.background[50];
|
|
64
|
+
const detailTile = bandOn(colors.primary[50], surface);
|
|
63
65
|
const rowBackgrounds = useMemo(() => listRowBackgrounds(colors), [colors]);
|
|
64
66
|
const muted = colors.textMuted;
|
|
65
67
|
const heading = colors.text[900];
|
|
@@ -100,7 +102,7 @@ const UserDetails = ({ users, selectedUser, selectedUserId, roleOptions = [], ca
|
|
|
100
102
|
const Icon = (_a = detail.icon) !== null && _a !== void 0 ? _a : UserRound;
|
|
101
103
|
return (_jsxs(React.Fragment, { children: [_jsxs(Flex, { gap: 3, px: 3, py: 2.5, _hover: {
|
|
102
104
|
bg: resolveHoverTint(colors.gray[50], surface),
|
|
103
|
-
}, alignItems: "center", transition: "background 0.15s ease", children: [_jsx(Flex, { align: "center", justify: "center", boxSize: "30px", bg:
|
|
105
|
+
}, alignItems: "center", transition: "background 0.15s ease", children: [_jsx(Flex, { align: "center", justify: "center", boxSize: "30px", bg: detailTile, borderRadius: "lg", color: accentTextOnCanvas(colors.primary, detailTile), flexShrink: 0, children: _jsx(Icon, { size: 15 }) }), _jsx(Box, { minWidth: "110px", children: _jsx(Text, { fontSize: "xs", fontWeight: 600, color: muted, children: detail.label }) }), _jsx(Box, { flex: 1, children: _jsx(Text, { fontSize: "sm", color: heading, fontWeight: 500, children: detail.value }) })] }), index < selectedUser.details.length - 1 && (_jsx(Divider, { borderColor: border }))] }, index));
|
|
104
106
|
}) })] })] })) : (_jsx(EmptyState, { icon: UserRound, title: labels.selectTeamMember, description: labels.noUserSelected, minH: "300px" })) })] }), _jsx(AddUserModal, { isOpen: isAddUserOpen, onClose: onAddUserClose, roleOptions: roleOptions, isLoading: isAddUserLoading, onSubmit: async (values) => {
|
|
105
107
|
await (onAddUserSubmit === null || onAddUserSubmit === void 0 ? void 0 : onAddUserSubmit(values));
|
|
106
108
|
onAddUserClose();
|
|
@@ -15,7 +15,11 @@ export default function WorkspaceTrayPreview({ children, preview, enabled = true
|
|
|
15
15
|
const [open, setOpen] = useState(false);
|
|
16
16
|
const openTimer = useRef(null);
|
|
17
17
|
const closeTimer = useRef(null);
|
|
18
|
+
const openRef = useRef(false);
|
|
18
19
|
const setOpenState = useCallback((next) => {
|
|
20
|
+
if (openRef.current === next)
|
|
21
|
+
return;
|
|
22
|
+
openRef.current = next;
|
|
19
23
|
setOpen(next);
|
|
20
24
|
onOpenChange === null || onOpenChange === void 0 ? void 0 : onOpenChange(next);
|
|
21
25
|
}, [onOpenChange]);
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { Box, Flex, HStack, IconButton, Modal, ModalContent, ModalOverlay, Text, useModalContext, } from "@chakra-ui/react";
|
|
2
|
+
import { Box, Flex, HStack, IconButton, Modal, ModalContent, ModalOverlay, Portal, Text, useModalContext, } from "@chakra-ui/react";
|
|
3
3
|
import { useEffect } from "react";
|
|
4
4
|
import { ExternalLink, Minus, X } from "lucide-react";
|
|
5
5
|
import { useCustomTheme } from "../../Theme/useCustomTheme.js";
|
|
6
6
|
import zIndices from "../../Theme/tokens/primitives/zIndices.js";
|
|
7
7
|
import { accentTextOnCanvas } from "../../Theme/tokens/builders/accentText.js";
|
|
8
|
-
// NOTE: no maximize/restore toggle (removed by product decision)
|
|
8
|
+
// NOTE: no maximize/restore toggle (removed by product decision); onMedium/onMaximize stay as deprecated no-ops.
|
|
9
9
|
const WINDOW_SIZE = { maxW: "88rem", h: "92vh" };
|
|
10
10
|
const WindowTitle = ({ testId, color, children }) => {
|
|
11
11
|
const { headerId, setHeaderMounted } = useModalContext();
|
|
@@ -16,7 +16,8 @@ const WindowTitle = ({ testId, color, children }) => {
|
|
|
16
16
|
return (_jsx(Text, { id: headerId, fontSize: "sm", fontWeight: 600, color: color, noOfLines: 1, "data-testid": `${testId}-title`, children: children }));
|
|
17
17
|
};
|
|
18
18
|
// Presentational floating "workspace window" (Jira-style dialog), headless — the parent owns window state.
|
|
19
|
-
export default function WorkspaceWindow({ title, state, children, onMinimize, onClose, onOpenFullPage, onOverlayClick, headerActions, testId = "workspace-window", }) {
|
|
19
|
+
export default function WorkspaceWindow({ title, state, children, onMinimize, onClose, onOpenFullPage, onOverlayClick, headerActions, labels, finalFocusRef, testId = "workspace-window", }) {
|
|
20
|
+
var _a, _b, _c;
|
|
20
21
|
// Must run before the early return: a minimized render would otherwise skip the hook
|
|
21
22
|
// and change hook order when the window reopens.
|
|
22
23
|
const theme = useCustomTheme();
|
|
@@ -26,28 +27,34 @@ export default function WorkspaceWindow({ title, state, children, onMinimize, on
|
|
|
26
27
|
return (_jsxs(Modal, { isOpen: true, onClose: () => onClose === null || onClose === void 0 ? void 0 : onClose(), size: "full", isCentered: true, scrollBehavior: "inside",
|
|
27
28
|
// Don't discard unsaved work on an accidental overlay click / Esc — the
|
|
28
29
|
// parent decides via the explicit Close control.
|
|
29
|
-
closeOnOverlayClick: false, closeOnEsc: false, children: [_jsx(ModalOverlay, { backdropFilter: "blur(3px)" }), _jsx(ModalContent, { bg: "transparent", boxShadow: "none", m: 0, display: "flex", alignItems: "center", justifyContent: "center",
|
|
30
|
+
closeOnOverlayClick: false, closeOnEsc: false, finalFocusRef: finalFocusRef, children: [_jsx(ModalOverlay, { backdropFilter: "blur(3px)" }), _jsx(ModalContent, { bg: "transparent", boxShadow: "none", m: 0, display: "flex", alignItems: "center", justifyContent: "center",
|
|
30
31
|
// NOTE: size="full" blocks Chakra's own closeOnOverlayClick — detect the outside click ourselves instead.
|
|
31
32
|
onMouseDown: (e) => {
|
|
32
33
|
if (e.target === e.currentTarget)
|
|
33
34
|
onOverlayClick === null || onOverlayClick === void 0 ? void 0 : onOverlayClick();
|
|
34
|
-
}, "data-testid": `${testId}-backdrop`, children: _jsxs(Box, { bg: theme.colors.surfaceRaised, borderRadius: "xl", boxShadow: "2xl", overflow: "hidden", w: "100%", maxW: size.maxW, h: size.h, display: "flex", flexDirection: "column", "data-testid": testId, "data-window-state": state, children: [_jsxs(Flex, { align: "center", justify: "space-between", px: 3, py: 2, borderBottomWidth: "1px", borderColor: theme.colors.boxborder[200], bg: theme.colors.background[100], flexShrink: 0, children: [_jsx(WindowTitle, { testId: testId, color: theme.colors.text[700], children: title }), _jsxs(HStack, { spacing: 1, children: [headerActions, onOpenFullPage ? (_jsx(IconButton, { "aria-label": "Open full page", size: "xs", variant: "ghost", icon: _jsx(ExternalLink, { size: 14 }), onClick: onOpenFullPage, "data-testid": `${testId}-fullpage` })) : null, onMinimize ? (_jsx(IconButton, { "aria-label": "Minimize", size: "xs", variant: "ghost", icon: _jsx(Minus, { size: 15 }), onClick: onMinimize, "data-testid": `${testId}-minimize` })) : null, onClose ? (_jsx(IconButton, { "aria-label": "Close", size: "xs", variant: "ghost", colorScheme: "red", icon: _jsx(X, { size: 15 }), onClick: onClose, "data-testid": `${testId}-close` })) : null] })] }), _jsx(Box, { flex: "1", overflow: "auto", px: { base: 3, md: 5 }, py: 4, children: children })] }) })] }));
|
|
35
|
+
}, "data-testid": `${testId}-backdrop`, children: _jsxs(Box, { bg: theme.colors.surfaceRaised, borderRadius: "xl", boxShadow: "2xl", overflow: "hidden", w: "100%", maxW: size.maxW, h: size.h, display: "flex", flexDirection: "column", "data-testid": testId, "data-window-state": state, children: [_jsxs(Flex, { align: "center", justify: "space-between", px: 3, py: 2, borderBottomWidth: "1px", borderColor: theme.colors.boxborder[200], bg: theme.colors.background[100], flexShrink: 0, children: [_jsx(WindowTitle, { testId: testId, color: theme.colors.text[700], children: title }), _jsxs(HStack, { spacing: 1, children: [headerActions, onOpenFullPage ? (_jsx(IconButton, { "aria-label": (_a = labels === null || labels === void 0 ? void 0 : labels.openFullPage) !== null && _a !== void 0 ? _a : "Open full page", size: "xs", variant: "ghost", icon: _jsx(ExternalLink, { size: 14 }), onClick: onOpenFullPage, "data-testid": `${testId}-fullpage` })) : null, onMinimize ? (_jsx(IconButton, { "aria-label": (_b = labels === null || labels === void 0 ? void 0 : labels.minimize) !== null && _b !== void 0 ? _b : "Minimize", size: "xs", variant: "ghost", icon: _jsx(Minus, { size: 15 }), onClick: onMinimize, "data-testid": `${testId}-minimize` })) : null, onClose ? (_jsx(IconButton, { "aria-label": (_c = labels === null || labels === void 0 ? void 0 : labels.close) !== null && _c !== void 0 ? _c : "Close", size: "xs", variant: "ghost", colorScheme: "red", icon: _jsx(X, { size: 15 }), onClick: onClose, "data-testid": `${testId}-close` })) : null] })] }), _jsx(Box, { flex: "1", overflow: "auto", px: { base: 3, md: 5 }, py: 4, children: children })] }) })] }));
|
|
35
36
|
}
|
|
36
|
-
|
|
37
|
-
|
|
37
|
+
const cssLength = (value) => (typeof value === "number" ? `${value}px` : value);
|
|
38
|
+
// Portalled above modal overlays; aria-live keeps Chakra's modal aria-hidden off it, data-no-focus-lock keeps the focus trap off it.
|
|
39
|
+
export function WorkspaceTray({ items, onRestore, onClose, testId = "workspace-tray", placement = "bottom-end", offset, closeLabel, dirtyLabel = "Unsaved changes", label = "Minimized windows", renderItem, }) {
|
|
40
|
+
var _a, _b;
|
|
38
41
|
const theme = useCustomTheme();
|
|
39
42
|
if (!items.length)
|
|
40
43
|
return null;
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
44
|
+
const atEnd = placement === "bottom-end";
|
|
45
|
+
const inset = {
|
|
46
|
+
bottom: cssLength((_a = offset === null || offset === void 0 ? void 0 : offset.y) !== null && _a !== void 0 ? _a : "1rem"),
|
|
47
|
+
[atEnd ? "right" : "left"]: cssLength((_b = offset === null || offset === void 0 ? void 0 : offset.x) !== null && _b !== void 0 ? _b : "1rem"),
|
|
48
|
+
};
|
|
49
|
+
const ink = accentTextOnCanvas(theme.colors.primary, theme.colors.primary[100]);
|
|
50
|
+
return (_jsx(Portal, { children: _jsx(Flex, { role: "region", "aria-label": label, "aria-live": "polite", "data-no-focus-lock": "true", position: "fixed", ...inset, zIndex: zIndices.modal + 1, direction: atEnd ? "row-reverse" : "row", wrap: "wrap-reverse", justify: "flex-start", gap: 2, maxW: { base: "calc(100vw - 2rem)", md: "36rem" }, "data-testid": testId, children: items.map((item) => {
|
|
51
|
+
const api = {
|
|
52
|
+
restore: () => onRestore === null || onRestore === void 0 ? void 0 : onRestore(item.id),
|
|
53
|
+
close: () => onClose === null || onClose === void 0 ? void 0 : onClose(item.id),
|
|
54
|
+
};
|
|
55
|
+
if (renderItem) {
|
|
56
|
+
return _jsx(Box, { children: renderItem(item, api) }, item.id);
|
|
57
|
+
}
|
|
58
|
+
return (_jsxs(HStack, { spacing: 1, pl: 3, pr: 1, py: 1, borderRadius: "full", bg: theme.colors.primary[100], color: ink, boxShadow: "md", borderWidth: "1px", borderColor: theme.colors.primary[200], "data-testid": `${testId}-pill`, children: [item.isDirty ? (_jsx(Box, { role: "img", "aria-label": dirtyLabel, boxSize: "0.5rem", borderRadius: "full", bg: "currentColor", flexShrink: 0, "data-testid": `${testId}-dirty` })) : null, _jsxs(Box, { as: "button", type: "button", fontSize: "sm", onClick: api.restore, "data-testid": `${testId}-restore`, maxW: "16rem", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", children: [item.title, item.subtitle ? (_jsx(Box, { as: "span", fontWeight: 400, ml: 1.5, children: item.subtitle })) : null] }), onClose ? (_jsx(IconButton, { "aria-label": closeLabel ? closeLabel(item) : "Close", size: "xs", variant: "ghost", borderRadius: "full", minW: "auto", h: "auto", p: 1, color: "inherit", icon: _jsx(X, { size: 13 }), onClick: api.close, "data-testid": `${testId}-close` })) : null] }, item.id));
|
|
59
|
+
}) }) }));
|
|
53
60
|
}
|
|
@@ -36,10 +36,13 @@ const variants = {
|
|
|
36
36
|
outline: definePartsStyle({
|
|
37
37
|
container: { [$border.variable]: "1px", [$shadow.variable]: "none" },
|
|
38
38
|
}),
|
|
39
|
+
elevated: definePartsStyle({
|
|
40
|
+
container: { [$border.variable]: "0", [$shadow.variable]: "shadows.card" },
|
|
41
|
+
}),
|
|
39
42
|
};
|
|
40
43
|
export const Card = defineMultiStyleConfig({
|
|
41
44
|
baseStyle,
|
|
42
45
|
sizes,
|
|
43
46
|
variants,
|
|
44
|
-
defaultProps: { variant: "
|
|
47
|
+
defaultProps: { variant: "elevated", size: "md" },
|
|
45
48
|
});
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { createMultiStyleConfigHelpers, cssVar } from "@chakra-ui/react";
|
|
2
2
|
import { menuAnatomy } from "@chakra-ui/anatomy";
|
|
3
3
|
import { listRowBackgrounds } from "../tokens/builders/rowStates.js";
|
|
4
|
+
import { optionRowInk, optionRowWeight } from "../../Components/Select/optionRowInk.js";
|
|
4
5
|
import { OPTION_ROW_SIZES, OPTION_ROW_RADIUS } from "../tokens/primitives/optionRowSizes.js";
|
|
5
6
|
import { paletteOf } from "./paletteFromTheme.js";
|
|
7
|
+
import { POPUP_SURFACE } from "./overlay.styles.js";
|
|
6
8
|
const itemRowSpec = OPTION_ROW_SIZES.sm;
|
|
7
9
|
const { defineMultiStyleConfig, definePartsStyle } = createMultiStyleConfigHelpers(menuAnatomy.keys);
|
|
8
10
|
const $bg = cssVar("menu-bg");
|
|
@@ -21,12 +23,15 @@ const baseStyle = definePartsStyle(({ theme }) => {
|
|
|
21
23
|
borderWidth: "1px",
|
|
22
24
|
borderStyle: "solid",
|
|
23
25
|
borderColor: colors.boxborder[200],
|
|
26
|
+
...POPUP_SURFACE,
|
|
24
27
|
},
|
|
25
28
|
item: {
|
|
29
|
+
color: optionRowInk(colors, false),
|
|
26
30
|
minH: itemRowSpec.minH,
|
|
27
31
|
px: itemRowSpec.px,
|
|
28
32
|
py: itemRowSpec.py,
|
|
29
33
|
mx: itemRowSpec.mx,
|
|
34
|
+
width: `calc(100% - 2 * ${itemRowSpec.mx})`,
|
|
30
35
|
fontSize: itemRowSpec.fontSize,
|
|
31
36
|
borderRadius: OPTION_ROW_RADIUS,
|
|
32
37
|
bg: "transparent",
|
|
@@ -34,6 +39,11 @@ const baseStyle = definePartsStyle(({ theme }) => {
|
|
|
34
39
|
_hover: { [$itemBg.variable]: hoverBg, bg: $itemBg.reference },
|
|
35
40
|
_active: { [$itemBg.variable]: activeBg, bg: $itemBg.reference },
|
|
36
41
|
_expanded: { [$itemBg.variable]: hoverBg, bg: $itemBg.reference },
|
|
42
|
+
"&[aria-checked=true]": {
|
|
43
|
+
color: optionRowInk(colors, true),
|
|
44
|
+
fontWeight: optionRowWeight(true),
|
|
45
|
+
"& .chakra-menu__icon-wrapper": { color: colors.accentText },
|
|
46
|
+
},
|
|
37
47
|
},
|
|
38
48
|
};
|
|
39
49
|
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createMultiStyleConfigHelpers, cssVar } from "@chakra-ui/react";
|
|
2
2
|
import { popoverAnatomy } from "@chakra-ui/anatomy";
|
|
3
3
|
import { paletteOf } from "./paletteFromTheme.js";
|
|
4
|
+
import { POPUP_SURFACE } from "./overlay.styles.js";
|
|
4
5
|
const { defineMultiStyleConfig, definePartsStyle } = createMultiStyleConfigHelpers(popoverAnatomy.keys);
|
|
5
6
|
const $popperBg = cssVar("popper-bg");
|
|
6
7
|
const $arrowShadowColor = cssVar("popper-arrow-shadow-color");
|
|
@@ -16,6 +17,7 @@ const baseStyle = definePartsStyle(({ theme }) => {
|
|
|
16
17
|
borderWidth: "1px",
|
|
17
18
|
borderStyle: "solid",
|
|
18
19
|
borderColor: colors.boxborder[200],
|
|
20
|
+
...POPUP_SURFACE,
|
|
19
21
|
},
|
|
20
22
|
};
|
|
21
23
|
});
|
|
@@ -12,6 +12,7 @@ import { AA_NORMAL_TEXT, accentTextOnCanvas, isDarkCanvas } from "../tokens/buil
|
|
|
12
12
|
import { labelOnFill, solidFillRung } from "../tokens/builders/filledSurface.js";
|
|
13
13
|
import { liftToContrast, resolveHoverTint } from "../tokens/builders/outlineRung.js";
|
|
14
14
|
import { resolveSoftTone } from "../tokens/builders/tone.js";
|
|
15
|
+
import { skeletonShimmer } from "../tokens/builders/skeletonShimmer.js";
|
|
15
16
|
import { tooltipSurface } from "../tokens/builders/tooltipSurface.js";
|
|
16
17
|
import { Drawer } from "./Drawer.styles.js";
|
|
17
18
|
import { Menu } from "./Menu.styles.js";
|
|
@@ -22,7 +23,7 @@ import { Card } from "./Card.styles.js";
|
|
|
22
23
|
// NOTE: guards untethemed scales (blackAlpha/whiteAlpha) whose rgba() rungs would throw in hexToRgb.
|
|
23
24
|
const isHexColor = (color) => typeof color === "string" && /^#([0-9a-f]{3}|[0-9a-f]{6})$/i.test(color);
|
|
24
25
|
const solidFillStyle = (palette, swatch) => {
|
|
25
|
-
const rung = solidFillRung(swatch, palette.white);
|
|
26
|
+
const rung = solidFillRung(swatch, palette.white, palette.backgroundColor.main);
|
|
26
27
|
const bg = swatch[rung];
|
|
27
28
|
return {
|
|
28
29
|
bg,
|
|
@@ -142,19 +143,22 @@ const $skeletonStart = cssVar("skeleton-start-color");
|
|
|
142
143
|
const $skeletonEnd = cssVar("skeleton-end-color");
|
|
143
144
|
// NOTE: fixes Chakra's Skeleton hardcoding gray.100/.400 via `_dark` (dead here) — an explicit startColor/endColor prop still wins.
|
|
144
145
|
const Skeleton = {
|
|
145
|
-
baseStyle: ({ theme }) =>
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
146
|
+
baseStyle: ({ theme }) => {
|
|
147
|
+
const shimmer = skeletonShimmer(paletteOf(theme));
|
|
148
|
+
return {
|
|
149
|
+
[$skeletonStart.variable]: shimmer.start,
|
|
150
|
+
[$skeletonEnd.variable]: shimmer.end,
|
|
151
|
+
background: $skeletonStart.reference,
|
|
152
|
+
borderColor: $skeletonEnd.reference,
|
|
153
|
+
};
|
|
154
|
+
},
|
|
151
155
|
};
|
|
152
156
|
// NOTE: uses Chakra's own shorthand style keys (bg/w/h/pos) + !important — extendTheme deep-merges by key, so mismatched keys let Chakra's stock value win.
|
|
153
157
|
const Radio = {
|
|
154
158
|
baseStyle: ({ theme, colorScheme }) => {
|
|
155
159
|
const palette = paletteOf(theme);
|
|
156
160
|
const swatch = scaleFor(palette, colorScheme);
|
|
157
|
-
const fill = swatch[solidFillRung(swatch, palette.white)];
|
|
161
|
+
const fill = swatch[solidFillRung(swatch, palette.white, palette.backgroundColor.main)];
|
|
158
162
|
const dot = labelOnFill(fill, palette.white, palette.black);
|
|
159
163
|
const hoverFill = resolveHoverTint(fill, fill);
|
|
160
164
|
return {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { useMatchMedia } from "../../Hooks/useMatchMedia.js";
|
|
2
2
|
export const REDUCED_MOTION_QUERY = "@media (prefers-reduced-motion: reduce)";
|
|
3
|
+
export const MOTION_OK_QUERY = "@media (prefers-reduced-motion: no-preference)";
|
|
3
4
|
const MEDIA = "(prefers-reduced-motion: reduce)";
|
|
4
5
|
export const usePrefersReducedMotion = () => useMatchMedia(MEDIA, false);
|
|
5
6
|
/** Spread into `sx`: drops transitions and animations when the user asks for less motion. */
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { overlayScrim } from "../tokens/builders/scrim.js";
|
|
2
2
|
import { raisedRule } from "../tokens/builders/surfaceRaised.js";
|
|
3
|
+
import { RADIUS_ROLE } from "../tokens/primitives/radii.js";
|
|
3
4
|
export const OVERLAY_BLUR = "blur(4px)";
|
|
5
|
+
/** Radius and elevation every anchored popup shares: menus, popovers, selects, dropdowns. */
|
|
6
|
+
export const POPUP_SURFACE = { borderRadius: RADIUS_ROLE.float, boxShadow: "md" };
|
|
4
7
|
/** The one Modal/Drawer backdrop; reuse it for any custom full-screen scrim. */
|
|
5
8
|
export const overlayScrimStyles = (colors) => ({
|
|
6
9
|
bg: overlayScrim(colors),
|
|
@@ -27,9 +27,25 @@ import { withSurfaceRungs } from "../builders/surfaceRungs.js";
|
|
|
27
27
|
import { buildSurfaceRaised, withSurfaceRaised } from "../builders/surfaceRaised.js";
|
|
28
28
|
import { buildStar } from "../builders/star.js";
|
|
29
29
|
import { lazyPalette } from "../builders/lazy.js";
|
|
30
|
+
import { contrastRatio, mix } from "../builders/color.js";
|
|
31
|
+
export const LIGHT_CANVAS_STEP = 1.09;
|
|
32
|
+
const CANVAS_MIX_STEP = 0.0025;
|
|
33
|
+
const CANVAS_MIX_MAX = 0.5;
|
|
34
|
+
const lightCanvas = (canvas, card, ink) => {
|
|
35
|
+
for (let weight = 0; weight < CANVAS_MIX_MAX; weight += CANVAS_MIX_STEP) {
|
|
36
|
+
const next = mix(canvas, ink, weight);
|
|
37
|
+
if (contrastRatio(next, card) >= LIGHT_CANVAS_STEP)
|
|
38
|
+
return next;
|
|
39
|
+
}
|
|
40
|
+
return mix(canvas, ink, CANVAS_MIX_MAX);
|
|
41
|
+
};
|
|
30
42
|
/** Derived, never hand-written: a copied hex goes stale the moment a canvas moves. */
|
|
31
43
|
export const finalizeLightPalette = (source) => ({
|
|
32
44
|
...source,
|
|
45
|
+
backgroundColor: {
|
|
46
|
+
...source.backgroundColor,
|
|
47
|
+
base: lightCanvas(source.backgroundColor.base, source.background[50], source.text[900]),
|
|
48
|
+
},
|
|
33
49
|
sidebar: withSidebarTokens(source),
|
|
34
50
|
accentText: pickAccentText(source.primary, source.backgroundColor.main),
|
|
35
51
|
textMuted: buildMutedText(source.text, source.backgroundColor.main),
|