@atlaskit/navigation-system 2.19.0 → 2.20.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 (30) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/cjs/ui/page-layout/side-nav/side-nav.compiled.css +4 -1
  3. package/dist/cjs/ui/page-layout/side-nav/side-nav.js +41 -9
  4. package/dist/cjs/ui/page-layout/side-nav/toggle-button-context.js +2 -7
  5. package/dist/cjs/ui/page-layout/side-nav/toggle-button-provider.js +1 -13
  6. package/dist/cjs/ui/page-layout/side-nav/toggle-button.compiled.css +1 -2
  7. package/dist/cjs/ui/page-layout/side-nav/toggle-button.js +1 -18
  8. package/dist/cjs/ui/page-layout/top-nav/top-nav-start.compiled.css +6 -1
  9. package/dist/cjs/ui/page-layout/top-nav/top-nav-start.js +120 -8
  10. package/dist/es2019/ui/page-layout/side-nav/side-nav.compiled.css +4 -1
  11. package/dist/es2019/ui/page-layout/side-nav/side-nav.js +41 -9
  12. package/dist/es2019/ui/page-layout/side-nav/toggle-button-context.js +1 -6
  13. package/dist/es2019/ui/page-layout/side-nav/toggle-button-provider.js +1 -14
  14. package/dist/es2019/ui/page-layout/side-nav/toggle-button.compiled.css +1 -2
  15. package/dist/es2019/ui/page-layout/side-nav/toggle-button.js +2 -19
  16. package/dist/es2019/ui/page-layout/top-nav/top-nav-start.compiled.css +6 -1
  17. package/dist/es2019/ui/page-layout/top-nav/top-nav-start.js +117 -8
  18. package/dist/esm/ui/page-layout/side-nav/side-nav.compiled.css +4 -1
  19. package/dist/esm/ui/page-layout/side-nav/side-nav.js +41 -9
  20. package/dist/esm/ui/page-layout/side-nav/toggle-button-context.js +1 -6
  21. package/dist/esm/ui/page-layout/side-nav/toggle-button-provider.js +1 -13
  22. package/dist/esm/ui/page-layout/side-nav/toggle-button.compiled.css +1 -2
  23. package/dist/esm/ui/page-layout/side-nav/toggle-button.js +2 -19
  24. package/dist/esm/ui/page-layout/top-nav/top-nav-start.compiled.css +6 -1
  25. package/dist/esm/ui/page-layout/top-nav/top-nav-start.js +120 -8
  26. package/dist/types/ui/page-layout/side-nav/toggle-button-context.d.ts +0 -4
  27. package/dist/types/ui/page-layout/side-nav/toggle-button-provider.d.ts +0 -8
  28. package/dist/types-ts4.5/ui/page-layout/side-nav/toggle-button-context.d.ts +0 -4
  29. package/dist/types-ts4.5/ui/page-layout/side-nav/toggle-button-provider.d.ts +0 -8
  30. package/package.json +2 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  # @atlassian/navigation-system
2
2
 
3
+ ## 2.20.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`bfed073f1849d`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/bfed073f1849d) -
8
+ Animations have been added to the `TopNavStart` component, as part of the full height sidebar
9
+ animations. The reorder of `TopNavStart`'s children elements (toggle button, app switcher, app
10
+ logo) when the side nav is toggled (on desktop) will have slide animations.
11
+
12
+ These changes are behind the feature gate `navx-full-height-sidebar`.
13
+
14
+ ## 2.19.1
15
+
16
+ ### Patch Changes
17
+
18
+ - [`8622b99ec3d36`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/8622b99ec3d36) -
19
+ Internal refactors to the full height sidebar animations to workaround some Compiled style
20
+ ordering issues. These changes are behind the feature gate `navx-full-height-sidear`.
21
+
3
22
  ## 2.19.0
4
23
 
5
24
  ### Minor Changes
@@ -14,6 +14,9 @@
14
14
  ._bfhk1bhr{background-color:var(--ds-surface-overlay,#fff)}
15
15
  ._kqsw1if8{position:sticky}
16
16
  ._vchhusvi{box-sizing:border-box}
17
+ @media (prefers-reduced-motion:no-preference){._10t88iot{transition-property:transform,display}._1vrh1a5r{transition-behavior:allow-discrete}._xrrp188d{transition-duration:.3s}._1lh81gzg{grid-area:main}._1xq51mm8{transition-timing-function:cubic-bezier(0,.4,0,1)}@starting-style{._1nu5jq3t{transform:translateX(-100%)}}._1xq51ku9{transition-timing-function:cubic-bezier(.6,0,0,1)}}
17
18
  @media (min-width:48rem){._14b5hc79{width:var(--n_snvRsz,var(--n_sNvw))}}
18
19
  @media (min-width:64rem){._165t56xv{height:calc(100vh - var(--n_bnrM, 0px))}._180k1wjm{inset-block-start:calc(var(--n_bnrM, 0px))}._26vxoned{padding-block-start:calc(var(--n_tNvM, 0px))}._1mt19dtb{margin-block-start:calc(var(--n_tNvM, 0px)*-1)}._dm2518uv{display:initial}._dm25glyw{display:none}._qiln1gzg{grid-area:main}._p5clglyw{border-inline-end:none}._4ap31bhr{background-color:var(--ds-surface-overlay,#fff)}._scbp1cd0{box-shadow:var(--ds-shadow-overlay,0 8px 9pt #091e4226,0 0 1px #091e424f)}._qilnk0mc{grid-area:side-nav}._p5cl7r9e{border-inline-end:var(--ds-border-width,1px) solid var(--ds-border,#091e4224)}._4ap3vuon{background-color:var(--ds-surface,#fff)}._scbpglyw{box-shadow:none}}
19
- @supports not (-moz-appearance:none){@media (prefers-reduced-motion:no-preference) and (min-width:64rem){@starting-style{._121hjq3t{transform:translateX(-100%)}}._1ee1188d{transition-duration:.3s}._1t2c1ku9{transition-timing-function:cubic-bezier(.6,0,0,1)}._14ckglyw{transform:none}}@media (prefers-reduced-motion:no-preference) and (min-width:64rem){._1ee1fnf5{transition-duration:.2s}._1t2c1mm8{transition-timing-function:cubic-bezier(0,.4,0,1)}._14ckjq3t{transform:translateX(-100%)}}@media (prefers-reduced-motion:no-preference) and (min-width:64rem){._2dsh8iot{transition-property:transform,display}._15ld1a5r{transition-behavior:allow-discrete}}@media (prefers-reduced-motion:no-preference) and (min-width:64rem){._kzn71gzg{grid-area:main}._1t2c1mm8{transition-timing-function:cubic-bezier(0,.4,0,1)}._14ckjq3t{transform:translateX(-100%)}}@media (prefers-reduced-motion:no-preference) and (min-width:64rem){@starting-style{._121hjq3t{transform:translateX(-100%)}}._kzn7k0mc{grid-area:side-nav}._1t2c1ku9{transition-timing-function:cubic-bezier(.6,0,0,1)}._14ckglyw{transform:none}}@media (prefers-reduced-motion:no-preference){._139f8iot{transition-property:transform,display}._1tpvfnf5{transition-duration:.2s}._sylc1a5r{transition-behavior:allow-discrete}._1uwsjq3t{transform:translateX(-100%)}}@media (prefers-reduced-motion:no-preference){@starting-style{._oyeijq3t{transform:translateX(-100%)}}._139f8iot{transition-property:transform,display}._1tpvfnf5{transition-duration:.2s}._sylc1a5r{transition-behavior:allow-discrete}}@media (prefers-reduced-motion:no-preference){._139f8iot{transition-property:transform,display}._sylc1a5r{transition-behavior:allow-discrete}._1tpv188d{transition-duration:.3s}}@media (prefers-reduced-motion:no-preference){._1h8i1gzg{grid-area:main}._ik8q1mm8{transition-timing-function:cubic-bezier(0,.4,0,1)}._1uwsjq3t{transform:translateX(-100%)}}@media (prefers-reduced-motion:no-preference){@starting-style{._oyeijq3t{transform:translateX(-100%)}}._ik8q1ku9{transition-timing-function:cubic-bezier(.6,0,0,1)}}}
20
+ @media (prefers-reduced-motion:no-preference) and (min-width:64rem){._17ly8iot{transition-property:transform,display}._177m1a5r{transition-behavior:allow-discrete}._1sg81gzg{grid-area:main}._vgub1mm8{transition-timing-function:cubic-bezier(0,.4,0,1)}._hh1ujq3t{transform:translateX(-100%)}@starting-style{._s2egjq3t{transform:translateX(-100%)}}._1sg8k0mc{grid-area:side-nav}._vgub1ku9{transition-timing-function:cubic-bezier(.6,0,0,1)}._hjoi188d{transition-duration:.3s}._hjoifnf5{transition-duration:.2s}}
21
+ @media (prefers-reduced-motion:no-preference) and (not (min-width:64rem)){._aadijq3t{transform:translateX(-100%)}}
22
+ @supports not (-moz-appearance:none){@media (prefers-reduced-motion:no-preference){._139f8iot{transition-property:transform,display}._1tpvfnf5{transition-duration:.2s}._sylc1a5r{transition-behavior:allow-discrete}._1uwsjq3t{transform:translateX(-100%)}}@media (prefers-reduced-motion:no-preference){@starting-style{._oyeijq3t{transform:translateX(-100%)}}._139f8iot{transition-property:transform,display}._1tpvfnf5{transition-duration:.2s}._sylc1a5r{transition-behavior:allow-discrete}}}
@@ -49,23 +49,30 @@ var widthResizeBounds = {
49
49
  function getResizeBounds() {
50
50
  return widthResizeBounds;
51
51
  }
52
+
53
+ /**
54
+ * We are using JS to detect Firefox and disable animations, instead of using CSS, as Compiled currently does not merge duplicate
55
+ * CSS at-rules when at-rules are nested: https://github.com/atlassian-labs/compiled/blob/e04a325915e1d13010205089e4915de0e53bc2d4/packages/css/src/plugins/merge-duplicate-at-rules.ts#L5
56
+ * Avoiding nesting the `@supports` at-rule inside of `@media` means Compiled can remove duplicate styles from the generated CSS.
57
+ */
58
+ var isFirefox = typeof navigator !== 'undefined' && navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
52
59
  var openLayerObserverSideNavNamespace = 'side-nav';
53
60
  var styles = {
54
61
  root: "_nd5l1b6c _191wglyw _t51zglyw _bfhk1bhr _16qs1cd0 _vchhusvi _4t3ieqxy _152timx3 _kqsw1if8 _1bsb1ego _1pbycs5v _14b5hc79 _qilnk0mc _p5cl7r9e _4ap3vuon _scbpglyw",
55
62
  flyoutOpen: "_qiln1gzg _p5clglyw _4ap31bhr _scbp1cd0 _139f8iot _1tpvfnf5 _sylc1a5r _oyeijq3t",
56
63
  flyoutAnimateClosed: "_1e0cglyw _qiln1gzg _139f8iot _1tpvfnf5 _sylc1a5r _1uwsjq3t",
57
- flyoutBaseStylesFullHeightSidebar: "_qiln1gzg _p5clglyw _4ap31bhr _scbp1cd0 _2dsh8iot _15ld1a5r",
58
- flyoutOpenFullHeightSidebar: "_1ee1188d _1t2c1ku9 _14ckglyw _121hjq3t",
59
- flyoutAnimateClosedFullHeightSidebar: "_dm25glyw _1ee1fnf5 _1t2c1mm8 _14ckjq3t",
64
+ flyoutBaseStylesFullHeightSidebar: "_qiln1gzg _p5clglyw _4ap31bhr _scbp1cd0 _17ly8iot _177m1a5r",
65
+ flyoutOpenFullHeightSidebar: "_hjoi188d _vgub1ku9 _s2egjq3t",
66
+ flyoutAnimateClosedFullHeightSidebar: "_dm25glyw _hjoifnf5 _vgub1mm8 _hh1ujq3t",
60
67
  flexContainer: "_4t3i1osq _1e0c1txw _2lx21bp4 _1bah1yb4",
61
68
  hiddenMobileAndDesktop: "_1e0cglyw",
62
69
  hiddenMobileOnly: "_1e0cglyw _dm2518uv",
63
70
  hiddenDesktopOnly: "_dm25glyw",
64
- animationBaseStyles: "_139f8iot _sylc1a5r _1tpv188d",
65
- expandAnimationMobile: "_ik8q1ku9 _oyeijq3t",
66
- collapseAnimationMobile: "_1h8i1gzg _ik8q1mm8 _1uwsjq3t",
67
- expandAnimationDesktop: "_kzn7k0mc _1t2c1ku9 _14ckglyw _121hjq3t",
68
- collapseAnimationDesktop: "_kzn71gzg _1t2c1mm8 _14ckjq3t",
71
+ animationBaseStyles: "_10t88iot _1vrh1a5r _xrrp188d",
72
+ expandAnimationMobile: "_1xq51ku9 _1nu5jq3t",
73
+ collapseAnimationMobile: "_1lh81gzg _1xq51mm8 _aadijq3t",
74
+ expandAnimationDesktop: "_1sg8k0mc _vgub1ku9 _s2egjq3t",
75
+ collapseAnimationDesktop: "_1sg81gzg _vgub1mm8 _hh1ujq3t",
69
76
  fullHeightSidebar: "_165t56xv _180k1wjm _26vxoned _1mt19dtb"
70
77
  };
71
78
  var fallbackDefaultWidth = 320;
@@ -592,6 +599,31 @@ function SideNavInternal(_ref) {
592
599
  isFirstRenderRef.current = false;
593
600
  }
594
601
  }, []);
602
+
603
+ // This is only used for the regular expand and collapse animations, not the flyout animations.
604
+ var shouldShowSidebarToggleAnimation =
605
+ // We do not apply the animation styles on the initial render, as the `@starting-style` rule will cause the sidebar to
606
+ // slide in initially.
607
+ !isFirstRenderRef.current &&
608
+ // We also do not apply the animation styles if the side nav is in flyout mode to make sure we don't override flyout styles.
609
+ // If we instead try to unset the `transform` property in the flyout styles using `transform: initial`, it results in the entire
610
+ // flyout animation being disabled.
611
+ !isFlyoutVisible &&
612
+ /**
613
+ * Disabling animations for Firefox, as it doesn't support animating the `display` property:
614
+ * https://caniuse.com/mdn-css_properties_display_is_transitionable
615
+ *
616
+ * As of October 2025, Firefox supports the expand animation, but not the collapse animation (it instantly changes to `display: none`).
617
+ * Because of this, we are disabling all sidebar animations for Firefox so it doesn't look like a bug.
618
+ *
619
+ * Unfortunately we cannot use `@supports` to target the support of `transition-behavior: allow-discrete` specifically
620
+ * for the `display` property. And `@supports at-rule(@starting-style)` is also not ready for browser use yet.
621
+ *
622
+ * We are using JS to detect Firefox and disable animations, instead of using CSS, as Compiled currently does not merge duplicate
623
+ * CSS at-rules when at-rules are nested: https://github.com/atlassian-labs/compiled/blob/e04a325915e1d13010205089e4915de0e53bc2d4/packages/css/src/plugins/merge-duplicate-at-rules.ts#L5
624
+ * Avoiding nesting the `@supports` at-rule inside of `@media` means Compiled can remove duplicate styles from the generated CSS.
625
+ */
626
+ !isFirefox;
595
627
  return /*#__PURE__*/React.createElement("nav", (0, _extends2.default)({
596
628
  id: id
597
629
  }, devTimeOnlyAttributes, {
@@ -600,7 +632,7 @@ function SideNavInternal(_ref) {
600
632
  style: (0, _defineProperty2.default)({}, _constants.sideNavVar, clampedWidth),
601
633
  ref: mergedRef,
602
634
  "data-testid": testId,
603
- className: (0, _runtime.ax)([styles.root, isExpandedOnDesktop && !isExpandedOnMobile && !isFlyoutVisible && styles.hiddenMobileOnly, !isExpandedOnDesktop && isExpandedOnMobile && !isFlyoutVisible && styles.hiddenDesktopOnly, !isExpandedOnDesktop && !isExpandedOnMobile && !isFlyoutVisible && styles.hiddenMobileAndDesktop, !isFirstRenderRef.current && (0, _platformFeatureFlags.fg)('navx-full-height-sidebar') && styles.animationBaseStyles, isExpandedOnMobile && !isFirstRenderRef.current && (0, _platformFeatureFlags.fg)('navx-full-height-sidebar') && styles.expandAnimationMobile, !isExpandedOnMobile && !isFirstRenderRef.current && (0, _platformFeatureFlags.fg)('navx-full-height-sidebar') && styles.collapseAnimationMobile, isExpandedOnDesktop && !isFirstRenderRef.current && (0, _platformFeatureFlags.fg)('navx-full-height-sidebar') && styles.expandAnimationDesktop, !isExpandedOnDesktop && !isFirstRenderRef.current && (0, _platformFeatureFlags.fg)('navx-full-height-sidebar') && styles.collapseAnimationDesktop, (sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === 'open' && !(0, _platformFeatureFlags.fg)('navx-full-height-sidebar') && styles.flyoutOpen, (sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === 'triggered-animate-close' && !(0, _platformFeatureFlags.fg)('navx-full-height-sidebar') && styles.flyoutAnimateClosed, ((sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === 'open' || (sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === 'triggered-animate-close') && (0, _platformFeatureFlags.fg)('navx-full-height-sidebar') && styles.flyoutBaseStylesFullHeightSidebar, (sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === 'triggered-animate-close' && (0, _platformFeatureFlags.fg)('navx-full-height-sidebar') && styles.flyoutAnimateClosedFullHeightSidebar, (sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === 'open' && (0, _platformFeatureFlags.fg)('navx-full-height-sidebar') && styles.flyoutOpenFullHeightSidebar, (sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === 'triggered-animate-close' && (0, _platformFeatureFlags.fg)('navx-full-height-sidebar') && styles.flyoutAnimateClosedFullHeightSidebar, isFlyoutClosed && (0, _platformFeatureFlags.fg)('navx-full-height-sidebar') && styles.fullHeightSidebar])
635
+ className: (0, _runtime.ax)([styles.root, isExpandedOnDesktop && !isExpandedOnMobile && !isFlyoutVisible && styles.hiddenMobileOnly, !isExpandedOnDesktop && isExpandedOnMobile && !isFlyoutVisible && styles.hiddenDesktopOnly, !isExpandedOnDesktop && !isExpandedOnMobile && !isFlyoutVisible && styles.hiddenMobileAndDesktop, shouldShowSidebarToggleAnimation && (0, _platformFeatureFlags.fg)('navx-full-height-sidebar') && styles.animationBaseStyles, isExpandedOnMobile && shouldShowSidebarToggleAnimation && (0, _platformFeatureFlags.fg)('navx-full-height-sidebar') && styles.expandAnimationMobile, !isExpandedOnMobile && shouldShowSidebarToggleAnimation && (0, _platformFeatureFlags.fg)('navx-full-height-sidebar') && styles.collapseAnimationMobile, isExpandedOnDesktop && shouldShowSidebarToggleAnimation && (0, _platformFeatureFlags.fg)('navx-full-height-sidebar') && styles.expandAnimationDesktop, !isExpandedOnDesktop && shouldShowSidebarToggleAnimation && (0, _platformFeatureFlags.fg)('navx-full-height-sidebar') && styles.collapseAnimationDesktop, (sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === 'open' && !(0, _platformFeatureFlags.fg)('navx-full-height-sidebar') && styles.flyoutOpen, (sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === 'triggered-animate-close' && !(0, _platformFeatureFlags.fg)('navx-full-height-sidebar') && styles.flyoutAnimateClosed, ((sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === 'open' || (sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === 'triggered-animate-close') && !isFirefox && (0, _platformFeatureFlags.fg)('navx-full-height-sidebar') && styles.flyoutBaseStylesFullHeightSidebar, (sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === 'triggered-animate-close' && !isFirefox && (0, _platformFeatureFlags.fg)('navx-full-height-sidebar') && styles.flyoutAnimateClosedFullHeightSidebar, (sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === 'open' && !isFirefox && (0, _platformFeatureFlags.fg)('navx-full-height-sidebar') && styles.flyoutOpenFullHeightSidebar, (sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === 'triggered-animate-close' && !isFirefox && (0, _platformFeatureFlags.fg)('navx-full-height-sidebar') && styles.flyoutAnimateClosedFullHeightSidebar, isFlyoutClosed && (0, _platformFeatureFlags.fg)('navx-full-height-sidebar') && styles.fullHeightSidebar])
604
636
  }), /*#__PURE__*/React.createElement(_hoistUtils.DangerouslyHoistCssVarToDocumentRoot, {
605
637
  variableName: _constants.sideNavLiveWidthVar,
606
638
  value: "0px",
@@ -4,7 +4,7 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
- exports.SideNavToggleButtonSlotContext = exports.SideNavToggleButtonElement = exports.SideNavToggleButtonAttachRef = void 0;
7
+ exports.SideNavToggleButtonElement = exports.SideNavToggleButtonAttachRef = void 0;
8
8
  var _react = require("react");
9
9
  var _noop = _interopRequireDefault(require("@atlaskit/ds-lib/noop"));
10
10
  /**
@@ -23,9 +23,4 @@ var SideNavToggleButtonElement = exports.SideNavToggleButtonElement = /*#__PURE_
23
23
  * A callback ref is needed because the side nav can be mounted before the elements in the top bar (e.g. if the element
24
24
  * is lazy loaded, which happens in Jira and Confluence), which would prevent the event listeners from being set up.
25
25
  */
26
- var SideNavToggleButtonAttachRef = exports.SideNavToggleButtonAttachRef = /*#__PURE__*/(0, _react.createContext)(_noop.default);
27
-
28
- /**
29
- * Used to check if the SideNavToggleButton is rendered inside of its slot in `TopNavStart`.
30
- */
31
- var SideNavToggleButtonSlotContext = exports.SideNavToggleButtonSlotContext = /*#__PURE__*/(0, _react.createContext)(false);
26
+ var SideNavToggleButtonAttachRef = exports.SideNavToggleButtonAttachRef = /*#__PURE__*/(0, _react.createContext)(_noop.default);
@@ -5,7 +5,7 @@ var _typeof = require("@babel/runtime/helpers/typeof");
5
5
  Object.defineProperty(exports, "__esModule", {
6
6
  value: true
7
7
  });
8
- exports.SideNavToggleButtonSlotProvider = exports.SideNavToggleButtonProvider = void 0;
8
+ exports.SideNavToggleButtonProvider = void 0;
9
9
  var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
10
10
  var _react = _interopRequireWildcard(require("react"));
11
11
  var _toggleButtonContext = require("./toggle-button-context");
@@ -34,16 +34,4 @@ var SideNavToggleButtonProvider = exports.SideNavToggleButtonProvider = function
34
34
  }, /*#__PURE__*/_react.default.createElement(_toggleButtonContext.SideNavToggleButtonAttachRef.Provider, {
35
35
  value: setElement
36
36
  }, children));
37
- };
38
-
39
- /**
40
- * Provider for the side nav toggle button slot.
41
- *
42
- * This allows us to determine if the toggle button is rendered inside or outside of its slot.
43
- */
44
- var SideNavToggleButtonSlotProvider = exports.SideNavToggleButtonSlotProvider = function SideNavToggleButtonSlotProvider(_ref2) {
45
- var children = _ref2.children;
46
- return /*#__PURE__*/_react.default.createElement(_toggleButtonContext.SideNavToggleButtonSlotContext.Provider, {
47
- value: true
48
- }, children);
49
37
  };
@@ -1,3 +1,2 @@
1
1
  ._1e0c1bgi{display:contents}
2
- ._lcxvglyw{pointer-events:none}
3
- @media (min-width:64rem){._3l1a1wug{margin-inline-start:auto}}
2
+ ._lcxvglyw{pointer-events:none}
@@ -32,12 +32,6 @@ var toggleButtonTooltipOptions = {
32
32
  // For duplicate "mouseenter" issue when changing icons (see below)
33
33
  var silentIconStyles = null;
34
34
 
35
- /**
36
- * Wrapper styles to align the toggle button to the end of `TopNavStart`
37
- * when FHS is expanded.
38
- */
39
- var fullHeightSidebarExpandedWrapperStyles = null;
40
-
41
35
  /**
42
36
  * __SideNavToggleButton__
43
37
  *
@@ -144,7 +138,7 @@ var SideNavToggleButton = exports.SideNavToggleButton = function SideNavToggleBu
144
138
  }
145
139
  return toggleButtonTooltipOptions;
146
140
  }, [shortcut]);
147
- var iconButton = /*#__PURE__*/_react.default.createElement(_migration.IconButton, {
141
+ return /*#__PURE__*/_react.default.createElement(_migration.IconButton, {
148
142
  appearance: "subtle",
149
143
  label: isSideNavExpanded ? collapseLabel : expandLabel,
150
144
  icon: icon,
@@ -155,15 +149,4 @@ var SideNavToggleButton = exports.SideNavToggleButton = function SideNavToggleBu
155
149
  ref: (0, _platformFeatureFlags.fg)('platform_dst_nav4_side_nav_toggle_ref_fix') ? setElement : elementRef,
156
150
  tooltip: tooltipProps
157
151
  });
158
- var isInsideSlot = (0, _react.useContext)(_toggleButtonContext.SideNavToggleButtonSlotContext);
159
-
160
- // Checking `isInsideSlot` in case an app isn't using the slot
161
- // We don't want to break existing non-slot usage with the left margin
162
- // This check can be removed in the future, after slot is required for a while.
163
- if (isInsideSlot && (0, _platformFeatureFlags.fg)('navx-full-height-sidebar')) {
164
- return /*#__PURE__*/_react.default.createElement("div", {
165
- className: (0, _runtime.ax)([isSideNavExpandedOnDesktop && "_3l1a1wug"])
166
- }, iconButton);
167
- }
168
- return iconButton;
169
152
  };
@@ -1,9 +1,14 @@
1
1
 
2
2
  ._zulp1b66{gap:var(--ds-space-050,4px)}
3
- ._yyhykb7n{grid-column:1}._1e0c1txw{display:flex}
3
+ ._zulp1kw7{gap:inherit}
4
+ ._yyhykb7n{grid-column:1}._1e0c1kw7{display:inherit}
5
+ ._1e0c1txw{display:flex}
6
+ ._1ul9idpf{min-width:0}
4
7
  ._4cvr1h6o{align-items:center}
5
8
  ._4t3i1osq{height:100%}
9
+ ._ahbq1wug{margin-inline-start:auto}
6
10
  ._bozgutpp{padding-inline-start:var(--ds-space-150,9pt)}
7
11
  ._lcxv1wug{pointer-events:auto}
8
12
  ._vchhusvi{box-sizing:border-box}
13
+ @media (prefers-reduced-motion:no-preference){._10t81e03{transition-property:transform}._10t81rjc{transition-property:transform,opacity}._1xq51ytf{transition-timing-function:ease-in-out}._1xq55ucs{transition-timing-function:ease}._mjvc162w{transform:translateX(calc(-2rem + var(--ds-space-050, 4px)*-1))}._mjvcjq3t{transform:translateX(-100%)}._bgpzidpf{opacity:0}._mjvcsws1{transform:translateX(calc(2rem + var(--ds-space-050, 4px)))}._mjvcxwn4{transform:translateX(100%)}._mjvcz12g{transform:translateX(0)}._xrrp188d{transition-duration:.3s}._bgpzkb7n{opacity:1}}
9
14
  @media (min-width:64rem){._15rin7od{min-width:unset}._glte1osq{width:100%}._15rip2n4{min-width:330px}._glte1ris{width:max-content}._15ri1mjv{min-width:300px}._1gs5usvi{box-sizing:border-box}._glte93mn{width:var(--n_sNvlw,100%)}._exxmpxbi{padding-inline-end:var(--ds-space-200,1pc)}}
@@ -11,12 +11,24 @@ require("./top-nav-start.compiled.css");
11
11
  var _runtime = require("@compiled/react/runtime");
12
12
  var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
13
13
  var _react = _interopRequireWildcard(require("react"));
14
+ var _useStableRef = _interopRequireDefault(require("@atlaskit/ds-lib/use-stable-ref"));
14
15
  var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
15
16
  var _compiled = require("@atlaskit/primitives/compiled");
16
17
  var _topNavStartContext = require("../../../context/top-nav-start/top-nav-start-context");
17
- var _toggleButtonProvider = require("../side-nav/toggle-button-provider");
18
18
  var _useSideNavVisibility3 = require("../side-nav/use-side-nav-visibility");
19
19
  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); }
20
+ /**
21
+ * Firefox does support these reorder animations, but only partially enabling layout animations would look odd.
22
+ *
23
+ * We are using JS to detect Firefox and disable animations, instead of using CSS, as Compiled currently does not merge duplicate
24
+ * CSS at-rules when at-rules are nested: https://github.com/atlassian-labs/compiled/blob/e04a325915e1d13010205089e4915de0e53bc2d4/packages/css/src/plugins/merge-duplicate-at-rules.ts#L5
25
+ * Avoiding nesting the `@supports` at-rule inside of `@media` means Compiled can remove duplicate styles from the generated CSS.
26
+ */
27
+ var isFirefox = typeof navigator !== 'undefined' && navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
28
+
29
+ // Placed in a variable, as the value is used in the translateX value for the children wrapper animation.
30
+ var flexGap = "var(--ds-space-050, 4px)";
31
+
20
32
  /**
21
33
  * Styles for the TopNavStart element.
22
34
  *
@@ -39,10 +51,48 @@ var innerStyles = {
39
51
  var wrapperStyles = {
40
52
  root: "_vchhusvi",
41
53
  fullHeightSidebar: "_bozgutpp",
42
- fullHeightSidebarCollapsed: "_15rip2n4",
43
54
  fullHeightSidebarExpanded: "_glte93mn _exxmpxbi"
44
55
  };
45
56
 
57
+ /**
58
+ * We use a fixed translateX offset for the slide animation (used when the TopNavStart children elements are reordered).
59
+ * This fixed offset makes the elements appear to animate smoothly from the old to the new position.
60
+ * This offset is calculated based on:
61
+ * - 32px (2rem) width of the side nav toggle button (IconButton)
62
+ * - 4px gap ('space.050' token) of the flex container
63
+ *
64
+ * The benefit of hardcoding this offset is that we don't need to calculate it using JS each time the sidebar is toggled.
65
+ * However, it could become out of sync if the width of IconButton changes.
66
+ *
67
+ * The alternative is using JS to store the previous position of the children wrapper element, and calculate the offset based on
68
+ * the new position, and then transforming using that offset. This would prevent the animation from going out of sync.
69
+ */
70
+ var childrenWrapperAnimationOffset = "calc(2rem + ".concat(flexGap, ")");
71
+ var childrenWrapperStyles = {
72
+ root: "_zulp1kw7 _1e0c1kw7 _1ul9idpf",
73
+ animationBaseStyles: "_10t81e03",
74
+ finalPosition: "_mjvcz12g _xrrp188d",
75
+ expandAnimationStartPosition: "_mjvcsws1",
76
+ collapseAnimationStartPosition: "_mjvc162w"
77
+ };
78
+
79
+ /**
80
+ * We use a fixed translateX offset for the toggle button slide animation (used when the TopNavStart children elements are reordered).
81
+ * The specific value doesn't matter too much for the toggle button animation, so we are using `100%`, which will match the toggle button width.
82
+ *
83
+ * By combining the `translateX` animation with an `opacity` fade, the feel and experience is actually quite similar to animating the
84
+ * element from the exact old position (offset), and it avoids the additional complexity of needing to track and calculate the exact offset.
85
+ */
86
+ var toggleButtonWrapperStyles = {
87
+ root: "_10t81rjc",
88
+ finalPosition: "_mjvcz12g _xrrp188d _bgpzkb7n",
89
+ expandAnimationStartPosition: "_mjvcjq3t _bgpzidpf",
90
+ collapseAnimationStartPosition: "_mjvcxwn4 _bgpzidpf",
91
+ expandAnimationTimingFunction: "_1xq51ytf",
92
+ collapseAnimationTimingFunction: "_1xq55ucs",
93
+ alignEnd: "_ahbq1wug"
94
+ };
95
+
46
96
  /**
47
97
  * The consistent key used for the side nav toggle button to ensure it does not get remounted
48
98
  * when it is reordered.
@@ -122,15 +172,77 @@ function TopNavStart(_ref3) {
122
172
  (0, _compiled.UNSAFE_useMediaQuery)('above.md', function (event) {
123
173
  setIsDesktop(event.matches);
124
174
  });
175
+ var _useState3 = (0, _react.useState)({
176
+ type: 'idle'
177
+ }),
178
+ _useState4 = (0, _slicedToArray2.default)(_useState3, 2),
179
+ animationState = _useState4[0],
180
+ setAnimationState = _useState4[1];
181
+
182
+ // Used to prevent the reorder animations from running on the initial render.
183
+ var isFirstRenderRef = (0, _react.useRef)(true);
184
+ (0, _react.useEffect)(function () {
185
+ if (!(0, _platformFeatureFlags.fg)('navx-full-height-sidebar')) {
186
+ return;
187
+ }
188
+ if (isFirstRenderRef.current) {
189
+ isFirstRenderRef.current = false;
190
+ }
191
+ }, []);
192
+
193
+ // Using a stable ref to avoid re-running the animation layout effect when the toggle button prop value changes, which
194
+ // can happen a lot (e.g. if the parent re-renders)
195
+ var sideNavToggleButtonStableRef = (0, _useStableRef.default)(sideNavToggleButton);
196
+ (0, _react.useLayoutEffect)(function () {
197
+ if (!(0, _platformFeatureFlags.fg)('navx-full-height-sidebar')) {
198
+ return;
199
+ }
200
+
201
+ /**
202
+ * This layout effect is used to animate the TopNavStart children elements to their new position after being reordered.
203
+ * It is called when the sidebar's desktop expansion state changes.
204
+ *
205
+ * It works by first setting a translateX offset on the elements, used as the start position of the slide animation.
206
+ * - For the toggle button, it's a fixed offset. It's combined with an opacity, so the exact offset doesn't matter too much.
207
+ * - For the children wrapper (wrapping everything except the toggle button), an offset was chosen to make the animation
208
+ * start position the exact same as the element's old position. See comments for `childrenWrapperStyles` for more details.
209
+ *
210
+ * On the next frame, the translateX offset is cleared, triggering the animation to the new position.
211
+ */
212
+
213
+ if (isFirstRenderRef.current) {
214
+ // No animations on initial render.
215
+ return;
216
+ }
217
+ if (!sideNavToggleButtonStableRef.current) {
218
+ // If there is no toggle button, there should be no re-order animations.
219
+ return;
220
+ }
221
+
222
+ // Set the translateX offsets so elements are ready to animate to their actual new position after being reordered
223
+ setAnimationState({
224
+ type: isExpandedOnDesktop ? 'expand' : 'collapse'
225
+ });
226
+ requestAnimationFrame(function () {
227
+ // Clear translateX offsets on next frame to trigger animation to new position in a re-render
228
+ setAnimationState({
229
+ type: 'idle'
230
+ });
231
+ });
232
+
233
+ // This layout effect is called when the sidebar's desktop expansion state changes.
234
+ }, [isExpandedOnDesktop, sideNavToggleButtonStableRef]);
125
235
  var TopNavStartInner = (0, _platformFeatureFlags.fg)('navx-full-height-sidebar') ? TopNavStartInnerFHS : TopNavStartInnerOld;
126
236
  return /*#__PURE__*/_react.default.createElement(TopNavStartInner, {
127
237
  ref: elementRef,
128
238
  testId: testId
129
- }, !(0, _platformFeatureFlags.fg)('navx-full-height-sidebar') && /*#__PURE__*/_react.default.createElement(_toggleButtonProvider.SideNavToggleButtonSlotProvider, {
130
- key: sideNavToggleButtonKey
131
- }, sideNavToggleButton), sideNavToggleButton && (!isDesktop || !isExpandedOnDesktop) && (0, _platformFeatureFlags.fg)('navx-full-height-sidebar') && /*#__PURE__*/_react.default.createElement(_toggleButtonProvider.SideNavToggleButtonSlotProvider, {
132
- key: sideNavToggleButtonKey
133
- }, sideNavToggleButton), children, sideNavToggleButton && isDesktop && isExpandedOnDesktop && (0, _platformFeatureFlags.fg)('navx-full-height-sidebar') && /*#__PURE__*/_react.default.createElement(_toggleButtonProvider.SideNavToggleButtonSlotProvider, {
134
- key: sideNavToggleButtonKey
239
+ }, !(0, _platformFeatureFlags.fg)('navx-full-height-sidebar') && sideNavToggleButton, sideNavToggleButton && (!isDesktop || !isExpandedOnDesktop) && (0, _platformFeatureFlags.fg)('navx-full-height-sidebar') && /*#__PURE__*/_react.default.createElement("div", {
240
+ key: sideNavToggleButtonKey,
241
+ className: (0, _runtime.ax)([!isFirefox && toggleButtonWrapperStyles.root, !isFirefox && animationState.type === 'idle' && toggleButtonWrapperStyles.finalPosition, !isFirefox && animationState.type === 'idle' && toggleButtonWrapperStyles.collapseAnimationTimingFunction, !isFirefox && animationState.type === 'collapse' && toggleButtonWrapperStyles.collapseAnimationStartPosition])
242
+ }, sideNavToggleButton), (0, _platformFeatureFlags.fg)('navx-full-height-sidebar') ? /*#__PURE__*/_react.default.createElement("div", {
243
+ className: (0, _runtime.ax)([childrenWrapperStyles.root, !isFirefox && childrenWrapperStyles.animationBaseStyles, !isFirefox && animationState.type === 'idle' && childrenWrapperStyles.finalPosition, !isFirefox && animationState.type === 'expand' && childrenWrapperStyles.expandAnimationStartPosition, !isFirefox && animationState.type === 'collapse' && childrenWrapperStyles.collapseAnimationStartPosition])
244
+ }, children) : children, sideNavToggleButton && isDesktop && isExpandedOnDesktop && (0, _platformFeatureFlags.fg)('navx-full-height-sidebar') && /*#__PURE__*/_react.default.createElement("div", {
245
+ key: sideNavToggleButtonKey,
246
+ className: (0, _runtime.ax)([!isFirefox && toggleButtonWrapperStyles.root, toggleButtonWrapperStyles.alignEnd, !isFirefox && animationState.type === 'idle' && toggleButtonWrapperStyles.finalPosition, !isFirefox && animationState.type === 'idle' && toggleButtonWrapperStyles.expandAnimationTimingFunction, !isFirefox && animationState.type === 'expand' && toggleButtonWrapperStyles.expandAnimationStartPosition])
135
247
  }, sideNavToggleButton));
136
248
  }
@@ -14,6 +14,9 @@
14
14
  ._bfhk1bhr{background-color:var(--ds-surface-overlay,#fff)}
15
15
  ._kqsw1if8{position:sticky}
16
16
  ._vchhusvi{box-sizing:border-box}
17
+ @media (prefers-reduced-motion:no-preference){._10t88iot{transition-property:transform,display}._1vrh1a5r{transition-behavior:allow-discrete}._xrrp188d{transition-duration:.3s}._1lh81gzg{grid-area:main}._1xq51mm8{transition-timing-function:cubic-bezier(0,.4,0,1)}@starting-style{._1nu5jq3t{transform:translateX(-100%)}}._1xq51ku9{transition-timing-function:cubic-bezier(.6,0,0,1)}}
17
18
  @media (min-width:48rem){._14b5hc79{width:var(--n_snvRsz,var(--n_sNvw))}}
18
19
  @media (min-width:64rem){._165t56xv{height:calc(100vh - var(--n_bnrM, 0px))}._180k1wjm{inset-block-start:calc(var(--n_bnrM, 0px))}._26vxoned{padding-block-start:calc(var(--n_tNvM, 0px))}._1mt19dtb{margin-block-start:calc(var(--n_tNvM, 0px)*-1)}._dm2518uv{display:initial}._dm25glyw{display:none}._qiln1gzg{grid-area:main}._p5clglyw{border-inline-end:none}._4ap31bhr{background-color:var(--ds-surface-overlay,#fff)}._scbp1cd0{box-shadow:var(--ds-shadow-overlay,0 8px 9pt #091e4226,0 0 1px #091e424f)}._qilnk0mc{grid-area:side-nav}._p5cl7r9e{border-inline-end:var(--ds-border-width,1px) solid var(--ds-border,#091e4224)}._4ap3vuon{background-color:var(--ds-surface,#fff)}._scbpglyw{box-shadow:none}}
19
- @supports not (-moz-appearance:none){@media (prefers-reduced-motion:no-preference) and (min-width:64rem){@starting-style{._121hjq3t{transform:translateX(-100%)}}._1ee1188d{transition-duration:.3s}._1t2c1ku9{transition-timing-function:cubic-bezier(.6,0,0,1)}._14ckglyw{transform:none}}@media (prefers-reduced-motion:no-preference) and (min-width:64rem){._1ee1fnf5{transition-duration:.2s}._1t2c1mm8{transition-timing-function:cubic-bezier(0,.4,0,1)}._14ckjq3t{transform:translateX(-100%)}}@media (prefers-reduced-motion:no-preference) and (min-width:64rem){._2dsh8iot{transition-property:transform,display}._15ld1a5r{transition-behavior:allow-discrete}}@media (prefers-reduced-motion:no-preference) and (min-width:64rem){._kzn71gzg{grid-area:main}._1t2c1mm8{transition-timing-function:cubic-bezier(0,.4,0,1)}._14ckjq3t{transform:translateX(-100%)}}@media (prefers-reduced-motion:no-preference) and (min-width:64rem){@starting-style{._121hjq3t{transform:translateX(-100%)}}._kzn7k0mc{grid-area:side-nav}._1t2c1ku9{transition-timing-function:cubic-bezier(.6,0,0,1)}._14ckglyw{transform:none}}@media (prefers-reduced-motion:no-preference){._139f8iot{transition-property:transform,display}._1tpvfnf5{transition-duration:.2s}._sylc1a5r{transition-behavior:allow-discrete}._1uwsjq3t{transform:translateX(-100%)}}@media (prefers-reduced-motion:no-preference){@starting-style{._oyeijq3t{transform:translateX(-100%)}}._139f8iot{transition-property:transform,display}._1tpvfnf5{transition-duration:.2s}._sylc1a5r{transition-behavior:allow-discrete}}@media (prefers-reduced-motion:no-preference){._139f8iot{transition-property:transform,display}._sylc1a5r{transition-behavior:allow-discrete}._1tpv188d{transition-duration:.3s}}@media (prefers-reduced-motion:no-preference){._1h8i1gzg{grid-area:main}._ik8q1mm8{transition-timing-function:cubic-bezier(0,.4,0,1)}._1uwsjq3t{transform:translateX(-100%)}}@media (prefers-reduced-motion:no-preference){@starting-style{._oyeijq3t{transform:translateX(-100%)}}._ik8q1ku9{transition-timing-function:cubic-bezier(.6,0,0,1)}}}
20
+ @media (prefers-reduced-motion:no-preference) and (min-width:64rem){._17ly8iot{transition-property:transform,display}._177m1a5r{transition-behavior:allow-discrete}._1sg81gzg{grid-area:main}._vgub1mm8{transition-timing-function:cubic-bezier(0,.4,0,1)}._hh1ujq3t{transform:translateX(-100%)}@starting-style{._s2egjq3t{transform:translateX(-100%)}}._1sg8k0mc{grid-area:side-nav}._vgub1ku9{transition-timing-function:cubic-bezier(.6,0,0,1)}._hjoi188d{transition-duration:.3s}._hjoifnf5{transition-duration:.2s}}
21
+ @media (prefers-reduced-motion:no-preference) and (not (min-width:64rem)){._aadijq3t{transform:translateX(-100%)}}
22
+ @supports not (-moz-appearance:none){@media (prefers-reduced-motion:no-preference){._139f8iot{transition-property:transform,display}._1tpvfnf5{transition-duration:.2s}._sylc1a5r{transition-behavior:allow-discrete}._1uwsjq3t{transform:translateX(-100%)}}@media (prefers-reduced-motion:no-preference){@starting-style{._oyeijq3t{transform:translateX(-100%)}}._139f8iot{transition-property:transform,display}._1tpvfnf5{transition-duration:.2s}._sylc1a5r{transition-behavior:allow-discrete}}}
@@ -36,23 +36,30 @@ const widthResizeBounds = {
36
36
  function getResizeBounds() {
37
37
  return widthResizeBounds;
38
38
  }
39
+
40
+ /**
41
+ * We are using JS to detect Firefox and disable animations, instead of using CSS, as Compiled currently does not merge duplicate
42
+ * CSS at-rules when at-rules are nested: https://github.com/atlassian-labs/compiled/blob/e04a325915e1d13010205089e4915de0e53bc2d4/packages/css/src/plugins/merge-duplicate-at-rules.ts#L5
43
+ * Avoiding nesting the `@supports` at-rule inside of `@media` means Compiled can remove duplicate styles from the generated CSS.
44
+ */
45
+ const isFirefox = typeof navigator !== 'undefined' && navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
39
46
  const openLayerObserverSideNavNamespace = 'side-nav';
40
47
  const styles = {
41
48
  root: "_nd5l1b6c _191wglyw _t51zglyw _bfhk1bhr _16qs1cd0 _vchhusvi _4t3ieqxy _152timx3 _kqsw1if8 _1bsb1ego _1pbycs5v _14b5hc79 _qilnk0mc _p5cl7r9e _4ap3vuon _scbpglyw",
42
49
  flyoutOpen: "_qiln1gzg _p5clglyw _4ap31bhr _scbp1cd0 _139f8iot _1tpvfnf5 _sylc1a5r _oyeijq3t",
43
50
  flyoutAnimateClosed: "_1e0cglyw _qiln1gzg _139f8iot _1tpvfnf5 _sylc1a5r _1uwsjq3t",
44
- flyoutBaseStylesFullHeightSidebar: "_qiln1gzg _p5clglyw _4ap31bhr _scbp1cd0 _2dsh8iot _15ld1a5r",
45
- flyoutOpenFullHeightSidebar: "_1ee1188d _1t2c1ku9 _14ckglyw _121hjq3t",
46
- flyoutAnimateClosedFullHeightSidebar: "_dm25glyw _1ee1fnf5 _1t2c1mm8 _14ckjq3t",
51
+ flyoutBaseStylesFullHeightSidebar: "_qiln1gzg _p5clglyw _4ap31bhr _scbp1cd0 _17ly8iot _177m1a5r",
52
+ flyoutOpenFullHeightSidebar: "_hjoi188d _vgub1ku9 _s2egjq3t",
53
+ flyoutAnimateClosedFullHeightSidebar: "_dm25glyw _hjoifnf5 _vgub1mm8 _hh1ujq3t",
47
54
  flexContainer: "_4t3i1osq _1e0c1txw _2lx21bp4 _1bah1yb4",
48
55
  hiddenMobileAndDesktop: "_1e0cglyw",
49
56
  hiddenMobileOnly: "_1e0cglyw _dm2518uv",
50
57
  hiddenDesktopOnly: "_dm25glyw",
51
- animationBaseStyles: "_139f8iot _sylc1a5r _1tpv188d",
52
- expandAnimationMobile: "_ik8q1ku9 _oyeijq3t",
53
- collapseAnimationMobile: "_1h8i1gzg _ik8q1mm8 _1uwsjq3t",
54
- expandAnimationDesktop: "_kzn7k0mc _1t2c1ku9 _14ckglyw _121hjq3t",
55
- collapseAnimationDesktop: "_kzn71gzg _1t2c1mm8 _14ckjq3t",
58
+ animationBaseStyles: "_10t88iot _1vrh1a5r _xrrp188d",
59
+ expandAnimationMobile: "_1xq51ku9 _1nu5jq3t",
60
+ collapseAnimationMobile: "_1lh81gzg _1xq51mm8 _aadijq3t",
61
+ expandAnimationDesktop: "_1sg8k0mc _vgub1ku9 _s2egjq3t",
62
+ collapseAnimationDesktop: "_1sg81gzg _vgub1mm8 _hh1ujq3t",
56
63
  fullHeightSidebar: "_165t56xv _180k1wjm _26vxoned _1mt19dtb"
57
64
  };
58
65
  const fallbackDefaultWidth = 320;
@@ -581,6 +588,31 @@ function SideNavInternal({
581
588
  isFirstRenderRef.current = false;
582
589
  }
583
590
  }, []);
591
+
592
+ // This is only used for the regular expand and collapse animations, not the flyout animations.
593
+ const shouldShowSidebarToggleAnimation =
594
+ // We do not apply the animation styles on the initial render, as the `@starting-style` rule will cause the sidebar to
595
+ // slide in initially.
596
+ !isFirstRenderRef.current &&
597
+ // We also do not apply the animation styles if the side nav is in flyout mode to make sure we don't override flyout styles.
598
+ // If we instead try to unset the `transform` property in the flyout styles using `transform: initial`, it results in the entire
599
+ // flyout animation being disabled.
600
+ !isFlyoutVisible &&
601
+ /**
602
+ * Disabling animations for Firefox, as it doesn't support animating the `display` property:
603
+ * https://caniuse.com/mdn-css_properties_display_is_transitionable
604
+ *
605
+ * As of October 2025, Firefox supports the expand animation, but not the collapse animation (it instantly changes to `display: none`).
606
+ * Because of this, we are disabling all sidebar animations for Firefox so it doesn't look like a bug.
607
+ *
608
+ * Unfortunately we cannot use `@supports` to target the support of `transition-behavior: allow-discrete` specifically
609
+ * for the `display` property. And `@supports at-rule(@starting-style)` is also not ready for browser use yet.
610
+ *
611
+ * We are using JS to detect Firefox and disable animations, instead of using CSS, as Compiled currently does not merge duplicate
612
+ * CSS at-rules when at-rules are nested: https://github.com/atlassian-labs/compiled/blob/e04a325915e1d13010205089e4915de0e53bc2d4/packages/css/src/plugins/merge-duplicate-at-rules.ts#L5
613
+ * Avoiding nesting the `@supports` at-rule inside of `@media` means Compiled can remove duplicate styles from the generated CSS.
614
+ */
615
+ !isFirefox;
584
616
  return /*#__PURE__*/React.createElement("nav", _extends({
585
617
  id: id
586
618
  }, devTimeOnlyAttributes, {
@@ -592,7 +624,7 @@ function SideNavInternal({
592
624
  },
593
625
  ref: mergedRef,
594
626
  "data-testid": testId,
595
- className: ax([styles.root, isExpandedOnDesktop && !isExpandedOnMobile && !isFlyoutVisible && styles.hiddenMobileOnly, !isExpandedOnDesktop && isExpandedOnMobile && !isFlyoutVisible && styles.hiddenDesktopOnly, !isExpandedOnDesktop && !isExpandedOnMobile && !isFlyoutVisible && styles.hiddenMobileAndDesktop, !isFirstRenderRef.current && fg('navx-full-height-sidebar') && styles.animationBaseStyles, isExpandedOnMobile && !isFirstRenderRef.current && fg('navx-full-height-sidebar') && styles.expandAnimationMobile, !isExpandedOnMobile && !isFirstRenderRef.current && fg('navx-full-height-sidebar') && styles.collapseAnimationMobile, isExpandedOnDesktop && !isFirstRenderRef.current && fg('navx-full-height-sidebar') && styles.expandAnimationDesktop, !isExpandedOnDesktop && !isFirstRenderRef.current && fg('navx-full-height-sidebar') && styles.collapseAnimationDesktop, (sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === 'open' && !fg('navx-full-height-sidebar') && styles.flyoutOpen, (sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === 'triggered-animate-close' && !fg('navx-full-height-sidebar') && styles.flyoutAnimateClosed, ((sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === 'open' || (sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === 'triggered-animate-close') && fg('navx-full-height-sidebar') && styles.flyoutBaseStylesFullHeightSidebar, (sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === 'triggered-animate-close' && fg('navx-full-height-sidebar') && styles.flyoutAnimateClosedFullHeightSidebar, (sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === 'open' && fg('navx-full-height-sidebar') && styles.flyoutOpenFullHeightSidebar, (sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === 'triggered-animate-close' && fg('navx-full-height-sidebar') && styles.flyoutAnimateClosedFullHeightSidebar, isFlyoutClosed && fg('navx-full-height-sidebar') && styles.fullHeightSidebar])
627
+ className: ax([styles.root, isExpandedOnDesktop && !isExpandedOnMobile && !isFlyoutVisible && styles.hiddenMobileOnly, !isExpandedOnDesktop && isExpandedOnMobile && !isFlyoutVisible && styles.hiddenDesktopOnly, !isExpandedOnDesktop && !isExpandedOnMobile && !isFlyoutVisible && styles.hiddenMobileAndDesktop, shouldShowSidebarToggleAnimation && fg('navx-full-height-sidebar') && styles.animationBaseStyles, isExpandedOnMobile && shouldShowSidebarToggleAnimation && fg('navx-full-height-sidebar') && styles.expandAnimationMobile, !isExpandedOnMobile && shouldShowSidebarToggleAnimation && fg('navx-full-height-sidebar') && styles.collapseAnimationMobile, isExpandedOnDesktop && shouldShowSidebarToggleAnimation && fg('navx-full-height-sidebar') && styles.expandAnimationDesktop, !isExpandedOnDesktop && shouldShowSidebarToggleAnimation && fg('navx-full-height-sidebar') && styles.collapseAnimationDesktop, (sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === 'open' && !fg('navx-full-height-sidebar') && styles.flyoutOpen, (sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === 'triggered-animate-close' && !fg('navx-full-height-sidebar') && styles.flyoutAnimateClosed, ((sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === 'open' || (sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === 'triggered-animate-close') && !isFirefox && fg('navx-full-height-sidebar') && styles.flyoutBaseStylesFullHeightSidebar, (sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === 'triggered-animate-close' && !isFirefox && fg('navx-full-height-sidebar') && styles.flyoutAnimateClosedFullHeightSidebar, (sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === 'open' && !isFirefox && fg('navx-full-height-sidebar') && styles.flyoutOpenFullHeightSidebar, (sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === 'triggered-animate-close' && !isFirefox && fg('navx-full-height-sidebar') && styles.flyoutAnimateClosedFullHeightSidebar, isFlyoutClosed && fg('navx-full-height-sidebar') && styles.fullHeightSidebar])
596
628
  }), /*#__PURE__*/React.createElement(DangerouslyHoistCssVarToDocumentRoot, {
597
629
  variableName: sideNavLiveWidthVar,
598
630
  value: "0px",
@@ -16,9 +16,4 @@ export const SideNavToggleButtonElement = /*#__PURE__*/createContext(null);
16
16
  * A callback ref is needed because the side nav can be mounted before the elements in the top bar (e.g. if the element
17
17
  * is lazy loaded, which happens in Jira and Confluence), which would prevent the event listeners from being set up.
18
18
  */
19
- export const SideNavToggleButtonAttachRef = /*#__PURE__*/createContext(__noop);
20
-
21
- /**
22
- * Used to check if the SideNavToggleButton is rendered inside of its slot in `TopNavStart`.
23
- */
24
- export const SideNavToggleButtonSlotContext = /*#__PURE__*/createContext(false);
19
+ export const SideNavToggleButtonAttachRef = /*#__PURE__*/createContext(__noop);
@@ -1,5 +1,5 @@
1
1
  import React, { useState } from 'react';
2
- import { SideNavToggleButtonAttachRef, SideNavToggleButtonElement, SideNavToggleButtonSlotContext } from './toggle-button-context';
2
+ import { SideNavToggleButtonAttachRef, SideNavToggleButtonElement } from './toggle-button-context';
3
3
 
4
4
  /**
5
5
  * Provider for the side nav toggle button contexts.
@@ -23,17 +23,4 @@ export const SideNavToggleButtonProvider = ({
23
23
  }, /*#__PURE__*/React.createElement(SideNavToggleButtonAttachRef.Provider, {
24
24
  value: setElement
25
25
  }, children));
26
- };
27
-
28
- /**
29
- * Provider for the side nav toggle button slot.
30
- *
31
- * This allows us to determine if the toggle button is rendered inside or outside of its slot.
32
- */
33
- export const SideNavToggleButtonSlotProvider = ({
34
- children
35
- }) => {
36
- return /*#__PURE__*/React.createElement(SideNavToggleButtonSlotContext.Provider, {
37
- value: true
38
- }, children);
39
26
  };
@@ -1,3 +1,2 @@
1
1
  ._1e0c1bgi{display:contents}
2
- ._lcxvglyw{pointer-events:none}
3
- @media (min-width:64rem){._3l1a1wug{margin-inline-start:auto}}
2
+ ._lcxvglyw{pointer-events:none}
@@ -7,7 +7,7 @@ import SidebarCollapseIcon from '@atlaskit/icon/core/sidebar-collapse';
7
7
  import SidebarExpandIcon from '@atlaskit/icon/core/sidebar-expand';
8
8
  import { fg } from '@atlaskit/platform-feature-flags';
9
9
  import { IconButton } from '../../top-nav-items/themed/migration';
10
- import { SideNavToggleButtonAttachRef, SideNavToggleButtonSlotContext } from './toggle-button-context';
10
+ import { SideNavToggleButtonAttachRef } from './toggle-button-context';
11
11
  import { useSideNavVisibility } from './use-side-nav-visibility';
12
12
  import { useToggleSideNav } from './use-toggle-side-nav';
13
13
  const toggleButtonTooltipOptions = {
@@ -19,12 +19,6 @@ const toggleButtonTooltipOptions = {
19
19
  // For duplicate "mouseenter" issue when changing icons (see below)
20
20
  const silentIconStyles = null;
21
21
 
22
- /**
23
- * Wrapper styles to align the toggle button to the end of `TopNavStart`
24
- * when FHS is expanded.
25
- */
26
- const fullHeightSidebarExpandedWrapperStyles = null;
27
-
28
22
  /**
29
23
  * __SideNavToggleButton__
30
24
  *
@@ -125,7 +119,7 @@ export const SideNavToggleButton = ({
125
119
  }
126
120
  return toggleButtonTooltipOptions;
127
121
  }, [shortcut]);
128
- const iconButton = /*#__PURE__*/React.createElement(IconButton, {
122
+ return /*#__PURE__*/React.createElement(IconButton, {
129
123
  appearance: "subtle",
130
124
  label: isSideNavExpanded ? collapseLabel : expandLabel,
131
125
  icon: icon,
@@ -136,15 +130,4 @@ export const SideNavToggleButton = ({
136
130
  ref: fg('platform_dst_nav4_side_nav_toggle_ref_fix') ? setElement : elementRef,
137
131
  tooltip: tooltipProps
138
132
  });
139
- const isInsideSlot = useContext(SideNavToggleButtonSlotContext);
140
-
141
- // Checking `isInsideSlot` in case an app isn't using the slot
142
- // We don't want to break existing non-slot usage with the left margin
143
- // This check can be removed in the future, after slot is required for a while.
144
- if (isInsideSlot && fg('navx-full-height-sidebar')) {
145
- return /*#__PURE__*/React.createElement("div", {
146
- className: ax([isSideNavExpandedOnDesktop && "_3l1a1wug"])
147
- }, iconButton);
148
- }
149
- return iconButton;
150
133
  };
@@ -1,9 +1,14 @@
1
1
 
2
2
  ._zulp1b66{gap:var(--ds-space-050,4px)}
3
- ._yyhykb7n{grid-column:1}._1e0c1txw{display:flex}
3
+ ._zulp1kw7{gap:inherit}
4
+ ._yyhykb7n{grid-column:1}._1e0c1kw7{display:inherit}
5
+ ._1e0c1txw{display:flex}
6
+ ._1ul9idpf{min-width:0}
4
7
  ._4cvr1h6o{align-items:center}
5
8
  ._4t3i1osq{height:100%}
9
+ ._ahbq1wug{margin-inline-start:auto}
6
10
  ._bozgutpp{padding-inline-start:var(--ds-space-150,9pt)}
7
11
  ._lcxv1wug{pointer-events:auto}
8
12
  ._vchhusvi{box-sizing:border-box}
13
+ @media (prefers-reduced-motion:no-preference){._10t81e03{transition-property:transform}._10t81rjc{transition-property:transform,opacity}._1xq51ytf{transition-timing-function:ease-in-out}._1xq55ucs{transition-timing-function:ease}._mjvc162w{transform:translateX(calc(-2rem + var(--ds-space-050, 4px)*-1))}._mjvcjq3t{transform:translateX(-100%)}._bgpzidpf{opacity:0}._mjvcsws1{transform:translateX(calc(2rem + var(--ds-space-050, 4px)))}._mjvcxwn4{transform:translateX(100%)}._mjvcz12g{transform:translateX(0)}._xrrp188d{transition-duration:.3s}._bgpzkb7n{opacity:1}}
9
14
  @media (min-width:64rem){._15rin7od{min-width:unset}._glte1osq{width:100%}._15rip2n4{min-width:330px}._glte1ris{width:max-content}._15ri1mjv{min-width:300px}._1gs5usvi{box-sizing:border-box}._glte93mn{width:var(--n_sNvlw,100%)}._exxmpxbi{padding-inline-end:var(--ds-space-200,1pc)}}