@moderneinc/neo-styled-components 5.0.0 → 5.1.0-next.0868e6

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.
@@ -2,18 +2,16 @@ import { type ComponentPropsWithoutRef, type ReactNode } from 'react';
2
2
  export type NeoSideNavProps = {
3
3
  /** Controlled collapsed state. */
4
4
  collapsed: boolean;
5
- /** Called with the next collapsed value when the toggle is activated. */
5
+ /** Called with the next collapsed value when the edge-handle is activated. */
6
6
  onCollapsedChange: (next: boolean) => void;
7
7
  /** Fixed top slot (e.g. product logo). */
8
8
  header?: ReactNode;
9
- /** Fixed bottom slot (e.g. tenant branding), rendered above the toggle. */
9
+ /** Fixed bottom slot (e.g. tenant branding). */
10
10
  footer?: ReactNode;
11
11
  /** Scrolling content slot — the nav items. */
12
- children: ReactNode;
13
- /** Toggle label shown when expanded. Default "Less". */
14
- collapseLabel?: string;
12
+ children?: ReactNode;
15
13
  } & Pick<ComponentPropsWithoutRef<'nav'>, 'className' | 'id' | 'aria-label'>;
16
- export declare function NeoSideNav({ collapsed, onCollapsedChange, header, footer, children, collapseLabel, ...rest }: NeoSideNavProps): import("react/jsx-runtime").JSX.Element;
14
+ export declare function NeoSideNav({ collapsed, onCollapsedChange, header, footer, children, className, id, 'aria-label': ariaLabel, }: NeoSideNavProps): import("react/jsx-runtime").JSX.Element;
17
15
  export declare namespace NeoSideNav {
18
16
  var displayName: string;
19
17
  }
package/dist/index.d.ts CHANGED
@@ -2452,18 +2452,16 @@ type NeoSelectFieldChangeEvent<T = unknown> = SelectChangeEvent<T>;
2452
2452
  type NeoSideNavProps = {
2453
2453
  /** Controlled collapsed state. */
2454
2454
  collapsed: boolean;
2455
- /** Called with the next collapsed value when the toggle is activated. */
2455
+ /** Called with the next collapsed value when the edge-handle is activated. */
2456
2456
  onCollapsedChange: (next: boolean) => void;
2457
2457
  /** Fixed top slot (e.g. product logo). */
2458
2458
  header?: ReactNode;
2459
- /** Fixed bottom slot (e.g. tenant branding), rendered above the toggle. */
2459
+ /** Fixed bottom slot (e.g. tenant branding). */
2460
2460
  footer?: ReactNode;
2461
2461
  /** Scrolling content slot — the nav items. */
2462
- children: ReactNode;
2463
- /** Toggle label shown when expanded. Default "Less". */
2464
- collapseLabel?: string;
2462
+ children?: ReactNode;
2465
2463
  } & Pick<ComponentPropsWithoutRef<'nav'>, 'className' | 'id' | 'aria-label'>;
2466
- declare function NeoSideNav({ collapsed, onCollapsedChange, header, footer, children, collapseLabel, ...rest }: NeoSideNavProps): react_jsx_runtime.JSX.Element;
2464
+ declare function NeoSideNav({ collapsed, onCollapsedChange, header, footer, children, className, id, 'aria-label': ariaLabel, }: NeoSideNavProps): react_jsx_runtime.JSX.Element;
2467
2465
  declare namespace NeoSideNav {
2468
2466
  var displayName: string;
2469
2467
  }
package/dist/index.esm.js CHANGED
@@ -600,11 +600,11 @@ const createLucideIcon = (iconName, iconNode) => {
600
600
  */
601
601
 
602
602
 
603
- const __iconNode$p = [
603
+ const __iconNode$n = [
604
604
  ["path", { d: "M12 5v14", key: "s699le" }],
605
605
  ["path", { d: "m19 12-7 7-7-7", key: "1idqje" }]
606
606
  ];
607
- const ArrowDown = createLucideIcon("arrow-down", __iconNode$p);
607
+ const ArrowDown = createLucideIcon("arrow-down", __iconNode$n);
608
608
 
609
609
  /**
610
610
  * @license lucide-react v1.16.0 - ISC
@@ -614,11 +614,11 @@ const ArrowDown = createLucideIcon("arrow-down", __iconNode$p);
614
614
  */
615
615
 
616
616
 
617
- const __iconNode$o = [
617
+ const __iconNode$m = [
618
618
  ["path", { d: "m5 12 7-7 7 7", key: "hav0vg" }],
619
619
  ["path", { d: "M12 19V5", key: "x0mq9r" }]
620
620
  ];
621
- const ArrowUp = createLucideIcon("arrow-up", __iconNode$o);
621
+ const ArrowUp = createLucideIcon("arrow-up", __iconNode$m);
622
622
 
623
623
  /**
624
624
  * @license lucide-react v1.16.0 - ISC
@@ -628,7 +628,7 @@ const ArrowUp = createLucideIcon("arrow-up", __iconNode$o);
628
628
  */
629
629
 
630
630
 
631
- const __iconNode$n = [
631
+ const __iconNode$l = [
632
632
  [
633
633
  "path",
634
634
  {
@@ -639,7 +639,7 @@ const __iconNode$n = [
639
639
  ["line", { x1: "12", x2: "12", y1: "16", y2: "12", key: "1y1yb1" }],
640
640
  ["line", { x1: "12", x2: "12.01", y1: "8", y2: "8", key: "110wyk" }]
641
641
  ];
642
- const BadgeInfo = createLucideIcon("badge-info", __iconNode$n);
642
+ const BadgeInfo = createLucideIcon("badge-info", __iconNode$l);
643
643
 
644
644
  /**
645
645
  * @license lucide-react v1.16.0 - ISC
@@ -649,7 +649,7 @@ const BadgeInfo = createLucideIcon("badge-info", __iconNode$n);
649
649
  */
650
650
 
651
651
 
652
- const __iconNode$m = [
652
+ const __iconNode$k = [
653
653
  ["path", { d: "M8 2v4", key: "1cmpym" }],
654
654
  ["path", { d: "M16 2v4", key: "4m81vk" }],
655
655
  ["rect", { width: "18", height: "18", x: "3", y: "4", rx: "2", key: "1hopcy" }],
@@ -661,7 +661,7 @@ const __iconNode$m = [
661
661
  ["path", { d: "M12 18h.01", key: "mhygvu" }],
662
662
  ["path", { d: "M16 18h.01", key: "kzsmim" }]
663
663
  ];
664
- const CalendarDays = createLucideIcon("calendar-days", __iconNode$m);
664
+ const CalendarDays = createLucideIcon("calendar-days", __iconNode$k);
665
665
 
666
666
  /**
667
667
  * @license lucide-react v1.16.0 - ISC
@@ -671,8 +671,8 @@ const CalendarDays = createLucideIcon("calendar-days", __iconNode$m);
671
671
  */
672
672
 
673
673
 
674
- const __iconNode$l = [["path", { d: "m6 9 6 6 6-6", key: "qrunsl" }]];
675
- const ChevronDown = createLucideIcon("chevron-down", __iconNode$l);
674
+ const __iconNode$j = [["path", { d: "m6 9 6 6 6-6", key: "qrunsl" }]];
675
+ const ChevronDown = createLucideIcon("chevron-down", __iconNode$j);
676
676
 
677
677
  /**
678
678
  * @license lucide-react v1.16.0 - ISC
@@ -682,8 +682,8 @@ const ChevronDown = createLucideIcon("chevron-down", __iconNode$l);
682
682
  */
683
683
 
684
684
 
685
- const __iconNode$k = [["path", { d: "m15 18-6-6 6-6", key: "1wnfg3" }]];
686
- const ChevronLeft = createLucideIcon("chevron-left", __iconNode$k);
685
+ const __iconNode$i = [["path", { d: "m15 18-6-6 6-6", key: "1wnfg3" }]];
686
+ const ChevronLeft = createLucideIcon("chevron-left", __iconNode$i);
687
687
 
688
688
  /**
689
689
  * @license lucide-react v1.16.0 - ISC
@@ -693,8 +693,8 @@ const ChevronLeft = createLucideIcon("chevron-left", __iconNode$k);
693
693
  */
694
694
 
695
695
 
696
- const __iconNode$j = [["path", { d: "m9 18 6-6-6-6", key: "mthhwq" }]];
697
- const ChevronRight = createLucideIcon("chevron-right", __iconNode$j);
696
+ const __iconNode$h = [["path", { d: "m9 18 6-6-6-6", key: "mthhwq" }]];
697
+ const ChevronRight = createLucideIcon("chevron-right", __iconNode$h);
698
698
 
699
699
  /**
700
700
  * @license lucide-react v1.16.0 - ISC
@@ -704,8 +704,8 @@ const ChevronRight = createLucideIcon("chevron-right", __iconNode$j);
704
704
  */
705
705
 
706
706
 
707
- const __iconNode$i = [["path", { d: "m18 15-6-6-6 6", key: "153udz" }]];
708
- const ChevronUp = createLucideIcon("chevron-up", __iconNode$i);
707
+ const __iconNode$g = [["path", { d: "m18 15-6-6-6 6", key: "153udz" }]];
708
+ const ChevronUp = createLucideIcon("chevron-up", __iconNode$g);
709
709
 
710
710
  /**
711
711
  * @license lucide-react v1.16.0 - ISC
@@ -715,11 +715,11 @@ const ChevronUp = createLucideIcon("chevron-up", __iconNode$i);
715
715
  */
716
716
 
717
717
 
718
- const __iconNode$h = [
718
+ const __iconNode$f = [
719
719
  ["path", { d: "m7 15 5 5 5-5", key: "1hf1tw" }],
720
720
  ["path", { d: "m7 9 5-5 5 5", key: "sgt6xg" }]
721
721
  ];
722
- const ChevronsUpDown = createLucideIcon("chevrons-up-down", __iconNode$h);
722
+ const ChevronsUpDown = createLucideIcon("chevrons-up-down", __iconNode$f);
723
723
 
724
724
  /**
725
725
  * @license lucide-react v1.16.0 - ISC
@@ -729,12 +729,12 @@ const ChevronsUpDown = createLucideIcon("chevrons-up-down", __iconNode$h);
729
729
  */
730
730
 
731
731
 
732
- const __iconNode$g = [
732
+ const __iconNode$e = [
733
733
  ["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }],
734
734
  ["line", { x1: "12", x2: "12", y1: "8", y2: "12", key: "1pkeuh" }],
735
735
  ["line", { x1: "12", x2: "12.01", y1: "16", y2: "16", key: "4dfq90" }]
736
736
  ];
737
- const CircleAlert = createLucideIcon("circle-alert", __iconNode$g);
737
+ const CircleAlert = createLucideIcon("circle-alert", __iconNode$e);
738
738
 
739
739
  /**
740
740
  * @license lucide-react v1.16.0 - ISC
@@ -744,11 +744,11 @@ const CircleAlert = createLucideIcon("circle-alert", __iconNode$g);
744
744
  */
745
745
 
746
746
 
747
- const __iconNode$f = [
747
+ const __iconNode$d = [
748
748
  ["path", { d: "M21.801 10A10 10 0 1 1 17 3.335", key: "yps3ct" }],
749
749
  ["path", { d: "m9 11 3 3L22 4", key: "1pflzl" }]
750
750
  ];
751
- const CircleCheckBig = createLucideIcon("circle-check-big", __iconNode$f);
751
+ const CircleCheckBig = createLucideIcon("circle-check-big", __iconNode$d);
752
752
 
753
753
  /**
754
754
  * @license lucide-react v1.16.0 - ISC
@@ -758,12 +758,12 @@ const CircleCheckBig = createLucideIcon("circle-check-big", __iconNode$f);
758
758
  */
759
759
 
760
760
 
761
- const __iconNode$e = [
761
+ const __iconNode$c = [
762
762
  ["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }],
763
763
  ["path", { d: "M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3", key: "1u773s" }],
764
764
  ["path", { d: "M12 17h.01", key: "p32p05" }]
765
765
  ];
766
- const CircleQuestionMark = createLucideIcon("circle-question-mark", __iconNode$e);
766
+ const CircleQuestionMark = createLucideIcon("circle-question-mark", __iconNode$c);
767
767
 
768
768
  /**
769
769
  * @license lucide-react v1.16.0 - ISC
@@ -773,12 +773,12 @@ const CircleQuestionMark = createLucideIcon("circle-question-mark", __iconNode$e
773
773
  */
774
774
 
775
775
 
776
- const __iconNode$d = [
776
+ const __iconNode$b = [
777
777
  ["rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", key: "afitv7" }],
778
778
  ["path", { d: "M9 3v18", key: "fh3hqa" }],
779
779
  ["path", { d: "M15 3v18", key: "14nvp0" }]
780
780
  ];
781
- const Columns3 = createLucideIcon("columns-3", __iconNode$d);
781
+ const Columns3 = createLucideIcon("columns-3", __iconNode$b);
782
782
 
783
783
  /**
784
784
  * @license lucide-react v1.16.0 - ISC
@@ -788,38 +788,12 @@ const Columns3 = createLucideIcon("columns-3", __iconNode$d);
788
788
  */
789
789
 
790
790
 
791
- const __iconNode$c = [
791
+ const __iconNode$a = [
792
792
  ["path", { d: "M2 5h20", key: "1fs1ex" }],
793
793
  ["path", { d: "M6 12h12", key: "8npq4p" }],
794
794
  ["path", { d: "M9 19h6", key: "456am0" }]
795
795
  ];
796
- const ListFilter = createLucideIcon("list-filter", __iconNode$c);
797
-
798
- /**
799
- * @license lucide-react v1.16.0 - ISC
800
- *
801
- * This source code is licensed under the ISC license.
802
- * See the LICENSE file in the root directory of this source tree.
803
- */
804
-
805
-
806
- const __iconNode$b = [["path", { d: "M5 12h14", key: "1ays0h" }]];
807
- const Minus = createLucideIcon("minus", __iconNode$b);
808
-
809
- /**
810
- * @license lucide-react v1.16.0 - ISC
811
- *
812
- * This source code is licensed under the ISC license.
813
- * See the LICENSE file in the root directory of this source tree.
814
- */
815
-
816
-
817
- const __iconNode$a = [
818
- ["rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", key: "afitv7" }],
819
- ["path", { d: "M9 3v18", key: "fh3hqa" }],
820
- ["path", { d: "m16 15-3-3 3-3", key: "14y99z" }]
821
- ];
822
- const PanelLeftClose = createLucideIcon("panel-left-close", __iconNode$a);
796
+ const ListFilter = createLucideIcon("list-filter", __iconNode$a);
823
797
 
824
798
  /**
825
799
  * @license lucide-react v1.16.0 - ISC
@@ -829,12 +803,8 @@ const PanelLeftClose = createLucideIcon("panel-left-close", __iconNode$a);
829
803
  */
830
804
 
831
805
 
832
- const __iconNode$9 = [
833
- ["rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", key: "afitv7" }],
834
- ["path", { d: "M9 3v18", key: "fh3hqa" }],
835
- ["path", { d: "m14 9 3 3-3 3", key: "8010ee" }]
836
- ];
837
- const PanelLeftOpen = createLucideIcon("panel-left-open", __iconNode$9);
806
+ const __iconNode$9 = [["path", { d: "M5 12h14", key: "1ays0h" }]];
807
+ const Minus = createLucideIcon("minus", __iconNode$9);
838
808
 
839
809
  /**
840
810
  * @license lucide-react v1.16.0 - ISC
@@ -2781,15 +2751,18 @@ function NeoDataGrid({ autoHeight = false, toolbar, slots, sx, density = 'standa
2781
2751
  ...getDataGridHeaderStyles(),
2782
2752
  ...getDataGridRowStyles(),
2783
2753
  border: `1px solid ${semanticColors.border.secondary}`,
2784
- // Style row selection checkboxes to match header (16px, proper spacing).
2785
- // Target `& svg` (not `.MuiSvgIcon-root`) so the rule also matches the
2786
- // lucide `<svg>` icons NeoCheckbox renders, mirroring the header rule.
2754
+ // Target `& svg` (not `.MuiSvgIcon-root`) to match the lucide icons
2755
+ // NeoCheckbox renders, mirroring the header rule below.
2756
+ // flexShrink: 0 stops the icon collapsing to 0 width when the checkbox
2757
+ // column is narrower than the 32px box (16px icon + 16px padding) —
2758
+ // without it the checkbox becomes invisible but stays clickable.
2787
2759
  [`& .${gridClasses.cellCheckbox}`]: {
2788
2760
  [`& .${checkboxClasses.root}`]: {
2789
2761
  padding: `${spacing.spacing_1}px`,
2790
2762
  '& svg': {
2791
2763
  width: 16,
2792
2764
  height: 16,
2765
+ flexShrink: 0,
2793
2766
  },
2794
2767
  },
2795
2768
  },
@@ -6417,7 +6390,7 @@ const NeoSelectField = ({ size = 'medium', destructive = false, label, required
6417
6390
  NeoSelectField.displayName = 'NeoSelectField';
6418
6391
 
6419
6392
  const EXPANDED_WIDTH = 98;
6420
- const COLLAPSED_WIDTH = 56;
6393
+ const COLLAPSED_WIDTH = 68;
6421
6394
  // The fade overlay must end on the same color as the rail to blend cleanly.
6422
6395
  const RAIL_BACKGROUND = colors.grey[100];
6423
6396
  /**
@@ -6427,8 +6400,28 @@ const RAIL_BACKGROUND = colors.grey[100];
6427
6400
  * scrolling content area. Controlled via `collapsed` + `onCollapsedChange`;
6428
6401
  * broadcasts collapsed state to descendant `NeoNavigationItem`s through context.
6429
6402
  *
6403
+ * A chevron handle on the rail's trailing edge (beside the tenant-logo row)
6404
+ * toggles the controlled state. Consumers that want the rail to auto-collapse
6405
+ * on viewport changes compute `collapsed` themselves (e.g. via `useMediaQuery`)
6406
+ * and pass it in — see the `AutoCollapseOnResize` Storybook story for the
6407
+ * pattern.
6408
+ *
6430
6409
  * @figma https://www.figma.com/design/fQTkGSFbYyE7LiHuQJsENC?node-id=4065-3425
6431
6410
  */
6411
+ // Unclipped positioning context so the edge handle can straddle the rail's
6412
+ // trailing edge (Root itself clips its overflow during the width transition).
6413
+ const Frame = styled('div', {
6414
+ shouldForwardProp: prop => prop !== 'collapsed',
6415
+ })(({ collapsed, theme }) => ({
6416
+ position: 'relative',
6417
+ display: 'flex',
6418
+ height: '100%',
6419
+ width: collapsed ? COLLAPSED_WIDTH : EXPANDED_WIDTH,
6420
+ minWidth: collapsed ? COLLAPSED_WIDTH : EXPANDED_WIDTH,
6421
+ transition: theme.transitions.create(['width', 'min-width'], {
6422
+ duration: theme.transitions.duration.shorter,
6423
+ }),
6424
+ }));
6432
6425
  const Root = styled('nav', {
6433
6426
  shouldForwardProp: prop => prop !== 'collapsed',
6434
6427
  })(({ collapsed, theme }) => ({
@@ -6454,6 +6447,10 @@ const Scroll = styled('div')({
6454
6447
  minHeight: 0,
6455
6448
  overflowY: 'auto',
6456
6449
  overflowX: 'hidden',
6450
+ // Reserve the scrollbar gutter symmetrically on both edges at all times, so
6451
+ // the centered nav items stay aligned with the header/footer icons and don't
6452
+ // jump when the scrollbar shows or hides.
6453
+ scrollbarGutter: 'stable both-edges',
6457
6454
  display: 'flex',
6458
6455
  flexDirection: 'column',
6459
6456
  alignItems: 'center',
@@ -6461,7 +6458,7 @@ const Scroll = styled('div')({
6461
6458
  paddingInline: spacing.spacing_1,
6462
6459
  '&::-webkit-scrollbar': { width: spacing.spacing_1_2 },
6463
6460
  '&::-webkit-scrollbar-thumb': {
6464
- backgroundColor: semanticColors.border.primary,
6461
+ backgroundColor: semanticColors.border.secondary,
6465
6462
  borderRadius: borderRadius.xXS,
6466
6463
  },
6467
6464
  });
@@ -6485,29 +6482,34 @@ const Fade = styled('div')({
6485
6482
  pointerEvents: 'none',
6486
6483
  background: `linear-gradient(to bottom, transparent, ${RAIL_BACKGROUND})`,
6487
6484
  });
6488
- const Toggle = styled(ButtonBase)(({ theme }) => ({
6485
+ // A small rectangular tab that straddles the rail's trailing edge, pinned down
6486
+ // beside the tenant-logo row (not floating at the rail's vertical center) so
6487
+ // it reads as attached to the panel.
6488
+ const Handle = styled(ButtonBase)(({ theme }) => ({
6489
+ position: 'absolute',
6490
+ right: 0,
6491
+ bottom: spacing.spacing_1,
6492
+ transform: 'translateX(50%)',
6493
+ zIndex: 1,
6489
6494
  display: 'flex',
6490
6495
  alignItems: 'center',
6491
6496
  justifyContent: 'center',
6492
- flexDirection: 'column',
6493
- gap: spacing.spacing_1_2,
6494
- width: '100%',
6495
- paddingBlock: spacing.spacing_1,
6497
+ width: spacing.spacing_1_1_2,
6498
+ height: spacing.spacing_5,
6496
6499
  borderRadius: borderRadius.s,
6500
+ backgroundColor: RAIL_BACKGROUND,
6497
6501
  border: `1px solid ${semanticColors.border.secondary}`,
6498
6502
  color: semanticColors.typography.bodySecondary,
6499
- fontFamily: typography.fontFamily.body,
6500
- fontSize: theme.typography.pxToRem(11),
6501
- lineHeight: 1,
6503
+ transition: theme.transitions.create(['color', 'border-color']),
6502
6504
  '&:hover': {
6503
6505
  color: semanticColors.typography.body,
6504
6506
  borderColor: semanticColors.border.primary,
6505
6507
  },
6506
6508
  }));
6507
- function NeoSideNav({ collapsed, onCollapsedChange, header, footer, children, collapseLabel = 'Less', ...rest }) {
6508
- const ToggleIcon = collapsed ? PanelLeftOpen : PanelLeftClose;
6509
+ function NeoSideNav({ collapsed, onCollapsedChange, header, footer, children, className, id, 'aria-label': ariaLabel, }) {
6509
6510
  const contextValue = useMemo(() => ({ collapsed }), [collapsed]);
6510
- return (jsx(NeoSideNavContext.Provider, { value: contextValue, children: jsxs(Root, { collapsed: collapsed, ...rest, children: [header && jsx(Header, { children: header }), jsx(Scroll, { children: children }), jsxs(FooterRegion, { children: [jsx(Fade, {}), footer, jsxs(Toggle, { "data-testid": "neo-side-nav-toggle", "aria-label": collapsed ? 'Expand navigation' : 'Collapse navigation', disableRipple: true, onClick: () => onCollapsedChange(!collapsed), children: [jsx(ToggleIcon, { size: 18 }), !collapsed && jsx("span", { children: collapseLabel })] })] })] }) }));
6511
+ const HandleIcon = collapsed ? ChevronRight : ChevronLeft;
6512
+ return (jsx(NeoSideNavContext.Provider, { value: contextValue, children: jsxs(Frame, { collapsed: collapsed, children: [jsxs(Root, { collapsed: collapsed, "aria-label": ariaLabel, className: className, id: id, children: [header && jsx(Header, { children: header }), jsx(Scroll, { children: children }), jsxs(FooterRegion, { children: [jsx(Fade, {}), footer] })] }), jsx(Handle, { "data-testid": "neo-side-nav-handle", "aria-label": collapsed ? 'Expand navigation' : 'Collapse navigation', disableRipple: true, onClick: () => onCollapsedChange(!collapsed), children: jsx(HandleIcon, { size: 14 }) })] }) }));
6511
6513
  }
6512
6514
  NeoSideNav.displayName = 'NeoSideNav';
6513
6515