@common-origin/design-system 3.1.0 → 3.3.0

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.
Files changed (89) hide show
  1. package/dist/client.js +1050 -722
  2. package/dist/client.js.map +1 -1
  3. package/dist/components/atoms/Badge/Badge.d.mts +2 -2
  4. package/dist/components/atoms/Badge/Badge.d.ts +2 -2
  5. package/dist/components/atoms/Badge/Badge.mjs +15 -9
  6. package/dist/components/atoms/Box/Box.d.mts +3 -2
  7. package/dist/components/atoms/Box/Box.d.ts +3 -2
  8. package/dist/components/atoms/Button/Button.mjs +1 -1
  9. package/dist/components/atoms/Chip/shared/ChipBase.mjs +1 -1
  10. package/dist/components/atoms/Icon/Icon.d.mts +1 -1
  11. package/dist/components/atoms/Icon/Icon.d.ts +1 -1
  12. package/dist/components/atoms/Icon/Icon.mjs +35 -10
  13. package/dist/components/atoms/IconButton/IconButton.mjs +1 -1
  14. package/dist/components/atoms/ProgressBar/ProgressBar.d.mts +1 -1
  15. package/dist/components/atoms/ProgressBar/ProgressBar.d.ts +1 -1
  16. package/dist/components/atoms/Tag/Tag.d.mts +1 -1
  17. package/dist/components/atoms/Tag/Tag.d.ts +1 -1
  18. package/dist/components/atoms/Tooltip/Tooltip.d.mts +7 -1
  19. package/dist/components/atoms/Tooltip/Tooltip.d.ts +7 -1
  20. package/dist/components/atoms/Tooltip/Tooltip.mjs +18 -8
  21. package/dist/components/molecules/ActionSheet/ActionSheet.mjs +2 -2
  22. package/dist/components/molecules/Alert/Alert.mjs +1 -1
  23. package/dist/components/molecules/Checkbox/SelectableInputBase.mjs +1 -1
  24. package/dist/components/molecules/Dropdown/Dropdown.mjs +1 -1
  25. package/dist/components/molecules/List/ListItem.mjs +3 -3
  26. package/dist/components/molecules/Menu/Menu.d.mts +8 -1
  27. package/dist/components/molecules/Menu/Menu.d.ts +8 -1
  28. package/dist/components/molecules/Menu/Menu.mjs +12 -9
  29. package/dist/components/molecules/Modal/Modal.mjs +1 -1
  30. package/dist/components/molecules/NumberInput/NumberInput.mjs +2 -1
  31. package/dist/components/molecules/PasswordField/PasswordField.mjs +3 -2
  32. package/dist/components/molecules/SearchField/SearchField.mjs +3 -3
  33. package/dist/components/molecules/Sheet/Sheet.mjs +3 -3
  34. package/dist/components/molecules/SidebarNavItem/SidebarNavItem.d.mts +3 -2
  35. package/dist/components/molecules/SidebarNavItem/SidebarNavItem.d.ts +3 -2
  36. package/dist/components/molecules/SidebarNavItem/SidebarNavItem.mjs +128 -41
  37. package/dist/components/molecules/SidebarNavItem/sidebarNavMotion.d.mts +30 -0
  38. package/dist/components/molecules/SidebarNavItem/sidebarNavMotion.d.ts +30 -0
  39. package/dist/components/molecules/SidebarNavItem/sidebarNavMotion.mjs +69 -0
  40. package/dist/components/molecules/SidebarNavItem/sidebarNavMotion.mjs.map +1 -0
  41. package/dist/components/molecules/SidebarNavSection/SidebarNavSection.mjs +57 -43
  42. package/dist/components/molecules/TabBar/TabBar.mjs +3 -3
  43. package/dist/components/molecules/WorkspaceSwitcher/WorkspaceSwitcher.mjs +3 -1
  44. package/dist/components/organisms/SidebarNav/SidebarNav.mjs +173 -62
  45. package/dist/data.js +2680 -190
  46. package/dist/data.js.map +1 -1
  47. package/dist/index.d.mts +2 -1
  48. package/dist/index.d.ts +2 -1
  49. package/dist/index.js +1 -0
  50. package/dist/index.js.map +1 -1
  51. package/dist/index.mjs +1 -0
  52. package/dist/index.mjs.map +1 -1
  53. package/dist/lib/statusShapes.mjs +1 -1
  54. package/dist/lib/statusShapes.mjs.map +1 -1
  55. package/dist/lib/styleUtils.d.mts +4 -0
  56. package/dist/lib/styleUtils.d.ts +4 -0
  57. package/dist/lib/styleUtils.mjs +5 -1
  58. package/dist/lib/styleUtils.mjs.map +1 -1
  59. package/dist/lib/tokenAliases.mjs +1 -0
  60. package/dist/lib/tokenAliases.mjs.map +1 -1
  61. package/dist/lib/useFloatingLayer.d.mts +8 -1
  62. package/dist/lib/useFloatingLayer.d.ts +8 -1
  63. package/dist/lib/useFloatingLayer.mjs +11 -2
  64. package/dist/lib/useFloatingLayer.mjs.map +1 -1
  65. package/dist/styles/iconSet.json.mjs +2442 -0
  66. package/dist/styles/iconSet.json.mjs.map +1 -0
  67. package/dist/styles/tokens.d.mts +93 -24
  68. package/dist/styles/tokens.d.ts +93 -24
  69. package/dist/styles/tokens.json +96 -59
  70. package/dist/styles/tokens.json.mjs +96 -59
  71. package/dist/styles/tokens.json.mjs.map +1 -1
  72. package/dist/tokens/index.js +96 -59
  73. package/dist/tokens/index.js.map +1 -1
  74. package/dist/tokens/index.mjs +96 -59
  75. package/dist/tokens/index.mjs.map +1 -1
  76. package/dist/tokens/styles/tokens.d.mts +93 -24
  77. package/dist/tokens/styles/tokens.d.ts +93 -24
  78. package/dist/tokens.css +1105 -74
  79. package/dist/types/iconSet.d.mts +6 -0
  80. package/dist/types/iconSet.d.ts +6 -0
  81. package/dist/types/iconSet.mjs +12 -0
  82. package/dist/types/iconSet.mjs.map +1 -0
  83. package/dist/types/icons.d.mts +58 -6
  84. package/dist/types/icons.d.ts +58 -6
  85. package/dist/types/icons.mjs +5 -0
  86. package/dist/types/icons.mjs.map +1 -1
  87. package/dist/types/index.d.mts +1 -0
  88. package/dist/types/index.d.ts +1 -0
  89. package/package.json +7 -3
@@ -8,7 +8,7 @@ import tokens from '../../../lib/cssTokens.mjs';
8
8
  import { exitAnimation, reducedMotion, forcedColorsEdge, interactiveRow } from '../../../lib/styleUtils.mjs';
9
9
  import { usePresence } from '../../../lib/usePresence.mjs';
10
10
  import { laidOutElement } from '../../../lib/floatingPosition.mjs';
11
- import { useIsomorphicLayoutEffect, useFloatingLayer } from '../../../lib/useFloatingLayer.mjs';
11
+ import { ANCHOR_WIDTH_VAR, useIsomorphicLayoutEffect, useFloatingLayer } from '../../../lib/useFloatingLayer.mjs';
12
12
  import { Icon } from '../../atoms/Icon/Icon.mjs';
13
13
 
14
14
  var semantic = tokens.semantic;
@@ -42,9 +42,9 @@ var Panel = /*#__PURE__*/styled.div.withConfig({
42
42
  },
43
43
  displayName: "Menu__Panel",
44
44
  componentId: "sc-13mple2-0"
45
- })(templateObject_5 || (templateObject_5 = __makeTemplateObject(["\n position: fixed;\n inset: auto;\n top: 0;\n left: 0;\n margin: 0;\n box-sizing: border-box;\n min-width: ", ";\n max-width: ", ";\n max-height: ", ";\n overflow-y: auto;\n padding: ", " 0;\n background-color: ", ";\n color: ", ";\n border: ", ";\n border-radius: ", ";\n box-shadow: ", ";\n animation: ", " ", " ", "\n ", ";\n\n ", " {\n animation: ", " ", " ", "\n ", ";\n }\n\n ", "\n\n &:focus {\n outline: none;\n }\n"], ["\n position: fixed;\n inset: auto;\n top: 0;\n left: 0;\n margin: 0;\n box-sizing: border-box;\n min-width: ", ";\n max-width: ", ";\n max-height: ", ";\n overflow-y: auto;\n padding: ", " 0;\n background-color: ", ";\n color: ", ";\n border: ", ";\n border-radius: ", ";\n box-shadow: ", ";\n animation: ", " ", " ", "\n ", ";\n\n ", " {\n animation: ", " ", " ", "\n ", ";\n }\n\n ", "\n\n &:focus {\n outline: none;\n }\n"
45
+ })(templateObject_5 || (templateObject_5 = __makeTemplateObject(["\n position: fixed;\n inset: auto;\n top: 0;\n left: 0;\n margin: 0;\n box-sizing: border-box;\n /* At least the trigger's width when matchTriggerWidth sets the variable, within the usual range */\n min-width: min(max(", ", var(", ", 0px)), ", ");\n max-width: ", ";\n max-height: ", ";\n overflow-y: auto;\n padding: ", " 0;\n background-color: ", ";\n color: ", ";\n border: ", ";\n border-radius: ", ";\n box-shadow: ", ";\n animation: ", " ", " ", "\n ", ";\n\n ", " {\n animation: ", " ", " ", "\n ", ";\n }\n\n ", "\n\n &:focus {\n outline: none;\n }\n"], ["\n position: fixed;\n inset: auto;\n top: 0;\n left: 0;\n margin: 0;\n box-sizing: border-box;\n /* At least the trigger's width when matchTriggerWidth sets the variable, within the usual range */\n min-width: min(max(", ", var(", ", 0px)), ", ");\n max-width: ", ";\n max-height: ", ";\n overflow-y: auto;\n padding: ", " 0;\n background-color: ", ";\n color: ", ";\n border: ", ";\n border-radius: ", ";\n box-shadow: ", ";\n animation: ", " ", " ", "\n ", ";\n\n ", " {\n animation: ", " ", " ", "\n ", ";\n }\n\n ", "\n\n &:focus {\n outline: none;\n }\n"
46
46
  // The trigger's wrapper takes no box of its own
47
- ])), size[4500], size[7500], size.menu.maxHeight, space[100], semantic.surface.raised, color.text["default"], border["default"], radius.md, elevation.floating, enter, motion.duration.fast, motion.easing.decelerate, function (_a) {
47
+ ])), size[4500], ANCHOR_WIDTH_VAR, size[7500], size[7500], size.menu.maxHeight, space[100], semantic.surface.overlay, color.text["default"], border["default"], radius.md, elevation.floating, enter, motion.duration.fast, motion.easing.decelerate, function (_a) {
48
48
  var $exiting = _a.$exiting;
49
49
  return $exiting ? exitAnimation : css(templateObject_3 || (templateObject_3 = __makeTemplateObject([""], [""])));
50
50
  }, reducedMotion, fade, motion.duration.fast, motion.easing.decelerate, function (_a) {
@@ -76,6 +76,8 @@ var Menu = function Menu(_a) {
76
76
  side = _c === void 0 ? 'bottom' : _c,
77
77
  _d = _a.align,
78
78
  align = _d === void 0 ? 'start' : _d,
79
+ _e = _a.matchTriggerWidth,
80
+ matchTriggerWidth = _e === void 0 ? false : _e,
79
81
  dataTestId = _a["data-testid"];
80
82
  var menuId = useId();
81
83
  var triggerId = useId();
@@ -88,14 +90,14 @@ var Menu = function Menu(_a) {
88
90
  text: '',
89
91
  timer: undefined
90
92
  });
91
- var _e = useState(defaultOpen),
92
- uncontrolledOpen = _e[0],
93
- setUncontrolledOpen = _e[1];
93
+ var _f = useState(defaultOpen),
94
+ uncontrolledOpen = _f[0],
95
+ setUncontrolledOpen = _f[1];
94
96
  var isControlled = openProp !== undefined;
95
97
  var isOpen = isControlled ? openProp : uncontrolledOpen;
96
- var _f = usePresence(isOpen),
97
- isPresent = _f.isPresent,
98
- isExiting = _f.isExiting;
98
+ var _g = usePresence(isOpen),
99
+ isPresent = _g.isPresent,
100
+ isExiting = _g.isExiting;
99
101
  var triggerElement = function triggerElement() {
100
102
  return laidOutElement(anchorRef.current);
101
103
  };
@@ -146,6 +148,7 @@ var Menu = function Menu(_a) {
146
148
  anchorRef: anchorRef,
147
149
  side: side,
148
150
  align: align,
151
+ matchAnchorWidth: matchTriggerWidth,
149
152
  onDetach: detach
150
153
  });
151
154
  // Opening from the trigger focuses the first or last item. An open that didn't come from the
@@ -54,7 +54,7 @@ var StyledDialog = /*#__PURE__*/styled.div.withConfig({
54
54
  })(templateObject_6 || (templateObject_6 = __makeTemplateObject(["\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%) scale(1);\n z-index: ", ";\n\n width: ", ";\n max-width: calc(100vw - ", " * 2);\n max-height: calc(100vh - ", " * 2);\n\n display: flex;\n flex-direction: column;\n\n background-color: ", ";\n border-radius: ", ";\n box-shadow: ", ";\n overflow: hidden;\n\n ", "\n\n ", " {\n animation: ", " ", " ", "", ";\n }\n\n /* Auto-fullscreen below md breakpoint (768px) */\n @media (max-width: ", ") {\n width: 100vw;\n height: 100vh;\n max-width: 100vw;\n max-height: 100vh;\n border-radius: 0;\n top: 0;\n left: 0;\n transform: none;\n animation: ", " ", " ", "", ";\n }\n\n &:focus {\n outline: none;\n }\n\n"], ["\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%) scale(1);\n z-index: ", ";\n\n width: ", ";\n max-width: calc(100vw - ", " * 2);\n max-height: calc(100vh - ", " * 2);\n\n display: flex;\n flex-direction: column;\n\n background-color: ", ";\n border-radius: ", ";\n box-shadow: ", ";\n overflow: hidden;\n\n ", "\n\n ", " {\n animation: ", " ", " ", "", ";\n }\n\n /* Auto-fullscreen below md breakpoint (768px) */\n @media (max-width: ", ") {\n width: 100vw;\n height: 100vh;\n max-width: 100vw;\n max-height: 100vh;\n border-radius: 0;\n top: 0;\n left: 0;\n transform: none;\n animation: ", " ", " ", "", ";\n }\n\n &:focus {\n outline: none;\n }\n\n"])), semantic.layer.modal, function (_a) {
55
55
  var $width = _a.$width;
56
56
  return $width;
57
- }, space[400], space[400], semantic.surface.raised, semantic.radius.xl, elevation.overlay, css(templateObject_5 || (templateObject_5 = __makeTemplateObject(["animation: ", " ", " ", "", ";"], ["animation: ", " ", " ", "", ";"])), scaleIn, motion.duration.moderate, motion.easing.decelerate, function (_a) {
57
+ }, space[400], space[400], semantic.surface.overlay, tokens.component.overlay.borderRadius, elevation.overlay, css(templateObject_5 || (templateObject_5 = __makeTemplateObject(["animation: ", " ", " ", "", ";"], ["animation: ", " ", " ", "", ";"])), scaleIn, motion.duration.moderate, motion.easing.decelerate, function (_a) {
58
58
  var $isExiting = _a.$isExiting;
59
59
  return $isExiting && exitAnimation;
60
60
  }), reducedMotion, fadeIn, motion.duration.moderate, motion.easing.decelerate, function (_a) {
@@ -7,6 +7,7 @@ const styled = styled$module.default || styled$module;
7
7
  import { StyledInputBase } from '../TextField/InputBase.mjs';
8
8
  import { IconButton } from '../../atoms/IconButton/IconButton.mjs';
9
9
  import tokens from '../../../lib/cssTokens.mjs';
10
+ import { fieldButtonRadius } from '../../../lib/styleUtils.mjs';
10
11
 
11
12
  var field = tokens.component.field;
12
13
  // Gaps come from the semantic spacing scale: no component spacing tokens (decision 0022)
@@ -34,7 +35,7 @@ var StyledNumberInput = /*#__PURE__*/styled(StyledInputBase).withConfig({
34
35
  var StyledStepperContainer = /*#__PURE__*/styled.div.withConfig({
35
36
  displayName: "NumberInput__StyledStepperContainer",
36
37
  componentId: "sc-qotc3w-5"
37
- })(templateObject_6 || (templateObject_6 = __makeTemplateObject(["\n position: absolute;\n right: ", ";\n display: flex;\n flex-direction: row;\n gap: ", ";\n"], ["\n position: absolute;\n right: ", ";\n display: flex;\n flex-direction: row;\n gap: ", ";\n"])), tokens.semantic.space[200], tokens.semantic.space[200]);
38
+ })(templateObject_6 || (templateObject_6 = __makeTemplateObject(["\n position: absolute;\n right: ", ";\n display: flex;\n flex-direction: row;\n gap: ", ";\n\n /* Buttons inside the field nest within its corner: a step tighter than the control radius (decision 0055) */\n & > button {\n border-radius: ", ";\n }\n"], ["\n position: absolute;\n right: ", ";\n display: flex;\n flex-direction: row;\n gap: ", ";\n\n /* Buttons inside the field nest within its corner: a step tighter than the control radius (decision 0055) */\n & > button {\n border-radius: ", ";\n }\n"])), tokens.semantic.space[200], tokens.semantic.space[200], fieldButtonRadius);
38
39
  var StyledHelperText = /*#__PURE__*/styled.div.withConfig({
39
40
  displayName: "NumberInput__StyledHelperText",
40
41
  componentId: "sc-qotc3w-6"
@@ -7,6 +7,7 @@ const styled = styled$module.default || styled$module;
7
7
  import { StyledInputBase } from '../TextField/InputBase.mjs';
8
8
  import { IconButton } from '../../atoms/IconButton/IconButton.mjs';
9
9
  import tokens from '../../../lib/cssTokens.mjs';
10
+ import { fieldButtonRadius } from '../../../lib/styleUtils.mjs';
10
11
 
11
12
  var field = tokens.component.field;
12
13
  // Gaps come from the semantic spacing scale: no component spacing tokens (decision 0022)
@@ -37,7 +38,7 @@ var StyledInputWrapper = /*#__PURE__*/styled.div.withConfig({
37
38
  var StyledToggleButton = /*#__PURE__*/styled.div.withConfig({
38
39
  displayName: "PasswordField__StyledToggleButton",
39
40
  componentId: "sc-1p15zk0-5"
40
- })(templateObject_6 || (templateObject_6 = __makeTemplateObject(["\n position: absolute;\n right: ", ";\n top: 50%;\n transform: translateY(-50%);\n"], ["\n position: absolute;\n right: ", ";\n top: 50%;\n transform: translateY(-50%);\n"
41
+ })(templateObject_6 || (templateObject_6 = __makeTemplateObject(["\n position: absolute;\n right: ", ";\n top: 50%;\n transform: translateY(-50%);\n\n /* Buttons inside the field nest within its corner: a step tighter than the control radius (decision 0055) */\n & > button {\n border-radius: ", ";\n }\n"], ["\n position: absolute;\n right: ", ";\n top: 50%;\n transform: translateY(-50%);\n\n /* Buttons inside the field nest within its corner: a step tighter than the control radius (decision 0055) */\n & > button {\n border-radius: ", ";\n }\n"
41
42
  /**
42
43
  * PasswordField component for secure password input with visibility toggle
43
44
  *
@@ -49,7 +50,7 @@ var StyledToggleButton = /*#__PURE__*/styled.div.withConfig({
49
50
  * required
50
51
  * />
51
52
  * ```
52
- */])), tokens.semantic.space[200]);
53
+ */])), tokens.semantic.space[200], fieldButtonRadius);
53
54
  /**
54
55
  * PasswordField component for secure password input with visibility toggle
55
56
  *
@@ -8,7 +8,7 @@ import { Icon } from '../../atoms/Icon/Icon.mjs';
8
8
  import { IconButton } from '../../atoms/IconButton/IconButton.mjs';
9
9
  import { ListItem } from '../List/ListItem.mjs';
10
10
  import tokens from '../../../lib/cssTokens.mjs';
11
- import { rowStates } from '../../../lib/styleUtils.mjs';
11
+ import { fieldButtonRadius, rowStates } from '../../../lib/styleUtils.mjs';
12
12
 
13
13
  var semantic = tokens.semantic,
14
14
  component = tokens.component;
@@ -19,7 +19,7 @@ var StyledSearchContainer = /*#__PURE__*/styled.div.withConfig({
19
19
  var StyledInputWrapper = /*#__PURE__*/styled.div.withConfig({
20
20
  displayName: "SearchField__StyledInputWrapper",
21
21
  componentId: "sc-qhz9i8-1"
22
- })(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n display: flex;\n align-items: center;\n gap: ", ";\n /* The field's height comes from size.control.lg as a minimum, matching the other fields\n (decision 0034); the padding only matters if the content grows past it */\n box-sizing: border-box;\n min-height: ", ";\n padding: ", " ", ";\n background-color: ", ";\n border: ", " solid ", ";\n border-radius: ", ";\n transition: border-color ", " ", ", outline ", " ", ";\n \n ", "\n \n ", "\n \n &:hover:not([data-disabled='true']) {\n border-color: ", ";\n }\n"], ["\n display: flex;\n align-items: center;\n gap: ", ";\n /* The field's height comes from size.control.lg as a minimum, matching the other fields\n (decision 0034); the padding only matters if the content grows past it */\n box-sizing: border-box;\n min-height: ", ";\n padding: ", " ", ";\n background-color: ", ";\n border: ", " solid ", ";\n border-radius: ", ";\n transition: border-color ", " ", ", outline ", " ", ";\n \n ", "\n \n ", "\n \n &:hover:not([data-disabled='true']) {\n border-color: ", ";\n }\n"])), semantic.space[200], semantic.size.control.lg, semantic.space[200], semantic.space[300], component.input["default"].backgroundColor, component.input["default"].borderWidth, component.input["default"].borderColor, component.input["default"].borderRadius, semantic.motion.duration.moderate, semantic.motion.easing.standard, semantic.motion.duration.moderate, semantic.motion.easing.standard, function (props) {
22
+ })(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n display: flex;\n align-items: center;\n gap: ", ";\n /* The field's height comes from size.control.lg as a minimum, matching the other fields\n (decision 0034); the padding only matters if the content grows past it */\n box-sizing: border-box;\n min-height: ", ";\n padding: ", " ", ";\n background-color: ", ";\n border: ", " solid ", ";\n border-radius: ", ";\n\n /* Buttons inside the field nest within its corner: a step tighter than the control radius (decision 0055) */\n & > button {\n border-radius: ", ";\n }\n\n transition: border-color ", " ", ", outline ", " ", ";\n \n ", "\n \n ", "\n \n &:hover:not([data-disabled='true']) {\n border-color: ", ";\n }\n"], ["\n display: flex;\n align-items: center;\n gap: ", ";\n /* The field's height comes from size.control.lg as a minimum, matching the other fields\n (decision 0034); the padding only matters if the content grows past it */\n box-sizing: border-box;\n min-height: ", ";\n padding: ", " ", ";\n background-color: ", ";\n border: ", " solid ", ";\n border-radius: ", ";\n\n /* Buttons inside the field nest within its corner: a step tighter than the control radius (decision 0055) */\n & > button {\n border-radius: ", ";\n }\n\n transition: border-color ", " ", ", outline ", " ", ";\n \n ", "\n \n ", "\n \n &:hover:not([data-disabled='true']) {\n border-color: ", ";\n }\n"])), semantic.space[200], semantic.size.control.lg, semantic.space[200], semantic.space[300], component.input["default"].backgroundColor, component.input["default"].borderWidth, component.input["default"].borderColor, component.input["default"].borderRadius, fieldButtonRadius, semantic.motion.duration.moderate, semantic.motion.easing.standard, semantic.motion.duration.moderate, semantic.motion.easing.standard, function (props) {
23
23
  return props.$isFocused && "\n border-color: ".concat(component.input.focus.borderColor, ";\n outline: ").concat(component.input.focus.outline, ";\n outline-offset: ").concat(semantic.border.focusOffset, ";\n ");
24
24
  }, function (props) {
25
25
  return props.$disabled && "\n background-color: ".concat(component.input.disabled.backgroundColor, ";\n border-color: ").concat(component.input.disabled.borderColor, ";\n cursor: not-allowed;\n ");
@@ -31,7 +31,7 @@ var StyledInput = /*#__PURE__*/styled.input.withConfig({
31
31
  var StyledSuggestionsList = /*#__PURE__*/styled.ul.withConfig({
32
32
  displayName: "SearchField__StyledSuggestionsList",
33
33
  componentId: "sc-qhz9i8-3"
34
- })(templateObject_4 || (templateObject_4 = __makeTemplateObject(["\n position: absolute;\n top: calc(100% + ", ");\n left: 0;\n right: 0;\n max-height: ", ";\n overflow-y: auto;\n background-color: ", ";\n border: ", " solid ", ";\n border-radius: ", ";\n box-shadow: ", ";\n list-style: none;\n padding: ", " 0;\n margin: 0;\n z-index: ", ";\n\n /* The highlighted suggestion has keyboard focus, which is grey, not the light-blue selected\n treatment (decision 0029). Its row is the option's first child. While pressed, the row's own\n pressed state shows (decision 0030) */\n & > [data-highlighted] > :first-child:not(:active) {\n background-color: ", ";\n }\n"], ["\n position: absolute;\n top: calc(100% + ", ");\n left: 0;\n right: 0;\n max-height: ", ";\n overflow-y: auto;\n background-color: ", ";\n border: ", " solid ", ";\n border-radius: ", ";\n box-shadow: ", ";\n list-style: none;\n padding: ", " 0;\n margin: 0;\n z-index: ", ";\n\n /* The highlighted suggestion has keyboard focus, which is grey, not the light-blue selected\n treatment (decision 0029). Its row is the option's first child. While pressed, the row's own\n pressed state shows (decision 0030) */\n & > [data-highlighted] > :first-child:not(:active) {\n background-color: ", ";\n }\n"])), semantic.space[100], tokens.semantic.size.menu.maxHeight, semantic.surface.raised, semantic.border.width.thin, semantic.color.border["default"], semantic.radius.md, semantic.elevation.floating, semantic.space[100], semantic.layer.dropdown, rowStates.unselected.hover.background);
34
+ })(templateObject_4 || (templateObject_4 = __makeTemplateObject(["\n position: absolute;\n top: calc(100% + ", ");\n left: 0;\n right: 0;\n max-height: ", ";\n overflow-y: auto;\n background-color: ", ";\n border: ", " solid ", ";\n border-radius: ", ";\n box-shadow: ", ";\n list-style: none;\n padding: ", " 0;\n margin: 0;\n z-index: ", ";\n\n /* The highlighted suggestion has keyboard focus, which is grey, not the light-blue selected\n treatment (decision 0029). Its row is the option's first child. While pressed, the row's own\n pressed state shows (decision 0030) */\n & > [data-highlighted] > :first-child:not(:active) {\n background-color: ", ";\n }\n"], ["\n position: absolute;\n top: calc(100% + ", ");\n left: 0;\n right: 0;\n max-height: ", ";\n overflow-y: auto;\n background-color: ", ";\n border: ", " solid ", ";\n border-radius: ", ";\n box-shadow: ", ";\n list-style: none;\n padding: ", " 0;\n margin: 0;\n z-index: ", ";\n\n /* The highlighted suggestion has keyboard focus, which is grey, not the light-blue selected\n treatment (decision 0029). Its row is the option's first child. While pressed, the row's own\n pressed state shows (decision 0030) */\n & > [data-highlighted] > :first-child:not(:active) {\n background-color: ", ";\n }\n"])), semantic.space[100], tokens.semantic.size.menu.maxHeight, semantic.surface.overlay, semantic.border.width.thin, semantic.color.border["default"], semantic.radius.md, semantic.elevation.floating, semantic.space[100], semantic.layer.dropdown, rowStates.unselected.hover.background);
35
35
  var StyledSectionHeader = /*#__PURE__*/styled.div.withConfig({
36
36
  displayName: "SearchField__StyledSectionHeader",
37
37
  componentId: "sc-qhz9i8-4"
@@ -34,14 +34,14 @@ var StyledSheet = /*#__PURE__*/styled.div.withConfig({
34
34
  },
35
35
  displayName: "Sheet__StyledSheet",
36
36
  componentId: "sc-8abisx-1"
37
- })(templateObject_12 || (templateObject_12 = __makeTemplateObject(["\n position: fixed;\n background-color: ", ";\n box-shadow: ", ";\n z-index: ", ";\n overflow-y: auto;\n \n /* Position-specific styles */\n ", "\n\n ", " {\n animation: ", " ", " ", "", ";\n }\n \n /* Focus trap styling */\n &:focus {\n outline: none;\n }\n\n \n /* Scrollbar styling */\n &::-webkit-scrollbar {\n width: ", ";\n }\n \n &::-webkit-scrollbar-track {\n background: ", ";\n }\n \n &::-webkit-scrollbar-thumb {\n background: ", ";\n border-radius: ", ";\n }\n \n &::-webkit-scrollbar-thumb:hover {\n background: ", ";\n }\n"], ["\n position: fixed;\n background-color: ", ";\n box-shadow: ", ";\n z-index: ", ";\n overflow-y: auto;\n \n /* Position-specific styles */\n ", "\n\n ", " {\n animation: ", " ", " ", "", ";\n }\n \n /* Focus trap styling */\n &:focus {\n outline: none;\n }\n\n \n /* Scrollbar styling */\n &::-webkit-scrollbar {\n width: ", ";\n }\n \n &::-webkit-scrollbar-track {\n background: ", ";\n }\n \n &::-webkit-scrollbar-thumb {\n background: ", ";\n border-radius: ", ";\n }\n \n &::-webkit-scrollbar-thumb:hover {\n background: ", ";\n }\n"])), semantic.surface.base, semantic.elevation.overlay, semantic.layer.overlay, function (_a) {
37
+ })(templateObject_12 || (templateObject_12 = __makeTemplateObject(["\n position: fixed;\n /* A floating layer: one step above raised content in the dark theme (issue 356) */\n background-color: ", ";\n box-shadow: ", ";\n z-index: ", ";\n overflow-y: auto;\n \n /* Position-specific styles */\n ", "\n\n ", " {\n animation: ", " ", " ", "", ";\n }\n \n /* Focus trap styling */\n &:focus {\n outline: none;\n }\n\n \n /* Scrollbar styling */\n &::-webkit-scrollbar {\n width: ", ";\n }\n \n &::-webkit-scrollbar-track {\n background: ", "; /* matches the panel */\n }\n \n &::-webkit-scrollbar-thumb {\n background: ", ";\n border-radius: ", ";\n }\n \n &::-webkit-scrollbar-thumb:hover {\n background: ", ";\n }\n"], ["\n position: fixed;\n /* A floating layer: one step above raised content in the dark theme (issue 356) */\n background-color: ", ";\n box-shadow: ", ";\n z-index: ", ";\n overflow-y: auto;\n \n /* Position-specific styles */\n ", "\n\n ", " {\n animation: ", " ", " ", "", ";\n }\n \n /* Focus trap styling */\n &:focus {\n outline: none;\n }\n\n \n /* Scrollbar styling */\n &::-webkit-scrollbar {\n width: ", ";\n }\n \n &::-webkit-scrollbar-track {\n background: ", "; /* matches the panel */\n }\n \n &::-webkit-scrollbar-thumb {\n background: ", ";\n border-radius: ", ";\n }\n \n &::-webkit-scrollbar-thumb:hover {\n background: ", ";\n }\n"])), semantic.surface.overlay, semantic.elevation.overlay, semantic.layer.overlay, function (_a) {
38
38
  var $position = _a.$position,
39
39
  $variant = _a.$variant,
40
40
  $width = _a.$width,
41
41
  $height = _a.$height;
42
42
  var isDrawer = $variant === 'drawer';
43
43
  var margin = isDrawer ? semantic.space[400] : '0';
44
- var borderRadius = isDrawer ? semantic.radius.md : '0';
44
+ var borderRadius = isDrawer ? tokens.component.overlay.borderRadius : '0';
45
45
  switch ($position) {
46
46
  case 'right':
47
47
  return css(templateObject_8 || (templateObject_8 = __makeTemplateObject(["\n top: ", ";\n right: ", ";\n bottom: ", ";\n width: ", ";\n max-width: calc(100vw - ", ");\n border-radius: ", " 0 0 ", ";\n animation: ", " ", " ", "", ";\n "], ["\n top: ", ";\n right: ", ";\n bottom: ", ";\n width: ", ";\n max-width: calc(100vw - ", ");\n border-radius: ", " 0 0 ", ";\n animation: ", " ", " ", "", ";\n "])), margin, margin, margin, $width, isDrawer ? "".concat(semantic.space[400], " * 2") : '0px', borderRadius, borderRadius, slideInRight, semantic.motion.duration.moderate, semantic.motion.easing.standard, function (_a) {
@@ -67,7 +67,7 @@ var StyledSheet = /*#__PURE__*/styled.div.withConfig({
67
67
  }, reducedMotion, fadeIn, semantic.motion.duration.moderate, semantic.motion.easing.standard, function (_a) {
68
68
  var $isExiting = _a.$isExiting;
69
69
  return $isExiting && exitAnimation;
70
- }, semantic.space[200], semantic.surface.raised, semantic.color.border["default"], semantic.radius.full, semantic.color.fill.inverse);
70
+ }, semantic.space[200], semantic.surface.overlay, semantic.color.border["default"], semantic.radius.full, semantic.color.fill.inverse);
71
71
  var StyledSheetContent = /*#__PURE__*/styled.div.withConfig({
72
72
  displayName: "Sheet__StyledSheetContent",
73
73
  componentId: "sc-8abisx-2"
@@ -22,7 +22,8 @@ export interface SidebarNavItemProps {
22
22
  meta?: string;
23
23
  /**
24
24
  * New or unread items (decision 0045): a count, or `'dot'` for "something new". Shown as an
25
- * accent Badge on the icon, so it stays visible in the rail, and added to the item's name.
25
+ * accent Badge count at the end of the row, or as a dot inside the icon's corner in the rail, and
26
+ * added to the item's name.
26
27
  */
27
28
  badge?: number | 'dot';
28
29
  /**
@@ -38,6 +39,6 @@ export interface SidebarNavItemProps {
38
39
  * Renders an `li`, so it sits in SidebarNav's or a SidebarNavSection's list.
39
40
  */
40
41
  export declare const SidebarNavItem: {
41
- ({ label, icon, url, onClick, current, meta, badge, badgeLabel, "data-testid": dataTestId, }: SidebarNavItemProps): import("react/jsx-runtime").JSX.Element | null;
42
+ ({ label, icon, url, onClick, current, meta, badge, badgeLabel, "data-testid": dataTestId, }: SidebarNavItemProps): import("react/jsx-runtime").JSX.Element;
42
43
  displayName: string;
43
44
  };
@@ -22,7 +22,8 @@ export interface SidebarNavItemProps {
22
22
  meta?: string;
23
23
  /**
24
24
  * New or unread items (decision 0045): a count, or `'dot'` for "something new". Shown as an
25
- * accent Badge on the icon, so it stays visible in the rail, and added to the item's name.
25
+ * accent Badge count at the end of the row, or as a dot inside the icon's corner in the rail, and
26
+ * added to the item's name.
26
27
  */
27
28
  badge?: number | 'dot';
28
29
  /**
@@ -38,6 +39,6 @@ export interface SidebarNavItemProps {
38
39
  * Renders an `li`, so it sits in SidebarNav's or a SidebarNavSection's list.
39
40
  */
40
41
  export declare const SidebarNavItem: {
41
- ({ label, icon, url, onClick, current, meta, badge, badgeLabel, "data-testid": dataTestId, }: SidebarNavItemProps): import("react/jsx-runtime").JSX.Element | null;
42
+ ({ label, icon, url, onClick, current, meta, badge, badgeLabel, "data-testid": dataTestId, }: SidebarNavItemProps): import("react/jsx-runtime").JSX.Element;
42
43
  displayName: string;
43
44
  };
@@ -4,17 +4,17 @@ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
4
4
  import styled$module, { css } from 'styled-components';
5
5
  const styled = styled$module.default || styled$module;
6
6
  import tokens from '../../../lib/cssTokens.mjs';
7
- import { interactiveRow } from '../../../lib/styleUtils.mjs';
7
+ import { rowRadius, interactiveRow } from '../../../lib/styleUtils.mjs';
8
8
  import { Icon } from '../../atoms/Icon/Icon.mjs';
9
9
  import { Tooltip } from '../../atoms/Tooltip/Tooltip.mjs';
10
10
  import { Badge } from '../../atoms/Badge/Badge.mjs';
11
11
  import { useSidebarNav } from './SidebarNavContext.mjs';
12
+ import { ROW_INSET, EXPANDED_WIDTH_VAR, SCROLLBAR_VAR, NAV_PADDING, fade, Fold } from './sidebarNavMotion.mjs';
12
13
 
13
14
  var semantic = tokens.semantic;
14
15
  var space = semantic.space,
15
16
  color = semantic.color,
16
17
  motion = semantic.motion,
17
- radius = semantic.radius,
18
18
  size = semantic.size,
19
19
  border = semantic.border,
20
20
  typography = semantic.typography;
@@ -29,7 +29,10 @@ var Row = /*#__PURE__*/styled.a.withConfig({
29
29
  },
30
30
  displayName: "SidebarNavItem__Row",
31
31
  componentId: "sc-1nfqk5n-0"
32
- })(templateObject_3 || (templateObject_3 = __makeTemplateObject(["\n display: flex;\n align-items: center;\n gap: ", ";\n box-sizing: border-box;\n width: 100%;\n /* The row's height is its token, with the content centred (as controls, 0034): vertical\n padding would hold a compact row above its 24px (0051) */\n min-height: ", ";\n padding: 0 ", ";\n border: none;\n border-radius: ", ";\n background: none;\n font: ", ";\n color: ", ";\n text-align: left;\n text-decoration: none;\n cursor: pointer;\n transition: background-color ", " ", ",\n color ", " ", ";\n\n /* The shared row states (0030); the current page takes the light-blue selected ladder */\n ", "\n\n /* Inside SidebarNav one highlight glides to the hovered row, so an unselected row stays clear\n underneath it; pressed and selected rows keep their own fills (0053) */\n ", "\n\n ", "\n\n &:focus {\n outline: none;\n }\n\n &:focus-visible {\n outline: ", ";\n outline-offset: calc(-1 * ", ");\n }\n"], ["\n display: flex;\n align-items: center;\n gap: ", ";\n box-sizing: border-box;\n width: 100%;\n /* The row's height is its token, with the content centred (as controls, 0034): vertical\n padding would hold a compact row above its 24px (0051) */\n min-height: ", ";\n padding: 0 ", ";\n border: none;\n border-radius: ", ";\n background: none;\n font: ", ";\n color: ", ";\n text-align: left;\n text-decoration: none;\n cursor: pointer;\n transition: background-color ", " ", ",\n color ", " ", ";\n\n /* The shared row states (0030); the current page takes the light-blue selected ladder */\n ", "\n\n /* Inside SidebarNav one highlight glides to the hovered row, so an unselected row stays clear\n underneath it; pressed and selected rows keep their own fills (0053) */\n ", "\n\n ", "\n\n &:focus {\n outline: none;\n }\n\n &:focus-visible {\n outline: ", ";\n outline-offset: calc(-1 * ", ");\n }\n"])), space[200], size.row.sm, space.inset.sm, radius.sm, typography.small, color.text["default"], motion.duration.fast, motion.easing.decelerate, motion.duration.fast, motion.easing.decelerate, function (_a) {
32
+ })(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n display: flex;\n align-items: center;\n gap: ", ";\n box-sizing: border-box;\n width: 100%;\n /* The row's height is its token, with the content centred (as controls, 0034): vertical\n padding would hold a compact row above its 24px (0051) */\n min-height: ", ";\n /* The left inset is the same expanded and in the rail, so the icon never moves (issue 348); the row\n clips what the rail doesn't show as the nav narrows */\n padding: 0 ", " 0 ", ";\n overflow: hidden;\n border: none;\n border-radius: ", ";\n background: none;\n font: ", ";\n color: ", ";\n text-align: left;\n text-decoration: none;\n cursor: pointer;\n transition: background-color ", " ", ",\n color ", " ", ";\n\n /* The shared row states (0030); the current page takes the light-blue selected ladder */\n ", "\n\n /* Inside SidebarNav one highlight glides to the hovered row, so an unselected row stays clear\n underneath it; pressed and selected rows keep their own fills (0053) */\n ", "\n\n &:focus {\n outline: none;\n }\n\n &:focus-visible {\n outline: ", ";\n outline-offset: calc(-1 * ", ");\n }\n"], ["\n display: flex;\n align-items: center;\n gap: ", ";\n box-sizing: border-box;\n width: 100%;\n /* The row's height is its token, with the content centred (as controls, 0034): vertical\n padding would hold a compact row above its 24px (0051) */\n min-height: ", ";\n /* The left inset is the same expanded and in the rail, so the icon never moves (issue 348); the row\n clips what the rail doesn't show as the nav narrows */\n padding: 0 ", " 0 ", ";\n overflow: hidden;\n border: none;\n border-radius: ", ";\n background: none;\n font: ", ";\n color: ", ";\n text-align: left;\n text-decoration: none;\n cursor: pointer;\n transition: background-color ", " ", ",\n color ", " ", ";\n\n /* The shared row states (0030); the current page takes the light-blue selected ladder */\n ", "\n\n /* Inside SidebarNav one highlight glides to the hovered row, so an unselected row stays clear\n underneath it; pressed and selected rows keep their own fills (0053) */\n ", "\n\n &:focus {\n outline: none;\n }\n\n &:focus-visible {\n outline: ", ";\n outline-offset: calc(-1 * ", ");\n }\n"
33
+ // The row's content keeps the nav's expanded width (when it's in a SidebarNav), so the nav's edge
34
+ // clips it as the nav narrows, instead of the label reflowing or ellipsising mid-move
35
+ ])), space[200], size.row.sm, space.inset.sm, ROW_INSET, rowRadius, typography.small, color.text["default"], motion.duration.fast, motion.easing.decelerate, motion.duration.fast, motion.easing.decelerate, function (_a) {
33
36
  var $current = _a.$current;
34
37
  return interactiveRow({
35
38
  selected: $current
@@ -38,25 +41,88 @@ var Row = /*#__PURE__*/styled.a.withConfig({
38
41
  var $glide = _a.$glide,
39
42
  $current = _a.$current;
40
43
  return $glide && !$current && css(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n &:hover:not(:active) {\n background-color: transparent;\n }\n "], ["\n &:hover:not(:active) {\n background-color: transparent;\n }\n "])));
41
- }, function (_a) {
42
- var $collapsed = _a.$collapsed;
43
- return $collapsed && css(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n justify-content: center;\n padding: 0 ", ";\n "], ["\n justify-content: center;\n padding: 0 ", ";\n "])), space.inset.xs);
44
44
  }, border.focus, border.focusOffset);
45
+ // The row's content keeps the nav's expanded width (when it's in a SidebarNav), so the nav's edge
46
+ // clips it as the nav narrows, instead of the label reflowing or ellipsising mid-move
47
+ var Inner = /*#__PURE__*/styled.span.withConfig({
48
+ shouldForwardProp: function shouldForwardProp(prop) {
49
+ return !prop.startsWith('$');
50
+ },
51
+ displayName: "SidebarNavItem__Inner",
52
+ componentId: "sc-1nfqk5n-1"
53
+ })(templateObject_3 || (templateObject_3 = __makeTemplateObject(["\n display: flex;\n flex: 1 0 auto;\n align-items: center;\n gap: ", ";\n min-width: 0;\n /* The row's content width when expanded: the nav's width less any scrollbar, its padding, the row's\n insets and, beside an icon, the icon and its gap */\n width: calc(\n var(", ", 0px) - var(", ", 0px) - 2 * ", " - ", " - ", "\n ", "\n );\n"], ["\n display: flex;\n flex: 1 0 auto;\n align-items: center;\n gap: ", ";\n min-width: 0;\n /* The row's content width when expanded: the nav's width less any scrollbar, its padding, the row's\n insets and, beside an icon, the icon and its gap */\n width: calc(\n var(", ", 0px) - var(", ", 0px) - 2 * ", " - ", " - ", "\n ", "\n );\n"])), space[200], EXPANDED_WIDTH_VAR, SCROLLBAR_VAR, NAV_PADDING, ROW_INSET, space.inset.sm, function (_a) {
54
+ var $withIcon = _a.$withIcon;
55
+ return $withIcon ? "- ".concat(size.icon.md, " - ").concat(space[200]) : '';
56
+ });
45
57
  var Label = /*#__PURE__*/styled.span.withConfig({
58
+ shouldForwardProp: function shouldForwardProp(prop) {
59
+ return !prop.startsWith('$');
60
+ },
46
61
  displayName: "SidebarNavItem__Label",
47
- componentId: "sc-1nfqk5n-1"
48
- })(templateObject_4 || (templateObject_4 = __makeTemplateObject(["\n flex: 1;\n min-width: 0;\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n"], ["\n flex: 1;\n min-width: 0;\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n"])));
62
+ componentId: "sc-1nfqk5n-2"
63
+ })(templateObject_4 || (templateObject_4 = __makeTemplateObject(["\n flex: 1;\n min-width: 0;\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n ", "\n"], ["\n flex: 1;\n min-width: 0;\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n ", "\n"])), function (_a) {
64
+ var $hidden = _a.$hidden;
65
+ return fade($hidden);
66
+ });
49
67
  var Meta = /*#__PURE__*/styled.span.withConfig({
68
+ shouldForwardProp: function shouldForwardProp(prop) {
69
+ return !prop.startsWith('$');
70
+ },
50
71
  displayName: "SidebarNavItem__Meta",
51
- componentId: "sc-1nfqk5n-2"
52
- })(templateObject_5 || (templateObject_5 = __makeTemplateObject(["\n flex-shrink: 0;\n font: ", ";\n color: ", ";\n"], ["\n flex-shrink: 0;\n font: ", ";\n color: ", ";\n"
72
+ componentId: "sc-1nfqk5n-3"
73
+ })(templateObject_5 || (templateObject_5 = __makeTemplateObject(["\n flex-shrink: 0;\n font: ", ";\n color: ", ";\n ", "\n"], ["\n flex-shrink: 0;\n font: ", ";\n color: ", ";\n ", "\n"
53
74
  // A badge needs something to sit on: the icon, or this mark at the end of an item without one
54
- ])), typography.caption, color.text.muted);
75
+ // Badge normally sits centred on its anchor's top-right corner (0045). At the end of the row the
76
+ // count is laid out in place instead, so a count of any width ("3", "12", "99+") stays inside the
77
+ // row in every density and never reaches the rows around it
78
+ ])), typography.caption, color.text.muted, function (_a) {
79
+ var $hidden = _a.$hidden;
80
+ return fade($hidden);
81
+ });
55
82
  // A badge needs something to sit on: the icon, or this mark at the end of an item without one
56
- var BadgeAnchor = /*#__PURE__*/styled.span.withConfig({
57
- displayName: "SidebarNavItem__BadgeAnchor",
58
- componentId: "sc-1nfqk5n-3"
59
- })(templateObject_6 || (templateObject_6 = __makeTemplateObject(["\n display: inline-flex;\n flex-shrink: 0;\n"], ["\n display: inline-flex;\n flex-shrink: 0;\n"
83
+ // Badge normally sits centred on its anchor's top-right corner (0045). At the end of the row the
84
+ // count is laid out in place instead, so a count of any width ("3", "12", "99+") stays inside the
85
+ // row in every density and never reaches the rows around it
86
+ var EndSlot = /*#__PURE__*/styled.span.withConfig({
87
+ shouldForwardProp: function shouldForwardProp(prop) {
88
+ return !prop.startsWith('$');
89
+ },
90
+ displayName: "SidebarNavItem__EndSlot",
91
+ componentId: "sc-1nfqk5n-4"
92
+ })(templateObject_6 || (templateObject_6 = __makeTemplateObject(["\n display: inline-flex;\n flex-shrink: 0;\n ", "\n\n & [role='status'] {\n position: static;\n transform: none;\n }\n"], ["\n display: inline-flex;\n flex-shrink: 0;\n ", "\n\n & [role='status'] {\n position: static;\n transform: none;\n }\n"])), function (_a) {
93
+ var $hidden = _a.$hidden;
94
+ return fade($hidden);
95
+ });
96
+ var EndAnchor = /*#__PURE__*/styled.span.withConfig({
97
+ displayName: "SidebarNavItem__EndAnchor",
98
+ componentId: "sc-1nfqk5n-5"
99
+ })(templateObject_7 || (templateObject_7 = __makeTemplateObject(["\n display: inline-flex;\n width: 0;\n height: 0;\n"], ["\n display: inline-flex;\n width: 0;\n height: 0;\n"
100
+ // In the rail there's no room for a count, so a dot sits inside the icon's top-right corner
101
+ ])));
102
+ // In the rail there's no room for a count, so a dot sits inside the icon's top-right corner
103
+ var IconBox = /*#__PURE__*/styled.span.withConfig({
104
+ displayName: "SidebarNavItem__IconBox",
105
+ componentId: "sc-1nfqk5n-6"
106
+ })(templateObject_8 || (templateObject_8 = __makeTemplateObject(["\n position: relative;\n display: inline-flex;\n flex-shrink: 0;\n"], ["\n position: relative;\n display: inline-flex;\n flex-shrink: 0;\n"])));
107
+ var Corner = /*#__PURE__*/styled.span.withConfig({
108
+ shouldForwardProp: function shouldForwardProp(prop) {
109
+ return !prop.startsWith('$');
110
+ },
111
+ displayName: "SidebarNavItem__Corner",
112
+ componentId: "sc-1nfqk5n-7"
113
+ })(templateObject_9 || (templateObject_9 = __makeTemplateObject(["\n position: absolute;\n top: 25%;\n right: 25%;\n display: inline-flex;\n ", "\n"], ["\n position: absolute;\n top: 25%;\n right: 25%;\n display: inline-flex;\n ", "\n"
114
+ // An item folds away in the rail when it has no icon to show there
115
+ ])), function (_a) {
116
+ var $hidden = _a.$hidden;
117
+ return fade($hidden);
118
+ });
119
+ // An item folds away in the rail when it has no icon to show there
120
+ var Item = /*#__PURE__*/styled(Fold).attrs({
121
+ as: 'li'
122
+ }).withConfig({
123
+ displayName: "SidebarNavItem__Item",
124
+ componentId: "sc-1nfqk5n-8"
125
+ })(templateObject_10 || (templateObject_10 = __makeTemplateObject([""], [""
60
126
  /**
61
127
  * One row of a SidebarNav (#327): a link to a page, or a button for an action such as "New chat".
62
128
  * Renders an `li`, so it sits in SidebarNav's or a SidebarNavSection's list.
@@ -80,39 +146,52 @@ var SidebarNavItem = function SidebarNavItem(_a) {
80
146
  collapsed = _c.collapsed,
81
147
  linkComponent = _c.linkComponent,
82
148
  glide = _c.glide;
83
- // The rail shows icons only: an item without one has nothing to show there
84
- if (collapsed && !icon) return null;
85
149
  var hasBadge = badge === 'dot' || typeof badge === 'number' && badge > 0;
86
150
  var badgeText = badgeLabel !== null && badgeLabel !== void 0 ? badgeLabel : badge === 'dot' ? 'new' : "".concat(badge, " new");
87
151
  // The badge's own text would make a noisy name, so a badged item is named outright; so is an
88
152
  // item in the rail, where the label isn't shown
89
153
  var name = hasBadge ? "".concat(label, ", ").concat(badgeText) : collapsed ? label : undefined;
90
- var withBadge = function withBadge(anchor) {
91
- return hasBadge ? jsx(Badge, {
92
- variant: "accent",
93
- dot: badge === 'dot',
94
- count: typeof badge === 'number' ? badge : 0,
95
- "aria-label": badgeText,
96
- children: anchor
97
- }) : anchor;
98
- };
154
+ var count = typeof badge === 'number' ? badge : 0;
155
+ // Everything stays mounted and fades, so collapsing and expanding never jump (issue 348). Hidden
156
+ // content leaves screen readers once its fade ends; the rail names the row with aria-label.
99
157
  var content = jsxs(Fragment, {
100
- children: [icon && withBadge(jsx(Icon, {
101
- name: icon,
102
- size: "md",
103
- iconColor: "inherit"
104
- })), !collapsed && jsxs(Fragment, {
158
+ children: [icon && jsxs(IconBox, {
159
+ children: [jsx(Icon, {
160
+ name: icon,
161
+ size: "md",
162
+ iconColor: "inherit"
163
+ }), hasBadge && jsx(Corner, {
164
+ "$hidden": !collapsed,
165
+ children: jsx(Badge, {
166
+ variant: "accent",
167
+ dot: true,
168
+ "aria-label": badgeText,
169
+ children: jsx("span", {})
170
+ })
171
+ })]
172
+ }), jsxs(Inner, {
173
+ "$withIcon": Boolean(icon),
105
174
  children: [jsx(Label, {
175
+ "$hidden": collapsed,
106
176
  children: label
107
177
  }), meta && jsx(Meta, {
178
+ "$hidden": collapsed,
108
179
  children: meta
109
- }), !icon && hasBadge && withBadge(jsx(BadgeAnchor, {}))]
180
+ }), hasBadge && jsx(EndSlot, {
181
+ "$hidden": collapsed,
182
+ children: jsx(Badge, {
183
+ variant: "accent",
184
+ dot: badge === 'dot',
185
+ count: count,
186
+ "aria-label": badgeText,
187
+ children: jsx(EndAnchor, {})
188
+ })
189
+ })]
110
190
  })]
111
191
  });
112
192
  var shared = {
113
193
  $current: current,
114
194
  $glide: glide,
115
- $collapsed: collapsed,
116
195
  // The icon is decorative (0028)
117
196
  'aria-label': name,
118
197
  'data-testid': dataTestId,
@@ -133,16 +212,24 @@ var SidebarNavItem = function SidebarNavItem(_a) {
133
212
  type: "button",
134
213
  children: content
135
214
  }));
136
- return jsx("li", {
137
- children: collapsed ? jsx(Tooltip, {
138
- text: label,
139
- side: "right",
140
- children: row
141
- }) : row
142
- });
215
+ return (
216
+ // The Tooltip is always there, turned off while the label is visible, so collapsing never
217
+ // remounts the row (which would lose focus and skip its transitions)
218
+ jsx(Item, {
219
+ "$open": !collapsed || Boolean(icon),
220
+ children: jsx("div", {
221
+ children: jsx(Tooltip, {
222
+ text: label,
223
+ side: "right",
224
+ disabled: !collapsed,
225
+ children: row
226
+ })
227
+ })
228
+ })
229
+ );
143
230
  };
144
231
  SidebarNavItem.displayName = 'SidebarNavItem';
145
- var templateObject_1, templateObject_2, templateObject_3, templateObject_4, templateObject_5, templateObject_6;
232
+ var templateObject_1, templateObject_2, templateObject_3, templateObject_4, templateObject_5, templateObject_6, templateObject_7, templateObject_8, templateObject_9, templateObject_10;
146
233
 
147
234
  export { SidebarNavItem };
148
235
  //# sourceMappingURL=SidebarNavItem.mjs.map
@@ -0,0 +1,30 @@
1
+ /**
2
+ * SidebarNav sets this on itself: its expanded width. Content inside keeps that width while the nav
3
+ * narrows, so the nav's edge clips it instead of it reflowing or ellipsising mid-move.
4
+ */
5
+ export declare const EXPANDED_WIDTH_VAR = "--co-sidebar-nav-expanded";
6
+ /**
7
+ * SidebarNav sets this to its body's scrollbar width (0 for overlay scrollbars), measured while
8
+ * expanded, since a classic scrollbar narrows every row
9
+ */
10
+ export declare const SCROLLBAR_VAR = "--co-sidebar-nav-scrollbar";
11
+ /** The nav's own side padding: the rail's inner width is the rail less twice this */
12
+ export declare const NAV_PADDING: string;
13
+ /** A row's left inset: centres an icon in the rail, and stays the same expanded, so icons never move */
14
+ export declare const ROW_INSET: string;
15
+ /**
16
+ * Fades content that the rail doesn't show (labels, meta text, the badge count, the header and
17
+ * footer). Leaving is quick and accelerates; arriving decelerates over the width's duration (0037).
18
+ * Hidden content also leaves the keyboard and screen readers once the fade ends.
19
+ */
20
+ export declare const fade: (hidden: boolean) => import("styled-components").RuleSet<object>;
21
+ /**
22
+ * Folds something away (its height animates to nothing, with a fade), for what the rail leaves out:
23
+ * a section's header, a section with nothing to show, an item without an icon. Under reduced motion
24
+ * the height changes at once and only the fade remains (0015).
25
+ */
26
+ export declare const Fold: import("styled-components/dist/types.js").IStyledComponentBase<"web", import("styled-components/dist/types.js").Merged<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "style"> & {
27
+ style?: import("react").CSSProperties | import("styled-components/dist/types.js").CSSPropertiesWithVars | undefined;
28
+ }, {
29
+ $open: boolean;
30
+ }>> & string;
@@ -0,0 +1,30 @@
1
+ /**
2
+ * SidebarNav sets this on itself: its expanded width. Content inside keeps that width while the nav
3
+ * narrows, so the nav's edge clips it instead of it reflowing or ellipsising mid-move.
4
+ */
5
+ export declare const EXPANDED_WIDTH_VAR = "--co-sidebar-nav-expanded";
6
+ /**
7
+ * SidebarNav sets this to its body's scrollbar width (0 for overlay scrollbars), measured while
8
+ * expanded, since a classic scrollbar narrows every row
9
+ */
10
+ export declare const SCROLLBAR_VAR = "--co-sidebar-nav-scrollbar";
11
+ /** The nav's own side padding: the rail's inner width is the rail less twice this */
12
+ export declare const NAV_PADDING: string;
13
+ /** A row's left inset: centres an icon in the rail, and stays the same expanded, so icons never move */
14
+ export declare const ROW_INSET: string;
15
+ /**
16
+ * Fades content that the rail doesn't show (labels, meta text, the badge count, the header and
17
+ * footer). Leaving is quick and accelerates; arriving decelerates over the width's duration (0037).
18
+ * Hidden content also leaves the keyboard and screen readers once the fade ends.
19
+ */
20
+ export declare const fade: (hidden: boolean) => import("styled-components").RuleSet<object>;
21
+ /**
22
+ * Folds something away (its height animates to nothing, with a fade), for what the rail leaves out:
23
+ * a section's header, a section with nothing to show, an item without an icon. Under reduced motion
24
+ * the height changes at once and only the fade remains (0015).
25
+ */
26
+ export declare const Fold: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Merged<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "style"> & {
27
+ style?: import("react").CSSProperties | import("styled-components/dist/types").CSSPropertiesWithVars | undefined;
28
+ }, {
29
+ $open: boolean;
30
+ }>> & string;