@atlaskit/popup 1.25.0 → 1.27.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  # @atlaskit/popup
2
2
 
3
+ ## 1.27.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#143323](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/143323)
8
+ [`4fdf6347eb506`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/4fdf6347eb506) -
9
+ Popup and compositional popup now take an xcss prop that can adjust the popup contents padding and
10
+ width.
11
+ - [#143323](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/143323)
12
+ [`4fdf6347eb506`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/4fdf6347eb506) -
13
+ Popup and compositional popup now have a new appearance prop. Pass it "modal" to enable the popup
14
+ to appear as a modal on small viewports.
15
+
16
+ ### Patch Changes
17
+
18
+ - Updated dependencies
19
+
20
+ ## 1.26.0
21
+
22
+ ### Minor Changes
23
+
24
+ - [#142538](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/142538)
25
+ [`3979d0196514a`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/3979d0196514a) -
26
+ [ux] We are testing focus ring for popup wrapper `onKeyDown`. Changes are implemented behind
27
+ feature flag. If this fix is successful, it will be available in a later release.
28
+
3
29
  ## 1.25.0
4
30
 
5
31
  ### Minor Changes
@@ -16,9 +16,10 @@ var _popper = require("@atlaskit/popper");
16
16
  var _portal = _interopRequireDefault(require("@atlaskit/portal"));
17
17
  var _constants = require("@atlaskit/theme/constants");
18
18
  var _popperWrapper = _interopRequireDefault(require("../popper-wrapper"));
19
+ var _useAppearance = require("../use-appearance");
19
20
  var _useGetMemoizedMergedTriggerRef = require("../use-get-memoized-merged-trigger-ref");
20
21
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
21
- function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
22
+ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
22
23
  var IsOpenContext = /*#__PURE__*/(0, _react.createContext)(false);
23
24
  var IdContext = /*#__PURE__*/(0, _react.createContext)(undefined);
24
25
  var TriggerRefContext = /*#__PURE__*/(0, _react.createContext)(null);
@@ -106,7 +107,10 @@ var defaultLayer = _constants.layers.layer();
106
107
  * It must be a child of the Popup component.
107
108
  */
108
109
  var PopupContent = exports.PopupContent = function PopupContent(_ref4) {
109
- var children = _ref4.children,
110
+ var xcss = _ref4.xcss,
111
+ _ref4$appearance = _ref4.appearance,
112
+ inAppearance = _ref4$appearance === void 0 ? 'default' : _ref4$appearance,
113
+ children = _ref4.children,
110
114
  boundary = _ref4.boundary,
111
115
  offset = _ref4.offset,
112
116
  strategy = _ref4.strategy,
@@ -126,7 +130,7 @@ var PopupContent = exports.PopupContent = function PopupContent(_ref4) {
126
130
  zIndex = _ref4$zIndex === void 0 ? defaultLayer : _ref4$zIndex,
127
131
  _ref4$shouldUseCaptur = _ref4.shouldUseCaptureOnOutsideClick,
128
132
  shouldUseCaptureOnOutsideClick = _ref4$shouldUseCaptur === void 0 ? false : _ref4$shouldUseCaptur,
129
- shouldRenderToParent = _ref4.shouldRenderToParent,
133
+ inShouldRenderToParent = _ref4.shouldRenderToParent,
130
134
  _ref4$shouldDisableFo = _ref4.shouldDisableFocusLock,
131
135
  shouldDisableFocusLock = _ref4$shouldDisableFo === void 0 ? false : _ref4$shouldDisableFo,
132
136
  shouldFitContainer = _ref4.shouldFitContainer,
@@ -135,12 +139,22 @@ var PopupContent = exports.PopupContent = function PopupContent(_ref4) {
135
139
  var isOpen = (0, _react.useContext)(IsOpenContext);
136
140
  var id = (0, _react.useContext)(IdContext);
137
141
  var triggerRef = (0, _react.useContext)(TriggerRefContext);
142
+ var _usePopupAppearance = (0, _useAppearance.usePopupAppearance)({
143
+ appearance: inAppearance,
144
+ shouldRenderToParent: inShouldRenderToParent
145
+ }),
146
+ appearance = _usePopupAppearance.appearance,
147
+ shouldRenderToParent = _usePopupAppearance.shouldRenderToParent;
138
148
  if (!isOpen) {
139
149
  return null;
140
150
  }
141
151
  var popperWrapper = /*#__PURE__*/_react.default.createElement(_layering.UNSAFE_LAYERING, {
142
152
  isDisabled: false
143
- }, /*#__PURE__*/_react.default.createElement(_popperWrapper.default, {
153
+ }, /*#__PURE__*/_react.default.createElement(_popperWrapper.default
154
+ // eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage
155
+ , {
156
+ xcss: xcss,
157
+ appearance: appearance,
144
158
  content: children,
145
159
  isOpen: isOpen,
146
160
  placement: placement,
@@ -12,7 +12,9 @@ var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/h
12
12
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
13
13
  var _react = require("react");
14
14
  var _react2 = require("@emotion/react");
15
+ var _focusRing = _interopRequireDefault(require("@atlaskit/focus-ring"));
15
16
  var _layering = require("@atlaskit/layering");
17
+ var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
16
18
  var _popper = require("@atlaskit/popper");
17
19
  var _colors = require("@atlaskit/theme/colors");
18
20
  var _constants = require("@atlaskit/theme/constants");
@@ -20,20 +22,19 @@ var _tokens = require("@atlaskit/tokens");
20
22
  var _repositionOnUpdate = require("./reposition-on-update");
21
23
  var _useCloseManager = require("./use-close-manager");
22
24
  var _useFocusManager = require("./use-focus-manager");
23
- var _excluded = ["shouldRenderToParent", "shouldFitContainer", "children"];
25
+ var _excluded = ["shouldRenderToParent", "shouldFitContainer", "children", "appearance", "xcss"];
24
26
  var _css;
25
27
  /**
26
28
  * @jsxRuntime classic
27
29
  * @jsx jsx
28
30
  */
29
- var popupFullWidthStyles = (0, _react2.css)({
31
+ var fullWidthStyles = (0, _react2.css)({
30
32
  width: '100%'
31
33
  });
32
- var popupStyles = (0, _react2.css)((_css = {
34
+ var rootStyles = (0, _react2.css)((_css = {
33
35
  display: 'block',
34
36
  boxSizing: 'border-box',
35
37
  zIndex: _constants.layers.layer(),
36
- flex: '1 1 auto',
37
38
  backgroundColor: "var(--ds-surface-overlay, ".concat(_colors.N0, ")"),
38
39
  borderRadius: "var(--ds-border-radius, 3px)",
39
40
  boxShadow: "var(--ds-shadow-overlay, ".concat("0 4px 8px -2px ".concat(_colors.N50A, ", 0 0 1px ").concat(_colors.N60A), ")"),
@@ -44,22 +45,39 @@ var popupStyles = (0, _react2.css)((_css = {
44
45
  }, (0, _defineProperty2.default)(_css, _tokens.CURRENT_SURFACE_CSS_VAR, "var(--ds-surface-overlay, ".concat(_colors.N0, ")")), (0, _defineProperty2.default)(_css, '&:focus', {
45
46
  outline: 'none'
46
47
  }), _css));
47
- var popupOverflowStyles = (0, _react2.css)({
48
+ var scrollableStyles = (0, _react2.css)({
48
49
  overflow: 'auto'
49
50
  });
51
+ var blanketStyles = (0, _react2.css)({
52
+ position: 'fixed',
53
+ inset: 0,
54
+ backgroundColor: "var(--ds-blanket, #091E427D)"
55
+ });
56
+ var modalStyles = (0, _react2.css)({
57
+ maxHeight: '50vh',
58
+ position: 'fixed',
59
+ insetBlockStart: "var(--ds-space-050, 4px)",
60
+ insetInline: "var(--ds-space-050, 4px)"
61
+ });
50
62
  var DefaultPopupComponent = /*#__PURE__*/(0, _react.forwardRef)(function (props, ref) {
51
63
  var shouldRenderToParent = props.shouldRenderToParent,
52
64
  shouldFitContainer = props.shouldFitContainer,
53
65
  children = props.children,
66
+ appearance = props.appearance,
67
+ xcss = props.xcss,
54
68
  htmlAttributes = (0, _objectWithoutProperties2.default)(props, _excluded);
55
69
  return (0, _react2.jsx)("div", (0, _extends2.default)({
56
- css: [popupStyles, !shouldRenderToParent && popupOverflowStyles, shouldFitContainer && popupFullWidthStyles]
70
+ // We suppress this for now as we can't use the Compiled pragma until this module has migrated to Compiled.
71
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop, @compiled/jsx-pragma
72
+ className: xcss,
73
+ css: [rootStyles, appearance === 'UNSAFE_modal-below-sm' && modalStyles, !shouldRenderToParent && scrollableStyles, shouldFitContainer && fullWidthStyles]
57
74
  }, htmlAttributes, {
58
75
  ref: ref
59
76
  }), children);
60
77
  });
61
78
  function PopperWrapper(_ref) {
62
- var isOpen = _ref.isOpen,
79
+ var xcss = _ref.xcss,
80
+ isOpen = _ref.isOpen,
63
81
  id = _ref.id,
64
82
  offset = _ref.offset,
65
83
  testId = _ref.testId,
@@ -87,7 +105,9 @@ function PopperWrapper(_ref) {
87
105
  label = _ref.label,
88
106
  titleId = _ref.titleId,
89
107
  modifiers = _ref.modifiers,
90
- shouldFitViewport = _ref.shouldFitViewport;
108
+ shouldFitViewport = _ref.shouldFitViewport,
109
+ _ref$appearance = _ref.appearance,
110
+ appearance = _ref$appearance === void 0 ? 'default' : _ref$appearance;
91
111
  var _useState = (0, _react.useState)(null),
92
112
  _useState2 = (0, _slicedToArray2.default)(_useState, 2),
93
113
  popupRef = _useState2[0],
@@ -96,9 +116,7 @@ function PopperWrapper(_ref) {
96
116
  _useState4 = (0, _slicedToArray2.default)(_useState3, 2),
97
117
  initialFocusRef = _useState4[0],
98
118
  setInitialFocusRef = _useState4[1];
99
-
100
- // We have cases where we need to close the Popup on Tab press.
101
- // Example: DropdownMenu
119
+ // We have cases where we need to close the Popup on Tab press, e.g. DropdownMenu
102
120
  var shouldCloseOnTab = shouldRenderToParent && shouldDisableFocusLock;
103
121
  var shouldDisableFocusTrap = role !== 'dialog';
104
122
  (0, _useFocusManager.useFocusManager)({
@@ -145,7 +163,11 @@ function PopperWrapper(_ref) {
145
163
  style = _ref2.style,
146
164
  placement = _ref2.placement,
147
165
  update = _ref2.update;
148
- return (0, _react2.jsx)(PopupContainer, {
166
+ var popupContainer = (0, _react2.jsx)(PopupContainer
167
+ // eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage
168
+ , {
169
+ xcss: xcss,
170
+ appearance: appearance,
149
171
  id: id,
150
172
  "data-ds--level": currentLevel,
151
173
  "data-placement": placement,
@@ -165,7 +187,7 @@ function PopperWrapper(_ref) {
165
187
  }
166
188
  // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766
167
189
  ,
168
- style: style
190
+ style: appearance === 'UNSAFE_modal-below-sm' ? {} : style
169
191
  // using tabIndex={-1} would cause a bug where Safari focuses
170
192
  // first on the browser address bar when using keyboard
171
193
  ,
@@ -180,6 +202,11 @@ function PopperWrapper(_ref) {
180
202
  onClose: onClose,
181
203
  setInitialFocusRef: setInitialFocusRef
182
204
  })));
205
+ return !initialFocusRef && (0, _platformFeatureFlags.fg)('platform-design-system-apply-popup-wrapper-focus') ? (0, _react2.jsx)(_react.Fragment, null, (0, _react2.jsx)(_focusRing.default, null, popupContainer), appearance === 'UNSAFE_modal-below-sm' && (0, _react2.jsx)("div", {
206
+ css: blanketStyles
207
+ })) : (0, _react2.jsx)(_react.Fragment, null, popupContainer, appearance === 'UNSAFE_modal-below-sm' && (0, _react2.jsx)("div", {
208
+ css: blanketStyles
209
+ }));
183
210
  });
184
211
  }
185
212
 
package/dist/cjs/popup.js CHANGED
@@ -16,6 +16,7 @@ var _portal = _interopRequireDefault(require("@atlaskit/portal"));
16
16
  var _primitives = require("@atlaskit/primitives");
17
17
  var _constants = require("@atlaskit/theme/constants");
18
18
  var _popperWrapper = _interopRequireDefault(require("./popper-wrapper"));
19
+ var _useAppearance = require("./use-appearance");
19
20
  var _useGetMemoizedMergedTriggerRef = require("./use-get-memoized-merged-trigger-ref");
20
21
  var _useGetMemoizedMergedTriggerRefNew = require("./use-get-memoized-merged-trigger-ref-new");
21
22
  /* eslint-disable @repo/internal/react/require-jsdoc */
@@ -31,7 +32,10 @@ var wrapperStyles = (0, _primitives.xcss)({
31
32
  position: 'relative'
32
33
  });
33
34
  var Popup = exports.Popup = /*#__PURE__*/(0, _react.memo)(function (_ref) {
34
- var isOpen = _ref.isOpen,
35
+ var xcss = _ref.xcss,
36
+ _ref$appearance = _ref.appearance,
37
+ inAppearance = _ref$appearance === void 0 ? 'default' : _ref$appearance,
38
+ isOpen = _ref.isOpen,
35
39
  providedId = _ref.id,
36
40
  offset = _ref.offset,
37
41
  testId = _ref.testId,
@@ -54,7 +58,7 @@ var Popup = exports.Popup = /*#__PURE__*/(0, _react.memo)(function (_ref) {
54
58
  _ref$shouldUseCapture = _ref.shouldUseCaptureOnOutsideClick,
55
59
  shouldUseCaptureOnOutsideClick = _ref$shouldUseCapture === void 0 ? false : _ref$shouldUseCapture,
56
60
  _ref$shouldRenderToPa = _ref.shouldRenderToParent,
57
- shouldRenderToParent = _ref$shouldRenderToPa === void 0 ? false : _ref$shouldRenderToPa,
61
+ inShouldRenderToParent = _ref$shouldRenderToPa === void 0 ? false : _ref$shouldRenderToPa,
58
62
  _ref$shouldFitContain = _ref.shouldFitContainer,
59
63
  shouldFitContainer = _ref$shouldFitContain === void 0 ? false : _ref$shouldFitContain,
60
64
  _ref$shouldDisableFoc = _ref.shouldDisableFocusLock,
@@ -74,10 +78,20 @@ var Popup = exports.Popup = /*#__PURE__*/(0, _react.memo)(function (_ref) {
74
78
  var getMergedTriggerRef = (0, _useGetMemoizedMergedTriggerRef.useGetMemoizedMergedTriggerRef)();
75
79
  var getMergedTriggerRefNew = (0, _useGetMemoizedMergedTriggerRefNew.useGetMemoizedMergedTriggerRefNew)();
76
80
  var generatedId = (0, _reactUid.useId)();
81
+ var _usePopupAppearance = (0, _useAppearance.usePopupAppearance)({
82
+ appearance: inAppearance,
83
+ shouldRenderToParent: inShouldRenderToParent
84
+ }),
85
+ appearance = _usePopupAppearance.appearance,
86
+ shouldRenderToParent = _usePopupAppearance.shouldRenderToParent;
77
87
  var id = providedId || generatedId;
78
88
  var renderPopperWrapper = (0, _react2.jsx)(_layering.UNSAFE_LAYERING, {
79
89
  isDisabled: false
80
- }, (0, _react2.jsx)(_popperWrapper.default, {
90
+ }, (0, _react2.jsx)(_popperWrapper.default
91
+ // eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage
92
+ , {
93
+ xcss: xcss,
94
+ appearance: appearance,
81
95
  content: content,
82
96
  isOpen: isOpen,
83
97
  placement: placement,
@@ -7,7 +7,7 @@ Object.defineProperty(exports, "__esModule", {
7
7
  exports.RepositionOnUpdate = void 0;
8
8
  var _react = _interopRequireWildcard(require("react"));
9
9
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
10
- function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
10
+ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
11
11
  // eslint-disable-next-line @repo/internal/react/require-jsdoc
12
12
  var RepositionOnUpdate = exports.RepositionOnUpdate = function RepositionOnUpdate(_ref) {
13
13
  var children = _ref.children,
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.usePopupAppearance = usePopupAppearance;
8
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
9
+ var _react = require("react");
10
+ var _responsive = require("@atlaskit/primitives/responsive");
11
+ /**
12
+ * **usePopupAppearance()**
13
+ *
14
+ * Abstracts away calculating the appearance for a popup including if it should
15
+ * be portalled or not, this is done to ensure that if the popup needs to render
16
+ * as a modal that it is also forcibly portalled. If it's not portalled when rendering
17
+ * as a modal it will appear below the top bar.
18
+ */
19
+ function usePopupAppearance(_ref) {
20
+ var _appearance = _ref.appearance,
21
+ _shouldRenderToParent = _ref.shouldRenderToParent;
22
+ var mq = (0, _responsive.UNSAFE_useMediaQuery)('below.sm', function (e) {
23
+ setIsSmallViewport(!!e.matches);
24
+ });
25
+ var _useState = (0, _react.useState)(!!(mq !== null && mq !== void 0 && mq.matches)),
26
+ _useState2 = (0, _slicedToArray2.default)(_useState, 2),
27
+ isSmallViewport = _useState2[0],
28
+ setIsSmallViewport = _useState2[1];
29
+ var appearance = _appearance === 'UNSAFE_modal-below-sm' && isSmallViewport ? 'UNSAFE_modal-below-sm' : 'default';
30
+ var shouldRenderToParent = _shouldRenderToParent && appearance === 'default';
31
+ return {
32
+ appearance: appearance,
33
+ shouldRenderToParent: shouldRenderToParent
34
+ };
35
+ }
@@ -49,10 +49,12 @@ var useCloseManager = exports.useCloseManager = function useCloseManager(_ref) {
49
49
  }
50
50
  if (shouldDisableFocusTrap && (0, _platformFeatureFlags.fg)('platform_dst_popup-disable-focuslock')) {
51
51
  // Restoring the normal focus order for trigger.
52
- triggerRef === null || triggerRef === void 0 || triggerRef.setAttribute('tabindex', '0');
53
- if (popupRef && autoFocus) {
54
- popupRef.setAttribute('tabindex', '0');
55
- }
52
+ requestFrame(function () {
53
+ triggerRef === null || triggerRef === void 0 || triggerRef.setAttribute('tabindex', '0');
54
+ if (popupRef && autoFocus) {
55
+ popupRef.setAttribute('tabindex', '0');
56
+ }
57
+ });
56
58
  }
57
59
  };
58
60
 
@@ -7,6 +7,7 @@ import { Manager, Reference } from '@atlaskit/popper';
7
7
  import Portal from '@atlaskit/portal';
8
8
  import { layers } from '@atlaskit/theme/constants';
9
9
  import PopperWrapper from '../popper-wrapper';
10
+ import { usePopupAppearance } from '../use-appearance';
10
11
  import { useGetMemoizedMergedTriggerRef } from '../use-get-memoized-merged-trigger-ref';
11
12
  const IsOpenContext = /*#__PURE__*/createContext(false);
12
13
  const IdContext = /*#__PURE__*/createContext(undefined);
@@ -92,6 +93,8 @@ const defaultLayer = layers.layer();
92
93
  * It must be a child of the Popup component.
93
94
  */
94
95
  export const PopupContent = ({
96
+ xcss,
97
+ appearance: inAppearance = 'default',
95
98
  children,
96
99
  boundary,
97
100
  offset,
@@ -106,7 +109,7 @@ export const PopupContent = ({
106
109
  autoFocus = true,
107
110
  zIndex = defaultLayer,
108
111
  shouldUseCaptureOnOutsideClick = false,
109
- shouldRenderToParent,
112
+ shouldRenderToParent: inShouldRenderToParent,
110
113
  shouldDisableFocusLock = false,
111
114
  shouldFitContainer,
112
115
  shouldFitViewport
@@ -115,12 +118,23 @@ export const PopupContent = ({
115
118
  const isOpen = useContext(IsOpenContext);
116
119
  const id = useContext(IdContext);
117
120
  const triggerRef = useContext(TriggerRefContext);
121
+ const {
122
+ appearance,
123
+ shouldRenderToParent
124
+ } = usePopupAppearance({
125
+ appearance: inAppearance,
126
+ shouldRenderToParent: inShouldRenderToParent
127
+ });
118
128
  if (!isOpen) {
119
129
  return null;
120
130
  }
121
131
  const popperWrapper = /*#__PURE__*/React.createElement(UNSAFE_LAYERING, {
122
132
  isDisabled: false
123
- }, /*#__PURE__*/React.createElement(PopperWrapper, {
133
+ }, /*#__PURE__*/React.createElement(PopperWrapper
134
+ // eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage
135
+ , {
136
+ xcss: xcss,
137
+ appearance: appearance,
124
138
  content: children,
125
139
  isOpen: isOpen,
126
140
  placement: placement,
@@ -3,9 +3,11 @@ import _extends from "@babel/runtime/helpers/extends";
3
3
  * @jsxRuntime classic
4
4
  * @jsx jsx
5
5
  */
6
- import { forwardRef, useMemo, useState } from 'react';
6
+ import { forwardRef, Fragment, useMemo, useState } from 'react';
7
7
  import { css, jsx } from '@emotion/react';
8
+ import FocusRing from '@atlaskit/focus-ring';
8
9
  import { UNSAFE_useLayering } from '@atlaskit/layering';
10
+ import { fg } from '@atlaskit/platform-feature-flags';
9
11
  import { Popper } from '@atlaskit/popper';
10
12
  import { N0, N50A, N60A } from '@atlaskit/theme/colors';
11
13
  import { layers } from '@atlaskit/theme/constants';
@@ -13,14 +15,13 @@ import { CURRENT_SURFACE_CSS_VAR } from '@atlaskit/tokens';
13
15
  import { RepositionOnUpdate } from './reposition-on-update';
14
16
  import { useCloseManager } from './use-close-manager';
15
17
  import { useFocusManager } from './use-focus-manager';
16
- const popupFullWidthStyles = css({
18
+ const fullWidthStyles = css({
17
19
  width: '100%'
18
20
  });
19
- const popupStyles = css({
21
+ const rootStyles = css({
20
22
  display: 'block',
21
23
  boxSizing: 'border-box',
22
24
  zIndex: layers.layer(),
23
- flex: '1 1 auto',
24
25
  backgroundColor: `var(--ds-surface-overlay, ${N0})`,
25
26
  borderRadius: "var(--ds-border-radius, 3px)",
26
27
  boxShadow: `var(--ds-shadow-overlay, ${`0 4px 8px -2px ${N50A}, 0 0 1px ${N60A}`})`,
@@ -33,23 +34,40 @@ const popupStyles = css({
33
34
  outline: 'none'
34
35
  }
35
36
  });
36
- const popupOverflowStyles = css({
37
+ const scrollableStyles = css({
37
38
  overflow: 'auto'
38
39
  });
40
+ const blanketStyles = css({
41
+ position: 'fixed',
42
+ inset: 0,
43
+ backgroundColor: "var(--ds-blanket, #091E427D)"
44
+ });
45
+ const modalStyles = css({
46
+ maxHeight: '50vh',
47
+ position: 'fixed',
48
+ insetBlockStart: "var(--ds-space-050, 4px)",
49
+ insetInline: "var(--ds-space-050, 4px)"
50
+ });
39
51
  const DefaultPopupComponent = /*#__PURE__*/forwardRef((props, ref) => {
40
52
  const {
41
53
  shouldRenderToParent,
42
54
  shouldFitContainer,
43
55
  children,
56
+ appearance,
57
+ xcss,
44
58
  ...htmlAttributes
45
59
  } = props;
46
60
  return jsx("div", _extends({
47
- css: [popupStyles, !shouldRenderToParent && popupOverflowStyles, shouldFitContainer && popupFullWidthStyles]
61
+ // We suppress this for now as we can't use the Compiled pragma until this module has migrated to Compiled.
62
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop, @compiled/jsx-pragma
63
+ className: xcss,
64
+ css: [rootStyles, appearance === 'UNSAFE_modal-below-sm' && modalStyles, !shouldRenderToParent && scrollableStyles, shouldFitContainer && fullWidthStyles]
48
65
  }, htmlAttributes, {
49
66
  ref: ref
50
67
  }), children);
51
68
  });
52
69
  function PopperWrapper({
70
+ xcss,
53
71
  isOpen,
54
72
  id,
55
73
  offset,
@@ -75,13 +93,12 @@ function PopperWrapper({
75
93
  label,
76
94
  titleId,
77
95
  modifiers,
78
- shouldFitViewport
96
+ shouldFitViewport,
97
+ appearance = 'default'
79
98
  }) {
80
99
  const [popupRef, setPopupRef] = useState(null);
81
100
  const [initialFocusRef, setInitialFocusRef] = useState(null);
82
-
83
- // We have cases where we need to close the Popup on Tab press.
84
- // Example: DropdownMenu
101
+ // We have cases where we need to close the Popup on Tab press, e.g. DropdownMenu
85
102
  const shouldCloseOnTab = shouldRenderToParent && shouldDisableFocusLock;
86
103
  const shouldDisableFocusTrap = role !== 'dialog';
87
104
  useFocusManager({
@@ -128,7 +145,11 @@ function PopperWrapper({
128
145
  placement,
129
146
  update
130
147
  }) => {
131
- return jsx(PopupContainer, {
148
+ const popupContainer = jsx(PopupContainer
149
+ // eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage
150
+ , {
151
+ xcss: xcss,
152
+ appearance: appearance,
132
153
  id: id,
133
154
  "data-ds--level": currentLevel,
134
155
  "data-placement": placement,
@@ -148,7 +169,7 @@ function PopperWrapper({
148
169
  }
149
170
  // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766
150
171
  ,
151
- style: style
172
+ style: appearance === 'UNSAFE_modal-below-sm' ? {} : style
152
173
  // using tabIndex={-1} would cause a bug where Safari focuses
153
174
  // first on the browser address bar when using keyboard
154
175
  ,
@@ -163,6 +184,11 @@ function PopperWrapper({
163
184
  onClose,
164
185
  setInitialFocusRef
165
186
  })));
187
+ return !initialFocusRef && fg('platform-design-system-apply-popup-wrapper-focus') ? jsx(Fragment, null, jsx(FocusRing, null, popupContainer), appearance === 'UNSAFE_modal-below-sm' && jsx("div", {
188
+ css: blanketStyles
189
+ })) : jsx(Fragment, null, popupContainer, appearance === 'UNSAFE_modal-below-sm' && jsx("div", {
190
+ css: blanketStyles
191
+ }));
166
192
  });
167
193
  }
168
194
 
@@ -15,6 +15,7 @@ import Portal from '@atlaskit/portal';
15
15
  import { Box, xcss } from '@atlaskit/primitives';
16
16
  import { layers } from '@atlaskit/theme/constants';
17
17
  import PopperWrapper from './popper-wrapper';
18
+ import { usePopupAppearance } from './use-appearance';
18
19
  import { useGetMemoizedMergedTriggerRef } from './use-get-memoized-merged-trigger-ref';
19
20
  import { useGetMemoizedMergedTriggerRefNew } from './use-get-memoized-merged-trigger-ref-new';
20
21
  const defaultLayer = layers.layer();
@@ -22,6 +23,8 @@ const wrapperStyles = xcss({
22
23
  position: 'relative'
23
24
  });
24
25
  export const Popup = /*#__PURE__*/memo(({
26
+ xcss,
27
+ appearance: inAppearance = 'default',
25
28
  isOpen,
26
29
  id: providedId,
27
30
  offset,
@@ -38,7 +41,7 @@ export const Popup = /*#__PURE__*/memo(({
38
41
  autoFocus = true,
39
42
  zIndex = defaultLayer,
40
43
  shouldUseCaptureOnOutsideClick = false,
41
- shouldRenderToParent = false,
44
+ shouldRenderToParent: inShouldRenderToParent = false,
42
45
  shouldFitContainer = false,
43
46
  shouldDisableFocusLock = false,
44
47
  shouldReturnFocus = true,
@@ -53,10 +56,21 @@ export const Popup = /*#__PURE__*/memo(({
53
56
  const getMergedTriggerRef = useGetMemoizedMergedTriggerRef();
54
57
  const getMergedTriggerRefNew = useGetMemoizedMergedTriggerRefNew();
55
58
  const generatedId = useId();
59
+ const {
60
+ appearance,
61
+ shouldRenderToParent
62
+ } = usePopupAppearance({
63
+ appearance: inAppearance,
64
+ shouldRenderToParent: inShouldRenderToParent
65
+ });
56
66
  const id = providedId || generatedId;
57
67
  const renderPopperWrapper = jsx(UNSAFE_LAYERING, {
58
68
  isDisabled: false
59
- }, jsx(PopperWrapper, {
69
+ }, jsx(PopperWrapper
70
+ // eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage
71
+ , {
72
+ xcss: xcss,
73
+ appearance: appearance,
60
74
  content: content,
61
75
  isOpen: isOpen,
62
76
  placement: placement,
@@ -0,0 +1,26 @@
1
+ import { useState } from 'react';
2
+ import { UNSAFE_useMediaQuery as useMediaQuery } from '@atlaskit/primitives/responsive';
3
+
4
+ /**
5
+ * **usePopupAppearance()**
6
+ *
7
+ * Abstracts away calculating the appearance for a popup including if it should
8
+ * be portalled or not, this is done to ensure that if the popup needs to render
9
+ * as a modal that it is also forcibly portalled. If it's not portalled when rendering
10
+ * as a modal it will appear below the top bar.
11
+ */
12
+ export function usePopupAppearance({
13
+ appearance: _appearance,
14
+ shouldRenderToParent: _shouldRenderToParent
15
+ }) {
16
+ const mq = useMediaQuery('below.sm', e => {
17
+ setIsSmallViewport(!!e.matches);
18
+ });
19
+ const [isSmallViewport, setIsSmallViewport] = useState(!!(mq !== null && mq !== void 0 && mq.matches));
20
+ const appearance = _appearance === 'UNSAFE_modal-below-sm' && isSmallViewport ? 'UNSAFE_modal-below-sm' : 'default';
21
+ const shouldRenderToParent = _shouldRenderToParent && appearance === 'default';
22
+ return {
23
+ appearance,
24
+ shouldRenderToParent
25
+ };
26
+ }
@@ -44,10 +44,12 @@ export const useCloseManager = ({
44
44
  }
45
45
  if (shouldDisableFocusTrap && fg('platform_dst_popup-disable-focuslock')) {
46
46
  // Restoring the normal focus order for trigger.
47
- triggerRef === null || triggerRef === void 0 ? void 0 : triggerRef.setAttribute('tabindex', '0');
48
- if (popupRef && autoFocus) {
49
- popupRef.setAttribute('tabindex', '0');
50
- }
47
+ requestFrame(() => {
48
+ triggerRef === null || triggerRef === void 0 ? void 0 : triggerRef.setAttribute('tabindex', '0');
49
+ if (popupRef && autoFocus) {
50
+ popupRef.setAttribute('tabindex', '0');
51
+ }
52
+ });
51
53
  }
52
54
  };
53
55
 
@@ -8,6 +8,7 @@ import { Manager, Reference } from '@atlaskit/popper';
8
8
  import Portal from '@atlaskit/portal';
9
9
  import { layers } from '@atlaskit/theme/constants';
10
10
  import PopperWrapper from '../popper-wrapper';
11
+ import { usePopupAppearance } from '../use-appearance';
11
12
  import { useGetMemoizedMergedTriggerRef } from '../use-get-memoized-merged-trigger-ref';
12
13
  var IsOpenContext = /*#__PURE__*/createContext(false);
13
14
  var IdContext = /*#__PURE__*/createContext(undefined);
@@ -96,7 +97,10 @@ var defaultLayer = layers.layer();
96
97
  * It must be a child of the Popup component.
97
98
  */
98
99
  export var PopupContent = function PopupContent(_ref4) {
99
- var children = _ref4.children,
100
+ var xcss = _ref4.xcss,
101
+ _ref4$appearance = _ref4.appearance,
102
+ inAppearance = _ref4$appearance === void 0 ? 'default' : _ref4$appearance,
103
+ children = _ref4.children,
100
104
  boundary = _ref4.boundary,
101
105
  offset = _ref4.offset,
102
106
  strategy = _ref4.strategy,
@@ -116,7 +120,7 @@ export var PopupContent = function PopupContent(_ref4) {
116
120
  zIndex = _ref4$zIndex === void 0 ? defaultLayer : _ref4$zIndex,
117
121
  _ref4$shouldUseCaptur = _ref4.shouldUseCaptureOnOutsideClick,
118
122
  shouldUseCaptureOnOutsideClick = _ref4$shouldUseCaptur === void 0 ? false : _ref4$shouldUseCaptur,
119
- shouldRenderToParent = _ref4.shouldRenderToParent,
123
+ inShouldRenderToParent = _ref4.shouldRenderToParent,
120
124
  _ref4$shouldDisableFo = _ref4.shouldDisableFocusLock,
121
125
  shouldDisableFocusLock = _ref4$shouldDisableFo === void 0 ? false : _ref4$shouldDisableFo,
122
126
  shouldFitContainer = _ref4.shouldFitContainer,
@@ -125,12 +129,22 @@ export var PopupContent = function PopupContent(_ref4) {
125
129
  var isOpen = useContext(IsOpenContext);
126
130
  var id = useContext(IdContext);
127
131
  var triggerRef = useContext(TriggerRefContext);
132
+ var _usePopupAppearance = usePopupAppearance({
133
+ appearance: inAppearance,
134
+ shouldRenderToParent: inShouldRenderToParent
135
+ }),
136
+ appearance = _usePopupAppearance.appearance,
137
+ shouldRenderToParent = _usePopupAppearance.shouldRenderToParent;
128
138
  if (!isOpen) {
129
139
  return null;
130
140
  }
131
141
  var popperWrapper = /*#__PURE__*/React.createElement(UNSAFE_LAYERING, {
132
142
  isDisabled: false
133
- }, /*#__PURE__*/React.createElement(PopperWrapper, {
143
+ }, /*#__PURE__*/React.createElement(PopperWrapper
144
+ // eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage
145
+ , {
146
+ xcss: xcss,
147
+ appearance: appearance,
134
148
  content: children,
135
149
  isOpen: isOpen,
136
150
  placement: placement,
@@ -3,15 +3,17 @@ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
3
3
  import _extends from "@babel/runtime/helpers/extends";
4
4
  import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
5
5
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
6
- var _excluded = ["shouldRenderToParent", "shouldFitContainer", "children"];
6
+ var _excluded = ["shouldRenderToParent", "shouldFitContainer", "children", "appearance", "xcss"];
7
7
  var _css;
8
8
  /**
9
9
  * @jsxRuntime classic
10
10
  * @jsx jsx
11
11
  */
12
- import { forwardRef, useMemo, useState } from 'react';
12
+ import { forwardRef, Fragment, useMemo, useState } from 'react';
13
13
  import { css, jsx } from '@emotion/react';
14
+ import FocusRing from '@atlaskit/focus-ring';
14
15
  import { UNSAFE_useLayering } from '@atlaskit/layering';
16
+ import { fg } from '@atlaskit/platform-feature-flags';
15
17
  import { Popper } from '@atlaskit/popper';
16
18
  import { N0, N50A, N60A } from '@atlaskit/theme/colors';
17
19
  import { layers } from '@atlaskit/theme/constants';
@@ -19,14 +21,13 @@ import { CURRENT_SURFACE_CSS_VAR } from '@atlaskit/tokens';
19
21
  import { RepositionOnUpdate } from './reposition-on-update';
20
22
  import { useCloseManager } from './use-close-manager';
21
23
  import { useFocusManager } from './use-focus-manager';
22
- var popupFullWidthStyles = css({
24
+ var fullWidthStyles = css({
23
25
  width: '100%'
24
26
  });
25
- var popupStyles = css((_css = {
27
+ var rootStyles = css((_css = {
26
28
  display: 'block',
27
29
  boxSizing: 'border-box',
28
30
  zIndex: layers.layer(),
29
- flex: '1 1 auto',
30
31
  backgroundColor: "var(--ds-surface-overlay, ".concat(N0, ")"),
31
32
  borderRadius: "var(--ds-border-radius, 3px)",
32
33
  boxShadow: "var(--ds-shadow-overlay, ".concat("0 4px 8px -2px ".concat(N50A, ", 0 0 1px ").concat(N60A), ")"),
@@ -37,22 +38,39 @@ var popupStyles = css((_css = {
37
38
  }, _defineProperty(_css, CURRENT_SURFACE_CSS_VAR, "var(--ds-surface-overlay, ".concat(N0, ")")), _defineProperty(_css, '&:focus', {
38
39
  outline: 'none'
39
40
  }), _css));
40
- var popupOverflowStyles = css({
41
+ var scrollableStyles = css({
41
42
  overflow: 'auto'
42
43
  });
44
+ var blanketStyles = css({
45
+ position: 'fixed',
46
+ inset: 0,
47
+ backgroundColor: "var(--ds-blanket, #091E427D)"
48
+ });
49
+ var modalStyles = css({
50
+ maxHeight: '50vh',
51
+ position: 'fixed',
52
+ insetBlockStart: "var(--ds-space-050, 4px)",
53
+ insetInline: "var(--ds-space-050, 4px)"
54
+ });
43
55
  var DefaultPopupComponent = /*#__PURE__*/forwardRef(function (props, ref) {
44
56
  var shouldRenderToParent = props.shouldRenderToParent,
45
57
  shouldFitContainer = props.shouldFitContainer,
46
58
  children = props.children,
59
+ appearance = props.appearance,
60
+ xcss = props.xcss,
47
61
  htmlAttributes = _objectWithoutProperties(props, _excluded);
48
62
  return jsx("div", _extends({
49
- css: [popupStyles, !shouldRenderToParent && popupOverflowStyles, shouldFitContainer && popupFullWidthStyles]
63
+ // We suppress this for now as we can't use the Compiled pragma until this module has migrated to Compiled.
64
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop, @compiled/jsx-pragma
65
+ className: xcss,
66
+ css: [rootStyles, appearance === 'UNSAFE_modal-below-sm' && modalStyles, !shouldRenderToParent && scrollableStyles, shouldFitContainer && fullWidthStyles]
50
67
  }, htmlAttributes, {
51
68
  ref: ref
52
69
  }), children);
53
70
  });
54
71
  function PopperWrapper(_ref) {
55
- var isOpen = _ref.isOpen,
72
+ var xcss = _ref.xcss,
73
+ isOpen = _ref.isOpen,
56
74
  id = _ref.id,
57
75
  offset = _ref.offset,
58
76
  testId = _ref.testId,
@@ -80,7 +98,9 @@ function PopperWrapper(_ref) {
80
98
  label = _ref.label,
81
99
  titleId = _ref.titleId,
82
100
  modifiers = _ref.modifiers,
83
- shouldFitViewport = _ref.shouldFitViewport;
101
+ shouldFitViewport = _ref.shouldFitViewport,
102
+ _ref$appearance = _ref.appearance,
103
+ appearance = _ref$appearance === void 0 ? 'default' : _ref$appearance;
84
104
  var _useState = useState(null),
85
105
  _useState2 = _slicedToArray(_useState, 2),
86
106
  popupRef = _useState2[0],
@@ -89,9 +109,7 @@ function PopperWrapper(_ref) {
89
109
  _useState4 = _slicedToArray(_useState3, 2),
90
110
  initialFocusRef = _useState4[0],
91
111
  setInitialFocusRef = _useState4[1];
92
-
93
- // We have cases where we need to close the Popup on Tab press.
94
- // Example: DropdownMenu
112
+ // We have cases where we need to close the Popup on Tab press, e.g. DropdownMenu
95
113
  var shouldCloseOnTab = shouldRenderToParent && shouldDisableFocusLock;
96
114
  var shouldDisableFocusTrap = role !== 'dialog';
97
115
  useFocusManager({
@@ -138,7 +156,11 @@ function PopperWrapper(_ref) {
138
156
  style = _ref2.style,
139
157
  placement = _ref2.placement,
140
158
  update = _ref2.update;
141
- return jsx(PopupContainer, {
159
+ var popupContainer = jsx(PopupContainer
160
+ // eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage
161
+ , {
162
+ xcss: xcss,
163
+ appearance: appearance,
142
164
  id: id,
143
165
  "data-ds--level": currentLevel,
144
166
  "data-placement": placement,
@@ -158,7 +180,7 @@ function PopperWrapper(_ref) {
158
180
  }
159
181
  // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766
160
182
  ,
161
- style: style
183
+ style: appearance === 'UNSAFE_modal-below-sm' ? {} : style
162
184
  // using tabIndex={-1} would cause a bug where Safari focuses
163
185
  // first on the browser address bar when using keyboard
164
186
  ,
@@ -173,6 +195,11 @@ function PopperWrapper(_ref) {
173
195
  onClose: onClose,
174
196
  setInitialFocusRef: setInitialFocusRef
175
197
  })));
198
+ return !initialFocusRef && fg('platform-design-system-apply-popup-wrapper-focus') ? jsx(Fragment, null, jsx(FocusRing, null, popupContainer), appearance === 'UNSAFE_modal-below-sm' && jsx("div", {
199
+ css: blanketStyles
200
+ })) : jsx(Fragment, null, popupContainer, appearance === 'UNSAFE_modal-below-sm' && jsx("div", {
201
+ css: blanketStyles
202
+ }));
176
203
  });
177
204
  }
178
205
 
package/dist/esm/popup.js CHANGED
@@ -16,6 +16,7 @@ import Portal from '@atlaskit/portal';
16
16
  import { Box, xcss } from '@atlaskit/primitives';
17
17
  import { layers } from '@atlaskit/theme/constants';
18
18
  import PopperWrapper from './popper-wrapper';
19
+ import { usePopupAppearance } from './use-appearance';
19
20
  import { useGetMemoizedMergedTriggerRef } from './use-get-memoized-merged-trigger-ref';
20
21
  import { useGetMemoizedMergedTriggerRefNew } from './use-get-memoized-merged-trigger-ref-new';
21
22
  var defaultLayer = layers.layer();
@@ -23,7 +24,10 @@ var wrapperStyles = xcss({
23
24
  position: 'relative'
24
25
  });
25
26
  export var Popup = /*#__PURE__*/memo(function (_ref) {
26
- var isOpen = _ref.isOpen,
27
+ var xcss = _ref.xcss,
28
+ _ref$appearance = _ref.appearance,
29
+ inAppearance = _ref$appearance === void 0 ? 'default' : _ref$appearance,
30
+ isOpen = _ref.isOpen,
27
31
  providedId = _ref.id,
28
32
  offset = _ref.offset,
29
33
  testId = _ref.testId,
@@ -46,7 +50,7 @@ export var Popup = /*#__PURE__*/memo(function (_ref) {
46
50
  _ref$shouldUseCapture = _ref.shouldUseCaptureOnOutsideClick,
47
51
  shouldUseCaptureOnOutsideClick = _ref$shouldUseCapture === void 0 ? false : _ref$shouldUseCapture,
48
52
  _ref$shouldRenderToPa = _ref.shouldRenderToParent,
49
- shouldRenderToParent = _ref$shouldRenderToPa === void 0 ? false : _ref$shouldRenderToPa,
53
+ inShouldRenderToParent = _ref$shouldRenderToPa === void 0 ? false : _ref$shouldRenderToPa,
50
54
  _ref$shouldFitContain = _ref.shouldFitContainer,
51
55
  shouldFitContainer = _ref$shouldFitContain === void 0 ? false : _ref$shouldFitContain,
52
56
  _ref$shouldDisableFoc = _ref.shouldDisableFocusLock,
@@ -66,10 +70,20 @@ export var Popup = /*#__PURE__*/memo(function (_ref) {
66
70
  var getMergedTriggerRef = useGetMemoizedMergedTriggerRef();
67
71
  var getMergedTriggerRefNew = useGetMemoizedMergedTriggerRefNew();
68
72
  var generatedId = useId();
73
+ var _usePopupAppearance = usePopupAppearance({
74
+ appearance: inAppearance,
75
+ shouldRenderToParent: inShouldRenderToParent
76
+ }),
77
+ appearance = _usePopupAppearance.appearance,
78
+ shouldRenderToParent = _usePopupAppearance.shouldRenderToParent;
69
79
  var id = providedId || generatedId;
70
80
  var renderPopperWrapper = jsx(UNSAFE_LAYERING, {
71
81
  isDisabled: false
72
- }, jsx(PopperWrapper, {
82
+ }, jsx(PopperWrapper
83
+ // eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage
84
+ , {
85
+ xcss: xcss,
86
+ appearance: appearance,
73
87
  content: content,
74
88
  isOpen: isOpen,
75
89
  placement: placement,
@@ -0,0 +1,29 @@
1
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
2
+ import { useState } from 'react';
3
+ import { UNSAFE_useMediaQuery as useMediaQuery } from '@atlaskit/primitives/responsive';
4
+
5
+ /**
6
+ * **usePopupAppearance()**
7
+ *
8
+ * Abstracts away calculating the appearance for a popup including if it should
9
+ * be portalled or not, this is done to ensure that if the popup needs to render
10
+ * as a modal that it is also forcibly portalled. If it's not portalled when rendering
11
+ * as a modal it will appear below the top bar.
12
+ */
13
+ export function usePopupAppearance(_ref) {
14
+ var _appearance = _ref.appearance,
15
+ _shouldRenderToParent = _ref.shouldRenderToParent;
16
+ var mq = useMediaQuery('below.sm', function (e) {
17
+ setIsSmallViewport(!!e.matches);
18
+ });
19
+ var _useState = useState(!!(mq !== null && mq !== void 0 && mq.matches)),
20
+ _useState2 = _slicedToArray(_useState, 2),
21
+ isSmallViewport = _useState2[0],
22
+ setIsSmallViewport = _useState2[1];
23
+ var appearance = _appearance === 'UNSAFE_modal-below-sm' && isSmallViewport ? 'UNSAFE_modal-below-sm' : 'default';
24
+ var shouldRenderToParent = _shouldRenderToParent && appearance === 'default';
25
+ return {
26
+ appearance: appearance,
27
+ shouldRenderToParent: shouldRenderToParent
28
+ };
29
+ }
@@ -41,10 +41,12 @@ export var useCloseManager = function useCloseManager(_ref) {
41
41
  }
42
42
  if (shouldDisableFocusTrap && fg('platform_dst_popup-disable-focuslock')) {
43
43
  // Restoring the normal focus order for trigger.
44
- triggerRef === null || triggerRef === void 0 || triggerRef.setAttribute('tabindex', '0');
45
- if (popupRef && autoFocus) {
46
- popupRef.setAttribute('tabindex', '0');
47
- }
44
+ requestFrame(function () {
45
+ triggerRef === null || triggerRef === void 0 || triggerRef.setAttribute('tabindex', '0');
46
+ if (popupRef && autoFocus) {
47
+ popupRef.setAttribute('tabindex', '0');
48
+ }
49
+ });
48
50
  }
49
51
  };
50
52
 
@@ -36,7 +36,7 @@ export type PopupTriggerProps = {
36
36
  * It must be a child of the Popup component.
37
37
  */
38
38
  export declare const PopupTrigger: ({ children }: PopupTriggerProps) => JSX.Element;
39
- type CommonContentPopupProps = Pick<LegacyPopupProps, 'boundary' | 'offset' | 'onClose' | 'testId' | 'placement' | 'fallbackPlacements' | 'popupComponent' | 'shouldFlip' | 'rootBoundary' | 'autoFocus' | 'shouldRenderToParent' | 'shouldUseCaptureOnOutsideClick' | 'shouldDisableFocusLock' | 'strategy' | 'zIndex' | 'shouldFitViewport'> & {
39
+ type CommonContentPopupProps = Pick<LegacyPopupProps, 'xcss' | 'appearance' | 'boundary' | 'offset' | 'onClose' | 'testId' | 'placement' | 'fallbackPlacements' | 'popupComponent' | 'shouldFlip' | 'rootBoundary' | 'autoFocus' | 'shouldRenderToParent' | 'shouldUseCaptureOnOutsideClick' | 'shouldDisableFocusLock' | 'strategy' | 'zIndex' | 'shouldFitViewport'> & {
40
40
  children: (props: ContentProps) => React.ReactNode;
41
41
  };
42
42
  type ShouldFitContainerContentPopupProps = CommonContentPopupProps & {
@@ -55,5 +55,5 @@ export type PopupContentProps = ShouldFitContainerContentPopupProps | StandardPo
55
55
  *
56
56
  * It must be a child of the Popup component.
57
57
  */
58
- export declare const PopupContent: ({ children, boundary, offset, strategy, onClose, testId, rootBoundary, shouldFlip, placement, fallbackPlacements, popupComponent, autoFocus, zIndex, shouldUseCaptureOnOutsideClick, shouldRenderToParent, shouldDisableFocusLock, shouldFitContainer, shouldFitViewport, }: PopupContentProps) => JSX.Element | null;
58
+ export declare const PopupContent: ({ xcss, appearance: inAppearance, children, boundary, offset, strategy, onClose, testId, rootBoundary, shouldFlip, placement, fallbackPlacements, popupComponent, autoFocus, zIndex, shouldUseCaptureOnOutsideClick, shouldRenderToParent: inShouldRenderToParent, shouldDisableFocusLock, shouldFitContainer, shouldFitViewport, }: PopupContentProps) => JSX.Element | null;
59
59
  export {};
@@ -1,4 +1,4 @@
1
1
  import { jsx } from '@emotion/react';
2
2
  import { type PopperWrapperProps } from './types';
3
- declare function PopperWrapper({ isOpen, id, offset, testId, content, fallbackPlacements, onClose, boundary, rootBoundary, shouldFlip, placement, popupComponent: PopupContainer, autoFocus, triggerRef, shouldUseCaptureOnOutsideClick, shouldRenderToParent, shouldFitContainer, shouldDisableFocusLock, shouldReturnFocus, strategy, role, label, titleId, modifiers, shouldFitViewport, }: PopperWrapperProps): jsx.JSX.Element;
3
+ declare function PopperWrapper({ xcss, isOpen, id, offset, testId, content, fallbackPlacements, onClose, boundary, rootBoundary, shouldFlip, placement, popupComponent: PopupContainer, autoFocus, triggerRef, shouldUseCaptureOnOutsideClick, shouldRenderToParent, shouldFitContainer, shouldDisableFocusLock, shouldReturnFocus, strategy, role, label, titleId, modifiers, shouldFitViewport, appearance, }: PopperWrapperProps): jsx.JSX.Element;
4
4
  export default PopperWrapper;
@@ -1,4 +1,5 @@
1
1
  import { type ComponentType, type CSSProperties, type Dispatch, type PropsWithChildren, type default as React, type ReactNode, type Ref, type SetStateAction } from 'react';
2
+ import { type StrictXCSSProp } from '@atlaskit/css';
2
3
  import { type Modifier, type Placement, type PopperChildrenProps } from '@atlaskit/popper';
3
4
  export interface TriggerProps {
4
5
  ref: Ref<any>;
@@ -53,6 +54,7 @@ export interface PopupComponentProps {
53
54
  * Style that should be assigned to the root element.
54
55
  */
55
56
  style: CSSProperties;
57
+ xcss?: StrictXCSSProp<'padding' | 'paddingInline' | 'paddingBlock' | 'width', never>;
56
58
  /**
57
59
  * Tab index passed through by the parent popup.
58
60
  */
@@ -69,6 +71,11 @@ export interface PopupComponentProps {
69
71
  * The default is `false`.
70
72
  */
71
73
  shouldFitContainer?: boolean;
74
+ /**
75
+ * The "default" appearance is used for standard popups.
76
+ * The "UNSAFE_modal-below-sm" appearance makes the popup appear as a modal when the viewport is smaller than "sm".
77
+ */
78
+ appearance?: 'default' | 'UNSAFE_modal-below-sm';
72
79
  /**
73
80
  * Use this to set the accessibility role for the popup.
74
81
  * We strongly recommend using only `menu` or `dialog`.
@@ -76,6 +83,12 @@ export interface PopupComponentProps {
76
83
  role?: string;
77
84
  }
78
85
  interface BaseProps {
86
+ /**
87
+ * The "default" appearance is used for standard popups.
88
+ * The "UNSAFE_modal-below-sm" appearance makes the popup appear as a modal when the viewport is smaller than "sm".
89
+ */
90
+ appearance?: 'default' | 'UNSAFE_modal-below-sm';
91
+ xcss?: StrictXCSSProp<'padding' | 'paddingInline' | 'paddingBlock' | 'width', never>;
79
92
  /**
80
93
  * Use this to either show or hide the popup.
81
94
  * When set to `false` the popup will not render anything to the DOM.
@@ -0,0 +1,15 @@
1
+ /**
2
+ * **usePopupAppearance()**
3
+ *
4
+ * Abstracts away calculating the appearance for a popup including if it should
5
+ * be portalled or not, this is done to ensure that if the popup needs to render
6
+ * as a modal that it is also forcibly portalled. If it's not portalled when rendering
7
+ * as a modal it will appear below the top bar.
8
+ */
9
+ export declare function usePopupAppearance({ appearance: _appearance, shouldRenderToParent: _shouldRenderToParent, }: {
10
+ appearance: 'default' | 'UNSAFE_modal-below-sm';
11
+ shouldRenderToParent?: boolean;
12
+ }): {
13
+ appearance: "default" | "UNSAFE_modal-below-sm";
14
+ shouldRenderToParent: boolean | undefined;
15
+ };
@@ -36,7 +36,7 @@ export type PopupTriggerProps = {
36
36
  * It must be a child of the Popup component.
37
37
  */
38
38
  export declare const PopupTrigger: ({ children }: PopupTriggerProps) => JSX.Element;
39
- type CommonContentPopupProps = Pick<LegacyPopupProps, 'boundary' | 'offset' | 'onClose' | 'testId' | 'placement' | 'fallbackPlacements' | 'popupComponent' | 'shouldFlip' | 'rootBoundary' | 'autoFocus' | 'shouldRenderToParent' | 'shouldUseCaptureOnOutsideClick' | 'shouldDisableFocusLock' | 'strategy' | 'zIndex' | 'shouldFitViewport'> & {
39
+ type CommonContentPopupProps = Pick<LegacyPopupProps, 'xcss' | 'appearance' | 'boundary' | 'offset' | 'onClose' | 'testId' | 'placement' | 'fallbackPlacements' | 'popupComponent' | 'shouldFlip' | 'rootBoundary' | 'autoFocus' | 'shouldRenderToParent' | 'shouldUseCaptureOnOutsideClick' | 'shouldDisableFocusLock' | 'strategy' | 'zIndex' | 'shouldFitViewport'> & {
40
40
  children: (props: ContentProps) => React.ReactNode;
41
41
  };
42
42
  type ShouldFitContainerContentPopupProps = CommonContentPopupProps & {
@@ -55,5 +55,5 @@ export type PopupContentProps = ShouldFitContainerContentPopupProps | StandardPo
55
55
  *
56
56
  * It must be a child of the Popup component.
57
57
  */
58
- export declare const PopupContent: ({ children, boundary, offset, strategy, onClose, testId, rootBoundary, shouldFlip, placement, fallbackPlacements, popupComponent, autoFocus, zIndex, shouldUseCaptureOnOutsideClick, shouldRenderToParent, shouldDisableFocusLock, shouldFitContainer, shouldFitViewport, }: PopupContentProps) => JSX.Element | null;
58
+ export declare const PopupContent: ({ xcss, appearance: inAppearance, children, boundary, offset, strategy, onClose, testId, rootBoundary, shouldFlip, placement, fallbackPlacements, popupComponent, autoFocus, zIndex, shouldUseCaptureOnOutsideClick, shouldRenderToParent: inShouldRenderToParent, shouldDisableFocusLock, shouldFitContainer, shouldFitViewport, }: PopupContentProps) => JSX.Element | null;
59
59
  export {};
@@ -1,4 +1,4 @@
1
1
  import { jsx } from '@emotion/react';
2
2
  import { type PopperWrapperProps } from './types';
3
- declare function PopperWrapper({ isOpen, id, offset, testId, content, fallbackPlacements, onClose, boundary, rootBoundary, shouldFlip, placement, popupComponent: PopupContainer, autoFocus, triggerRef, shouldUseCaptureOnOutsideClick, shouldRenderToParent, shouldFitContainer, shouldDisableFocusLock, shouldReturnFocus, strategy, role, label, titleId, modifiers, shouldFitViewport, }: PopperWrapperProps): jsx.JSX.Element;
3
+ declare function PopperWrapper({ xcss, isOpen, id, offset, testId, content, fallbackPlacements, onClose, boundary, rootBoundary, shouldFlip, placement, popupComponent: PopupContainer, autoFocus, triggerRef, shouldUseCaptureOnOutsideClick, shouldRenderToParent, shouldFitContainer, shouldDisableFocusLock, shouldReturnFocus, strategy, role, label, titleId, modifiers, shouldFitViewport, appearance, }: PopperWrapperProps): jsx.JSX.Element;
4
4
  export default PopperWrapper;
@@ -1,4 +1,5 @@
1
1
  import { type ComponentType, type CSSProperties, type Dispatch, type PropsWithChildren, type default as React, type ReactNode, type Ref, type SetStateAction } from 'react';
2
+ import { type StrictXCSSProp } from '@atlaskit/css';
2
3
  import { type Modifier, type Placement, type PopperChildrenProps } from '@atlaskit/popper';
3
4
  export interface TriggerProps {
4
5
  ref: Ref<any>;
@@ -53,6 +54,7 @@ export interface PopupComponentProps {
53
54
  * Style that should be assigned to the root element.
54
55
  */
55
56
  style: CSSProperties;
57
+ xcss?: StrictXCSSProp<'padding' | 'paddingInline' | 'paddingBlock' | 'width', never>;
56
58
  /**
57
59
  * Tab index passed through by the parent popup.
58
60
  */
@@ -69,6 +71,11 @@ export interface PopupComponentProps {
69
71
  * The default is `false`.
70
72
  */
71
73
  shouldFitContainer?: boolean;
74
+ /**
75
+ * The "default" appearance is used for standard popups.
76
+ * The "UNSAFE_modal-below-sm" appearance makes the popup appear as a modal when the viewport is smaller than "sm".
77
+ */
78
+ appearance?: 'default' | 'UNSAFE_modal-below-sm';
72
79
  /**
73
80
  * Use this to set the accessibility role for the popup.
74
81
  * We strongly recommend using only `menu` or `dialog`.
@@ -76,6 +83,12 @@ export interface PopupComponentProps {
76
83
  role?: string;
77
84
  }
78
85
  interface BaseProps {
86
+ /**
87
+ * The "default" appearance is used for standard popups.
88
+ * The "UNSAFE_modal-below-sm" appearance makes the popup appear as a modal when the viewport is smaller than "sm".
89
+ */
90
+ appearance?: 'default' | 'UNSAFE_modal-below-sm';
91
+ xcss?: StrictXCSSProp<'padding' | 'paddingInline' | 'paddingBlock' | 'width', never>;
79
92
  /**
80
93
  * Use this to either show or hide the popup.
81
94
  * When set to `false` the popup will not render anything to the DOM.
@@ -0,0 +1,15 @@
1
+ /**
2
+ * **usePopupAppearance()**
3
+ *
4
+ * Abstracts away calculating the appearance for a popup including if it should
5
+ * be portalled or not, this is done to ensure that if the popup needs to render
6
+ * as a modal that it is also forcibly portalled. If it's not portalled when rendering
7
+ * as a modal it will appear below the top bar.
8
+ */
9
+ export declare function usePopupAppearance({ appearance: _appearance, shouldRenderToParent: _shouldRenderToParent, }: {
10
+ appearance: 'default' | 'UNSAFE_modal-below-sm';
11
+ shouldRenderToParent?: boolean;
12
+ }): {
13
+ appearance: "default" | "UNSAFE_modal-below-sm";
14
+ shouldRenderToParent: boolean | undefined;
15
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/popup",
3
- "version": "1.25.0",
3
+ "version": "1.27.0",
4
4
  "description": "A popup displays brief content in an overlay.",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/"
@@ -36,14 +36,16 @@
36
36
  }
37
37
  },
38
38
  "dependencies": {
39
- "@atlaskit/ds-lib": "^2.5.0",
39
+ "@atlaskit/css": "^0.5.0",
40
+ "@atlaskit/ds-lib": "^2.6.0",
41
+ "@atlaskit/focus-ring": "^1.6.0",
40
42
  "@atlaskit/layering": "^0.4.0",
41
43
  "@atlaskit/platform-feature-flags": "^0.3.0",
42
44
  "@atlaskit/popper": "^6.3.0",
43
45
  "@atlaskit/portal": "^4.9.0",
44
- "@atlaskit/primitives": "^12.1.0",
46
+ "@atlaskit/primitives": "^12.2.0",
45
47
  "@atlaskit/theme": "^13.0.0",
46
- "@atlaskit/tokens": "^1.59.0",
48
+ "@atlaskit/tokens": "^1.60.0",
47
49
  "@babel/runtime": "^7.0.0",
48
50
  "@emotion/react": "^11.7.1",
49
51
  "bind-event-listener": "^3.0.0",
@@ -60,14 +62,16 @@
60
62
  "@af/integration-testing": "*",
61
63
  "@af/visual-regression": "*",
62
64
  "@atlaskit/button": "^20.1.0",
63
- "@atlaskit/icon": "^22.16.0",
65
+ "@atlaskit/icon": "^22.18.0",
64
66
  "@atlaskit/ssr": "*",
65
67
  "@atlaskit/textfield": "^6.5.0",
66
68
  "@atlaskit/toggle": "^13.4.0",
67
69
  "@atlaskit/visual-regression": "*",
68
70
  "@atlassian/feature-flags-test-utils": "*",
71
+ "@compiled/react": "^0.17.3",
69
72
  "@testing-library/dom": "^10.1.0",
70
73
  "@testing-library/react": "^12.1.5",
74
+ "@testing-library/react-hooks": "^8.0.1",
71
75
  "@testing-library/user-event": "^14.4.3",
72
76
  "ast-types": "^0.13.3",
73
77
  "jscodeshift": "^0.13.0",
@@ -114,6 +118,9 @@
114
118
  },
115
119
  "sibling-dropdown-close-issue": {
116
120
  "type": "boolean"
121
+ },
122
+ "platform-design-system-apply-popup-wrapper-focus": {
123
+ "type": "boolean"
117
124
  }
118
125
  },
119
126
  "homepage": "https://atlassian.design/components/popup/"