@jobber/components 9.11.0 → 9.12.1

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.
@@ -106,11 +106,13 @@ export type DialogCloseRender = ReactElement | ((props: DialogCloseRenderProps)
106
106
  export interface DialogCloseProps extends DialogBaseProps, Omit<BaseDialog.Close.Props, BaseUIPropsToExclude> {
107
107
  /**
108
108
  * Optional content for the dismiss control. An Atlantis `<Button>` is adapted
109
- * automatically; any other valid element is used as-is. The default ButtonDismiss is used if no children or render is provided.
109
+ * automatically; any other valid element is used as-is. Defaults to a subtle
110
+ * tertiary `Button` with a `cross` icon when neither `children` nor `render`
111
+ * is provided.
110
112
  */
111
113
  readonly children?: ReactNode;
112
114
  /**
113
- * Renders a custom dismiss element in place of the default `ButtonDismiss`
115
+ * Renders a custom dismiss element in place of the default close button.
114
116
  * Pass an element or a function that receives the
115
117
  * BaseUI close props (so the element stays wired to close the dialog).
116
118
  */
@@ -15,8 +15,8 @@ export declare function resolveComposableTriggerRender({ children, render, }: {
15
15
  /**
16
16
  * Resolves the dismiss element for `Dialog.Close`, mirroring
17
17
  * `resolveComposableTriggerRender` so a custom render works in both shells.
18
- * Falls back to the subtle "cross" `ButtonDismiss` when neither `render` nor
19
- * `children` are supplied. An Atlantis `<Button>`/`<ButtonDismiss>` passed via
18
+ * Falls back to a subtle tertiary `Button` with a `cross` icon when neither
19
+ * `render` nor `children` are supplied. An Atlantis `<Button>` passed via
20
20
  * `render` or `children` is adapted; any other valid element is used as-is.
21
21
  */
22
22
  export declare function resolveComposableCloseRender({ children, render, }: {
@@ -1,3 +1,6 @@
1
1
  import React from "react";
2
2
  import type { ModalLegacyProps } from "./Modal.types";
3
+ /**
4
+ * @deprecated Use the `Dialog` component instead.
5
+ */
3
6
  export declare function ModalLegacy({ open, title, size, dismissible, children, primaryAction, secondaryAction, tertiaryAction, onRequestClose, ariaLabel, }: ModalLegacyProps): React.JSX.Element;
@@ -1,11 +1,25 @@
1
1
  import type { PropsWithChildren } from "react";
2
2
  import React from "react";
3
3
  import type { HeaderProps, ModalActionsProps, ModalContentProps as ModalContainerProps } from "./Modal.types";
4
+ /**
5
+ * @deprecated Use `Dialog.Header` with `Dialog.Title` and `Dialog.Close` instead.
6
+ */
4
7
  export declare function ModalHeader({ title, children }: HeaderProps): React.JSX.Element;
8
+ /**
9
+ * @deprecated Use `Dialog.Actions` inside a `Dialog.Footer` instead.
10
+ */
5
11
  export declare function ModalActions({ primary, secondary, tertiary, }: ModalActionsProps): React.JSX.Element;
12
+ /**
13
+ * @deprecated Use `Dialog.Trigger` instead.
14
+ */
6
15
  export declare function ModalActivator({ children }: PropsWithChildren): React.JSX.Element;
7
16
  /**
8
17
  * Background overlay for the modal. Used in the ModalContent.
18
+ *
19
+ * @deprecated Use the `Dialog` component instead, which renders its own overlay.
9
20
  */
10
21
  export declare function ModalOverlay({ children }: PropsWithChildren): React.JSX.Element;
22
+ /**
23
+ * @deprecated Use `Dialog.Content` with `Dialog.Body` instead.
24
+ */
11
25
  export declare function ModalContent({ children }: ModalContainerProps): React.JSX.Element;
@@ -112,6 +112,9 @@ type HeaderWithChildren = PropsWithChildren<{
112
112
  readonly variant?: "inline" | "sticky";
113
113
  }>;
114
114
  export type HeaderProps = XOR<HeaderPropsWithoutChildren, HeaderWithChildren>;
115
+ /**
116
+ * @deprecated Use the `Dialog` component instead.
117
+ */
115
118
  export interface ModalLegacyProps {
116
119
  /**
117
120
  * @default false
@@ -13,5 +13,11 @@ export interface ModalProviderProps {
13
13
  readonly modalLabelledBy?: string;
14
14
  readonly ariaLabel?: string;
15
15
  }
16
+ /**
17
+ * @deprecated Use `Dialog` as the composable root instead.
18
+ */
16
19
  export declare function ModalProvider({ children, open, size, onRequestClose, activatorRef: refProp, dismissible, modalLabelledBy, ariaLabel, }: ModalProviderProps): React.JSX.Element;
20
+ /**
21
+ * @deprecated Use `Dialog.Close` or `Dialog.createHandle` instead.
22
+ */
17
23
  export declare function useModalContext(): ModalContextType;
@@ -44,6 +44,10 @@ const modalMessages = useAtlantisI18n.defineMessages({
44
44
  },
45
45
  });
46
46
 
47
+ /* eslint-disable import/no-deprecated -- Implements the deprecated prop-driven Modal; the imports below are Modal's own internals. Dialog is the replacement. */
48
+ /**
49
+ * @deprecated Use the `Dialog` component instead.
50
+ */
47
51
  function ModalLegacy({ open = false, title, size, dismissible = true, children, primaryAction, secondaryAction, tertiaryAction, onRequestClose, ariaLabel, }) {
48
52
  const modalClassName = classnames(styles$1.modal, size && sizes[size]);
49
53
  const containerClassName = classnames(styles$1.container, size === "fullScreen" && styles$1.containerFullScreen);
@@ -155,6 +159,9 @@ const ModalContext = React.createContext({
155
159
  dismissible: true,
156
160
  getFloatingProps: identity.identity,
157
161
  });
162
+ /**
163
+ * @deprecated Use `Dialog` as the composable root instead.
164
+ */
158
165
  function ModalProvider({ children, open = false, size, onRequestClose = noop.noop, activatorRef: refProp, dismissible = true, modalLabelledBy = MODAL_HEADER_ID, ariaLabel, }) {
159
166
  const startedInsideRef = React.useRef(true);
160
167
  const { floatingRefs, floatingContext, nodeId, activatorRef, parentId, getFloatingProps, } = useModal({
@@ -182,12 +189,18 @@ function ModalProvider({ children, open = false, size, onRequestClose = noop.noo
182
189
  }
183
190
  return React.createElement(floatingUi_react.FloatingTree, null, content);
184
191
  }
192
+ /**
193
+ * @deprecated Use `Dialog.Close` or `Dialog.createHandle` instead.
194
+ */
185
195
  function useModalContext() {
186
196
  return React.useContext(ModalContext);
187
197
  }
188
198
 
189
199
  var styles = {"overlay":"cRhQeXmZobs-","overlayBackground":"PO6ZUDxQoFE-","modal":"OiqCKNmbHZ0-","modalWithStickyRegions":"_6dGKr5VVf9Y-","stickyHeaderRegion":"uo6BCADQuLU-","stickyActionsRegion":"Vq0y9ggAxtI-","modalBody":"zM9SWwAd5Dg-","header":"GDWGHwmjgAc-","closeButton":"KJlGo4z-E6Q-","actionBar":"ZGrhWCAymCw-","leftAction":"hOiEWds2Vq8-","rightAction":"K31NzxPZP9s-","spinning":"SKeimJFlB-g-"};
190
200
 
201
+ /**
202
+ * @deprecated Use the `Dialog` component instead, which owns its own styling.
203
+ */
191
204
  function useModalStyles(size) {
192
205
  return {
193
206
  modal: classnames(styles.modal, size && sizes[size]),
@@ -201,6 +214,9 @@ function useModalStyles(size) {
201
214
  };
202
215
  }
203
216
 
217
+ /**
218
+ * @deprecated Use `Dialog.Header` with `Dialog.Title` and `Dialog.Close` instead.
219
+ */
204
220
  function ModalHeader({ title, children }) {
205
221
  const { header, dismissButton } = useModalStyles();
206
222
  const { dismissible, onRequestClose, modalLabelledBy } = useModalContext();
@@ -213,6 +229,9 @@ function ModalHeader({ title, children }) {
213
229
  dismissible && (React.createElement("div", { className: dismissButton },
214
230
  React.createElement(ButtonDismiss.ButtonDismiss, { onClick: onRequestClose, ariaLabel: t("closeModal") })))));
215
231
  }
232
+ /**
233
+ * @deprecated Use `Dialog.Actions` inside a `Dialog.Footer` instead.
234
+ */
216
235
  function ModalActions({ primary, secondary, tertiary, }) {
217
236
  const { actionBar, rightAction, leftAction } = useModalStyles();
218
237
  const shouldShow = primary != undefined || secondary != undefined || tertiary != undefined;
@@ -223,12 +242,17 @@ function ModalActions({ primary, secondary, tertiary, }) {
223
242
  tertiary && (React.createElement("div", { className: leftAction },
224
243
  React.createElement(Button.Button, Object.assign({ type: "secondary", variation: "destructive" }, tertiary))))))));
225
244
  }
245
+ /**
246
+ * @deprecated Use `Dialog.Trigger` instead.
247
+ */
226
248
  function ModalActivator({ children }) {
227
249
  const { activatorRef } = useModalContext();
228
250
  return (React.createElement("span", { ref: activatorRef, style: { display: "contents" } }, children));
229
251
  }
230
252
  /**
231
253
  * Background overlay for the modal. Used in the ModalContent.
254
+ *
255
+ * @deprecated Use the `Dialog` component instead, which renders its own overlay.
232
256
  */
233
257
  function ModalOverlay({ children }) {
234
258
  const { overlay, overlayBackground } = useModalStyles();
@@ -241,6 +265,9 @@ function ModalOverlay({ children }) {
241
265
  } }),
242
266
  children));
243
267
  }
268
+ /**
269
+ * @deprecated Use `Dialog.Content` with `Dialog.Body` instead.
270
+ */
244
271
  function ModalContent({ children }) {
245
272
  const { open, floatingContext, activatorRef, floatingRefs, size, floatingNodeId, modalLabelledBy, ariaLabel, getFloatingProps, startedInsideRef, } = useModalContext();
246
273
  const { modal } = useModalStyles(size);
@@ -287,13 +314,33 @@ function extractSticky(children, componentType, match) {
287
314
  return { sticky, rest };
288
315
  }
289
316
 
317
+ /* eslint-disable import/no-deprecated -- Assembles the deprecated Modal namespace from its own parts. Dialog is the replacement. */
318
+ /**
319
+ * @deprecated Use the `Dialog` component instead.
320
+ * @see https://atlantis.getjobber.com/components/Dialog/implement#component-view-migrating-to-dialog
321
+ */
290
322
  function Modal(props) {
291
323
  return React.createElement(ModalLegacy, Object.assign({}, props));
292
324
  }
325
+ /**
326
+ * @deprecated Use `Dialog.Header` with `Dialog.Title` and `Dialog.Close` instead.
327
+ */
293
328
  Modal.Header = ModalHeader;
329
+ /**
330
+ * @deprecated Use `Dialog.Actions` inside a `Dialog.Footer` instead.
331
+ */
294
332
  Modal.Actions = ModalActions;
333
+ /**
334
+ * @deprecated Use `Dialog.Trigger` instead.
335
+ */
295
336
  Modal.Activator = ModalActivator;
337
+ /**
338
+ * @deprecated Use `Dialog` as the composable root instead.
339
+ */
296
340
  Modal.Provider = ModalProvider;
341
+ /**
342
+ * @deprecated Use `Dialog.Content` with `Dialog.Body` instead.
343
+ */
297
344
  Modal.Content = ModalContent;
298
345
 
299
346
  exports.Modal = Modal;
@@ -3,8 +3,12 @@ import { ModalProvider } from "./ModalContext.rebuilt";
3
3
  import { ModalActions, ModalActivator, ModalContent, ModalHeader } from "./Modal.rebuilt";
4
4
  import type { ModalLegacyProps } from "./Modal.types";
5
5
  export type { ModalLegacyProps as ModalProps } from "./Modal.types";
6
- declare function Modal(props: ModalLegacyProps): React.JSX.Element;
7
- declare namespace Modal {
6
+ /**
7
+ * @deprecated Use the `Dialog` component instead.
8
+ * @see https://atlantis.getjobber.com/components/Dialog/implement#component-view-migrating-to-dialog
9
+ */
10
+ export declare function Modal(props: ModalLegacyProps): React.JSX.Element;
11
+ export declare namespace Modal {
8
12
  var Header: typeof ModalHeader;
9
13
  var Actions: typeof ModalActions;
10
14
  var Activator: typeof ModalActivator;
@@ -13,4 +17,3 @@ declare namespace Modal {
13
17
  }
14
18
  export { useModalContext } from "./ModalContext.rebuilt";
15
19
  export { useModalStyles } from "./useModalStyles";
16
- export { Modal };
@@ -42,6 +42,10 @@ const modalMessages = defineMessages({
42
42
  },
43
43
  });
44
44
 
45
+ /* eslint-disable import/no-deprecated -- Implements the deprecated prop-driven Modal; the imports below are Modal's own internals. Dialog is the replacement. */
46
+ /**
47
+ * @deprecated Use the `Dialog` component instead.
48
+ */
45
49
  function ModalLegacy({ open = false, title, size, dismissible = true, children, primaryAction, secondaryAction, tertiaryAction, onRequestClose, ariaLabel, }) {
46
50
  const modalClassName = classnames(styles$1.modal, size && sizes[size]);
47
51
  const containerClassName = classnames(styles$1.container, size === "fullScreen" && styles$1.containerFullScreen);
@@ -153,6 +157,9 @@ const ModalContext = createContext({
153
157
  dismissible: true,
154
158
  getFloatingProps: identity,
155
159
  });
160
+ /**
161
+ * @deprecated Use `Dialog` as the composable root instead.
162
+ */
156
163
  function ModalProvider({ children, open = false, size, onRequestClose = noop, activatorRef: refProp, dismissible = true, modalLabelledBy = MODAL_HEADER_ID, ariaLabel, }) {
157
164
  const startedInsideRef = useRef(true);
158
165
  const { floatingRefs, floatingContext, nodeId, activatorRef, parentId, getFloatingProps, } = useModal({
@@ -180,12 +187,18 @@ function ModalProvider({ children, open = false, size, onRequestClose = noop, ac
180
187
  }
181
188
  return React__default.createElement(FloatingTree, null, content);
182
189
  }
190
+ /**
191
+ * @deprecated Use `Dialog.Close` or `Dialog.createHandle` instead.
192
+ */
183
193
  function useModalContext() {
184
194
  return useContext(ModalContext);
185
195
  }
186
196
 
187
197
  var styles = {"overlay":"cRhQeXmZobs-","overlayBackground":"PO6ZUDxQoFE-","modal":"OiqCKNmbHZ0-","modalWithStickyRegions":"_6dGKr5VVf9Y-","stickyHeaderRegion":"uo6BCADQuLU-","stickyActionsRegion":"Vq0y9ggAxtI-","modalBody":"zM9SWwAd5Dg-","header":"GDWGHwmjgAc-","closeButton":"KJlGo4z-E6Q-","actionBar":"ZGrhWCAymCw-","leftAction":"hOiEWds2Vq8-","rightAction":"K31NzxPZP9s-","spinning":"SKeimJFlB-g-"};
188
198
 
199
+ /**
200
+ * @deprecated Use the `Dialog` component instead, which owns its own styling.
201
+ */
189
202
  function useModalStyles(size) {
190
203
  return {
191
204
  modal: classnames(styles.modal, size && sizes[size]),
@@ -199,6 +212,9 @@ function useModalStyles(size) {
199
212
  };
200
213
  }
201
214
 
215
+ /**
216
+ * @deprecated Use `Dialog.Header` with `Dialog.Title` and `Dialog.Close` instead.
217
+ */
202
218
  function ModalHeader({ title, children }) {
203
219
  const { header, dismissButton } = useModalStyles();
204
220
  const { dismissible, onRequestClose, modalLabelledBy } = useModalContext();
@@ -211,6 +227,9 @@ function ModalHeader({ title, children }) {
211
227
  dismissible && (React__default.createElement("div", { className: dismissButton },
212
228
  React__default.createElement(ButtonDismiss, { onClick: onRequestClose, ariaLabel: t("closeModal") })))));
213
229
  }
230
+ /**
231
+ * @deprecated Use `Dialog.Actions` inside a `Dialog.Footer` instead.
232
+ */
214
233
  function ModalActions({ primary, secondary, tertiary, }) {
215
234
  const { actionBar, rightAction, leftAction } = useModalStyles();
216
235
  const shouldShow = primary != undefined || secondary != undefined || tertiary != undefined;
@@ -221,12 +240,17 @@ function ModalActions({ primary, secondary, tertiary, }) {
221
240
  tertiary && (React__default.createElement("div", { className: leftAction },
222
241
  React__default.createElement(Button, Object.assign({ type: "secondary", variation: "destructive" }, tertiary))))))));
223
242
  }
243
+ /**
244
+ * @deprecated Use `Dialog.Trigger` instead.
245
+ */
224
246
  function ModalActivator({ children }) {
225
247
  const { activatorRef } = useModalContext();
226
248
  return (React__default.createElement("span", { ref: activatorRef, style: { display: "contents" } }, children));
227
249
  }
228
250
  /**
229
251
  * Background overlay for the modal. Used in the ModalContent.
252
+ *
253
+ * @deprecated Use the `Dialog` component instead, which renders its own overlay.
230
254
  */
231
255
  function ModalOverlay({ children }) {
232
256
  const { overlay, overlayBackground } = useModalStyles();
@@ -239,6 +263,9 @@ function ModalOverlay({ children }) {
239
263
  } }),
240
264
  children));
241
265
  }
266
+ /**
267
+ * @deprecated Use `Dialog.Content` with `Dialog.Body` instead.
268
+ */
242
269
  function ModalContent({ children }) {
243
270
  const { open, floatingContext, activatorRef, floatingRefs, size, floatingNodeId, modalLabelledBy, ariaLabel, getFloatingProps, startedInsideRef, } = useModalContext();
244
271
  const { modal } = useModalStyles(size);
@@ -285,13 +312,33 @@ function extractSticky(children, componentType, match) {
285
312
  return { sticky, rest };
286
313
  }
287
314
 
315
+ /* eslint-disable import/no-deprecated -- Assembles the deprecated Modal namespace from its own parts. Dialog is the replacement. */
316
+ /**
317
+ * @deprecated Use the `Dialog` component instead.
318
+ * @see https://atlantis.getjobber.com/components/Dialog/implement#component-view-migrating-to-dialog
319
+ */
288
320
  function Modal(props) {
289
321
  return React__default.createElement(ModalLegacy, Object.assign({}, props));
290
322
  }
323
+ /**
324
+ * @deprecated Use `Dialog.Header` with `Dialog.Title` and `Dialog.Close` instead.
325
+ */
291
326
  Modal.Header = ModalHeader;
327
+ /**
328
+ * @deprecated Use `Dialog.Actions` inside a `Dialog.Footer` instead.
329
+ */
292
330
  Modal.Actions = ModalActions;
331
+ /**
332
+ * @deprecated Use `Dialog.Trigger` instead.
333
+ */
293
334
  Modal.Activator = ModalActivator;
335
+ /**
336
+ * @deprecated Use `Dialog` as the composable root instead.
337
+ */
294
338
  Modal.Provider = ModalProvider;
339
+ /**
340
+ * @deprecated Use `Dialog.Content` with `Dialog.Body` instead.
341
+ */
295
342
  Modal.Content = ModalContent;
296
343
 
297
344
  export { Modal, useModalContext, useModalStyles };
@@ -1,4 +1,7 @@
1
1
  import sizes from "./ModalSizes.module.css";
2
+ /**
3
+ * @deprecated Use the `Dialog` component instead, which owns its own styling.
4
+ */
2
5
  export declare function useModalStyles(size?: keyof typeof sizes): {
3
6
  modal: string;
4
7
  overlay: string;
@@ -4,8 +4,8 @@ var Page = require('../Page-cjs.js');
4
4
  require('../tslib.es6-cjs.js');
5
5
  require('react');
6
6
  require('classnames');
7
- require('@jobber/hooks');
8
7
  require('../Menu-cjs.js');
8
+ require('@jobber/hooks');
9
9
  require('framer-motion');
10
10
  require('../floating-ui.react-cjs.js');
11
11
  require('react/jsx-runtime');
@@ -2,8 +2,8 @@ export { P as Page } from '../Page-es.js';
2
2
  import '../tslib.es6-es.js';
3
3
  import 'react';
4
4
  import 'classnames';
5
- import '@jobber/hooks';
6
5
  import '../Menu-es.js';
6
+ import '@jobber/hooks';
7
7
  import 'framer-motion';
8
8
  import '../floating-ui.react-es.js';
9
9
  import 'react/jsx-runtime';
package/dist/Page-cjs.js CHANGED
@@ -3,7 +3,6 @@
3
3
  var tslib_es6 = require('./tslib.es6-cjs.js');
4
4
  var React = require('react');
5
5
  var classnames = require('classnames');
6
- var jobberHooks = require('@jobber/hooks');
7
6
  var Menu = require('./Menu-cjs.js');
8
7
  var Heading = require('./Heading-cjs.js');
9
8
  var Text = require('./Text-cjs.js');
@@ -15,7 +14,7 @@ var filterDataAttributes = require('./filterDataAttributes-cjs.js');
15
14
  var useAtlantisI18n = require('./useAtlantisI18n-cjs.js');
16
15
  require('./AtlantisContext-cjs.js');
17
16
 
18
- var styles = {"page":"BLYnKItuM3c-","fill":"n5WRRhMkoLs-","standard":"WziKEWW9nA8-","narrow":"qgGzgDyS2NY-","titleBar":"lbmoDvdtQO4-","titleRow":"k9y5NuqTcks-","actionGroup":"_7t53-bnzh98-","large":"SH0aNOLVhE8-","medium":"Lc7Z0FsBa6w-","small":"iF5IA1SYKoA-","primaryAction":"g-H7CKkX-LA-","actionButton":"RSP7jHjP-mw-","subtitle":"EqsNMrZVL-8-","spinning":"MJZVhEmx6h4-"};
17
+ var styles = {"page":"BLYnKItuM3c-","fill":"n5WRRhMkoLs-","standard":"WziKEWW9nA8-","narrow":"qgGzgDyS2NY-","titleBar":"lbmoDvdtQO4-","titleRow":"k9y5NuqTcks-","titleBarContainer":"QY-7D1tlDqY-","actionGroup":"_7t53-bnzh98-","primaryAction":"g-H7CKkX-LA-","actionButton":"RSP7jHjP-mw-","subtitle":"EqsNMrZVL-8-","spinning":"MJZVhEmx6h4-"};
19
18
 
20
19
  const PageContext = React.createContext({ width: undefined });
21
20
  function usePageContext() {
@@ -40,33 +39,28 @@ function Page(props) {
40
39
  function PageLegacy(_a) {
41
40
  var { title, titleMetaData, intro, externalIntroLinks, subtitle, children, primaryAction, secondaryAction, moreActionsMenu = [], pageStyles } = _a, rest = tslib_es6.__rest(_a, ["title", "titleMetaData", "intro", "externalIntroLinks", "subtitle", "children", "primaryAction", "secondaryAction", "moreActionsMenu", "pageStyles"]);
42
41
  const dataAttrs = filterDataAttributes.filterDataAttributes(rest);
43
- const [titleBarRef, { width: titleBarWidth = jobberHooks.Breakpoints.large }] = jobberHooks.useResizeObserver();
44
- const titleBarClasses = classnames(styles.titleBar, {
45
- [styles.small]: titleBarWidth > jobberHooks.Breakpoints.smaller,
46
- [styles.medium]: titleBarWidth > jobberHooks.Breakpoints.small,
47
- [styles.large]: titleBarWidth > jobberHooks.Breakpoints.base,
48
- });
49
42
  const showMenu = moreActionsMenu.length > 0;
50
43
  const showActionGroup = showMenu || primaryAction || secondaryAction;
51
44
  return (React.createElement("div", Object.assign({ className: pageStyles }, dataAttrs),
52
45
  React.createElement(Content.Content, null,
53
46
  React.createElement(Content.Content, null,
54
- React.createElement("div", { className: titleBarClasses, ref: titleBarRef },
55
- React.createElement("div", null,
56
- typeof title === "string" && titleMetaData ? (React.createElement("div", { className: styles.titleRow },
57
- React.createElement(Heading.Heading, { level: 1 }, title),
58
- titleMetaData)) : typeof title === "string" ? (React.createElement(Heading.Heading, { level: 1 }, title)) : (title),
59
- subtitle && (React.createElement("div", { className: styles.subtitle },
60
- React.createElement(Text.Text, { size: "large", variation: "subdued" },
61
- React.createElement(Emphasis.Emphasis, { variation: "bold" },
62
- React.createElement(Markdown.Markdown, { content: subtitle, basicUsage: true })))))),
63
- showActionGroup && (React.createElement("div", { className: styles.actionGroup },
64
- primaryAction && (React.createElement("div", { className: styles.primaryAction, ref: primaryAction.ref },
65
- React.createElement(Button.Button, Object.assign({}, getActionProps(primaryAction), { fullWidth: true })))),
66
- secondaryAction && (React.createElement("div", { className: styles.actionButton, ref: secondaryAction.ref },
67
- React.createElement(Button.Button, Object.assign({}, getActionProps(secondaryAction), { fullWidth: true, type: "secondary" })))),
68
- showMenu && (React.createElement("div", { className: styles.actionButton },
69
- React.createElement(Menu.Menu, { items: moreActionsMenu })))))),
47
+ React.createElement("div", { className: styles.titleBarContainer },
48
+ React.createElement("div", { className: styles.titleBar },
49
+ React.createElement("div", null,
50
+ typeof title === "string" && titleMetaData ? (React.createElement("div", { className: styles.titleRow },
51
+ React.createElement(Heading.Heading, { level: 1 }, title),
52
+ titleMetaData)) : typeof title === "string" ? (React.createElement(Heading.Heading, { level: 1 }, title)) : (title),
53
+ subtitle && (React.createElement("div", { className: styles.subtitle },
54
+ React.createElement(Text.Text, { size: "large", variation: "subdued" },
55
+ React.createElement(Emphasis.Emphasis, { variation: "bold" },
56
+ React.createElement(Markdown.Markdown, { content: subtitle, basicUsage: true })))))),
57
+ showActionGroup && (React.createElement("div", { className: styles.actionGroup },
58
+ primaryAction && (React.createElement("div", { className: styles.primaryAction, ref: primaryAction.ref },
59
+ React.createElement(Button.Button, Object.assign({}, getActionProps(primaryAction), { fullWidth: true })))),
60
+ secondaryAction && (React.createElement("div", { className: styles.actionButton, ref: secondaryAction.ref },
61
+ React.createElement(Button.Button, Object.assign({}, getActionProps(secondaryAction), { fullWidth: true, type: "secondary" })))),
62
+ showMenu && (React.createElement("div", { className: styles.actionButton },
63
+ React.createElement(Menu.Menu, { items: moreActionsMenu }))))))),
70
64
  intro && (React.createElement(Text.Text, { size: "large" },
71
65
  React.createElement(Markdown.Markdown, { content: intro, basicUsage: true, externalLink: externalIntroLinks })))),
72
66
  React.createElement(Content.Content, null, children))));
@@ -79,13 +73,8 @@ function PageLegacy(_a) {
79
73
  function PageHeader(_a) {
80
74
  var { children } = _a, rest = tslib_es6.__rest(_a, ["children"]);
81
75
  const dataAttrs = filterDataAttributes.filterDataAttributes(rest);
82
- const [titleBarRef, { width: titleBarWidth = jobberHooks.Breakpoints.large }] = jobberHooks.useResizeObserver();
83
- const titleBarClasses = classnames(styles.titleBar, {
84
- [styles.small]: titleBarWidth > jobberHooks.Breakpoints.smaller,
85
- [styles.medium]: titleBarWidth > jobberHooks.Breakpoints.small,
86
- [styles.large]: titleBarWidth > jobberHooks.Breakpoints.base,
87
- });
88
- return (React.createElement("div", Object.assign({ className: titleBarClasses, ref: titleBarRef }, dataAttrs), children));
76
+ return (React.createElement("div", { className: styles.titleBarContainer },
77
+ React.createElement("div", Object.assign({ className: styles.titleBar }, dataAttrs), children)));
89
78
  }
90
79
  /** Wraps the title area (title, subtitle) inside `Page.Header`. Use when the header contains more than one content element to keep them stacked vertically. */
91
80
  function PageHeaderContent(_a) {
package/dist/Page-es.js CHANGED
@@ -1,7 +1,6 @@
1
1
  import { _ as __rest } from './tslib.es6-es.js';
2
2
  import React__default, { createContext, useContext } from 'react';
3
3
  import classnames from 'classnames';
4
- import { useResizeObserver, Breakpoints } from '@jobber/hooks';
5
4
  import { M as Menu, m as menuMessages } from './Menu-es.js';
6
5
  import { H as Heading } from './Heading-es.js';
7
6
  import { T as Text } from './Text-es.js';
@@ -13,7 +12,7 @@ import { f as filterDataAttributes } from './filterDataAttributes-es.js';
13
12
  import { u as useAtlantisI18n } from './useAtlantisI18n-es.js';
14
13
  import './AtlantisContext-es.js';
15
14
 
16
- var styles = {"page":"BLYnKItuM3c-","fill":"n5WRRhMkoLs-","standard":"WziKEWW9nA8-","narrow":"qgGzgDyS2NY-","titleBar":"lbmoDvdtQO4-","titleRow":"k9y5NuqTcks-","actionGroup":"_7t53-bnzh98-","large":"SH0aNOLVhE8-","medium":"Lc7Z0FsBa6w-","small":"iF5IA1SYKoA-","primaryAction":"g-H7CKkX-LA-","actionButton":"RSP7jHjP-mw-","subtitle":"EqsNMrZVL-8-","spinning":"MJZVhEmx6h4-"};
15
+ var styles = {"page":"BLYnKItuM3c-","fill":"n5WRRhMkoLs-","standard":"WziKEWW9nA8-","narrow":"qgGzgDyS2NY-","titleBar":"lbmoDvdtQO4-","titleRow":"k9y5NuqTcks-","titleBarContainer":"QY-7D1tlDqY-","actionGroup":"_7t53-bnzh98-","primaryAction":"g-H7CKkX-LA-","actionButton":"RSP7jHjP-mw-","subtitle":"EqsNMrZVL-8-","spinning":"MJZVhEmx6h4-"};
17
16
 
18
17
  const PageContext = createContext({ width: undefined });
19
18
  function usePageContext() {
@@ -38,33 +37,28 @@ function Page(props) {
38
37
  function PageLegacy(_a) {
39
38
  var { title, titleMetaData, intro, externalIntroLinks, subtitle, children, primaryAction, secondaryAction, moreActionsMenu = [], pageStyles } = _a, rest = __rest(_a, ["title", "titleMetaData", "intro", "externalIntroLinks", "subtitle", "children", "primaryAction", "secondaryAction", "moreActionsMenu", "pageStyles"]);
40
39
  const dataAttrs = filterDataAttributes(rest);
41
- const [titleBarRef, { width: titleBarWidth = Breakpoints.large }] = useResizeObserver();
42
- const titleBarClasses = classnames(styles.titleBar, {
43
- [styles.small]: titleBarWidth > Breakpoints.smaller,
44
- [styles.medium]: titleBarWidth > Breakpoints.small,
45
- [styles.large]: titleBarWidth > Breakpoints.base,
46
- });
47
40
  const showMenu = moreActionsMenu.length > 0;
48
41
  const showActionGroup = showMenu || primaryAction || secondaryAction;
49
42
  return (React__default.createElement("div", Object.assign({ className: pageStyles }, dataAttrs),
50
43
  React__default.createElement(Content, null,
51
44
  React__default.createElement(Content, null,
52
- React__default.createElement("div", { className: titleBarClasses, ref: titleBarRef },
53
- React__default.createElement("div", null,
54
- typeof title === "string" && titleMetaData ? (React__default.createElement("div", { className: styles.titleRow },
55
- React__default.createElement(Heading, { level: 1 }, title),
56
- titleMetaData)) : typeof title === "string" ? (React__default.createElement(Heading, { level: 1 }, title)) : (title),
57
- subtitle && (React__default.createElement("div", { className: styles.subtitle },
58
- React__default.createElement(Text, { size: "large", variation: "subdued" },
59
- React__default.createElement(Emphasis, { variation: "bold" },
60
- React__default.createElement(Markdown, { content: subtitle, basicUsage: true })))))),
61
- showActionGroup && (React__default.createElement("div", { className: styles.actionGroup },
62
- primaryAction && (React__default.createElement("div", { className: styles.primaryAction, ref: primaryAction.ref },
63
- React__default.createElement(Button, Object.assign({}, getActionProps(primaryAction), { fullWidth: true })))),
64
- secondaryAction && (React__default.createElement("div", { className: styles.actionButton, ref: secondaryAction.ref },
65
- React__default.createElement(Button, Object.assign({}, getActionProps(secondaryAction), { fullWidth: true, type: "secondary" })))),
66
- showMenu && (React__default.createElement("div", { className: styles.actionButton },
67
- React__default.createElement(Menu, { items: moreActionsMenu })))))),
45
+ React__default.createElement("div", { className: styles.titleBarContainer },
46
+ React__default.createElement("div", { className: styles.titleBar },
47
+ React__default.createElement("div", null,
48
+ typeof title === "string" && titleMetaData ? (React__default.createElement("div", { className: styles.titleRow },
49
+ React__default.createElement(Heading, { level: 1 }, title),
50
+ titleMetaData)) : typeof title === "string" ? (React__default.createElement(Heading, { level: 1 }, title)) : (title),
51
+ subtitle && (React__default.createElement("div", { className: styles.subtitle },
52
+ React__default.createElement(Text, { size: "large", variation: "subdued" },
53
+ React__default.createElement(Emphasis, { variation: "bold" },
54
+ React__default.createElement(Markdown, { content: subtitle, basicUsage: true })))))),
55
+ showActionGroup && (React__default.createElement("div", { className: styles.actionGroup },
56
+ primaryAction && (React__default.createElement("div", { className: styles.primaryAction, ref: primaryAction.ref },
57
+ React__default.createElement(Button, Object.assign({}, getActionProps(primaryAction), { fullWidth: true })))),
58
+ secondaryAction && (React__default.createElement("div", { className: styles.actionButton, ref: secondaryAction.ref },
59
+ React__default.createElement(Button, Object.assign({}, getActionProps(secondaryAction), { fullWidth: true, type: "secondary" })))),
60
+ showMenu && (React__default.createElement("div", { className: styles.actionButton },
61
+ React__default.createElement(Menu, { items: moreActionsMenu }))))))),
68
62
  intro && (React__default.createElement(Text, { size: "large" },
69
63
  React__default.createElement(Markdown, { content: intro, basicUsage: true, externalLink: externalIntroLinks })))),
70
64
  React__default.createElement(Content, null, children))));
@@ -77,13 +71,8 @@ function PageLegacy(_a) {
77
71
  function PageHeader(_a) {
78
72
  var { children } = _a, rest = __rest(_a, ["children"]);
79
73
  const dataAttrs = filterDataAttributes(rest);
80
- const [titleBarRef, { width: titleBarWidth = Breakpoints.large }] = useResizeObserver();
81
- const titleBarClasses = classnames(styles.titleBar, {
82
- [styles.small]: titleBarWidth > Breakpoints.smaller,
83
- [styles.medium]: titleBarWidth > Breakpoints.small,
84
- [styles.large]: titleBarWidth > Breakpoints.base,
85
- });
86
- return (React__default.createElement("div", Object.assign({ className: titleBarClasses, ref: titleBarRef }, dataAttrs), children));
74
+ return (React__default.createElement("div", { className: styles.titleBarContainer },
75
+ React__default.createElement("div", Object.assign({ className: styles.titleBar }, dataAttrs), children)));
87
76
  }
88
77
  /** Wraps the title area (title, subtitle) inside `Page.Header`. Use when the header contains more than one content element to keep them stacked vertically. */
89
78
  function PageHeaderContent(_a) {
@@ -53,8 +53,8 @@ function resolveComposableTriggerRender({ children, render, }) {
53
53
  /**
54
54
  * Resolves the dismiss element for `Dialog.Close`, mirroring
55
55
  * `resolveComposableTriggerRender` so a custom render works in both shells.
56
- * Falls back to the subtle "cross" `ButtonDismiss` when neither `render` nor
57
- * `children` are supplied. An Atlantis `<Button>`/`<ButtonDismiss>` passed via
56
+ * Falls back to a subtle tertiary `Button` with a `cross` icon when neither
57
+ * `render` nor `children` are supplied. An Atlantis `<Button>` passed via
58
58
  * `render` or `children` is adapted; any other valid element is used as-is.
59
59
  */
60
60
  function resolveComposableCloseRender({ children, render, }) {
@@ -51,8 +51,8 @@ function resolveComposableTriggerRender({ children, render, }) {
51
51
  /**
52
52
  * Resolves the dismiss element for `Dialog.Close`, mirroring
53
53
  * `resolveComposableTriggerRender` so a custom render works in both shells.
54
- * Falls back to the subtle "cross" `ButtonDismiss` when neither `render` nor
55
- * `children` are supplied. An Atlantis `<Button>`/`<ButtonDismiss>` passed via
54
+ * Falls back to a subtle tertiary `Button` with a `cross` icon when neither
55
+ * `render` nor `children` are supplied. An Atlantis `<Button>` passed via
56
56
  * `render` or `children` is adapted; any other valid element is used as-is.
57
57
  */
58
58
  function resolveComposableCloseRender({ children, render, }) {
@@ -388,7 +388,7 @@ A key distinction between subtle buttons and the other variations is that the
388
388
  primary/secondary/tertiary scale is styled differently, but the conceptual
389
389
  hierarchy is the same. Notably, the tertiary subtle button has a transparent
390
390
  background, allowing it to be *extra* subtle when placed overtop
391
- `surface--background` elements such as a Modal header.
391
+ `surface--background` elements such as a Dialog header.
392
392
 
393
393
  ```tsx
394
394
  import React from "react";
@@ -1,7 +1,7 @@
1
1
  # Button Dismiss
2
2
 
3
3
  This private component is used as a dismissal button for public components, such
4
- as Modal and Popover.
4
+ as Popover and Drawer.
5
5
 
6
6
  ## Design & usage guidelines
7
7
 
@@ -156,7 +156,7 @@ application.
156
156
  #### Overlay
157
157
 
158
158
  Use to mask an area of the interface to promote focus to a foreground action,
159
- such as a [Modal](../Modal/Modal.md)'s appearance. Overlay includes built-in
159
+ such as a [Dialog](../Dialog/Dialog.md)'s appearance. Overlay includes built-in
160
160
  opacity values.
161
161
 
162
162
  #### Overlay--Dimmed
@@ -102,7 +102,7 @@ language should be direct and honest about the impact without being alarming.
102
102
  * To present non-blocking, contextual, text-only content, use a
103
103
  [Tooltip](../Tooltip/Tooltip.md)
104
104
  * To simply present information for users to view, edit, or for a temporary
105
- change of context, use a regular [Modal](../Modal/Modal.md)
105
+ change of context, use a regular [Dialog](../Dialog/Dialog.md)
106
106
 
107
107
 
108
108
  ## Props
@@ -295,12 +295,12 @@ control, omit `open`/`onRequestClose` and let the dialog manage itself.
295
295
 
296
296
  `Dialog.Trigger` and `Dialog.Close` accept Atlantis-style content and can render
297
297
  a default control, composed Atlantis `Button` content, or a custom element via
298
- `render`. An Atlantis `<Button>`/`<ButtonDismiss>` is adapted automatically; any
299
- other valid element is used as-is. When `render` is a function, it receives the
300
- Base UI props so the element stays wired to open/close the dialog.
298
+ `render`. An Atlantis `<Button>` is adapted automatically; any other valid
299
+ element is used as-is. When `render` is a function, it receives the Base UI
300
+ props so the element stays wired to open/close the dialog.
301
301
 
302
302
  ```tsx
303
- {/* default primary Button trigger / default ButtonDismiss close */}
303
+ {/* default primary Button trigger / default close Button */}
304
304
  <Dialog.Trigger>Open</Dialog.Trigger>
305
305
  <Dialog.Close />
306
306
 
@@ -951,7 +951,7 @@ verify the result rather than expecting an exact match.
951
951
  | `children` | `ReactNode` | No | — | Optional content for the dismiss control. An Atlantis `<Button>` is adapted automatically; any other valid element is... |
952
952
  | `className` | `string` | No | — | Class name applied to the part's root element. |
953
953
  | `nativeButton` | `boolean` | No | `true` | Whether the component renders a native `<button>` element when replacing it via the `render` prop. Set to `false` if ... |
954
- | `render` | `DialogCloseRender` | No | — | Renders a custom dismiss element in place of the default `ButtonDismiss` Pass an element or a function that receives ... |
954
+ | `render` | `DialogCloseRender` | No | — | Renders a custom dismiss element in place of the default close button. Pass an element or a function that receives th... |
955
955
  | `style` | `CSSProperties` | No | — | Inline styles applied to the part's root element. |
956
956
 
957
957
  #### Dialog.Content
@@ -9,7 +9,7 @@ Use [SideDrawer](../SideDrawer/SideDrawer.md) if you need to overlay the page's
9
9
  content and block user interaction with the page, while still maintaining
10
10
  visibilty of the page's primary contents.
11
11
 
12
- Use [Modal](../Modal/Modal.md) if you need to overlay the page's content and
12
+ Use [Dialog](../Dialog/Dialog.md) if you need to overlay the page's content and
13
13
  block user interaction with the page, and do not need the user to have visibilty
14
14
  of the page's primary contents.
15
15
 
@@ -1,5 +1,10 @@
1
1
  # Modal
2
2
 
3
+ > **WARNING:** This component is deprecated. Use [Dialog](../Dialog/Dialog.md) instead for new
4
+ > work — see [migrating to
5
+ > Dialog](/components/Dialog/implement#component-view-migrating-to-dialog).
6
+ > `Modal` continues to work unchanged for existing call sites.
7
+
3
8
  Modals are overlays that allow users to view, edit, or show informations that
4
9
  doesn't require a page to be built. It also prevent users from interacting with
5
10
  the rest of the application until a specific action is taken.
@@ -10,7 +10,7 @@ Use [Drawer](../Drawer/Drawer.md) if you need to allow users to view
10
10
  supplementary content while still allowing users to interact with the main
11
11
  contents of the page.
12
12
 
13
- Use [Modal](../Modal/Modal.md) if you need to overlay the page's content and
13
+ Use [Dialog](../Dialog/Dialog.md) if you need to overlay the page's content and
14
14
  block user interaction with the page, and do not need the user to have visibilty
15
15
  of the page's primary contents.
16
16
 
@@ -48,7 +48,7 @@ form elements.
48
48
  ### Large
49
49
 
50
50
  Use `large` spacing for higher-level "parent" containers.
51
- [Modal](../Modal/Modal.md) uses `large` spacing in its header and around the
51
+ [Dialog](../Dialog/Dialog.md) uses `large` spacing in its header and around the
52
52
  edges to give itself a bit more prominence as a standalone view, in a similar
53
53
  manner to [Page](../Page/Page.md).
54
54
 
@@ -43,6 +43,35 @@ More complex full-page scaffolding can be found on the [Scaffolding](../scaffold
43
43
  </Stack>
44
44
  ```
45
45
 
46
+ ```tsx
47
+ <Stack>
48
+ <Heading level={2}>Stack Dialog Layouts</Heading>
49
+ <Text>Stacks are a great way to layout content in a dialog format. They are responsive and easy to read.</Text>
50
+ <Dialog>
51
+ <Dialog.Trigger>
52
+ <Button label="Open Dialog" />
53
+ </Dialog.Trigger>
54
+ <Dialog.Content>
55
+ <Dialog.Header>
56
+ <Dialog.Title>Dialog Layout</Dialog.Title>
57
+ <Dialog.Close />
58
+ </Dialog.Header>
59
+ <Dialog.Body>
60
+ <Stack>
61
+ <Text>A dialog with a header, body text, and footer</Text>
62
+ <Text>And they're all stacked vertically with equal spacing</Text>
63
+ </Stack>
64
+ </Dialog.Body>
65
+ <Dialog.Footer>
66
+ <Dialog.Actions
67
+ primary={<Dialog.Close render={<Button label="Close the Dialog" />} />}
68
+ />
69
+ </Dialog.Footer>
70
+ </Dialog.Content>
71
+ </Dialog>
72
+ </Stack>
73
+ ```
74
+
46
75
  ```tsx
47
76
  <Stack>
48
77
  <Heading level={1}>Cluster</Heading>
@@ -26,7 +26,7 @@ Most settings can be managed with the
26
26
  [FeatureSwitch](../FeatureSwitch/FeatureSwitch.md) component, which allows:
27
27
 
28
28
  * turning functionality on and off
29
- * editing aspects of the feature via a [Modal](../Modal/Modal.md)
29
+ * editing aspects of the feature via a [Dialog](../Dialog/Dialog.md)
30
30
  * if the page supports it, live updates to the setting
31
31
 
32
32
  ### Grouping settings
@@ -37,7 +37,7 @@ Use a [Card](../Card/Card.md) to group related settings together.
37
37
 
38
38
  The [FeatureSwitch](../FeatureSwitch/FeatureSwitch.md) component is a good starting
39
39
  point for most settings. If the setting is more complex, you can trigger a
40
- [Modal](../Modal/Modal.md) to edit the setting.
40
+ [Dialog](../Dialog/Dialog.md) to edit the setting.
41
41
 
42
42
  For cases where you don't need the full functionality of the `FeatureSwitch`,
43
43
  you can either opt out of props like `onSwitch` or `onEdit`, or compose a layout
@@ -49,7 +49,7 @@ of the pieces you do need.
49
49
 
50
50
  * [FeatureSwitch](../FeatureSwitch/FeatureSwitch.md)
51
51
  * [Card](../Card/Card.md)
52
- * [Modal](../Modal/Modal.md)
52
+ * [Dialog](../Dialog/Dialog.md)
53
53
  * [Switch](../Switch/Switch.md)
54
54
 
55
55
  ## Principles
@@ -5,22 +5,13 @@ before generating any Atlantis code.
5
5
 
6
6
  ***
7
7
 
8
- ## Always use version= for migrated components
9
-
10
- The following components have a v2 implementation. **Always pass
11
- `version={2}`**. Never generate v1 usage for these components — v1 is
12
- deprecated.
13
-
14
- | Component | Import | v2 prop |
15
- | --------- | -------------------------------------------------- | ------------------------------------------------- |
16
- | Modal | `import { Modal } from "@jobber/components/Modal"` | `version={2}` — uses `Modal.Provider` composition |
17
-
18
8
  ## Deprecated components — do not use
19
9
 
20
- | Deprecated | Replacement | Notes |
21
- | --------------------- | ------------------------------------------------------ | ---------------------------------------- |
22
- | `MultiSelect` | `Autocomplete` with `multiple` prop, or `FilterPicker` | Fully deprecated, no longer supported. |
23
- | `Chips` (dismissible) | `Autocomplete` with `multiple` prop | Dismissible Chips variant is deprecated. |
10
+ | Deprecated | Replacement | Notes |
11
+ | --------------------- | ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
12
+ | `Modal` | `Dialog` | Includes `Modal.Provider` and the `Modal.*` subcomponents. See [migrating to Dialog](/components/Dialog/implement#component-view-migrating-to-dialog). |
13
+ | `MultiSelect` | `Autocomplete` with `multiple` prop, or `FilterPicker` | Fully deprecated, no longer supported. |
14
+ | `Chips` (dismissible) | `Autocomplete` with `multiple` prop | Dismissible Chips variant is deprecated. |
24
15
 
25
16
  ### Deprecated props on still-supported components
26
17
 
@@ -74,7 +65,7 @@ parent reads its compound children to wire up state, accessibility, and styling.
74
65
 
75
66
  | Component | Subcomponents | Usage |
76
67
  | ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
77
- | `Modal` v2 | `Modal.Provider`, `Modal.Activator`, `Modal.Content`, `Modal.Header`, `Modal.Actions` | Wrap with `Modal.Provider`. `Modal.Header` and `Modal.Actions` must be **direct children** of `Modal.Content` for sticky behavior to work. Use `Modal.Activator` to control focus return when the trigger element unmounts. |
68
+ | `Dialog` | `Dialog.Trigger`, `Dialog.Content`, `Dialog.Header`, `Dialog.Title`, `Dialog.Close`, `Dialog.Body`, `Dialog.Footer`, `Dialog.Actions`, `Dialog.ScrollArea` | `Dialog` > `Dialog.Trigger` + `Dialog.Content` containing `Dialog.Header` (with `Dialog.Title` and `Dialog.Close`), `Dialog.Body`, and `Dialog.Footer` (wrapping `Dialog.Actions`). `Dialog.Header` and `Dialog.Footer` are layout-only slots. Use `finalFocus` to control focus return when the trigger unmounts. |
78
69
  | `Banner` | `Banner.Provider`, `Banner.Content`, `Banner.Icon`, `Banner.DismissButton`, `Banner.Action` | Either the simple `<Banner type="...">children</Banner>` form, or the Provider form: `Banner.Provider` > `Banner.Content` (+ optional `Banner.Icon` / `Banner.Action` / `Banner.DismissButton`). |
79
70
  | `Card` | `Card.Header`, `Card.Body` | `Card` > `Card.Header` + `Card.Body`. The legacy `header` string/element prop still works for simple cases. Use composition for any header that needs richer markup. |
80
71
  | `FilterPicker` | `FilterPicker.Activator`, `FilterPicker.Option`, `FilterPicker.Action` | `FilterPicker` > optional `FilterPicker.Activator`, one or more `FilterPicker.Option`, optional `FilterPicker.Action`. Omitting `FilterPicker.Activator` renders the default activator. |
@@ -100,10 +91,9 @@ parent reads its compound children to wire up state, accessibility, and styling.
100
91
  returns a translated label per state (e.g. `"Next page"`, `"Previous page"`).
101
92
  * **`RadioGroup` options whose `children` aren't text** must provide
102
93
  `aria-label` on the option so it has an accessible name.
103
- * **`Modal` v2 without a `Modal.Header` title** must set either
104
- `modalLabelledBy` (id of an existing element) or `ariaLabel` on the modal so
105
- the dialog has an accessible name. A `Modal.Header` title takes precedence
106
- over `ariaLabel` when both are provided.
94
+ * **`Dialog` must include a `Dialog.Title`** so the dialog has an accessible
95
+ name. `Dialog.Title` is wired to `aria-labelledby` automatically, and
96
+ `Dialog.Body` to `aria-describedby` — do not wire these by hand.
107
97
 
108
98
  ## UNSAFE\_ props
109
99
 
@@ -123,12 +113,14 @@ prefer design tokens inside any custom styles you do write. See
123
113
  * If using two cards next to each other horizontally, ensure they have a gap
124
114
  between them
125
115
 
126
- ### Modal
116
+ ### Dialog
127
117
 
128
- * When using a modal as part of an app, always wrap the inner content of the
129
- modal in the Content component, this is what gives it the padding the form
130
- needs from the edges of the modal.
131
- * Content will also provide the gap necessary between fields
118
+ * Use `Dialog` for overlay content. `Modal` is deprecated — do not generate new
119
+ `Modal` or `Modal.Provider` usage.
120
+ * Put the dialog's inner content in `Dialog.Body`, which supplies the padding
121
+ from the edges of the dialog and the gap between fields.
122
+ * Put action buttons in a `Dialog.Actions` inside a `Dialog.Footer` rather than
123
+ placing bare buttons in the body.
132
124
 
133
125
  ### Color
134
126
 
package/dist/styles.css CHANGED
@@ -14749,6 +14749,16 @@ input.oOrjwubmsVA- {
14749
14749
  margin-bottom: 0;
14750
14750
  }
14751
14751
 
14752
+ /*
14753
+ * Wrapper because a container query can't style the container itself, and
14754
+ * containment on .page would capture fixed/absolute positioning of consumer
14755
+ * content in the page body.
14756
+ */
14757
+ .QY-7D1tlDqY- {
14758
+ container-name: page-titlebar;
14759
+ container-type: inline-size;
14760
+ }
14761
+
14752
14762
  .lbmoDvdtQO4- > ._7t53-bnzh98- {
14753
14763
  -ms-flex: 1 0 auto;
14754
14764
  flex: 1 0 auto;
@@ -14756,36 +14766,6 @@ input.oOrjwubmsVA- {
14756
14766
  align-self: baseline;
14757
14767
  }
14758
14768
 
14759
- .lbmoDvdtQO4-.SH0aNOLVhE8-,
14760
- .lbmoDvdtQO4-.Lc7Z0FsBa6w- {
14761
- display: -ms-flexbox;
14762
- display: flex;
14763
- -ms-flex-wrap: wrap;
14764
- flex-wrap: wrap;
14765
- -ms-flex-pack: justify;
14766
- justify-content: space-between;
14767
- }
14768
-
14769
- .lbmoDvdtQO4-.iF5IA1SYKoA- ._7t53-bnzh98- {
14770
- display: -ms-flexbox;
14771
- display: flex;
14772
- -ms-flex-wrap: wrap;
14773
- flex-wrap: wrap;
14774
- -ms-flex-pack: justify;
14775
- justify-content: space-between;
14776
- }
14777
-
14778
- .lbmoDvdtQO4-.Lc7Z0FsBa6w- ._7t53-bnzh98-,
14779
- .lbmoDvdtQO4-.SH0aNOLVhE8- ._7t53-bnzh98- {
14780
- -ms-flex-wrap: nowrap;
14781
- flex-wrap: nowrap;
14782
- }
14783
-
14784
- .lbmoDvdtQO4-.Lc7Z0FsBa6w- ._7t53-bnzh98- {
14785
- -ms-flex-pack: end;
14786
- justify-content: flex-end;
14787
- }
14788
-
14789
14769
  .g-H7CKkX-LA- {
14790
14770
  -ms-flex: 0 0 100%;
14791
14771
  flex: 0 0 100%;
@@ -14804,30 +14784,76 @@ input.oOrjwubmsVA- {
14804
14784
  width: 100%;
14805
14785
  }
14806
14786
 
14807
- .lbmoDvdtQO4-.iF5IA1SYKoA- .RSP7jHjP-mw- {
14808
- margin-top: 0;
14787
+ .lbmoDvdtQO4- .EqsNMrZVL-8- {
14788
+ margin-bottom: 16px;
14789
+ margin-bottom: var(--space-base);
14809
14790
  }
14810
14791
 
14811
- .lbmoDvdtQO4-.Lc7Z0FsBa6w- .g-H7CKkX-LA-,
14812
- .lbmoDvdtQO4-.Lc7Z0FsBa6w- .RSP7jHjP-mw- {
14813
- margin: 0;
14814
- -ms-flex: 0 auto;
14815
- flex: 0 auto;
14792
+ /*
14793
+ * The wrapper's containment traps trailing title/subtitle margins that used
14794
+ * to collapse out of the (block, below 640px) titlebar into the following
14795
+ * Content spacing; cancel them to keep that spacing unchanged.
14796
+ */
14797
+ @container page-titlebar (width < 640px) {
14798
+ .lbmoDvdtQO4- > :last-child,
14799
+ .lbmoDvdtQO4- > div:last-child > :last-child {
14800
+ margin-bottom: 0;
14801
+ }
14816
14802
  }
14817
14803
 
14818
- .lbmoDvdtQO4-.Lc7Z0FsBa6w- .RSP7jHjP-mw- {
14819
- margin-left: 8px;
14820
- margin-left: var(--space-small);
14821
- }
14804
+ /*
14805
+ * 500/640 are the effective switch points of the replaced useResizeObserver
14806
+ * implementation (it snapped widths to Breakpoints values before comparing).
14807
+ * Hardcoded because @container accepts neither custom media nor var().
14808
+ */
14809
+ @container page-titlebar (min-width: 500px) {
14810
+ .lbmoDvdtQO4- ._7t53-bnzh98- {
14811
+ display: -ms-flexbox;
14812
+ display: flex;
14813
+ -ms-flex-wrap: wrap;
14814
+ flex-wrap: wrap;
14815
+ -ms-flex-pack: justify;
14816
+ justify-content: space-between;
14817
+ }
14822
14818
 
14823
- .lbmoDvdtQO4-.iF5IA1SYKoA- .RSP7jHjP-mw- + .RSP7jHjP-mw- {
14824
- margin-left: 8px;
14825
- margin-left: var(--space-small);
14819
+ .lbmoDvdtQO4- .RSP7jHjP-mw- {
14820
+ margin-top: 0;
14821
+ }
14822
+
14823
+ .lbmoDvdtQO4- .RSP7jHjP-mw- + .RSP7jHjP-mw- {
14824
+ margin-left: 8px;
14825
+ margin-left: var(--space-small);
14826
+ }
14826
14827
  }
14827
14828
 
14828
- .lbmoDvdtQO4- .EqsNMrZVL-8- {
14829
- margin-bottom: 16px;
14830
- margin-bottom: var(--space-base);
14829
+ @container page-titlebar (min-width: 640px) {
14830
+ .lbmoDvdtQO4- {
14831
+ display: -ms-flexbox;
14832
+ display: flex;
14833
+ -ms-flex-wrap: wrap;
14834
+ flex-wrap: wrap;
14835
+ -ms-flex-pack: justify;
14836
+ justify-content: space-between;
14837
+ }
14838
+
14839
+ .lbmoDvdtQO4- ._7t53-bnzh98- {
14840
+ -ms-flex-wrap: nowrap;
14841
+ flex-wrap: nowrap;
14842
+ -ms-flex-pack: end;
14843
+ justify-content: flex-end;
14844
+ }
14845
+
14846
+ .lbmoDvdtQO4- .g-H7CKkX-LA-,
14847
+ .lbmoDvdtQO4- .RSP7jHjP-mw- {
14848
+ margin: 0;
14849
+ -ms-flex: 0 auto;
14850
+ flex: 0 auto;
14851
+ }
14852
+
14853
+ .lbmoDvdtQO4- .RSP7jHjP-mw- {
14854
+ margin-left: 8px;
14855
+ margin-left: var(--space-small);
14856
+ }
14831
14857
  }
14832
14858
 
14833
14859
  @-webkit-keyframes MJZVhEmx6h4- {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jobber/components",
3
- "version": "9.11.0",
3
+ "version": "9.12.1",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -506,13 +506,11 @@
506
506
  "@storybook/addon-mcp": "^0.4.2",
507
507
  "@storybook/addon-vitest": "10.3.5",
508
508
  "@storybook/react-vite": "10.3.5",
509
- "@types/glob": "^7.1.1",
510
509
  "@types/node": "^22.10.1",
511
510
  "@vitest/browser-playwright": "^4.1.2",
512
511
  "@vitest/coverage-v8": "^4.1.2",
513
512
  "autoprefixer": "^10.4.0",
514
513
  "copyfiles": "^2.4.1",
515
- "glob": "^7.1.4",
516
514
  "jsdom-testing-mocks": "^1.9.0",
517
515
  "playwright": "1.59.1",
518
516
  "postcss": "^8.5.25",
@@ -549,5 +547,5 @@
549
547
  "> 1%",
550
548
  "IE 10"
551
549
  ],
552
- "gitHead": "fa163fb08329a1c705f4c545a7082ad585e9a5a4"
550
+ "gitHead": "2631b0995f78204f24e3175185951d9b0f1ac4bc"
553
551
  }