cozy-ui 53.0.0 → 54.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/package.json +1 -1
  3. package/react/ContactsListModal/index.jsx +5 -1
  4. package/react/CozyDialogs/ConfirmDialog.jsx +21 -7
  5. package/react/CozyDialogs/Dialog.jsx +16 -8
  6. package/react/CozyDialogs/DialogBackButton.jsx +18 -11
  7. package/react/CozyDialogs/DialogCloseButton.jsx +6 -1
  8. package/react/CozyDialogs/FixedActionsDialog.jsx +20 -7
  9. package/react/CozyDialogs/FixedDialog.jsx +16 -8
  10. package/react/CozyDialogs/IllustrationDialog.jsx +18 -5
  11. package/react/CozyDialogs/Readme.md +23 -0
  12. package/react/CozyDialogs/dialogPropTypes.js +2 -0
  13. package/react/CozyDialogs/locales.js +6 -3
  14. package/react/CozyDialogs/styles.styl +11 -2
  15. package/react/CozyDialogs/testing.js +14 -0
  16. package/react/CozyDialogs/testing.spec.jsx +88 -4
  17. package/react/CozyDialogs/useCozyDialog.js +13 -1
  18. package/react/MuiCozyTheme/theme.jsx +38 -19
  19. package/transpiled/react/ContactsListModal/index.js +4 -1
  20. package/transpiled/react/CozyDialogs/ConfirmDialog.js +16 -7
  21. package/transpiled/react/CozyDialogs/Dialog.js +9 -7
  22. package/transpiled/react/CozyDialogs/DialogBackButton.js +23 -15
  23. package/transpiled/react/CozyDialogs/DialogCloseButton.js +4 -2
  24. package/transpiled/react/CozyDialogs/FixedActionsDialog.js +16 -7
  25. package/transpiled/react/CozyDialogs/FixedDialog.js +9 -7
  26. package/transpiled/react/CozyDialogs/IllustrationDialog.js +14 -7
  27. package/transpiled/react/CozyDialogs/dialogPropTypes.js +2 -0
  28. package/transpiled/react/CozyDialogs/locales.js +6 -3
  29. package/transpiled/react/CozyDialogs/testing.js +12 -0
  30. package/transpiled/react/CozyDialogs/useCozyDialog.js +14 -2
  31. package/transpiled/react/MuiCozyTheme/theme.js +37 -27
  32. package/transpiled/react/stylesheet.css +1 -1
package/CHANGELOG.md CHANGED
@@ -1,3 +1,40 @@
1
+ # [54.0.0](https://github.com/cozy/cozy-ui/compare/v53.0.0...v54.0.0) (2021-09-28)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * Add missing config properties to inverted theme ([85c9026](https://github.com/cozy/cozy-ui/commit/85c9026))
7
+ * Correctly override DialogTitle's className in `ContactsListModal` ([69e0fa6](https://github.com/cozy/cozy-ui/commit/69e0fa6))
8
+
9
+
10
+ ### Features
11
+
12
+ * Add `isFluidTitle` prop to `useCozyDialog` ([2d4f8b7](https://github.com/cozy/cozy-ui/commit/2d4f8b7))
13
+ * Add plain background to dialogs buttons ([82a4b78](https://github.com/cozy/cozy-ui/commit/82a4b78))
14
+ * Add tests for Dialog ([ec468db](https://github.com/cozy/cozy-ui/commit/ec468db))
15
+ * Handle `onBack` prop on CozyDialogs ([eb86578](https://github.com/cozy/cozy-ui/commit/eb86578))
16
+ * Rework CozyDialogs style to fit latest UI specs ([8ff3766](https://github.com/cozy/cozy-ui/commit/8ff3766))
17
+ * Set DialogBackButton's position to absolute ([98fe795](https://github.com/cozy/cozy-ui/commit/98fe795))
18
+
19
+
20
+ ### BREAKING CHANGES
21
+
22
+ * `<DialogBackButton>` is now using absolute positioning. To prevent
23
+ `<DialogTitle>` to overlap with this button, `useCozyDialog()` handles
24
+ its positioning with `dialogTitleProps`.
25
+ If you use `cozy-ui/transpiled/react/Dialog` with `useCozyDialog()` but
26
+ without `<DialogBackButton>` then you may be impacted as a left margin
27
+ will be applied on `<DialogTitle>` on mobile, which would leave a blank
28
+ space if no `<DialogBackButton>` is present.
29
+ In this case, please add `disableTitleAutoPadding` to
30
+ `useCozyDialog()` props. Then title will take all available space and
31
+ you will be able to handle its positionning by yourself.
32
+ ```js
33
+ const {
34
+ dialogTitleProps
35
+ } = useCozyDialog({ ...props, disableTitleAutoPadding: true })
36
+ ```
37
+
1
38
  # [53.0.0](https://github.com/cozy/cozy-ui/compare/v52.0.1...v53.0.0) (2021-09-28)
2
39
 
3
40
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cozy-ui",
3
- "version": "53.0.0",
3
+ "version": "54.0.0",
4
4
  "description": "Cozy apps UI SDK",
5
5
  "main": "./index.js",
6
6
  "bin": {
@@ -27,6 +27,8 @@ import Icon from '../Icon'
27
27
  import AddContactButton from './AddContactButton'
28
28
  import EmptyMessage from './EmptyMessage'
29
29
 
30
+ import cx from 'classnames'
31
+
30
32
  const thirtySeconds = 30000
31
33
  const olderThan30s = fetchPolicies.olderThan(thirtySeconds)
32
34
 
@@ -115,7 +117,9 @@ const ContactsListModal = props => {
115
117
  </CozyTheme>
116
118
  <DialogTitle
117
119
  {...dialogTitleProps}
118
- className={isMobile ? 'u-p-0 u-w-100' : undefined}
120
+ className={cx(dialogTitleProps.className, {
121
+ 'u-p-0 u-w-100': isMobile
122
+ })}
119
123
  >
120
124
  {isMobile ? (
121
125
  <>
@@ -1,5 +1,5 @@
1
1
  import React from 'react'
2
- import cx from 'classnames'
2
+ import cx from 'classnames/dedupe'
3
3
 
4
4
  import useCozyDialog from './useCozyDialog'
5
5
  import Dialog, { DialogTitle, DialogActions, DialogContent } from '../Dialog'
@@ -9,14 +9,17 @@ import DialogBackButton from './DialogBackButton'
9
9
  import DialogCloseButton from './DialogCloseButton'
10
10
 
11
11
  const ConfirmDialog = props => {
12
- const { onClose, title, content, actions, actionsLayout } = props
12
+ const { onClose, onBack, title, content, actions, actionsLayout } = props
13
13
  const {
14
14
  dialogProps,
15
15
  dialogTitleProps,
16
16
  fullScreen,
17
17
  id,
18
18
  dialogActionsProps
19
- } = useCozyDialog(props)
19
+ } = useCozyDialog({ ...props, isFluidTitle: true })
20
+
21
+ const onBackOrClose = onBack || onClose
22
+
20
23
  return (
21
24
  <Dialog {...dialogProps}>
22
25
  {!fullScreen && onClose && (
@@ -25,12 +28,23 @@ const ConfirmDialog = props => {
25
28
  data-test-id={`modal-close-button-${id}`}
26
29
  />
27
30
  )}
31
+ {!fullScreen && onBack && (
32
+ <DialogBackButton
33
+ data-test-id={`modal-back-button-${id}`}
34
+ onClick={onBack}
35
+ />
36
+ )}
37
+ {fullScreen && onBackOrClose && (
38
+ <DialogBackButton
39
+ data-test-id={`modal-backclose-button-${id}`}
40
+ onClick={onBackOrClose}
41
+ />
42
+ )}
28
43
  <DialogContent>
29
44
  <div className="dialogContentInner withFluidActions">
30
- <DialogTitle {...dialogTitleProps} className="dialogTitleFluid">
31
- {fullScreen && onClose && <DialogBackButton onClick={onClose} />}
32
- {title}
33
- </DialogTitle>
45
+ <div className="dialogTitleFluidContainer">
46
+ <DialogTitle {...dialogTitleProps}>{title}</DialogTitle>
47
+ </div>
34
48
  {content}
35
49
  {actions && (
36
50
  <DialogActions
@@ -10,7 +10,7 @@ import DialogBackButton from './DialogBackButton'
10
10
  import DialogCloseButton from './DialogCloseButton'
11
11
 
12
12
  const Dialog = props => {
13
- const { onClose, title, content, actions, actionsLayout } = props
13
+ const { onClose, onBack, title, content, actions, actionsLayout } = props
14
14
  const {
15
15
  dialogProps,
16
16
  dialogTitleProps,
@@ -19,6 +19,8 @@ const Dialog = props => {
19
19
  dialogActionsProps
20
20
  } = useCozyDialog(props)
21
21
 
22
+ const onBackOrClose = onBack || onClose
23
+
22
24
  return (
23
25
  <MUIDialog {...dialogProps}>
24
26
  {!fullScreen && onClose && (
@@ -27,13 +29,19 @@ const Dialog = props => {
27
29
  data-test-id={`modal-close-button-${id}`}
28
30
  />
29
31
  )}
30
- <DialogTitle
31
- {...dialogTitleProps}
32
- className={cx('u-ellipsis', { dialogTitleFull: !onClose })}
33
- >
34
- {fullScreen && onClose && <DialogBackButton onClick={onClose} />}
35
- {title}
36
- </DialogTitle>
32
+ {!fullScreen && onBack && (
33
+ <DialogBackButton
34
+ onClick={onBack}
35
+ data-test-id={`modal-back-button-${id}`}
36
+ />
37
+ )}
38
+ {fullScreen && onBackOrClose && (
39
+ <DialogBackButton
40
+ data-test-id={`modal-backclose-button-${id}`}
41
+ onClick={onBackOrClose}
42
+ />
43
+ )}
44
+ <DialogTitle {...dialogTitleProps}>{title}</DialogTitle>
37
45
  <Divider />
38
46
  <DialogContent>
39
47
  <div className="dialogContentInner withFluidActions">
@@ -1,23 +1,30 @@
1
1
  import React from 'react'
2
2
  import PropTypes from 'prop-types'
3
- import { withStyles } from '@material-ui/core/styles'
4
3
 
5
4
  import IconButton from '../IconButton'
6
5
  import Icon from '../Icon'
7
6
 
8
7
  import PreviousIcon from '../Icons/Previous'
9
8
 
10
- const customStyles = () => ({
11
- root: {
12
- margin: '-1.1rem 0.25rem -0.9rem -0.5rem'
13
- }
14
- })
9
+ import styles from './styles.styl'
10
+ import locales from './locales'
11
+ import { createUseI18n } from '../I18n'
15
12
 
16
- const DialogBackButton = ({ classes, onClick }) => {
13
+ const useI18n = createUseI18n(locales)
14
+
15
+ const DialogBackButton = ({ onClick, ...props }) => {
16
+ const { t } = useI18n()
17
17
  return (
18
- <IconButton className={classes.root} onClick={onClick}>
19
- <Icon icon={PreviousIcon} />
20
- </IconButton>
18
+ <div className={styles.DialogBackButton}>
19
+ <IconButton
20
+ onClick={onClick}
21
+ {...props}
22
+ aria-label={t('backButton')}
23
+ className="dialogIconButton"
24
+ >
25
+ <Icon icon={PreviousIcon} />
26
+ </IconButton>
27
+ </div>
21
28
  )
22
29
  }
23
30
 
@@ -25,4 +32,4 @@ DialogBackButton.propTypes = {
25
32
  onClick: PropTypes.func.isRequired
26
33
  }
27
34
 
28
- export default withStyles(customStyles)(DialogBackButton)
35
+ export default DialogBackButton
@@ -15,7 +15,12 @@ const CloseButton = ({ onClick, ...props }) => {
15
15
  const { t } = useI18n()
16
16
  return (
17
17
  <div className={styles.DialogCloseButton}>
18
- <IconButton onClick={onClick} {...props} aria-label={t('closeButton')}>
18
+ <IconButton
19
+ onClick={onClick}
20
+ {...props}
21
+ aria-label={t('closeButton')}
22
+ className="dialogIconButton"
23
+ >
19
24
  <Icon icon={CrossMediumIcon} />
20
25
  </IconButton>
21
26
  </div>
@@ -1,5 +1,5 @@
1
1
  import React from 'react'
2
- import cx from 'classnames'
2
+ import cx from 'classnames/dedupe'
3
3
 
4
4
  import useCozyDialog from './useCozyDialog'
5
5
  import Dialog, { DialogTitle, DialogActions, DialogContent } from '../Dialog'
@@ -10,14 +10,16 @@ import DialogBackButton from './DialogBackButton'
10
10
  import DialogCloseButton from './DialogCloseButton'
11
11
 
12
12
  const FixedActionsDialog = props => {
13
- const { onClose, title, content, actions, actionsLayout } = props
13
+ const { onClose, onBack, title, content, actions, actionsLayout } = props
14
14
  const {
15
15
  dialogProps,
16
16
  dialogTitleProps,
17
17
  fullScreen,
18
18
  id,
19
19
  dialogActionsProps
20
- } = useCozyDialog(props)
20
+ } = useCozyDialog({ ...props, isFluidTitle: true })
21
+
22
+ const onBackOrClose = onBack || onClose
21
23
 
22
24
  return (
23
25
  <Dialog {...dialogProps}>
@@ -27,12 +29,23 @@ const FixedActionsDialog = props => {
27
29
  onClick={onClose}
28
30
  />
29
31
  )}
32
+ {!fullScreen && onBack && (
33
+ <DialogBackButton
34
+ data-test-id={`modal-back-button-${id}`}
35
+ onClick={onBack}
36
+ />
37
+ )}
38
+ {fullScreen && onBackOrClose && (
39
+ <DialogBackButton
40
+ data-test-id={`modal-backclose-button-${id}`}
41
+ onClick={onBackOrClose}
42
+ />
43
+ )}
30
44
  <DialogContent>
31
45
  <div className="dialogContentInner">
32
- <DialogTitle {...dialogTitleProps} className="dialogTitleFluid">
33
- {fullScreen && onClose && <DialogBackButton onClick={onClose} />}
34
- {title}
35
- </DialogTitle>
46
+ <div className="dialogTitleFluidContainer">
47
+ <DialogTitle {...dialogTitleProps}>{title}</DialogTitle>
48
+ </div>
36
49
  {content}
37
50
  </div>
38
51
  </DialogContent>
@@ -10,7 +10,7 @@ import DialogBackButton from './DialogBackButton'
10
10
  import DialogCloseButton from './DialogCloseButton'
11
11
 
12
12
  const FixedDialog = props => {
13
- const { onClose, title, content, actions, actionsLayout } = props
13
+ const { onClose, onBack, title, content, actions, actionsLayout } = props
14
14
  const {
15
15
  dialogProps,
16
16
  dialogTitleProps,
@@ -19,6 +19,8 @@ const FixedDialog = props => {
19
19
  dialogActionsProps
20
20
  } = useCozyDialog(props)
21
21
 
22
+ const onBackOrClose = onBack || onClose
23
+
22
24
  return (
23
25
  <Dialog {...dialogProps}>
24
26
  {!fullScreen && onClose && (
@@ -27,13 +29,19 @@ const FixedDialog = props => {
27
29
  onClick={onClose}
28
30
  />
29
31
  )}
30
- <DialogTitle
31
- {...dialogTitleProps}
32
- className={cx('u-ellipsis', { dialogTitleFull: !onClose })}
33
- >
34
- {fullScreen && onClose && <DialogBackButton onClick={onClose} />}
35
- {title}
36
- </DialogTitle>
32
+ {!fullScreen && onBack && (
33
+ <DialogBackButton
34
+ data-test-id={`modal-back-button-${id}`}
35
+ onClick={onBack}
36
+ />
37
+ )}
38
+ {fullScreen && onBackOrClose && (
39
+ <DialogBackButton
40
+ data-test-id={`modal-backclose-button-${id}`}
41
+ onClick={onBackOrClose}
42
+ />
43
+ )}
44
+ <DialogTitle {...dialogTitleProps}>{title}</DialogTitle>
37
45
  <Divider />
38
46
  <DialogContent>
39
47
  <div className="dialogContentInner">{content}</div>
@@ -1,5 +1,5 @@
1
1
  import React from 'react'
2
- import cx from 'classnames'
2
+ import cx from 'classnames/dedupe'
3
3
 
4
4
  import useCozyDialog from './useCozyDialog'
5
5
  import Dialog, { DialogTitle, DialogActions, DialogContent } from '../Dialog'
@@ -9,14 +9,16 @@ import DialogBackButton from './DialogBackButton'
9
9
  import DialogCloseButton from './DialogCloseButton'
10
10
 
11
11
  const IllustrationDialog = props => {
12
- const { onClose, title, content, actions, actionsLayout } = props
12
+ const { onClose, onBack, title, content, actions, actionsLayout } = props
13
13
  const {
14
14
  dialogProps,
15
15
  dialogTitleProps,
16
16
  id,
17
17
  fullScreen,
18
18
  dialogActionsProps
19
- } = useCozyDialog(props)
19
+ } = useCozyDialog({ ...props, isFluidTitle: true })
20
+
21
+ const onBackOrClose = onBack || onClose
20
22
 
21
23
  return (
22
24
  <Dialog {...dialogProps}>
@@ -26,10 +28,21 @@ const IllustrationDialog = props => {
26
28
  onClick={onClose}
27
29
  />
28
30
  )}
31
+ {!fullScreen && onBack && (
32
+ <DialogBackButton
33
+ onClick={onBack}
34
+ data-test-id={`modal-back-button-${id}`}
35
+ />
36
+ )}
37
+ {fullScreen && onBackOrClose && (
38
+ <DialogBackButton
39
+ data-test-id={`modal-backclose-button-${id}`}
40
+ onClick={onBackOrClose}
41
+ />
42
+ )}
29
43
  <DialogContent>
30
44
  <div className="dialogContentInner withFluidActions">
31
- <DialogTitle {...dialogTitleProps} className="dialogTitleFluid">
32
- {fullScreen && onClose && <DialogBackButton onClick={onClose} />}
45
+ <DialogTitle {...dialogTitleProps}>
33
46
  <div className="u-flex u-flex-justify-center">{title}</div>
34
47
  </DialogTitle>
35
48
  {content}
@@ -16,6 +16,13 @@ Will automatically:
16
16
  * size : `<string>` Can be "s", "m" (default) or "l"
17
17
  * opened : `<boolean>` (required) To open/close the modal
18
18
  * onClose : `<function>` (required) Triggered function on modal close action
19
+ * onBack : `<function>` (optional) Triggered function on modal back action
20
+ * if defined and in desktop mode then a back button is shown in addition to the close button and it will trigger onBack() on click
21
+ * if defined and in mobile mode then the back button will trigger onBack() instead of onClose()
22
+ * if not defined and in mobile mode then the back button will trigger onClose()
23
+ * disableTitleAutoPadding : `<boolean>` (optional) Disable title padding calculation that would prevent overlapping with close and back buttons
24
+ * if set to `true` then you should handle those CSS properties by yourself or title will take 100% of width
25
+ * if set to `false` then title will take only available space between close and back buttons regarding which of `onClose` or `onBack` props are defined or not
19
26
  * title : `<node>` Title of the modal
20
27
  * content : `<node>` Content of the modal
21
28
  * actions : `<node>` Actions of the modal
@@ -42,6 +49,10 @@ import Typography from 'cozy-ui/transpiled/react/Typography'
42
49
  import CloudIcon from "cozy-ui/transpiled/react/Icons/Cloud";
43
50
 
44
51
  const handleClose = () => setState({ modalOpened: !state.modalOpened })
52
+ const handleBack = () => {
53
+ Alerter.success('Back button has been pressed', { duration: 5000 })
54
+ setState({ modalOpened: !state.modalOpened })
55
+ }
45
56
 
46
57
  const DialogComponent = state.modal
47
58
 
@@ -134,7 +145,9 @@ initialState = {
134
145
  size: 'medium',
135
146
  actionsLayout: 'row',
136
147
  title: 'short',
148
+ disableTitleAutoPadding: false,
137
149
  withCloseButton: true,
150
+ withBackButton: false,
138
151
  content: 'default',
139
152
  theme: 'normal',
140
153
  align: 'middle',
@@ -147,6 +160,14 @@ initialState = {
147
160
  <StateRadio value={true} name='withCloseButton' /> yes{' '}
148
161
  <StateRadio value={false} name='withCloseButton' /> no
149
162
  </p>
163
+ <p>With back button:
164
+ <StateRadio value={true} name='withBackButton' /> yes{' '}
165
+ <StateRadio value={false} name='withBackButton' /> no
166
+ </p>
167
+ <p>Disable Title auto-positionning:
168
+ <StateRadio value={true} name='disableTitleAutoPadding' /> yes{' '}
169
+ <StateRadio value={false} name='disableTitleAutoPadding' /> no
170
+ </p>
150
171
  <p>Title:
151
172
  <StateRadio value='short' name='title' /> short{' '}
152
173
  <StateRadio value='long' name='title' /> long
@@ -177,6 +198,8 @@ initialState = {
177
198
  size={DialogComponent !== ConfirmDialog ? state.size : undefined}
178
199
  open={state.modalOpened}
179
200
  onClose={state.withCloseButton ? handleClose : undefined}
201
+ onBack={state.withBackButton ? handleBack : undefined}
202
+ disableTitleAutoPadding={state.disableTitleAutoPadding}
180
203
  align={state.align}
181
204
  title={DialogComponent !== IllustrationDialog && state.title === "long"
182
205
  ? `${dialogTitles[DialogComponent.name]} - ${content.ada.short}`
@@ -3,6 +3,8 @@ import PropTypes from 'prop-types'
3
3
  export default {
4
4
  open: PropTypes.bool.isRequired,
5
5
  onClose: PropTypes.func,
6
+ onBack: PropTypes.func,
7
+ disableTitleAutoPadding: PropTypes.bool,
6
8
  title: PropTypes.node,
7
9
  content: PropTypes.node,
8
10
  actions: PropTypes.node,
@@ -1,11 +1,14 @@
1
1
  export default {
2
2
  en: {
3
- closeButton: 'Close'
3
+ closeButton: 'Close',
4
+ backButton: 'Back'
4
5
  },
5
6
  fr: {
6
- closeButton: 'Fermer'
7
+ closeButton: 'Fermer',
8
+ backButton: 'Retour'
7
9
  },
8
10
  es: {
9
- closeButton: 'Cerrar'
11
+ closeButton: 'Cerrar',
12
+ backButton: 'Atrás'
10
13
  }
11
14
  }
@@ -2,9 +2,18 @@
2
2
 
3
3
  .DialogCloseButton
4
4
  position absolute
5
- top 0.75rem
6
- right 0.75rem
5
+ top 1.15rem
6
+ right 1.15rem
7
7
  z-index var(--zIndex-modal) //needed for an iOS bug https://github.com/cozy/cozy-ui/pull/1790
8
8
  +small-screen()
9
9
  top 0.25rem
10
10
  right 0.25rem
11
+
12
+ .DialogBackButton
13
+ position absolute
14
+ top 1.15rem
15
+ left 1.15rem
16
+ z-index var(--zIndex-modal) //needed for an iOS bug https://github.com/cozy/cozy-ui/pull/1790
17
+ +small-screen()
18
+ top 0.25rem
19
+ left 0.25rem
@@ -23,3 +23,17 @@ export const getCloseButton = dialogRoot => {
23
23
  x => x.dataset.testId && x.dataset.testId.includes('modal-close-button')
24
24
  )
25
25
  }
26
+
27
+ export const getBackButton = dialogRoot => {
28
+ const buttons = within(dialogRoot).getAllByRole('button')
29
+ return buttons.find(
30
+ x => x.dataset.testId && x.dataset.testId.includes('modal-back-button')
31
+ )
32
+ }
33
+
34
+ export const getBackCloseButton = dialogRoot => {
35
+ const buttons = within(dialogRoot).getAllByRole('button')
36
+ return buttons.find(
37
+ x => x.dataset.testId && x.dataset.testId.includes('modal-backclose-button')
38
+ )
39
+ }
@@ -3,14 +3,33 @@ import { render, fireEvent } from '@testing-library/react'
3
3
 
4
4
  import Dialog from './Dialog'
5
5
 
6
- import { getDialog, getCloseButton } from './testing'
7
- import { BreakpointsProvider } from '../hooks/useBreakpoints'
6
+ import {
7
+ getDialog,
8
+ getCloseButton,
9
+ getBackButton,
10
+ getBackCloseButton
11
+ } from './testing'
12
+ import useBreakpoints, { BreakpointsProvider } from '../hooks/useBreakpoints'
13
+
14
+ jest.mock('../hooks/useBreakpoints', () => ({
15
+ ...jest.requireActual('../hooks/useBreakpoints'),
16
+ __esModule: true,
17
+ default: jest.fn(),
18
+ useBreakpoints: jest.fn()
19
+ }))
8
20
 
9
21
  describe('testing utils for dialog', () => {
10
- const setup = ({ onClose } = {}) => {
22
+ const setup = ({ isMobile = false, onClose, onBack } = {}) => {
23
+ useBreakpoints.mockReturnValue({ isMobile })
11
24
  const root = render(
12
25
  <BreakpointsProvider>
13
- <Dialog open title="Title" content="Content" onClose={onClose} />
26
+ <Dialog
27
+ open
28
+ title="Title"
29
+ content="Content"
30
+ onClose={onClose}
31
+ onBack={onBack}
32
+ />
14
33
  </BreakpointsProvider>
15
34
  )
16
35
  return { root }
@@ -30,4 +49,69 @@ describe('testing utils for dialog', () => {
30
49
  fireEvent.click(closeBtn)
31
50
  expect(onClose).toHaveBeenCalled()
32
51
  })
52
+
53
+ it('should call onBack', () => {
54
+ const onBack = jest.fn()
55
+ const { root } = setup({ onBack })
56
+ const dialog = getDialog(root)
57
+ const backBtn = getBackButton(dialog)
58
+ fireEvent.click(backBtn)
59
+ expect(onBack).toHaveBeenCalled()
60
+ })
61
+
62
+ it('should call onBack when back and close are defined on mobile', () => {
63
+ const onClose = jest.fn()
64
+ const onBack = jest.fn()
65
+ const { root } = setup({ onBack, onClose, isMobile: true })
66
+ const dialog = getDialog(root)
67
+
68
+ const backCloseBtn = getBackCloseButton(dialog)
69
+ const backBtn = getBackButton(dialog)
70
+ const closeBtn = getCloseButton(dialog)
71
+
72
+ expect(backCloseBtn).toBeDefined()
73
+ expect(backBtn).toBeUndefined()
74
+ expect(closeBtn).toBeUndefined()
75
+
76
+ fireEvent.click(backCloseBtn)
77
+ expect(onBack).toHaveBeenCalled()
78
+ })
79
+
80
+ it('should call onClose when only close is defined on mobile', () => {
81
+ const onClose = jest.fn()
82
+ const { root } = setup({ onClose, isMobile: true })
83
+ const dialog = getDialog(root)
84
+
85
+ const backCloseBtn = getBackCloseButton(dialog)
86
+ const backBtn = getBackButton(dialog)
87
+ const closeBtn = getCloseButton(dialog)
88
+
89
+ expect(backCloseBtn).toBeDefined()
90
+ expect(backBtn).toBeUndefined()
91
+ expect(closeBtn).toBeUndefined()
92
+
93
+ fireEvent.click(backCloseBtn)
94
+ expect(onClose).toHaveBeenCalled()
95
+ })
96
+
97
+ it('should be able to call onBack or onClose when back and close are defined on desktop', () => {
98
+ const onClose = jest.fn()
99
+ const onBack = jest.fn()
100
+ const { root } = setup({ onBack, onClose })
101
+ const dialog = getDialog(root)
102
+
103
+ const backCloseBtn = getBackCloseButton(dialog)
104
+ const backBtn = getBackButton(dialog)
105
+ const closeBtn = getCloseButton(dialog)
106
+
107
+ expect(backCloseBtn).toBeUndefined()
108
+ expect(backBtn).toBeDefined()
109
+ expect(closeBtn).toBeDefined()
110
+
111
+ fireEvent.click(backBtn)
112
+ expect(onBack).toHaveBeenCalled()
113
+
114
+ fireEvent.click(closeBtn)
115
+ expect(onClose).toHaveBeenCalled()
116
+ })
33
117
  })
@@ -1,6 +1,7 @@
1
1
  import { useState } from 'react'
2
2
  import useBreakpoints from '../hooks/useBreakpoints'
3
3
  import DialogTransition from './DialogTransition'
4
+ import cx from 'classnames'
4
5
 
5
6
  let globalId = 0
6
7
 
@@ -21,8 +22,11 @@ const useCozyDialog = props => {
21
22
  content, // eslint-disable-line no-unused-vars
22
23
  open,
23
24
  opened,
25
+ onBack,
24
26
  onClose,
25
27
  align,
28
+ disableTitleAutoPadding,
29
+ isFluidTitle,
26
30
  ...otherProps
27
31
  } = props
28
32
  const { isMobile } = useBreakpoints()
@@ -52,10 +56,18 @@ const useCozyDialog = props => {
52
56
  }
53
57
  }
54
58
 
59
+ const showCloseButton = !fullScreen && onClose
60
+ const showBackButton = onBack || (fullScreen && onClose) // back and close buttons are merged in fullScreen
61
+
55
62
  const dialogTitleProps = {
56
63
  id: `modal-title-${id}`,
57
64
  disableTypography: true,
58
- className: 'u-ellipsis'
65
+ className: cx({
66
+ 'u-ellipsis': !isFluidTitle,
67
+ dialogTitleFluid: isFluidTitle,
68
+ dialogTitleWithClose: showCloseButton && !disableTitleAutoPadding,
69
+ dialogTitleWithBack: showBackButton && !disableTitleAutoPadding
70
+ })
59
71
  }
60
72
 
61
73
  const listItemClassName = 'listItem--dialog'