pixelize-design-library 2.4.2-beta.41 → 2.4.2-beta.43

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.
@@ -1094,6 +1094,37 @@ and submenu items. `disabled` is unchanged and still works independently.
1094
1094
  **Apply:** `locked: true` alone now prevents interaction; you no longer need to also set
1095
1095
  `disabled: true`.
1096
1096
 
1097
+ ### `SideBar` menu-item labels clipped the bottom of descenders (g/y/p/q/j) — fixed
1098
+
1099
+ `TextTruncation.tsx`'s label used `overflow="hidden"` (both axes) with `lineHeight="1"`, so the line
1100
+ box was exactly font-size tall and any glyph descender got clipped flat — reported live on
1101
+ lfour.pixelizetech.com ("Legal Requests"). Fixed with `overflowX="hidden"` (kept, needed for the
1102
+ ellipsis) plus `overflowY="clip"` and `sx={{ overflowClipMargin: "3px" }}` — `clip` (unlike `hidden`
1103
+ paired with `visible`) never promotes the axis to `auto`, so the label does not become its own
1104
+ scroll container; the margin just lets the descender's ink bleed 3px past the box without changing
1105
+ its layout height. If you rolled your own workaround (extra line-height, padding-bottom) for this on
1106
+ a consumer's own nav text, it's no longer needed upstream.
1107
+
1108
+ **Apply:** nothing to do — this was a rendering bug, not a prop. If you build another
1109
+ truncated-single-line label elsewhere in this library, use `overflow: clip` + `overflow-clip-margin`
1110
+ for the non-ellipsis axis — never pair `hidden` with a plain `visible` axis (CSS computes that to
1111
+ `auto`, turning every label into its own 1px-overflowing scroll container).
1112
+
1113
+ ### `SideBar` nav list showed a bare, unthemed scrollbar when items overflowed — fixed
1114
+
1115
+ `SideBar.tsx`'s `#sidebar-scroll-container` used `Constants/Sidebar.ts`'s `FlexCss`, which only set
1116
+ the `::-webkit-scrollbar-*` pseudo-elements — never the standard `scrollbar-width`/`scrollbar-color`
1117
+ properties. Chromium honors the webkit pseudo-elements, but any engine that reads the standard
1118
+ properties first, or doesn't support the pseudo-elements at all, fell back to the browser's default
1119
+ scrollbar: a plain bar with no relation to the dark sidebar theme, showing up the moment a nav list
1120
+ (enough sections/items) overflowed the viewport. Fixed by switching to the already-written
1121
+ `cssForScrollBar(theme)` (same file), which sets `scrollbarWidth`/`scrollbarColor` **and** the
1122
+ webkit pseudo-elements, themed to `sidebar.background[500]` / `primary[500]`, hidden until hover.
1123
+ `FlexCss` is removed — `cssForScrollBar` is now the only scrollbar treatment the SideBar uses.
1124
+
1125
+ **Apply:** nothing to do. If a nav list is long enough to scroll, the bar now stays invisible until
1126
+ hovered, in the sidebar's own colors, on every engine — not just Chromium.
1127
+
1097
1128
  ### `KanbanBoard`'s `permissions.isViewable: false` hides everything, including header actions
1098
1129
 
1099
1130
  Not just the columns — the select/edit/create header bar disappears too, since the whole component
@@ -242,7 +242,7 @@ function Sidebar({ menus, activeMenu, handleMenuClick, handleSecondaryNavClick,
242
242
  }, borderRadius: "none", boxShadow: mobileNav ? theme.shadows["2xl"] : { base: theme.shadows["2xl"], lg: theme.shadows.lg }, display: "flex", background: theme.colors.sidebar.background[500], borderRight: "1px solid", borderColor: "whiteAlpha.100", role: overlay ? "dialog" : undefined, "aria-modal": overlay ? true : undefined, "aria-label": overlay ? "Main navigation" : undefined, ...(overlay && !isOverlayOpen ? { inert: "" } : {}), sx: { touchAction: overlay ? "pan-y" : "auto" }, onMouseLeave: overlayPeeking ? onPeekEnd : undefined, onPointerDown: onPointerDown, onPointerMove: onPointerMove, onPointerUp: onPointerUp, onPointerCancel: onPointerUp, children: [(0, jsx_runtime_1.jsx)(react_2.Box, { width: mobileNav
243
243
  ? OVERLAY_WIDTH
244
244
  : { base: OVERLAY_WIDTH, lg: effToggle ? RAIL_WIDTH : EXPANDED_WIDTH }, transition: `width 0.26s ${PANEL_EASE}`, display: "flex", flexDirection: "column", justifyContent: "space-between", sx: { "@media (prefers-reduced-motion: reduce)": { transition: "none" } }, children: (0, jsx_runtime_1.jsxs)(react_2.Flex, { flexDir: "column", w: "100%", as: "nav", "aria-label": "Main navigation", h: "100vh", children: [(0, jsx_runtime_1.jsx)(SidebarHeader, { logo: logo, companyName: companyName, companySubtitle: companySubtitle, toggle: effToggle, isLoading: isLoading, onToggle: changeToggle, overlay: overlay, onClose: onMobileClose }), (0, jsx_runtime_1.jsx)(react_2.Box, { id: "sidebar-scroll-container", flex: "1", minH: 0, w: "100%", overflowY: "auto", overflowX: "hidden", p: "8px 6px", css: {
245
- ...Sidebar_1.FlexCss,
245
+ ...(0, Sidebar_1.cssForScrollBar)(theme),
246
246
  transition: "all 0.3s ease",
247
247
  // (a) larger touch targets for menu rows in overlay mode
248
248
  ...(overlay
@@ -24,6 +24,8 @@ const TruncatedTextWithTooltip = ({ children, ...props }) => {
24
24
  }
25
25
  return () => resizeObserver.disconnect();
26
26
  }, [children]);
27
- return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(react_2.Tooltip, { label: children, isDisabled: !isTruncated, hasArrow: true, placement: "right", children: (0, jsx_runtime_1.jsx)(react_2.Text, { ref: textRef, isTruncated: true, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis", maxW: "100%", ...props, children: children }) }), (0, jsx_runtime_1.jsx)(react_2.Box, { ref: shadowRef, position: "fixed", top: "-9999px", left: "-9999px", visibility: "hidden", whiteSpace: "nowrap", fontSize: props.fontSize, fontWeight: props.fontWeight, fontFamily: props.fontFamily, lineHeight: props.lineHeight, px: props.px, py: props.py, children: children })] }));
27
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(react_2.Tooltip, { label: children, isDisabled: !isTruncated, hasArrow: true, placement: "right", children: (0, jsx_runtime_1.jsx)(react_2.Text, { ref: textRef, isTruncated: true, whiteSpace: "nowrap", overflowX: "hidden", overflowY: "clip",
28
+ // clip (not auto) never becomes a scroll container; the margin lets descenders (g/y/p) bleed past it.
29
+ sx: { overflowClipMargin: "3px" }, textOverflow: "ellipsis", maxW: "100%", ...props, children: children }) }), (0, jsx_runtime_1.jsx)(react_2.Box, { ref: shadowRef, position: "fixed", top: "-9999px", left: "-9999px", visibility: "hidden", whiteSpace: "nowrap", fontSize: props.fontSize, fontWeight: props.fontWeight, fontFamily: props.fontFamily, lineHeight: props.lineHeight, px: props.px, py: props.py, children: children })] }));
28
30
  };
29
31
  exports.default = TruncatedTextWithTooltip;
@@ -1,40 +1,4 @@
1
1
  import type { CustomThemeProps } from "../Theme/themeProps";
2
+ import { ScrollbarStyle } from "../Theme/tokens/builders/scrollbar";
2
3
  export declare const HEADER_HEIGHT = "4.3rem";
3
- export declare const FlexCss: {
4
- "&::-webkit-scrollbar": {
5
- width: string;
6
- };
7
- "&::-webkit-scrollbar-track": {
8
- background: string;
9
- };
10
- "&::-webkit-scrollbar-thumb": {
11
- background: string;
12
- transition: string;
13
- };
14
- "&:hover::-webkit-scrollbar-thumb": {
15
- background: string;
16
- };
17
- };
18
- export declare const cssForScrollBar: (theme: CustomThemeProps) => {
19
- "&::-webkit-scrollbar": {
20
- width: string;
21
- };
22
- "&::-webkit-scrollbar-track": {
23
- background: string;
24
- };
25
- "&::-webkit-scrollbar-thumb": {
26
- background: string;
27
- borderRadius: string;
28
- };
29
- "&:hover::-webkit-scrollbar-thumb": {
30
- background: string;
31
- };
32
- "&:hover::-webkit-scrollbar-thumb:hover": {
33
- background: string;
34
- };
35
- scrollbarWidth: string;
36
- "&:hover": {
37
- scrollbarWidth: string;
38
- scrollbarColor: string;
39
- };
40
- };
4
+ export declare const cssForScrollBar: (theme: CustomThemeProps) => ScrollbarStyle;
@@ -1,23 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.cssForScrollBar = exports.FlexCss = exports.HEADER_HEIGHT = void 0;
3
+ exports.cssForScrollBar = exports.HEADER_HEIGHT = void 0;
4
4
  const scrollbar_1 = require("../Theme/tokens/builders/scrollbar");
5
5
  exports.HEADER_HEIGHT = "4.3rem";
6
- exports.FlexCss = {
7
- "&::-webkit-scrollbar": {
8
- width: scrollbar_1.SCROLLBAR_WIDTH,
9
- },
10
- "&::-webkit-scrollbar-track": {
11
- background: "transparent",
12
- },
13
- "&::-webkit-scrollbar-thumb": {
14
- background: "transparent",
15
- transition: "background 0.5s",
16
- },
17
- "&:hover::-webkit-scrollbar-thumb": {
18
- background: "var(--chakra-colors-primary-500, #718096)",
19
- },
20
- };
21
6
  const cssForScrollBar = (theme) => ({
22
7
  "&::-webkit-scrollbar": {
23
8
  width: scrollbar_1.SCROLLBAR_WIDTH,
@@ -4,7 +4,7 @@ import { Flex, Text, Image, Box, Skeleton, useBreakpointValue } from "@chakra-ui
4
4
  import { useCustomTheme } from "../../Theme/useCustomTheme.js";
5
5
  import { labelOnFill, solidFillRung } from "../../Theme/tokens/builders/filledSurface.js";
6
6
  import { getSidebarActiveAccent } from "./sidebarAccentColors.js";
7
- import { FlexCss, HEADER_HEIGHT } from "../../Constants/Sidebar.js";
7
+ import { cssForScrollBar, HEADER_HEIGHT } from "../../Constants/Sidebar.js";
8
8
  import { ArrowLeftToLine, ArrowRightToLine, ChevronLeft, Maximize2, MoreVertical, PanelLeft, Plus, X } from "lucide-react";
9
9
  // Overlay stacking — mirrors theme.zIndices (overlay=1300 scrim, modal=1400 panel).
10
10
  const Z_SCRIM = 1300;
@@ -236,7 +236,7 @@ export default function Sidebar({ menus, activeMenu, handleMenuClick, handleSeco
236
236
  }, borderRadius: "none", boxShadow: mobileNav ? theme.shadows["2xl"] : { base: theme.shadows["2xl"], lg: theme.shadows.lg }, display: "flex", background: theme.colors.sidebar.background[500], borderRight: "1px solid", borderColor: "whiteAlpha.100", role: overlay ? "dialog" : undefined, "aria-modal": overlay ? true : undefined, "aria-label": overlay ? "Main navigation" : undefined, ...(overlay && !isOverlayOpen ? { inert: "" } : {}), sx: { touchAction: overlay ? "pan-y" : "auto" }, onMouseLeave: overlayPeeking ? onPeekEnd : undefined, onPointerDown: onPointerDown, onPointerMove: onPointerMove, onPointerUp: onPointerUp, onPointerCancel: onPointerUp, children: [_jsx(Box, { width: mobileNav
237
237
  ? OVERLAY_WIDTH
238
238
  : { base: OVERLAY_WIDTH, lg: effToggle ? RAIL_WIDTH : EXPANDED_WIDTH }, transition: `width 0.26s ${PANEL_EASE}`, display: "flex", flexDirection: "column", justifyContent: "space-between", sx: { "@media (prefers-reduced-motion: reduce)": { transition: "none" } }, children: _jsxs(Flex, { flexDir: "column", w: "100%", as: "nav", "aria-label": "Main navigation", h: "100vh", children: [_jsx(SidebarHeader, { logo: logo, companyName: companyName, companySubtitle: companySubtitle, toggle: effToggle, isLoading: isLoading, onToggle: changeToggle, overlay: overlay, onClose: onMobileClose }), _jsx(Box, { id: "sidebar-scroll-container", flex: "1", minH: 0, w: "100%", overflowY: "auto", overflowX: "hidden", p: "8px 6px", css: {
239
- ...FlexCss,
239
+ ...cssForScrollBar(theme),
240
240
  transition: "all 0.3s ease",
241
241
  // (a) larger touch targets for menu rows in overlay mode
242
242
  ...(overlay
@@ -22,6 +22,8 @@ const TruncatedTextWithTooltip = ({ children, ...props }) => {
22
22
  }
23
23
  return () => resizeObserver.disconnect();
24
24
  }, [children]);
25
- return (_jsxs(_Fragment, { children: [_jsx(Tooltip, { label: children, isDisabled: !isTruncated, hasArrow: true, placement: "right", children: _jsx(Text, { ref: textRef, isTruncated: true, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis", maxW: "100%", ...props, children: children }) }), _jsx(Box, { ref: shadowRef, position: "fixed", top: "-9999px", left: "-9999px", visibility: "hidden", whiteSpace: "nowrap", fontSize: props.fontSize, fontWeight: props.fontWeight, fontFamily: props.fontFamily, lineHeight: props.lineHeight, px: props.px, py: props.py, children: children })] }));
25
+ return (_jsxs(_Fragment, { children: [_jsx(Tooltip, { label: children, isDisabled: !isTruncated, hasArrow: true, placement: "right", children: _jsx(Text, { ref: textRef, isTruncated: true, whiteSpace: "nowrap", overflowX: "hidden", overflowY: "clip",
26
+ // clip (not auto) never becomes a scroll container; the margin lets descenders (g/y/p) bleed past it.
27
+ sx: { overflowClipMargin: "3px" }, textOverflow: "ellipsis", maxW: "100%", ...props, children: children }) }), _jsx(Box, { ref: shadowRef, position: "fixed", top: "-9999px", left: "-9999px", visibility: "hidden", whiteSpace: "nowrap", fontSize: props.fontSize, fontWeight: props.fontWeight, fontFamily: props.fontFamily, lineHeight: props.lineHeight, px: props.px, py: props.py, children: children })] }));
26
28
  };
27
29
  export default TruncatedTextWithTooltip;
@@ -1,20 +1,5 @@
1
1
  import { SCROLLBAR_WIDTH } from "../Theme/tokens/builders/scrollbar.js";
2
2
  export const HEADER_HEIGHT = "4.3rem";
3
- export const FlexCss = {
4
- "&::-webkit-scrollbar": {
5
- width: SCROLLBAR_WIDTH,
6
- },
7
- "&::-webkit-scrollbar-track": {
8
- background: "transparent",
9
- },
10
- "&::-webkit-scrollbar-thumb": {
11
- background: "transparent",
12
- transition: "background 0.5s",
13
- },
14
- "&:hover::-webkit-scrollbar-thumb": {
15
- background: "var(--chakra-colors-primary-500, #718096)",
16
- },
17
- };
18
3
  export const cssForScrollBar = (theme) => ({
19
4
  "&::-webkit-scrollbar": {
20
5
  width: SCROLLBAR_WIDTH,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pixelize-design-library",
3
- "version": "2.4.2-beta.41",
3
+ "version": "2.4.2-beta.43",
4
4
  "description": "React component library for Pixelize apps: themeable Chakra-based components, design tokens and light/dark brand theming.",
5
5
  "keywords": [
6
6
  "react",
@@ -53,7 +53,8 @@
53
53
  "format:check": "prettier --check .",
54
54
  "format": "prettier --write .",
55
55
  "test:coverage": "jest --coverage",
56
- "clean": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\""
56
+ "clean": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\"",
57
+ "prepare": "husky"
57
58
  },
58
59
  "jest": {
59
60
  "testEnvironment": "jsdom",
@@ -105,6 +106,9 @@
105
106
  "**/?(*.)+(spec|test).[jt]s?(x)"
106
107
  ]
107
108
  },
109
+ "lint-staged": {
110
+ "**/*Props.{ts,tsx}": "eslint"
111
+ },
108
112
  "browserslist": {
109
113
  "production": [
110
114
  ">0.2%",
@@ -150,9 +154,11 @@
150
154
  "eslint-plugin-react-hooks": "^7.1.1",
151
155
  "framer-motion": "^10.18.0",
152
156
  "globals": "^17.6.0",
157
+ "husky": "^9.1.7",
153
158
  "jest": "^29.7.0",
154
159
  "jest-axe": "^11.0.0",
155
160
  "jest-environment-jsdom": "^29.7.0",
161
+ "lint-staged": "^17.5.1",
156
162
  "postcss": "^8.5.4",
157
163
  "prettier": "^3.3.2",
158
164
  "prop-types": "^15.8.1",