@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
@@ -1,23 +1,23 @@
1
1
  'use client';
2
2
  import { __makeTemplateObject, __assign } from '../../../vendor/tslib/tslib.es6.mjs';
3
- import { jsx, jsxs } from 'react/jsx-runtime';
4
- import { useState, useRef } from 'react';
5
- import styled$module, { css } from 'styled-components';
3
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
4
+ import { useState, useRef, useEffect } from 'react';
5
+ import styled$module from 'styled-components';
6
6
  const styled = styled$module.default || styled$module;
7
7
  import tokens from '../../../lib/cssTokens.mjs';
8
- import { reducedMotion, forcedColors } from '../../../lib/styleUtils.mjs';
8
+ import { reducedMotion, rowRadius, forcedColors } from '../../../lib/styleUtils.mjs';
9
9
  import { IconButton } from '../../atoms/IconButton/IconButton.mjs';
10
10
  import { Tooltip } from '../../atoms/Tooltip/Tooltip.mjs';
11
11
  import { isKeyboardFocus } from '../../../lib/keyboardFocus.mjs';
12
12
  import { SidebarNavContext } from '../../molecules/SidebarNavItem/SidebarNavContext.mjs';
13
+ import { fade, EXPANDED_WIDTH_VAR, NAV_PADDING, SCROLLBAR_VAR } from '../../molecules/SidebarNavItem/sidebarNavMotion.mjs';
13
14
 
14
15
  var semantic = tokens.semantic,
15
16
  component = tokens.component;
16
17
  var space = semantic.space,
17
18
  motion = semantic.motion,
18
- radius = semantic.radius,
19
- border = semantic.border,
20
- color = semantic.color;
19
+ color = semantic.color,
20
+ size = semantic.size;
21
21
  var widths = component.sidebarNav.width;
22
22
  var Nav = /*#__PURE__*/styled.nav.withConfig({
23
23
  shouldForwardProp: function shouldForwardProp(prop) {
@@ -25,39 +25,67 @@ var Nav = /*#__PURE__*/styled.nav.withConfig({
25
25
  },
26
26
  displayName: "SidebarNav__Nav",
27
27
  componentId: "sc-1as46tp-0"
28
- })(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n display: flex;\n flex-direction: column;\n gap: ", ";\n box-sizing: border-box;\n /* Its width is set; in a flex app shell it mustn't shrink to make room */\n flex-shrink: 0;\n width: ", ";\n height: 100%;\n padding: ", ";\n overflow: hidden;\n /* Quiet chrome (P1): the page's own background, with a thin edge */\n border-right: ", ";\n transition: width ", " ", ";\n\n ", " {\n transition: none;\n }\n"], ["\n display: flex;\n flex-direction: column;\n gap: ", ";\n box-sizing: border-box;\n /* Its width is set; in a flex app shell it mustn't shrink to make room */\n flex-shrink: 0;\n width: ", ";\n height: 100%;\n padding: ", ";\n overflow: hidden;\n /* Quiet chrome (P1): the page's own background, with a thin edge */\n border-right: ", ";\n transition: width ", " ", ";\n\n ", " {\n transition: none;\n }\n"])), space[200], function (_a) {
28
+ })(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n display: flex;\n flex-direction: column;\n gap: ", ";\n box-sizing: border-box;\n /* Its width is set; in a flex app shell it mustn't shrink to make room */\n flex-shrink: 0;\n width: ", ";\n height: 100%;\n padding: ", ";\n overflow: hidden;\n /* Quiet chrome (P1): the page's own background, with no edge of its own (issue 348). The width\n moves with everything inside it, decelerating (0037) */\n transition: width ", " ", ";\n\n ", " {\n transition: none;\n }\n"], ["\n display: flex;\n flex-direction: column;\n gap: ", ";\n box-sizing: border-box;\n /* Its width is set; in a flex app shell it mustn't shrink to make room */\n flex-shrink: 0;\n width: ", ";\n height: 100%;\n padding: ", ";\n overflow: hidden;\n /* Quiet chrome (P1): the page's own background, with no edge of its own (issue 348). The width\n moves with everything inside it, decelerating (0037) */\n transition: width ", " ", ";\n\n ", " {\n transition: none;\n }\n"
29
+ // The header holds two toggles in fixed places that cross-fade (issue 348): collapse beside the
30
+ // header content, and expand in the content's place, where the rail shows it. Nothing moves.
31
+ ])), space[200], function (_a) {
29
32
  var $width = _a.$width;
30
33
  return $width;
31
- }, space[200], border["default"], motion.duration.moderate, motion.easing.standard, reducedMotion);
34
+ }, space[200], motion.duration.moderate, motion.easing.decelerate, reducedMotion);
35
+ // The header holds two toggles in fixed places that cross-fade (issue 348): collapse beside the
36
+ // header content, and expand in the content's place, where the rail shows it. Nothing moves.
32
37
  var Header = /*#__PURE__*/styled.div.withConfig({
33
- shouldForwardProp: function shouldForwardProp(prop) {
34
- return !prop.startsWith('$');
35
- },
36
38
  displayName: "SidebarNav__Header",
37
39
  componentId: "sc-1as46tp-1"
38
- })(templateObject_3 || (templateObject_3 = __makeTemplateObject(["\n display: flex;\n align-items: center;\n gap: ", ";\n\n ", "\n"], ["\n display: flex;\n align-items: center;\n gap: ", ";\n\n ", "\n"])), space[100], function (_a) {
39
- var $collapsed = _a.$collapsed;
40
- return $collapsed && css(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n flex-direction: column;\n "], ["\n flex-direction: column;\n "])));
41
- });
40
+ })(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n position: relative;\n display: flex;\n align-items: center;\n gap: ", ";\n min-height: ", ";\n"], ["\n position: relative;\n display: flex;\n align-items: center;\n gap: ", ";\n min-height: ", ";\n"])), space[100], size.control.sm);
42
41
  var HeaderContent = /*#__PURE__*/styled.div.withConfig({
42
+ shouldForwardProp: function shouldForwardProp(prop) {
43
+ return !prop.startsWith('$');
44
+ },
43
45
  displayName: "SidebarNav__HeaderContent",
44
46
  componentId: "sc-1as46tp-2"
45
- })(templateObject_4 || (templateObject_4 = __makeTemplateObject(["\n flex: 1;\n min-width: 0;\n width: 100%;\n"], ["\n flex: 1;\n min-width: 0;\n width: 100%;\n"])));
47
+ })(templateObject_3 || (templateObject_3 = __makeTemplateObject(["\n flex: 1;\n min-width: 0;\n overflow: hidden;\n ", "\n\n /* Keeps its expanded width, so the nav's edge clips it rather than it reflowing mid-move */\n & > div {\n width: calc(var(", ") - 2 * ", " - ", " - ", ");\n }\n"], ["\n flex: 1;\n min-width: 0;\n overflow: hidden;\n ", "\n\n /* Keeps its expanded width, so the nav's edge clips it rather than it reflowing mid-move */\n & > div {\n width: calc(var(", ") - 2 * ", " - ", " - ", ");\n }\n"])), function (_a) {
48
+ var $hidden = _a.$hidden;
49
+ return fade($hidden);
50
+ }, EXPANDED_WIDTH_VAR, NAV_PADDING, size.control.sm, space[100]);
51
+ var CollapseSlot = /*#__PURE__*/styled.span.withConfig({
52
+ shouldForwardProp: function shouldForwardProp(prop) {
53
+ return !prop.startsWith('$');
54
+ },
55
+ displayName: "SidebarNav__CollapseSlot",
56
+ componentId: "sc-1as46tp-3"
57
+ })(templateObject_4 || (templateObject_4 = __makeTemplateObject(["\n display: inline-flex;\n flex-shrink: 0;\n margin-left: auto;\n ", "\n"], ["\n display: inline-flex;\n flex-shrink: 0;\n margin-left: auto;\n ", "\n"
58
+ // Centred in the rail, where the header content starts
59
+ ])), function (_a) {
60
+ var $hidden = _a.$hidden;
61
+ return fade($hidden);
62
+ });
63
+ // Centred in the rail, where the header content starts
64
+ var ExpandSlot = /*#__PURE__*/styled.span.withConfig({
65
+ shouldForwardProp: function shouldForwardProp(prop) {
66
+ return !prop.startsWith('$');
67
+ },
68
+ displayName: "SidebarNav__ExpandSlot",
69
+ componentId: "sc-1as46tp-4"
70
+ })(templateObject_5 || (templateObject_5 = __makeTemplateObject(["\n position: absolute;\n top: 0;\n bottom: 0;\n left: calc((", " - 2 * ", " - ", ") / 2);\n display: flex;\n align-items: center;\n ", "\n"], ["\n position: absolute;\n top: 0;\n bottom: 0;\n left: calc((", " - 2 * ", " - ", ") / 2);\n display: flex;\n align-items: center;\n ", "\n"])), component.sidebarNav.width.rail, NAV_PADDING, size.control.sm, function (_a) {
71
+ var $hidden = _a.$hidden;
72
+ return fade($hidden);
73
+ });
46
74
  var Body = /*#__PURE__*/styled.div.withConfig({
47
75
  displayName: "SidebarNav__Body",
48
- componentId: "sc-1as46tp-3"
49
- })(templateObject_5 || (templateObject_5 = __makeTemplateObject(["\n flex: 1;\n min-height: 0;\n overflow-x: hidden;\n overflow-y: auto;\n"], ["\n flex: 1;\n min-height: 0;\n overflow-x: hidden;\n overflow-y: auto;\n"
76
+ componentId: "sc-1as46tp-5"
77
+ })(templateObject_6 || (templateObject_6 = __makeTemplateObject(["\n flex: 1;\n min-height: 0;\n overflow-x: hidden;\n overflow-y: auto;\n"], ["\n flex: 1;\n min-height: 0;\n overflow-x: hidden;\n overflow-y: auto;\n"
50
78
  // The rows and the highlight share this box, so the highlight scrolls with the rows
51
79
  ])));
52
80
  // The rows and the highlight share this box, so the highlight scrolls with the rows
53
81
  var Content = /*#__PURE__*/styled.div.withConfig({
54
82
  displayName: "SidebarNav__Content",
55
- componentId: "sc-1as46tp-4"
56
- })(templateObject_6 || (templateObject_6 = __makeTemplateObject(["\n position: relative;\n isolation: isolate;\n display: flex;\n flex-direction: column;\n\n & [data-sidebar-row] {\n position: relative;\n z-index: 1;\n }\n"], ["\n position: relative;\n isolation: isolate;\n display: flex;\n flex-direction: column;\n\n & [data-sidebar-row] {\n position: relative;\n z-index: 1;\n }\n"])));
83
+ componentId: "sc-1as46tp-6"
84
+ })(templateObject_7 || (templateObject_7 = __makeTemplateObject(["\n position: relative;\n isolation: isolate;\n display: flex;\n flex-direction: column;\n\n & [data-sidebar-row] {\n position: relative;\n z-index: 1;\n }\n"], ["\n position: relative;\n isolation: isolate;\n display: flex;\n flex-direction: column;\n\n & [data-sidebar-row] {\n position: relative;\n z-index: 1;\n }\n"])));
57
85
  var List = /*#__PURE__*/styled.ul.withConfig({
58
86
  displayName: "SidebarNav__List",
59
- componentId: "sc-1as46tp-5"
60
- })(templateObject_7 || (templateObject_7 = __makeTemplateObject(["\n margin: 0;\n padding: 0;\n list-style: none;\n display: flex;\n flex-direction: column;\n"], ["\n margin: 0;\n padding: 0;\n list-style: none;\n display: flex;\n flex-direction: column;\n"])));
87
+ componentId: "sc-1as46tp-7"
88
+ })(templateObject_8 || (templateObject_8 = __makeTemplateObject(["\n margin: 0;\n padding: 0;\n list-style: none;\n display: flex;\n flex-direction: column;\n"], ["\n margin: 0;\n padding: 0;\n list-style: none;\n display: flex;\n flex-direction: column;\n"])));
61
89
  // One highlight glides to the hovered or keyboard-focused row (0053): the row hover colour,
62
90
  // moving over duration.fast. It jumps under reduced motion and hides in forced colours, where
63
91
  // rows outline themselves instead.
@@ -66,61 +94,109 @@ var Highlight = /*#__PURE__*/styled.div.withConfig({
66
94
  return !prop.startsWith('$');
67
95
  },
68
96
  displayName: "SidebarNav__Highlight",
69
- componentId: "sc-1as46tp-6"
70
- })(templateObject_8 || (templateObject_8 = __makeTemplateObject(["\n position: absolute;\n top: 0;\n left: 0;\n z-index: 0;\n border-radius: ", ";\n background-color: ", ";\n pointer-events: none;\n opacity: ", ";\n transition: ", ";\n\n ", " {\n transition: opacity ", " ", ";\n }\n\n ", " {\n display: none;\n }\n"], ["\n position: absolute;\n top: 0;\n left: 0;\n z-index: 0;\n border-radius: ", ";\n background-color: ", ";\n pointer-events: none;\n opacity: ", ";\n transition: ", ";\n\n ", " {\n transition: opacity ", " ", ";\n }\n\n ", " {\n display: none;\n }\n"])), radius.sm, color.fill.muted, function (_a) {
97
+ componentId: "sc-1as46tp-8"
98
+ })(templateObject_9 || (templateObject_9 = __makeTemplateObject(["\n position: absolute;\n top: 0;\n left: 0;\n z-index: 0;\n border-radius: ", ";\n background-color: ", ";\n pointer-events: none;\n opacity: ", ";\n transition: ", ";\n\n ", " {\n transition: opacity ", " ", ";\n }\n\n ", " {\n display: none;\n }\n"], ["\n position: absolute;\n top: 0;\n left: 0;\n z-index: 0;\n border-radius: ", ";\n background-color: ", ";\n pointer-events: none;\n opacity: ", ";\n transition: ", ";\n\n ", " {\n transition: opacity ", " ", ";\n }\n\n ", " {\n display: none;\n }\n"
99
+ // The footer fades out in the rail, keeping its expanded width so it doesn't reflow mid-move
100
+ ])), rowRadius, color.fill.muted, function (_a) {
71
101
  var $visible = _a.$visible;
72
102
  return $visible ? 1 : 0;
73
103
  }, function (_a) {
74
104
  var $instant = _a.$instant;
75
105
  return $instant ? "opacity ".concat(motion.duration.fast, " ").concat(motion.easing.decelerate) : "transform ".concat(motion.duration.fast, " ").concat(motion.easing.decelerate, ",\n height ").concat(motion.duration.fast, " ").concat(motion.easing.decelerate, ",\n width ").concat(motion.duration.fast, " ").concat(motion.easing.decelerate, ",\n opacity ").concat(motion.duration.fast, " ").concat(motion.easing.decelerate);
76
106
  }, reducedMotion, motion.duration.fast, motion.easing.decelerate, forcedColors);
107
+ // The footer fades out in the rail, keeping its expanded width so it doesn't reflow mid-move
77
108
  var Footer = /*#__PURE__*/styled.div.withConfig({
109
+ shouldForwardProp: function shouldForwardProp(prop) {
110
+ return !prop.startsWith('$');
111
+ },
78
112
  displayName: "SidebarNav__Footer",
79
- componentId: "sc-1as46tp-7"
80
- })(templateObject_9 || (templateObject_9 = __makeTemplateObject(["\n flex-shrink: 0;\n"], ["\n flex-shrink: 0;\n"
113
+ componentId: "sc-1as46tp-9"
114
+ })(templateObject_10 || (templateObject_10 = __makeTemplateObject(["\n flex-shrink: 0;\n overflow: hidden;\n ", "\n\n & > div {\n width: calc(var(", ") - 2 * ", ");\n }\n"], ["\n flex-shrink: 0;\n overflow: hidden;\n ", "\n\n & > div {\n width: calc(var(", ") - 2 * ", ");\n }\n"
81
115
  /**
82
116
  * A product's sidebar navigation (#331): a header, a scrolling body of items and sections, and a
83
117
  * footer, that collapses to an icon rail. Row heights follow density (0051); the width is a prop.
84
118
  * On small screens, place it in a Sheet with `collapsible={false}`.
85
- */])));
119
+ */])), function (_a) {
120
+ var $hidden = _a.$hidden;
121
+ return fade($hidden);
122
+ }, EXPANDED_WIDTH_VAR, NAV_PADDING);
86
123
  /**
87
124
  * A product's sidebar navigation (#331): a header, a scrolling body of items and sections, and a
88
125
  * footer, that collapses to an icon rail. Row heights follow density (0051); the width is a prop.
89
126
  * On small screens, place it in a Sheet with `collapsible={false}`.
90
127
  */
91
128
  var SidebarNav = function SidebarNav(_a) {
129
+ var _b;
92
130
  var label = _a.label,
93
131
  children = _a.children,
94
132
  header = _a.header,
95
133
  footer = _a.footer,
96
- _b = _a.width,
97
- width = _b === void 0 ? 'default' : _b,
134
+ _c = _a.width,
135
+ width = _c === void 0 ? 'default' : _c,
98
136
  collapsedProp = _a.collapsed,
99
- _c = _a.defaultCollapsed,
100
- defaultCollapsed = _c === void 0 ? false : _c,
137
+ _d = _a.defaultCollapsed,
138
+ defaultCollapsed = _d === void 0 ? false : _d,
101
139
  onCollapsedChange = _a.onCollapsedChange,
102
- _d = _a.collapsible,
103
- collapsible = _d === void 0 ? true : _d,
140
+ _e = _a.collapsible,
141
+ collapsible = _e === void 0 ? true : _e,
104
142
  linkComponent = _a.linkComponent,
105
143
  dataTestId = _a["data-testid"];
106
- var _e = useState(defaultCollapsed),
107
- uncontrolledCollapsed = _e[0],
108
- setUncontrolledCollapsed = _e[1];
144
+ var _f = useState(defaultCollapsed),
145
+ uncontrolledCollapsed = _f[0],
146
+ setUncontrolledCollapsed = _f[1];
109
147
  var isControlled = collapsedProp !== undefined;
110
148
  var collapsed = collapsible && (isControlled ? collapsedProp : uncontrolledCollapsed);
111
149
  var contentRef = useRef(null);
112
- var _f = useState({
150
+ var navRef = useRef(null);
151
+ var bodyRef = useRef(null);
152
+ // A classic scrollbar narrows every row, so rows need its width. Measured while expanded (the rail
153
+ // only clips what rows hold) and written straight to a CSS variable, so it re-renders nothing.
154
+ useEffect(function () {
155
+ var nav = navRef.current;
156
+ var body = bodyRef.current;
157
+ if (!nav || !body || collapsed) return;
158
+ var measure = function measure() {
159
+ return nav.style.setProperty(SCROLLBAR_VAR, "".concat(body.offsetWidth - body.clientWidth, "px"));
160
+ };
161
+ measure();
162
+ if (typeof ResizeObserver === 'undefined') return;
163
+ var observer = new ResizeObserver(measure);
164
+ observer.observe(body);
165
+ if (contentRef.current) observer.observe(contentRef.current);
166
+ return function () {
167
+ return observer.disconnect();
168
+ };
169
+ }, [collapsed]);
170
+ var _g = useState({
113
171
  box: null,
114
172
  visible: false,
115
173
  instant: true
116
174
  }),
117
- highlight = _f[0],
118
- setHighlight = _f[1];
175
+ highlight = _g[0],
176
+ setHighlight = _g[1];
177
+ // Focus follows the toggle: the one pressed fades away, so focus moves to the one now shown
178
+ var collapseSlot = useRef(null);
179
+ var expandSlot = useRef(null);
180
+ // Which state a toggle asked for, and when: focus moves only if that state arrives promptly, so a
181
+ // controlled parent that declined the change can't have focus jump on some later change
182
+ var focusToggle = useRef(null);
119
183
  var toggle = function toggle() {
120
184
  var next = !collapsed;
185
+ focusToggle.current = {
186
+ to: next,
187
+ at: Date.now()
188
+ };
121
189
  if (!isControlled) setUncontrolledCollapsed(next);
122
190
  onCollapsedChange === null || onCollapsedChange === void 0 ? void 0 : onCollapsedChange(next);
123
191
  };
192
+ useEffect(function () {
193
+ var _a;
194
+ var request = focusToggle.current;
195
+ focusToggle.current = null;
196
+ if (!request || request.to !== collapsed || Date.now() - request.at > 1000) return;
197
+ var slot = collapsed ? expandSlot.current : collapseSlot.current;
198
+ (_a = slot === null || slot === void 0 ? void 0 : slot.querySelector('button')) === null || _a === void 0 ? void 0 : _a.focus();
199
+ }, [collapsed]);
124
200
  var hide = function hide() {
125
201
  return setHighlight(function (state) {
126
202
  return __assign(__assign({}, state), {
@@ -130,9 +206,9 @@ var SidebarNav = function SidebarNav(_a) {
130
206
  };
131
207
  // Collapsing or expanding moves every row, so the highlight's box is stale: hide it until the
132
208
  // pointer or focus finds a row again (adjusted during render, React's pattern for a prop change)
133
- var _g = useState(collapsed),
134
- layout = _g[0],
135
- setLayout = _g[1];
209
+ var _h = useState(collapsed),
210
+ layout = _h[0],
211
+ setLayout = _h[1];
136
212
  if (layout !== collapsed) {
137
213
  setLayout(collapsed);
138
214
  setHighlight(function (state) {
@@ -169,32 +245,64 @@ var SidebarNav = function SidebarNav(_a) {
169
245
  glide: true,
170
246
  inNav: true
171
247
  };
172
- var toggleLabel = collapsed ? 'Expand sidebar' : 'Collapse sidebar';
173
- var toggleButton = collapsible && jsx(Tooltip, {
174
- text: toggleLabel,
175
- side: collapsed ? 'right' : 'bottom',
176
- children: jsx(IconButton, {
177
- variant: "naked",
178
- size: "small",
179
- iconName: "sidebar",
180
- "aria-label": toggleLabel,
181
- "aria-expanded": !collapsed,
182
- onClick: toggle
183
- })
248
+ // The header content keeps its expanded layout: it fades out in the rail rather than turning into
249
+ // a rail version of itself mid-move
250
+ var headerContext = __assign(__assign({}, context), {
251
+ collapsed: false
184
252
  });
185
253
  return jsx(SidebarNavContext.Provider, {
186
254
  value: context,
187
255
  children: jsxs(Nav, {
256
+ ref: navRef,
188
257
  "aria-label": label,
189
258
  "$width": collapsed ? widths.rail : widths[width],
190
259
  "data-collapsed": collapsed || undefined,
191
260
  "data-testid": dataTestId,
192
- children: [(header || toggleButton) && jsxs(Header, {
193
- "$collapsed": collapsed,
261
+ style: (_b = {}, _b[EXPANDED_WIDTH_VAR] = widths[width], _b),
262
+ children: [(header || collapsible) && jsxs(Header, {
194
263
  children: [header && jsx(HeaderContent, {
195
- children: header
196
- }), toggleButton]
264
+ "$hidden": collapsed,
265
+ children: jsx("div", {
266
+ children: jsx(SidebarNavContext.Provider, {
267
+ value: headerContext,
268
+ children: header
269
+ })
270
+ })
271
+ }), collapsible && jsxs(Fragment, {
272
+ children: [jsx(CollapseSlot, {
273
+ ref: collapseSlot,
274
+ "$hidden": collapsed,
275
+ children: jsx(Tooltip, {
276
+ text: "Collapse sidebar",
277
+ side: "bottom",
278
+ children: jsx(IconButton, {
279
+ variant: "naked",
280
+ size: "small",
281
+ iconName: "sidebar",
282
+ "aria-label": "Collapse sidebar",
283
+ "aria-expanded": true,
284
+ onClick: toggle
285
+ })
286
+ })
287
+ }), jsx(ExpandSlot, {
288
+ ref: expandSlot,
289
+ "$hidden": !collapsed,
290
+ children: jsx(Tooltip, {
291
+ text: "Expand sidebar",
292
+ side: "right",
293
+ children: jsx(IconButton, {
294
+ variant: "naked",
295
+ size: "small",
296
+ iconName: "sidebar",
297
+ "aria-label": "Expand sidebar",
298
+ "aria-expanded": false,
299
+ onClick: toggle
300
+ })
301
+ })
302
+ })]
303
+ })]
197
304
  }), jsx(Body, {
305
+ ref: bodyRef,
198
306
  children: jsxs(Content, {
199
307
  ref: contentRef,
200
308
  onPointerOver: function onPointerOver(event) {
@@ -222,14 +330,17 @@ var SidebarNav = function SidebarNav(_a) {
222
330
  children: children
223
331
  })]
224
332
  })
225
- }), footer && !collapsed && jsx(Footer, {
226
- children: footer
333
+ }), footer && jsx(Footer, {
334
+ "$hidden": collapsed,
335
+ children: jsx("div", {
336
+ children: footer
337
+ })
227
338
  })]
228
339
  })
229
340
  });
230
341
  };
231
342
  SidebarNav.displayName = 'SidebarNav';
232
- var templateObject_1, templateObject_2, templateObject_3, templateObject_4, templateObject_5, templateObject_6, templateObject_7, templateObject_8, templateObject_9;
343
+ var templateObject_1, templateObject_2, templateObject_3, templateObject_4, templateObject_5, templateObject_6, templateObject_7, templateObject_8, templateObject_9, templateObject_10;
233
344
 
234
345
  export { SidebarNav };
235
346
  //# sourceMappingURL=SidebarNav.mjs.map