@atlaskit/navigation-system 0.169.0 → 0.170.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 (41) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/dist/cjs/ui/page-layout/main/main.compiled.css +1 -0
  3. package/dist/cjs/ui/page-layout/main/main.js +3 -2
  4. package/dist/cjs/ui/page-layout/panel.js +11 -31
  5. package/dist/cjs/ui/page-layout/side-nav/side-nav.js +5 -14
  6. package/dist/cjs/ui/top-nav-items/search.js +6 -3
  7. package/dist/es2019/ui/page-layout/main/main.compiled.css +1 -0
  8. package/dist/es2019/ui/page-layout/main/main.js +3 -2
  9. package/dist/es2019/ui/page-layout/panel.js +11 -31
  10. package/dist/es2019/ui/page-layout/side-nav/side-nav.js +5 -14
  11. package/dist/es2019/ui/top-nav-items/search.js +6 -3
  12. package/dist/esm/ui/page-layout/main/main.compiled.css +1 -0
  13. package/dist/esm/ui/page-layout/main/main.js +3 -2
  14. package/dist/esm/ui/page-layout/panel.js +11 -31
  15. package/dist/esm/ui/page-layout/side-nav/side-nav.js +5 -14
  16. package/dist/esm/ui/top-nav-items/search.js +6 -3
  17. package/dist/types/ui/page-layout/panel.d.ts +2 -2
  18. package/dist/types/ui/top-nav-items/search.d.ts +2 -1
  19. package/dist/types-ts4.5/ui/page-layout/panel.d.ts +2 -2
  20. package/dist/types-ts4.5/ui/top-nav-items/search.d.ts +2 -1
  21. package/examples/layers-in-main.tsx +294 -0
  22. package/examples/page-layout.tsx +6 -1
  23. package/package.json +7 -7
  24. package/src/__tests__/informational-vr-tests/__snapshots__/layering/layers-in-main-slot--desktop--platform-dst-nav4-layering-in-main-slot-fixes-false.png +0 -0
  25. package/src/__tests__/informational-vr-tests/__snapshots__/layering/layers-in-main-slot--desktop--platform-dst-nav4-layering-in-main-slot-fixes-true.png +0 -0
  26. package/src/__tests__/informational-vr-tests/__snapshots__/layering/layers-in-main-slot-short-viewport--desktop--platform-dst-nav4-layering-in-main-slot-fixes-false.png +0 -0
  27. package/src/__tests__/informational-vr-tests/__snapshots__/layering/layers-in-main-slot-short-viewport--desktop--platform-dst-nav4-layering-in-main-slot-fixes-true.png +0 -0
  28. package/src/__tests__/informational-vr-tests/layering.vr.tsx +35 -0
  29. package/src/__tests__/playwright/legacy-vars.spec.tsx +3 -81
  30. package/src/__tests__/playwright/panel.spec.tsx +2 -4
  31. package/src/ui/page-layout/__tests__/unit/page-layout.test.tsx +26 -4
  32. package/src/ui/page-layout/__tests__/unit/panel.test.tsx +15 -29
  33. package/src/ui/page-layout/__tests__/unit/resizing.test.tsx +11 -5
  34. package/src/ui/page-layout/__tests__/vr-tests/__snapshots__/page-layout/panel-should-have-correct-width-when-there-is-no-sidenav-mounted--desktop.png +0 -0
  35. package/src/ui/page-layout/__tests__/vr-tests/page-layout.vr.tsx +0 -4
  36. package/src/ui/page-layout/main/main.tsx +17 -1
  37. package/src/ui/page-layout/panel.tsx +15 -37
  38. package/src/ui/page-layout/side-nav/side-nav.tsx +21 -31
  39. package/src/ui/top-nav-items/search.tsx +4 -0
  40. package/src/ui/page-layout/__tests__/vr-tests/__snapshots__/page-layout/panel-should-have-correct-width-when-there-is-no-sidenav-mounted--desktop--platform-design-system-nav4-preview-panel-support-false.png +0 -0
  41. package/src/ui/page-layout/__tests__/vr-tests/__snapshots__/page-layout/panel-should-have-correct-width-when-there-is-no-sidenav-mounted--desktop--platform-design-system-nav4-preview-panel-support-true.png +0 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,32 @@
1
1
  # @atlassian/navigation-system
2
2
 
3
+ ## 0.170.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#179366](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/pull-requests/179366)
8
+ [`c1cd1f32a9703`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/c1cd1f32a9703) -
9
+ Adds experimental containment to the `Main` slot behind the
10
+ `platform_dst_nav4_layering_in_main_slot_fixes` feature gate. When enabled, popups inside of
11
+ `Main` will automatically stay inside of the slot. This avoids popups from escaping the slot and
12
+ being hidden behind other slots.
13
+ - [#173274](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/pull-requests/173274)
14
+ [`e01dc06c9f06e`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/e01dc06c9f06e) -
15
+ Cleans up `platform_design_system_nav4_preview_panel_support` feature gate. Panel max width is now
16
+ constrained to half of the content area.
17
+
18
+ ### Patch Changes
19
+
20
+ - Updated dependencies
21
+
22
+ ## 0.169.1
23
+
24
+ ### Patch Changes
25
+
26
+ - [#182936](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/pull-requests/182936)
27
+ [`e51987d54c75f`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/e51987d54c75f) -
28
+ Allow aria-haspopup to be set on Search component.
29
+
3
30
  ## 0.169.0
4
31
 
5
32
  ### Minor Changes
@@ -3,4 +3,5 @@
3
3
  ._18m91wug{overflow-y:auto}
4
4
  ._19121cl4{isolation:isolate}
5
5
  ._1reo1wug{overflow-x:auto}
6
+ ._njlp1t7j{contain:paint}
6
7
  @media (min-width:64rem){._165teqxy{height:calc(100vh - var(--n_bnrM, 0px) - var(--n_tNvM, 0px))}._13wn1if8{position:sticky}._qwfh1wug{isolation:auto}}
@@ -18,7 +18,8 @@ var _mainStickyContext = require("./main-sticky-context");
18
18
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
19
19
  var mainElementStyles = {
20
20
  root: "_nd5l1gzg _19121cl4 _qwfh1wug",
21
- fixedContentArea: "_1reo1wug _18m91wug _152timx3 _165teqxy _13wn1if8"
21
+ fixedContentArea: "_1reo1wug _18m91wug _152timx3 _165teqxy _13wn1if8",
22
+ containPaint: "_njlp1t7j"
22
23
  };
23
24
 
24
25
  /**
@@ -40,7 +41,7 @@ function Main(_ref) {
40
41
  return /*#__PURE__*/React.createElement(_react.Fragment, null, /*#__PURE__*/React.createElement("div", {
41
42
  id: id,
42
43
  "data-layout-slot": true,
43
- className: (0, _runtime.ax)([mainElementStyles.root, isFixed && mainElementStyles.fixedContentArea, xcss]),
44
+ className: (0, _runtime.ax)([mainElementStyles.root, isFixed && mainElementStyles.fixedContentArea, (0, _platformFeatureFlags.fg)('platform_dst_nav4_layering_in_main_slot_fixes') && mainElementStyles.containPaint, xcss]),
44
45
  role: "main",
45
46
  "data-testid": testId
46
47
  }, /*#__PURE__*/React.createElement(_mainStickyContext.MainStickyContext.Provider, {
@@ -26,33 +26,6 @@ var _useResizingWidthCssVarOnRootElement = require("./use-resizing-width-css-var
26
26
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
27
27
  var panelSplitterResizingVar = '--n_pnlRsz';
28
28
 
29
- /**
30
- * The bounds for Aside and Panel are purposely set to support the current usage in Jira.
31
- *
32
- * Jira sets the slot's width to `0px` when there is no active content to display in it.
33
- * - This means the min width needs to support `0px`.
34
- * The Conversation Assistant component in Jira (rendered in a nav3 RightSidebar, or a nav4 Aside) has a custom resizing
35
- * implementation, which has a maximum width of `50vw`.
36
- * - This means the max width needs to support `50vw`.
37
- *
38
- * This is not the final implementation and will be updated once Jira's usage has been fixed.
39
- * Ticket to track this is: https://jplat.atlassian.net/browse/BLU-3951
40
- *
41
- * We're using two different bounds for each slot here, to support the `0px` min width when programatically set using the
42
- * `defaultWidth` prop, and another one that is used when resizing the slots which has a sensible min width.
43
- */
44
- var oldPanelWidthSlotBounds = {
45
- min: '0px',
46
- max: '50vw'
47
- };
48
- var oldPanelWidthResizeBounds = {
49
- min: '120px',
50
- max: '50vw'
51
- };
52
- function getOldResizeBounds() {
53
- return oldPanelWidthResizeBounds;
54
- }
55
-
56
29
  /**
57
30
  * We typically use the `defaultWidth` as the minimum resizing width,
58
31
  * but for large default widths we fallback to a standard value.
@@ -135,7 +108,14 @@ function Panel(_ref) {
135
108
  * We only use the `defaultWidth` up to a point to avoid huge panels.
136
109
  */
137
110
  var minWidth = Math.min(defaultWidth, fallbackResizeMinWidth);
138
- var getNewResizeBounds = (0, _react.useCallback)(function () {
111
+
112
+ /**
113
+ * Returns the bounds for resizing, evaluated lazily when needed.
114
+ *
115
+ * Defined separately to the slot bounds because the resizing bounds need to be resolvable to a pixel value,
116
+ * and the panel's slot bounds use a complex CSS expression.
117
+ */
118
+ var getResizeBounds = (0, _react.useCallback)(function () {
139
119
  var _sideNavRef$current$o, _sideNavRef$current;
140
120
  var sideNavWidth = (_sideNavRef$current$o = (_sideNavRef$current = sideNavRef.current) === null || _sideNavRef$current === void 0 ? void 0 : _sideNavRef$current.offsetWidth) !== null && _sideNavRef$current$o !== void 0 ? _sideNavRef$current$o : 0;
141
121
  /**
@@ -149,11 +129,11 @@ function Panel(_ref) {
149
129
  max: "".concat(maxWidth, "px")
150
130
  };
151
131
  }, [minWidth, sideNavRef]);
152
- var panelWidthSlotBounds = (0, _platformFeatureFlags.fg)('platform_design_system_nav4_preview_panel_support') ? {
132
+ var panelWidthSlotBounds = {
153
133
  min: "".concat(minWidth, "px"),
154
134
  // `sideNavLiveWidthVar` is not defined if the `SideNav` is not mounted, so we fallback to `0px`.
155
135
  max: "round(nearest, calc((100vw - var(".concat(_constants.sideNavLiveWidthVar, ", 0px)) / 2), 1px)")
156
- } : oldPanelWidthSlotBounds;
136
+ };
157
137
  var panelVariableWidth = "clamp(".concat(panelWidthSlotBounds.min, ", ").concat(width, "px, ").concat(panelWidthSlotBounds.max, ")");
158
138
  (0, _useResizingWidthCssVarOnRootElement.useResizingWidthCssVarOnRootElement)({
159
139
  isEnabled: dangerouslyHoistSlotSizes && (0, _platformFeatureFlags.fg)('platform_design_system_nav4_live_resizing_css_vars'),
@@ -185,7 +165,7 @@ function Panel(_ref) {
185
165
  panelRef: ref,
186
166
  panelWidth: width,
187
167
  onCompleteResize: setWidth,
188
- getResizeBounds: (0, _platformFeatureFlags.fg)('platform_design_system_nav4_preview_panel_support') ? getNewResizeBounds : getOldResizeBounds,
168
+ getResizeBounds: getResizeBounds,
189
169
  resizingCssVar: panelSplitterResizingVar,
190
170
  position: "start"
191
171
  }, /*#__PURE__*/React.createElement("div", {
@@ -523,7 +523,7 @@ function SideNavInternal(_ref) {
523
523
  devTimeOnlyAttributes['data-visible'] = visible.length ? visible.join(',') : 'false';
524
524
  }
525
525
  (0, _useResizingWidthCssVarOnRootElement.useResizingWidthCssVarOnRootElement)({
526
- isEnabled: (0, _platformFeatureFlags.fg)('platform_design_system_nav4_preview_panel_support'),
526
+ isEnabled: true,
527
527
  cssVar: panelSplitterResizingVar,
528
528
  panelId: _constants.sideNavPanelSplitterId
529
529
  });
@@ -533,19 +533,15 @@ function SideNavInternal(_ref) {
533
533
  "data-layout-slot": true,
534
534
  "aria-label": label,
535
535
  style: (0, _defineProperty2.default)({}, _constants.sideNavVar, clampedWidth),
536
- ref: (0, _platformFeatureFlags.fg)('platform_design_system_nav4_preview_panel_support') ? mergedRef : navRef,
536
+ ref: mergedRef,
537
537
  "data-testid": testId,
538
538
  className: (0, _runtime.ax)([styles.root, (0, _platformFeatureFlags.fg)('platform_design_system_nav4_sidenav_border') ? styles.newBorder : styles.oldBorder, isExpandedOnDesktop && !isExpandedOnMobile && !isFlyoutVisible && styles.hiddenMobileOnly, !isExpandedOnDesktop && isExpandedOnMobile && !isFlyoutVisible && styles.hiddenDesktopOnly, !isExpandedOnDesktop && !isExpandedOnMobile && !isFlyoutVisible && styles.hiddenMobileAndDesktop, (sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === 'open' && styles.flyoutOpen, (sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === 'open' && (0, _platformFeatureFlags.fg)('platform_design_system_nav4_sidenav_border') && styles.newBorderFlyoutOpen, (sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === 'triggered-animate-close' && styles.flyoutAnimateClosed])
539
- }), (0, _platformFeatureFlags.fg)('platform_design_system_nav4_preview_panel_support') &&
540
- /*#__PURE__*/
541
- // This CSS var is used by the `Panel` slot to enforce its maximum width constraint.
542
- // When we remove the UNSAFE legacy usage, we can change this to `HoistCssVarToLocalGrid`
543
- React.createElement(_hoistUtils.DangerouslyHoistCssVarToDocumentRoot, {
539
+ }), /*#__PURE__*/React.createElement(_hoistUtils.DangerouslyHoistCssVarToDocumentRoot, {
544
540
  variableName: _constants.sideNavLiveWidthVar,
545
541
  value: "0px",
546
542
  mediaQuery: _responsive.media.above.md,
547
543
  responsiveValue: isExpandedOnDesktop ? "var(".concat(panelSplitterResizingVar, ", ").concat(clampedWidth, ")") : 0
548
- }), dangerouslyHoistSlotSizes && ((0, _platformFeatureFlags.fg)('platform_design_system_nav4_preview_panel_support') ?
544
+ }), dangerouslyHoistSlotSizes &&
549
545
  /*#__PURE__*/
550
546
  // ------ START UNSAFE STYLES ------
551
547
  // These styles are only needed for the UNSAFE legacy use case for Jira + Confluence.
@@ -553,14 +549,9 @@ function SideNavInternal(_ref) {
553
549
  React.createElement(_hoistUtils.DangerouslyHoistCssVarToDocumentRoot, {
554
550
  variableName: _constants.UNSAFE_sideNavLayoutVar,
555
551
  value: "var(".concat(_constants.sideNavLiveWidthVar, ")")
556
- }) : /*#__PURE__*/React.createElement(_hoistUtils.DangerouslyHoistCssVarToDocumentRoot, {
557
- variableName: _constants.UNSAFE_sideNavLayoutVar,
558
- value: "0px",
559
- mediaQuery: _responsive.media.above.md,
560
- responsiveValue: isExpandedOnDesktop ? clampedWidth : 0
561
552
  })
562
553
  // ------ END UNSAFE STYLES ------
563
- ), /*#__PURE__*/React.createElement(_provider.PanelSplitterProvider, {
554
+ , /*#__PURE__*/React.createElement(_provider.PanelSplitterProvider, {
564
555
  panelId: _constants.sideNavPanelSplitterId,
565
556
  panelRef: navRef,
566
557
  panelWidth: width,
@@ -32,7 +32,8 @@ var Search = exports.Search = function Search(_ref) {
32
32
  _ref$iconBefore = _ref.iconBefore,
33
33
  IconBefore = _ref$iconBefore === void 0 ? _search.default : _ref$iconBefore,
34
34
  elemAfter = _ref.elemAfter,
35
- interactionName = _ref.interactionName;
35
+ interactionName = _ref.interactionName,
36
+ ariaHaspopup = _ref['aria-haspopup'];
36
37
  return /*#__PURE__*/_react.default.createElement(_react.Fragment, null, /*#__PURE__*/_react.default.createElement(_compiled.Pressable, {
37
38
  style: {
38
39
  // To win the specificity war against Emotion we move this into inline styles
@@ -43,7 +44,8 @@ var Search = exports.Search = function Search(_ref) {
43
44
  },
44
45
  onClick: onClick,
45
46
  xcss: styles.root,
46
- interactionName: interactionName
47
+ interactionName: interactionName,
48
+ "aria-haspopup": ariaHaspopup
47
49
  }, /*#__PURE__*/_react.default.createElement("span", {
48
50
  className: (0, _runtime.ax)([styles.iconBefore])
49
51
  }, /*#__PURE__*/_react.default.createElement(IconBefore, {
@@ -63,6 +65,7 @@ var Search = exports.Search = function Search(_ref) {
63
65
  appearance: "subtle",
64
66
  icon: _search.default,
65
67
  onClick: onClick,
66
- interactionName: interactionName
68
+ interactionName: interactionName,
69
+ "aria-haspopup": ariaHaspopup
67
70
  })));
68
71
  };
@@ -3,4 +3,5 @@
3
3
  ._18m91wug{overflow-y:auto}
4
4
  ._19121cl4{isolation:isolate}
5
5
  ._1reo1wug{overflow-x:auto}
6
+ ._njlp1t7j{contain:paint}
6
7
  @media (min-width:64rem){._165teqxy{height:calc(100vh - var(--n_bnrM, 0px) - var(--n_tNvM, 0px))}._13wn1if8{position:sticky}._qwfh1wug{isolation:auto}}
@@ -10,7 +10,8 @@ import { useLayoutId } from '../id-utils';
10
10
  import { MainStickyContext } from './main-sticky-context';
11
11
  const mainElementStyles = {
12
12
  root: "_nd5l1gzg _19121cl4 _qwfh1wug",
13
- fixedContentArea: "_1reo1wug _18m91wug _152timx3 _165teqxy _13wn1if8"
13
+ fixedContentArea: "_1reo1wug _18m91wug _152timx3 _165teqxy _13wn1if8",
14
+ containPaint: "_njlp1t7j"
14
15
  };
15
16
 
16
17
  /**
@@ -32,7 +33,7 @@ export function Main({
32
33
  return /*#__PURE__*/React.createElement(Fragment, null, /*#__PURE__*/React.createElement("div", {
33
34
  id: id,
34
35
  "data-layout-slot": true,
35
- className: ax([mainElementStyles.root, isFixed && mainElementStyles.fixedContentArea, xcss]),
36
+ className: ax([mainElementStyles.root, isFixed && mainElementStyles.fixedContentArea, fg('platform_dst_nav4_layering_in_main_slot_fixes') && mainElementStyles.containPaint, xcss]),
36
37
  role: "main",
37
38
  "data-testid": testId
38
39
  }, /*#__PURE__*/React.createElement(MainStickyContext.Provider, {
@@ -15,33 +15,6 @@ import { useSideNavRef } from './side-nav/element-context';
15
15
  import { useResizingWidthCssVarOnRootElement } from './use-resizing-width-css-var-on-root-element';
16
16
  const panelSplitterResizingVar = '--n_pnlRsz';
17
17
 
18
- /**
19
- * The bounds for Aside and Panel are purposely set to support the current usage in Jira.
20
- *
21
- * Jira sets the slot's width to `0px` when there is no active content to display in it.
22
- * - This means the min width needs to support `0px`.
23
- * The Conversation Assistant component in Jira (rendered in a nav3 RightSidebar, or a nav4 Aside) has a custom resizing
24
- * implementation, which has a maximum width of `50vw`.
25
- * - This means the max width needs to support `50vw`.
26
- *
27
- * This is not the final implementation and will be updated once Jira's usage has been fixed.
28
- * Ticket to track this is: https://jplat.atlassian.net/browse/BLU-3951
29
- *
30
- * We're using two different bounds for each slot here, to support the `0px` min width when programatically set using the
31
- * `defaultWidth` prop, and another one that is used when resizing the slots which has a sensible min width.
32
- */
33
- const oldPanelWidthSlotBounds = {
34
- min: '0px',
35
- max: '50vw'
36
- };
37
- const oldPanelWidthResizeBounds = {
38
- min: '120px',
39
- max: '50vw'
40
- };
41
- function getOldResizeBounds() {
42
- return oldPanelWidthResizeBounds;
43
- }
44
-
45
18
  /**
46
19
  * We typically use the `defaultWidth` as the minimum resizing width,
47
20
  * but for large default widths we fallback to a standard value.
@@ -118,7 +91,14 @@ export function Panel({
118
91
  * We only use the `defaultWidth` up to a point to avoid huge panels.
119
92
  */
120
93
  const minWidth = Math.min(defaultWidth, fallbackResizeMinWidth);
121
- const getNewResizeBounds = useCallback(() => {
94
+
95
+ /**
96
+ * Returns the bounds for resizing, evaluated lazily when needed.
97
+ *
98
+ * Defined separately to the slot bounds because the resizing bounds need to be resolvable to a pixel value,
99
+ * and the panel's slot bounds use a complex CSS expression.
100
+ */
101
+ const getResizeBounds = useCallback(() => {
122
102
  var _sideNavRef$current$o, _sideNavRef$current;
123
103
  const sideNavWidth = (_sideNavRef$current$o = (_sideNavRef$current = sideNavRef.current) === null || _sideNavRef$current === void 0 ? void 0 : _sideNavRef$current.offsetWidth) !== null && _sideNavRef$current$o !== void 0 ? _sideNavRef$current$o : 0;
124
104
  /**
@@ -132,11 +112,11 @@ export function Panel({
132
112
  max: `${maxWidth}px`
133
113
  };
134
114
  }, [minWidth, sideNavRef]);
135
- const panelWidthSlotBounds = fg('platform_design_system_nav4_preview_panel_support') ? {
115
+ const panelWidthSlotBounds = {
136
116
  min: `${minWidth}px`,
137
117
  // `sideNavLiveWidthVar` is not defined if the `SideNav` is not mounted, so we fallback to `0px`.
138
118
  max: `round(nearest, calc((100vw - var(${sideNavLiveWidthVar}, 0px)) / 2), 1px)`
139
- } : oldPanelWidthSlotBounds;
119
+ };
140
120
  const panelVariableWidth = `clamp(${panelWidthSlotBounds.min}, ${width}px, ${panelWidthSlotBounds.max})`;
141
121
  useResizingWidthCssVarOnRootElement({
142
122
  isEnabled: dangerouslyHoistSlotSizes && fg('platform_design_system_nav4_live_resizing_css_vars'),
@@ -172,7 +152,7 @@ export function Panel({
172
152
  panelRef: ref,
173
153
  panelWidth: width,
174
154
  onCompleteResize: setWidth,
175
- getResizeBounds: fg('platform_design_system_nav4_preview_panel_support') ? getNewResizeBounds : getOldResizeBounds,
155
+ getResizeBounds: getResizeBounds,
176
156
  resizingCssVar: panelSplitterResizingVar,
177
157
  position: "start"
178
158
  }, /*#__PURE__*/React.createElement("div", {
@@ -512,7 +512,7 @@ function SideNavInternal({
512
512
  devTimeOnlyAttributes['data-visible'] = visible.length ? visible.join(',') : 'false';
513
513
  }
514
514
  useResizingWidthCssVarOnRootElement({
515
- isEnabled: fg('platform_design_system_nav4_preview_panel_support'),
515
+ isEnabled: true,
516
516
  cssVar: panelSplitterResizingVar,
517
517
  panelId: sideNavPanelSplitterId
518
518
  });
@@ -525,19 +525,15 @@ function SideNavInternal({
525
525
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values, @atlaskit/ui-styling-standard/enforce-style-prop
526
526
  [sideNavVar]: clampedWidth
527
527
  },
528
- ref: fg('platform_design_system_nav4_preview_panel_support') ? mergedRef : navRef,
528
+ ref: mergedRef,
529
529
  "data-testid": testId,
530
530
  className: ax([styles.root, fg('platform_design_system_nav4_sidenav_border') ? styles.newBorder : styles.oldBorder, isExpandedOnDesktop && !isExpandedOnMobile && !isFlyoutVisible && styles.hiddenMobileOnly, !isExpandedOnDesktop && isExpandedOnMobile && !isFlyoutVisible && styles.hiddenDesktopOnly, !isExpandedOnDesktop && !isExpandedOnMobile && !isFlyoutVisible && styles.hiddenMobileAndDesktop, (sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === 'open' && styles.flyoutOpen, (sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === 'open' && fg('platform_design_system_nav4_sidenav_border') && styles.newBorderFlyoutOpen, (sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === 'triggered-animate-close' && styles.flyoutAnimateClosed])
531
- }), fg('platform_design_system_nav4_preview_panel_support') &&
532
- /*#__PURE__*/
533
- // This CSS var is used by the `Panel` slot to enforce its maximum width constraint.
534
- // When we remove the UNSAFE legacy usage, we can change this to `HoistCssVarToLocalGrid`
535
- React.createElement(DangerouslyHoistCssVarToDocumentRoot, {
531
+ }), /*#__PURE__*/React.createElement(DangerouslyHoistCssVarToDocumentRoot, {
536
532
  variableName: sideNavLiveWidthVar,
537
533
  value: "0px",
538
534
  mediaQuery: media.above.md,
539
535
  responsiveValue: isExpandedOnDesktop ? `var(${panelSplitterResizingVar}, ${clampedWidth})` : 0
540
- }), dangerouslyHoistSlotSizes && (fg('platform_design_system_nav4_preview_panel_support') ?
536
+ }), dangerouslyHoistSlotSizes &&
541
537
  /*#__PURE__*/
542
538
  // ------ START UNSAFE STYLES ------
543
539
  // These styles are only needed for the UNSAFE legacy use case for Jira + Confluence.
@@ -545,14 +541,9 @@ function SideNavInternal({
545
541
  React.createElement(DangerouslyHoistCssVarToDocumentRoot, {
546
542
  variableName: UNSAFE_sideNavLayoutVar,
547
543
  value: `var(${sideNavLiveWidthVar})`
548
- }) : /*#__PURE__*/React.createElement(DangerouslyHoistCssVarToDocumentRoot, {
549
- variableName: UNSAFE_sideNavLayoutVar,
550
- value: "0px",
551
- mediaQuery: media.above.md,
552
- responsiveValue: isExpandedOnDesktop ? clampedWidth : 0
553
544
  })
554
545
  // ------ END UNSAFE STYLES ------
555
- ), /*#__PURE__*/React.createElement(PanelSplitterProvider, {
546
+ , /*#__PURE__*/React.createElement(PanelSplitterProvider, {
556
547
  panelId: sideNavPanelSplitterId,
557
548
  panelRef: navRef,
558
549
  panelWidth: width,
@@ -22,7 +22,8 @@ export const Search = ({
22
22
  onClick,
23
23
  iconBefore: IconBefore = SearchIcon,
24
24
  elemAfter,
25
- interactionName
25
+ interactionName,
26
+ 'aria-haspopup': ariaHaspopup
26
27
  }) => /*#__PURE__*/React.createElement(Fragment, null, /*#__PURE__*/React.createElement(Pressable, {
27
28
  style: {
28
29
  // To win the specificity war against Emotion we move this into inline styles
@@ -33,7 +34,8 @@ export const Search = ({
33
34
  },
34
35
  onClick: onClick,
35
36
  xcss: styles.root,
36
- interactionName: interactionName
37
+ interactionName: interactionName,
38
+ "aria-haspopup": ariaHaspopup
37
39
  }, /*#__PURE__*/React.createElement("span", {
38
40
  className: ax([styles.iconBefore])
39
41
  }, /*#__PURE__*/React.createElement(IconBefore, {
@@ -53,5 +55,6 @@ export const Search = ({
53
55
  appearance: "subtle",
54
56
  icon: SearchIcon,
55
57
  onClick: onClick,
56
- interactionName: interactionName
58
+ interactionName: interactionName,
59
+ "aria-haspopup": ariaHaspopup
57
60
  })));
@@ -3,4 +3,5 @@
3
3
  ._18m91wug{overflow-y:auto}
4
4
  ._19121cl4{isolation:isolate}
5
5
  ._1reo1wug{overflow-x:auto}
6
+ ._njlp1t7j{contain:paint}
6
7
  @media (min-width:64rem){._165teqxy{height:calc(100vh - var(--n_bnrM, 0px) - var(--n_tNvM, 0px))}._13wn1if8{position:sticky}._qwfh1wug{isolation:auto}}
@@ -10,7 +10,8 @@ import { useLayoutId } from '../id-utils';
10
10
  import { MainStickyContext } from './main-sticky-context';
11
11
  var mainElementStyles = {
12
12
  root: "_nd5l1gzg _19121cl4 _qwfh1wug",
13
- fixedContentArea: "_1reo1wug _18m91wug _152timx3 _165teqxy _13wn1if8"
13
+ fixedContentArea: "_1reo1wug _18m91wug _152timx3 _165teqxy _13wn1if8",
14
+ containPaint: "_njlp1t7j"
14
15
  };
15
16
 
16
17
  /**
@@ -32,7 +33,7 @@ export function Main(_ref) {
32
33
  return /*#__PURE__*/React.createElement(Fragment, null, /*#__PURE__*/React.createElement("div", {
33
34
  id: id,
34
35
  "data-layout-slot": true,
35
- className: ax([mainElementStyles.root, isFixed && mainElementStyles.fixedContentArea, xcss]),
36
+ className: ax([mainElementStyles.root, isFixed && mainElementStyles.fixedContentArea, fg('platform_dst_nav4_layering_in_main_slot_fixes') && mainElementStyles.containPaint, xcss]),
36
37
  role: "main",
37
38
  "data-testid": testId
38
39
  }, /*#__PURE__*/React.createElement(MainStickyContext.Provider, {
@@ -17,33 +17,6 @@ import { useSideNavRef } from './side-nav/element-context';
17
17
  import { useResizingWidthCssVarOnRootElement } from './use-resizing-width-css-var-on-root-element';
18
18
  var panelSplitterResizingVar = '--n_pnlRsz';
19
19
 
20
- /**
21
- * The bounds for Aside and Panel are purposely set to support the current usage in Jira.
22
- *
23
- * Jira sets the slot's width to `0px` when there is no active content to display in it.
24
- * - This means the min width needs to support `0px`.
25
- * The Conversation Assistant component in Jira (rendered in a nav3 RightSidebar, or a nav4 Aside) has a custom resizing
26
- * implementation, which has a maximum width of `50vw`.
27
- * - This means the max width needs to support `50vw`.
28
- *
29
- * This is not the final implementation and will be updated once Jira's usage has been fixed.
30
- * Ticket to track this is: https://jplat.atlassian.net/browse/BLU-3951
31
- *
32
- * We're using two different bounds for each slot here, to support the `0px` min width when programatically set using the
33
- * `defaultWidth` prop, and another one that is used when resizing the slots which has a sensible min width.
34
- */
35
- var oldPanelWidthSlotBounds = {
36
- min: '0px',
37
- max: '50vw'
38
- };
39
- var oldPanelWidthResizeBounds = {
40
- min: '120px',
41
- max: '50vw'
42
- };
43
- function getOldResizeBounds() {
44
- return oldPanelWidthResizeBounds;
45
- }
46
-
47
20
  /**
48
21
  * We typically use the `defaultWidth` as the minimum resizing width,
49
22
  * but for large default widths we fallback to a standard value.
@@ -126,7 +99,14 @@ export function Panel(_ref) {
126
99
  * We only use the `defaultWidth` up to a point to avoid huge panels.
127
100
  */
128
101
  var minWidth = Math.min(defaultWidth, fallbackResizeMinWidth);
129
- var getNewResizeBounds = useCallback(function () {
102
+
103
+ /**
104
+ * Returns the bounds for resizing, evaluated lazily when needed.
105
+ *
106
+ * Defined separately to the slot bounds because the resizing bounds need to be resolvable to a pixel value,
107
+ * and the panel's slot bounds use a complex CSS expression.
108
+ */
109
+ var getResizeBounds = useCallback(function () {
130
110
  var _sideNavRef$current$o, _sideNavRef$current;
131
111
  var sideNavWidth = (_sideNavRef$current$o = (_sideNavRef$current = sideNavRef.current) === null || _sideNavRef$current === void 0 ? void 0 : _sideNavRef$current.offsetWidth) !== null && _sideNavRef$current$o !== void 0 ? _sideNavRef$current$o : 0;
132
112
  /**
@@ -140,11 +120,11 @@ export function Panel(_ref) {
140
120
  max: "".concat(maxWidth, "px")
141
121
  };
142
122
  }, [minWidth, sideNavRef]);
143
- var panelWidthSlotBounds = fg('platform_design_system_nav4_preview_panel_support') ? {
123
+ var panelWidthSlotBounds = {
144
124
  min: "".concat(minWidth, "px"),
145
125
  // `sideNavLiveWidthVar` is not defined if the `SideNav` is not mounted, so we fallback to `0px`.
146
126
  max: "round(nearest, calc((100vw - var(".concat(sideNavLiveWidthVar, ", 0px)) / 2), 1px)")
147
- } : oldPanelWidthSlotBounds;
127
+ };
148
128
  var panelVariableWidth = "clamp(".concat(panelWidthSlotBounds.min, ", ").concat(width, "px, ").concat(panelWidthSlotBounds.max, ")");
149
129
  useResizingWidthCssVarOnRootElement({
150
130
  isEnabled: dangerouslyHoistSlotSizes && fg('platform_design_system_nav4_live_resizing_css_vars'),
@@ -176,7 +156,7 @@ export function Panel(_ref) {
176
156
  panelRef: ref,
177
157
  panelWidth: width,
178
158
  onCompleteResize: setWidth,
179
- getResizeBounds: fg('platform_design_system_nav4_preview_panel_support') ? getNewResizeBounds : getOldResizeBounds,
159
+ getResizeBounds: getResizeBounds,
180
160
  resizingCssVar: panelSplitterResizingVar,
181
161
  position: "start"
182
162
  }, /*#__PURE__*/React.createElement("div", {
@@ -514,7 +514,7 @@ function SideNavInternal(_ref) {
514
514
  devTimeOnlyAttributes['data-visible'] = visible.length ? visible.join(',') : 'false';
515
515
  }
516
516
  useResizingWidthCssVarOnRootElement({
517
- isEnabled: fg('platform_design_system_nav4_preview_panel_support'),
517
+ isEnabled: true,
518
518
  cssVar: panelSplitterResizingVar,
519
519
  panelId: sideNavPanelSplitterId
520
520
  });
@@ -524,19 +524,15 @@ function SideNavInternal(_ref) {
524
524
  "data-layout-slot": true,
525
525
  "aria-label": label,
526
526
  style: _defineProperty({}, sideNavVar, clampedWidth),
527
- ref: fg('platform_design_system_nav4_preview_panel_support') ? mergedRef : navRef,
527
+ ref: mergedRef,
528
528
  "data-testid": testId,
529
529
  className: ax([styles.root, fg('platform_design_system_nav4_sidenav_border') ? styles.newBorder : styles.oldBorder, isExpandedOnDesktop && !isExpandedOnMobile && !isFlyoutVisible && styles.hiddenMobileOnly, !isExpandedOnDesktop && isExpandedOnMobile && !isFlyoutVisible && styles.hiddenDesktopOnly, !isExpandedOnDesktop && !isExpandedOnMobile && !isFlyoutVisible && styles.hiddenMobileAndDesktop, (sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === 'open' && styles.flyoutOpen, (sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === 'open' && fg('platform_design_system_nav4_sidenav_border') && styles.newBorderFlyoutOpen, (sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === 'triggered-animate-close' && styles.flyoutAnimateClosed])
530
- }), fg('platform_design_system_nav4_preview_panel_support') &&
531
- /*#__PURE__*/
532
- // This CSS var is used by the `Panel` slot to enforce its maximum width constraint.
533
- // When we remove the UNSAFE legacy usage, we can change this to `HoistCssVarToLocalGrid`
534
- React.createElement(DangerouslyHoistCssVarToDocumentRoot, {
530
+ }), /*#__PURE__*/React.createElement(DangerouslyHoistCssVarToDocumentRoot, {
535
531
  variableName: sideNavLiveWidthVar,
536
532
  value: "0px",
537
533
  mediaQuery: media.above.md,
538
534
  responsiveValue: isExpandedOnDesktop ? "var(".concat(panelSplitterResizingVar, ", ").concat(clampedWidth, ")") : 0
539
- }), dangerouslyHoistSlotSizes && (fg('platform_design_system_nav4_preview_panel_support') ?
535
+ }), dangerouslyHoistSlotSizes &&
540
536
  /*#__PURE__*/
541
537
  // ------ START UNSAFE STYLES ------
542
538
  // These styles are only needed for the UNSAFE legacy use case for Jira + Confluence.
@@ -544,14 +540,9 @@ function SideNavInternal(_ref) {
544
540
  React.createElement(DangerouslyHoistCssVarToDocumentRoot, {
545
541
  variableName: UNSAFE_sideNavLayoutVar,
546
542
  value: "var(".concat(sideNavLiveWidthVar, ")")
547
- }) : /*#__PURE__*/React.createElement(DangerouslyHoistCssVarToDocumentRoot, {
548
- variableName: UNSAFE_sideNavLayoutVar,
549
- value: "0px",
550
- mediaQuery: media.above.md,
551
- responsiveValue: isExpandedOnDesktop ? clampedWidth : 0
552
543
  })
553
544
  // ------ END UNSAFE STYLES ------
554
- ), /*#__PURE__*/React.createElement(PanelSplitterProvider, {
545
+ , /*#__PURE__*/React.createElement(PanelSplitterProvider, {
555
546
  panelId: sideNavPanelSplitterId,
556
547
  panelRef: navRef,
557
548
  panelWidth: width,
@@ -23,7 +23,8 @@ export var Search = function Search(_ref) {
23
23
  _ref$iconBefore = _ref.iconBefore,
24
24
  IconBefore = _ref$iconBefore === void 0 ? SearchIcon : _ref$iconBefore,
25
25
  elemAfter = _ref.elemAfter,
26
- interactionName = _ref.interactionName;
26
+ interactionName = _ref.interactionName,
27
+ ariaHaspopup = _ref['aria-haspopup'];
27
28
  return /*#__PURE__*/React.createElement(Fragment, null, /*#__PURE__*/React.createElement(Pressable, {
28
29
  style: {
29
30
  // To win the specificity war against Emotion we move this into inline styles
@@ -34,7 +35,8 @@ export var Search = function Search(_ref) {
34
35
  },
35
36
  onClick: onClick,
36
37
  xcss: styles.root,
37
- interactionName: interactionName
38
+ interactionName: interactionName,
39
+ "aria-haspopup": ariaHaspopup
38
40
  }, /*#__PURE__*/React.createElement("span", {
39
41
  className: ax([styles.iconBefore])
40
42
  }, /*#__PURE__*/React.createElement(IconBefore, {
@@ -54,6 +56,7 @@ export var Search = function Search(_ref) {
54
56
  appearance: "subtle",
55
57
  icon: SearchIcon,
56
58
  onClick: onClick,
57
- interactionName: interactionName
59
+ interactionName: interactionName,
60
+ "aria-haspopup": ariaHaspopup
58
61
  })));
59
62
  };
@@ -22,8 +22,8 @@ export declare function Panel({ children, defaultWidth, label, skipLinkLabel, te
22
22
  *
23
23
  * It should be between the resize bounds - the minimum is 120px and the maximum is 50% of the viewport width.
24
24
  *
25
- * When `platform_design_system_nav4_preview_panel_support` is enabled, it is used as the minimum resizing width.
26
- * If the `defaultWidth` is greater then `400px` then `400px` will be used as the minimum resizing width instead.
25
+ * This value is also used as the minimum resizing width, except when the `defaultWidth` is greater then `400px`,
26
+ * in which case `400px` will be used as the minimum resizing width instead.
27
27
  */
28
28
  defaultWidth?: number;
29
29
  /**
@@ -9,7 +9,7 @@ import type { NewIconProps } from '@atlaskit/icon';
9
9
  *
10
10
  * The search element for the top navigation.
11
11
  */
12
- export declare const Search: ({ label, onClick, iconBefore: IconBefore, elemAfter, interactionName, }: {
12
+ export declare const Search: ({ label, onClick, iconBefore: IconBefore, elemAfter, interactionName, "aria-haspopup": ariaHaspopup, }: {
13
13
  /**
14
14
  * Provide an accessible label, often used by screen readers.
15
15
  */
@@ -32,4 +32,5 @@ export declare const Search: ({ label, onClick, iconBefore: IconBefore, elemAfte
32
32
  * An optional name used to identify events for [React UFO (Unified Frontend Observability) press interactions](https://developer.atlassian.com/platform/ufo/react-ufo/react-ufo/getting-started/#quick-start--press-interactions). For more information, see [React UFO integration into Design System components](https://go.atlassian.com/react-ufo-dst-integration).
33
33
  */
34
34
  interactionName?: string | undefined;
35
+ 'aria-haspopup'?: React.AriaAttributes['aria-haspopup'];
35
36
  }) => JSX.Element;
@@ -22,8 +22,8 @@ export declare function Panel({ children, defaultWidth, label, skipLinkLabel, te
22
22
  *
23
23
  * It should be between the resize bounds - the minimum is 120px and the maximum is 50% of the viewport width.
24
24
  *
25
- * When `platform_design_system_nav4_preview_panel_support` is enabled, it is used as the minimum resizing width.
26
- * If the `defaultWidth` is greater then `400px` then `400px` will be used as the minimum resizing width instead.
25
+ * This value is also used as the minimum resizing width, except when the `defaultWidth` is greater then `400px`,
26
+ * in which case `400px` will be used as the minimum resizing width instead.
27
27
  */
28
28
  defaultWidth?: number;
29
29
  /**
@@ -9,7 +9,7 @@ import type { NewIconProps } from '@atlaskit/icon';
9
9
  *
10
10
  * The search element for the top navigation.
11
11
  */
12
- export declare const Search: ({ label, onClick, iconBefore: IconBefore, elemAfter, interactionName, }: {
12
+ export declare const Search: ({ label, onClick, iconBefore: IconBefore, elemAfter, interactionName, "aria-haspopup": ariaHaspopup, }: {
13
13
  /**
14
14
  * Provide an accessible label, often used by screen readers.
15
15
  */
@@ -32,4 +32,5 @@ export declare const Search: ({ label, onClick, iconBefore: IconBefore, elemAfte
32
32
  * An optional name used to identify events for [React UFO (Unified Frontend Observability) press interactions](https://developer.atlassian.com/platform/ufo/react-ufo/react-ufo/getting-started/#quick-start--press-interactions). For more information, see [React UFO integration into Design System components](https://go.atlassian.com/react-ufo-dst-integration).
33
33
  */
34
34
  interactionName?: string | undefined;
35
+ 'aria-haspopup'?: React.AriaAttributes['aria-haspopup'];
35
36
  }) => JSX.Element;