diff --git a/packages/web-react/src/components/Modal/README.md b/packages/web-react/src/components/Modal/README.md index d7b762c26a..72ed55640e 100644 --- a/packages/web-react/src/components/Modal/README.md +++ b/packages/web-react/src/components/Modal/README.md @@ -1,52 +1,24 @@ # Modal -```jsx -import { Modal, ModalDialog, ModalBody, ModalHeader, ModalFooter, Button } from '@lmc-eu/spirit-web-react/components'; -``` - -```jsx -const [isOpen, setOpen] = useState(false); - -const toggleModal = () => setOpen(!isOpen); +This is the React implementation of the [Modal] component. -const handleClose = () => { - setOpen(false); -}; +Modal is a composition of several subcomponents: -// Trigger - +- [Modal](#modal) + - [ModalDialog](#modaldialog) + - [ModalHeader](#modalheader) + - [ModalBody](#modalfooter) + - [ModalFooter](#modalfooter) -// Modal - - - Modal Title - Modal Body - - - - - - -``` +## Modal -## An example using a form as a ModalDialog element +Modal establishes the top layer with a backdrop. Under the hood it uses the [`` element][mdn-dialog] which +provides several accessibility advantages. ```jsx - - - ... - - + ``` -## Modal - ### API | Name | Type | Default | Required | Description | @@ -62,33 +34,100 @@ The rest of the properties are created from the default `` element. [Mor ## ModalDialog +ModalDialog is the actual dialog window, a place for the header, body, and footer of the dialog. + +```jsx + +``` + +## Forms in Modal + +Modal can also contain interactive content like forms. For such cases, you may find it convenient to use the `
` +element with the attribute `method="dialog"`. Buttons with `type="submit"` then [handle both][mdn-dialog-form] saving +the state of the form and closing the dialog. + +```jsx + + … + +``` + +### Expand on Mobile Screens + +We recommend expanding the dialog on mobile screens using the `isExpandedOnMobile` option. If you omit the option, the +dialog shrinks to fit the height of its content (if smaller than the viewport). + +```jsx + +``` + +### Custom Height + +By default, Modal expands to fit the height of its content, as long as it fits the viewport (see [more below](#custom-max-height)). +You can override this behavior by setting a preferred height using the following options: + +- `preferredHeightOnMobile` for mobile screens, and +- `preferredHeightFromTabletUp` for tablet screens and up. + +This is useful for Modals with dynamic content, e.g. a list of items that can be added or removed, or a multistep wizard. + +```jsx + + … + +``` + +👉 Please note the custom height values are considered **preferred:** Modal will not expand beyond the viewport height. + +### Custom Max Height + +The default maximum height of Modal is: + +- viewport height minus 1100 spacing on mobile screens, and +- 600 px on tablet screens and up (shrunk if necessary). + +You can use the `maxHeightFromTabletUp` option to override the max height on tablet screens and up: + +```jsx + +``` + +👉 Please note the max height on mobile screens is currently not customizable. Let us know if you need this feature! 🙏 + ### API -| Name | Type | Default | Required | Description | -| -------------------- | --------------------- | --------- | -------- | ---------------------------------------------------- | -| `children` | `ReactNode` | — | ✕ | Children node | -| `elementType` | [`article` \| `form`] | `article` | ✕ | ModalDialog element type | -| `UNSAFE_className` | `string` | — | ✕ | ModalDialog custom class name | -| `UNSAFE_style` | `CSSProperties` | — | ✕ | ModalDialog custom style | -| `isExpandedOnMobile` | `bool` | — | ✕ | ModalDialog shrinks to fit the height of its content | +| Name | Type | Default | Required | Description | +| ----------------------------- | --------------------- | --------- | -------- | -------------------------------------------------------------------------------- | +| `children` | `ReactNode` | — | ✕ | Children node | +| `elementType` | [`article` \| `form`] | `article` | ✕ | ModalDialog element type | +| `isExpandedOnMobile` | `bool` | — | ✕ | ModalDialog shrinks to fit the height of its content | +| `maxHeightFromTabletUp` | `string` | `null` | ✕ | Max height of the modal. Accepts any valid CSS value. | +| `preferredHeightFromTabletUp` | `string` | `null` | ✕ | Preferred height of the modal on tablet and larger. Accepts any valid CSS value. | +| `preferredHeightOnMobile` | `string` | `null` | ✕ | Preferred height of the modal on mobile. Accepts any valid CSS value. | +| `UNSAFE_className` | `string` | — | ✕ | ModalDialog custom class name | +| `UNSAFE_style` | `CSSProperties` | — | ✕ | ModalDialog custom style | The rest of the properties are formed from the selected type of element. Documentation for [Article][ArticleElementDocs], [Form][FormElementDocs]. ## ModalHeader +ModalHeader contains the title of the dialog and the close button. + +```jsx +Modal Title +``` + ### Hidden Title -Even in cases you don't need the title to be visible you should provide an +Even in cases where you don't need the title to be visible you should provide an accessible name for the dialog, e.g. using the `aria-label` attribute on `` component: -```twig +```jsx - - … - + ``` @@ -102,10 +141,22 @@ accessible name for the dialog, e.g. using the `aria-label` attribute on | `UNSAFE_className` | `string` | — | ✕ | ModalHeader custom class name | | `UNSAFE_style` | `CSSProperties` | — | ✕ | ModalHeader custom style | -The rest of the properties are based from type of `HTMLElement`. [Docs][HTMLElementDocs] +The rest of the properties are based on the type of `HTMLElement``. [Docs][HTMLElementDocs] ## ModalBody +ModalBody holds the actual content of the Modal. + +```jsx + +

+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquam at excepturi laudantium magnam mollitia + perferendis reprehenderit, voluptate. Cum delectus dicta ducimus eligendi excepturi natus perferendis provident + unde. Eveniet, iste, molestiae? +

+
+``` + ### API | Name | Type | Default | Required | Description | @@ -118,20 +169,71 @@ The rest of the properties are created from the default `
` element. [Docs][ ## ModalFooter +ModalFooter is the place for actions represented by the Button component. While there always must be a primary Button, +secondary actions are optional. + +👉 Please note the actions are _visually_ ordered from right to left from the tablet breakpoint up. However, the +_actual_ order in code is followed when users tab over the interface. + +```jsx + + + + +``` + +### Footer Description + +Optionally, you can add a description to the footer: + +```jsx + +``` + +### Footer Alignment + +ModalFooter can be aligned to the right (default), center, or left. These values come from the +[dictionary][dictionary-alignment]. Using a corresponding alignment option will align the footer actions accordingly: + +- `right` (default) +- `center` +- `left` + +```jsx + +``` + ### API | Name | Type | Default | Required | Description | | ------------------ | --------------------------------------------- | ------- | -------- | ----------------------------- | | `alignmentX` | [AlignmentX dictionary][dictionary-alignment] | `right` | ✕ | ModalFooter alignment | | `children` | `ReactNode` | — | ✕ | Children node | +| `description` | `string` | `null` | ✕ | Optional Footer Description | | `UNSAFE_className` | `string` | — | ✕ | ModalFooter custom class name | | `UNSAFE_style` | `CSSProperties` | — | ✕ | ModalFooter custom style | -The rest of the properties are based from type of `HTMLElement`. [Docs][HTMLElementDocs] +The rest of the properties are based on the type of `HTMLElement`. [Docs][HTMLElementDocs] + +## Opening the Modal + +Use a hook to open your Modal, e.g.: + +```jsx +const [isOpen, setOpen] = useState(false); +const toggleModal = () => setOpen(!isOpen); +const handleClose = () => setOpen(false); + +; +``` ## Scrolling Long Content -When Modals become too long for the user's viewport or device, they automatically scroll independent of the page itself. +When Modals become too long for the user's viewport or device, they automatically scroll independently of the page itself. + +### Scrolling with ScrollView To make content overflow more obvious to users, you can wrap the `ModalBody` content in a [ScrollView][scroll-view] that takes over the responsibility for scrolling and provides visual overflow decorators, e.g.: @@ -142,6 +244,51 @@ takes over the responsibility for scrolling and provides visual overflow decorat ``` +## Full Example + +When you put it all together: + +```jsx +import { + Button, + Modal, + ModalBody, + ModalDialog, + ModalFooter, + ModalHeader, + ScrollView, +} from '@lmc-eu/spirit-web-react/components'; + +const [isOpen, setOpen] = useState(false); +const toggleModal = () => setOpen(!isOpen); +const handleClose = () => setOpen(false); + + + + + + Title of the Modal + + Modal body + + + + + + + +``` + [DialogElementDocs]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dialog [ArticleElementDocs]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/article [FormElementDocs]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form @@ -149,3 +296,4 @@ takes over the responsibility for scrolling and provides visual overflow decorat [HTMLElementDocs]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement [dictionary-alignment]: https://github.com/lmc-eu/spirit-design-system/blob/main/docs/DICTIONARIES.md#alignment [scroll-view]: https://github.com/lmc-eu/spirit-design-system/blob/main/packages/web-react/src/components/ScrollView/README.md +[mdn-dialog]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dialog diff --git a/packages/web-twig/src/Resources/components/Modal/README.md b/packages/web-twig/src/Resources/components/Modal/README.md index f2c9af59d9..c5fb330b56 100644 --- a/packages/web-twig/src/Resources/components/Modal/README.md +++ b/packages/web-twig/src/Resources/components/Modal/README.md @@ -1,6 +1,6 @@ # Modal -This is Twig implementation of the [Modal] component. +This is the Twig implementation of the [Modal] component. Modal is a composition of several subcomponents: @@ -12,19 +12,17 @@ Modal is a composition of several subcomponents: ## Modal -### Examples: +Modal establishes the top layer with a backdrop. Under the hood it uses the [`` element][mdn-dialog] which +provides several accessibility advantages. ```twig - - … - ``` -👉 Please note the `titleId` attribute is linked to the title inside -[Modal Header](#modalheader) and provides an accessible name for the dialog. +👉 Please note the `titleId` attribute is linked to the title inside the [Modal Header](#modalheader) and provides an +accessible name for the dialog. ### API @@ -34,27 +32,79 @@ Modal is a composition of several subcomponents: | `titleId` | `string` | `null` | ✕ | ID of the title inside ModalHeader | On top of the API options, you can add `data-*` or `aria-*` attributes to -further extend component's descriptiveness and accessibility. Also, UNSAFE styling props are available, +further extend the component's descriptiveness and accessibility. Also, UNSAFE styling props are available, see the [Escape hatches][escape-hatches] section in README to learn how and when to use them. These attributes will be passed to the topmost HTML element of the component. ## ModalDialog -ModalDialog is the actual dialog window, a place for the header, body, and -footer of the dialog. - -### Examples: +ModalDialog is the actual dialog window, a place for the header, body, and footer of the dialog. ```twig +``` + +### Forms in Modal - +Modal can also contain interactive content like forms. For such cases, you may find it convenient to use the `` +element with the attribute `method="dialog"`. Buttons with `type="submit"` then [handle both][mdn-dialog-form] saving +the state of the form and closing the dialog. + +```twig + … + ``` +### Expand on Mobile Screens + +We recommend expanding the dialog on mobile screens using the `isExpandedOnMobile` option. If you omit the option, the +dialog shrinks to fit the height of its content (if smaller than the viewport). + +```twig + + … + +``` + +### Custom Height + +By default, Modal expands to fit the height of its content, as long as it fits the viewport (see [more below](#custom-max-height)). +You can override this behavior by setting a preferred height using the following options: + +- `preferredHeightOnMobile` for mobile screens, and +- `preferredHeightFromTabletUp` for tablet screens and up. + +This is useful for Modals with dynamic content, e.g. a list of items that can be added or removed, or a multistep wizard. + +```twig + + … + +``` + +👉 Please note the custom height values are considered **preferred:** Modal will not expand beyond the viewport height. + +### Custom Max Height + +The default maximum height of Modal is: + +- viewport height minus 1100 spacing on mobile screens, and +- 600 px on tablet screens and up (shrunk if necessary). + +You can use the `maxHeightFromTabletUp` option to override the max height on tablet screens and up: + +```twig + + … + +``` + +👉 Please note the max height on mobile screens is currently not customizable. Let us know if you need this feature! 🙏 + ### API | Name | Type | Default | Required | Description | @@ -75,56 +125,25 @@ footer of the dialog. | `target` | `string` | `null` | ✕ | `elementType="form"` only: Browsing context for form submission | On top of the API options, you can add `data-*` or `aria-*` attributes to -further extend component's descriptiveness and accessibility. Also, UNSAFE styling props are available, +further extend the component's descriptiveness and accessibility. Also, UNSAFE styling props are available, see the [Escape hatches][escape-hatches] section in README to learn how and when to use them. These attributes will be passed to the topmost HTML element of the component. Also, all `form` attributes are allowed when the `elementType` is set to `form`. -### Forms in Modal - -Modal can also contain interactive content like forms. For such cases, you may -find convenient to use the prop `elementType="form"` with the attribute -`method="dialog"`. Buttons with `type="submit"` then -[handle both][mdn-dialog-form] saving the state of the form and closing the -dialog. - -```html - -``` - -### Expand on Mobile Screens - -We recommend to expand the ModalDialog on mobile screens using the -`isExpandedOnMobile` prop. If you disable the prop, the ModalDialog shrinks -to fit the height of its content (if smaller than viewport). - ## ModalHeader -### Examples: +ModalHeader contains the title of the dialog and the close button. ```twig - - - - - - Title of the Modal - - … - - + + Title of the Modal + ``` ### Hidden Title -Even in cases you don't need the title to be visible you should provide an -accessible name for the dialog, e.g. using the `aria-label` attribute on -`` component: +👉 Even in cases you don't need the title to be visible you should provide an accessible name for the dialog, e.g. +using the `aria-label` attribute on `` component: ```twig @@ -147,17 +166,21 @@ accessible name for the dialog, e.g. using the `aria-label` attribute on | `titleId` | `string` | `null` | ✕ | ID of the title | On top of the API options, you can add `data-*` or `aria-*` attributes to -further extend component's descriptiveness and accessibility. Also, UNSAFE styling props are available, +further extend the component's descriptiveness and accessibility. Also, UNSAFE styling props are available, see the [Escape hatches][escape-hatches] section in README to learn how and when to use them. These attributes will be passed to the topmost HTML element of the component. ## ModalBody -### Examples: +ModalBody holds the actual content of the Modal. ```twig - … +

+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquam at excepturi laudantium magnam mollitia + perferendis reprehenderit, voluptate. Cum delectus dicta ducimus eligendi excepturi natus perferendis provident + unde. Eveniet, iste, molestiae? +

``` @@ -165,20 +188,51 @@ These attributes will be passed to the topmost HTML element of the component. There are no API options for ModalBody. -You can add `data-*` or `aria-*` attributes to further extend +You can add `data-*` or `aria-*` attributes to further extend the component's descriptiveness and accessibility. Also, UNSAFE styling props are available, see the [Escape hatches][escape-hatches] section in README to learn how and when to use them. These attributes will be passed to the topmost HTML element of the component. ## ModalFooter -### Examples: +ModalFooter is the place for actions represented by the Button component. While there always must be a primary Button, +secondary actions are optional. + +👉 Please note the actions are _visually_ ordered from right to left from the tablet breakpoint up. However, the +_actual_ order in code is followed when users tab over the interface. ```twig + + + +``` + +### Footer Description + +Optionally, you can add a description into the footer: + +```twig + - +``` + +### Footer Alignment + +ModalFooter can be aligned to the right (default), center, or left. These values come from the +[dictionary][dictionary-alignment]. Using a corresponding alignment option will align the footer actions accordingly: + +- `right` (default) +- `center` +- `left` + +```twig + ``` @@ -191,13 +245,30 @@ These attributes will be passed to the topmost HTML element of the component. | `description` | `string` | `null` | ✕ | Optional Footer Description | On top of the API options, you can add `data-*` or `aria-*` attributes to -further extend component's descriptiveness and accessibility. Also, UNSAFE styling props are available, +further extend the component's descriptiveness and accessibility. Also, UNSAFE styling props are available, see the [Escape hatches][escape-hatches] section in README to learn how and when to use them. These attributes will be passed to the topmost HTML element of the component. +## Opening the Modal + +Use our JavaScript plugin to open your Modal, e.g.: + +```twig + +``` + ## Scrolling Long Content -When Modals become too long for the user's viewport or device, they automatically scroll independent of the page itself. +When Modals become too long for the user's viewport or device, they automatically scroll independently of the page itself. + +### Scrolling with ScrollView To make content overflow more obvious to users, you can wrap the ModalBody content in a [ScrollView][scroll-view] that takes over the responsibility for scrolling and provides visual overflow decorators, e.g.: @@ -216,7 +287,6 @@ When you put it all together: ```twig @@ -271,6 +334,7 @@ Or, feel free to write the controlling script yourself. [web-js-api]: https://github.com/lmc-eu/spirit-design-system/blob/main/packages/web/src/scss/components/Modal/README.md#javascript-plugin [web-readme]: https://github.com/lmc-eu/spirit-design-system/blob/main/packages/web/README.md [modal]: https://github.com/lmc-eu/spirit-design-system/tree/main/packages/web/src/scss/components/Modal +[mdn-dialog]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dialog [mdn-dialog-form]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dialog#usage_notes [autocomplete-attr]: https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete [dictionary-alignment]: https://github.com/lmc-eu/spirit-design-system/blob/main/docs/DICTIONARIES.md#alignment diff --git a/packages/web/src/scss/components/Modal/README.md b/packages/web/src/scss/components/Modal/README.md index ddda8e4522..49b58202f1 100644 --- a/packages/web/src/scss/components/Modal/README.md +++ b/packages/web/src/scss/components/Modal/README.md @@ -10,9 +10,8 @@ Modal is a composition of several subcomponents: ## Modal -Modal establishes the layer with backdrop. Under the hood it uses the -[`` element][mdn-dialog] which provides several accessibility -advantages. +Modal establishes the top layer with a backdrop. Under the hood it uses the [`` element][mdn-dialog] which +provides several accessibility advantages. ```html @@ -20,10 +19,10 @@ advantages. ``` -👉 Please note the `aria-labelledby` attribute is linked to the title inside -[ModalHeader](#modalheader) and provides an accessible name for the dialog. +👉 Please note the `aria-labelledby` attribute is linked to the title inside [ModalHeader](#modalheader) and provides an +accessible name for the dialog. -### Custom Preferred Height +### Custom Height By default, Modal expands to fit the height of its content, as long as it fits the viewport (see [more below](#custom-max-height)). You can override this behavior by setting a custom preferred height using a custom property: @@ -44,6 +43,8 @@ This is useful for Modals with dynamic content, e.g. a list of items that can be ``` +👉 Please note the custom height values are considered **preferred:** Modal will not expand beyond the viewport height. + ### Custom Max Height The default maximum height of Modal is: @@ -63,8 +64,7 @@ You can use the custom property `--modal-max-height-tablet` to override the max ## ModalDialog -ModalDialog is the actual dialog window, a place for the header, body, and -footer of the dialog. +ModalDialog is the actual dialog window, a place for the header, body, and footer of the dialog. ```html
@@ -76,23 +76,27 @@ footer of the dialog. ### Forms in Modal -Modal can also contain interactive content like forms. For such cases, you may -find convenient to use the `` element with the attribute -`method="dialog"`. Buttons with `type="submit"` then -[handle both][mdn-dialog-form] saving the state of the form and closing the -dialog. +Modal can also contain interactive content like forms. For such cases, you may find it convenient to use the `` +element with the attribute `method="dialog"`. Buttons with `type="submit"` then [handle both][mdn-dialog-form] saving +the state of the form and closing the dialog. ```html + ``` ### Expand on Mobile Screens -We recommend to expand the dialog on mobile screens using the -`ModalDialog--expandOnMobile` modifier class. If you omit the class, the dialog -shrinks to fit the height of its content (if smaller than viewport). +We recommend expanding the dialog on mobile screens using the `ModalDialog--expandOnMobile` modifier class. If you omit +the class, the dialog shrinks to fit the height of its content (if smaller than the viewport). + +```html +
+ +
+``` ## ModalHeader @@ -117,8 +121,10 @@ ModalHeader contains the title of the dialog and the close button.
``` -👉 Even in cases you don't need the title to be visible you should provide an -accessible name for the dialog, e.g. using the `aria-label` attribute: +### Hidden Title + +👉 Even in cases you don't need the title to be visible you should provide an accessible name for the dialog, e.g. using +the `aria-label` attribute on the `` element: ```html @@ -142,12 +148,11 @@ ModalBody holds the actual content of the Modal. ## ModalFooter -ModalFooter is the place for actions represented by the Button component. -While there always must be a primary Button, secondary actions are optional. +ModalFooter is the place for actions represented by the Button component. While there always must be a primary Button, +secondary actions are optional. -👉 Please note the actions are _visually_ ordered from right to left from the -tablet breakpoint up. However, the _actual_ order in code is followed when users -tab over the interface. +👉 Please note the actions are _visually_ ordered from right to left from the tablet breakpoint up. However, the +_actual_ order in code is followed when users tab over the interface. ```html
@@ -174,7 +179,7 @@ tab over the interface. ### Footer Description -Optionally, you can add a description into the footer: +Optionally, you can add a description to the footer: ```html
@@ -187,9 +192,8 @@ Optionally, you can add a description into the footer: ### Footer Alignment -ModalFooter can be aligned to the right (default), center, or left. -These values come from the [dictionary][dictionary-alignment]. -Using a corresponding modifier class: +ModalFooter can be aligned to the right (default), center, or left. These values come from the +[dictionary][dictionary-alignment]. Using a corresponding modifier class will align the footer actions accordingly: - `ModalFooter--right` (default) - `ModalFooter--center` @@ -214,9 +218,11 @@ Use our JavaScript plugin to open your Modal, e.g.: ## Scrolling Long Content -When Modals become too long for the user's viewport or device, they scroll independent of the page itself. By default, +When Modals become too long for the user's viewport or device, they scroll independently of the page itself. By default, ModalBody has `overflow-y: auto` applied to it, so it scrolls vertically. +### Scrolling with ScrollView + Alternatively, you can wrap the ModalBody content in a [ScrollView][scroll-view] to take over the responsibility for scrolling, e.g.: @@ -333,21 +339,20 @@ Both trigger and close buttons use `data` attributes to open and close the Modal ## State Classes -If there is more content that could fit the screen, ModalBody provides -the following state classes: +If there is more content that could fit the screen, ModalBody provides the following state classes: - `.is-scrolled-at-top` if there is content overflowing at the top, - `.is-scrolled-at-bottom` if there is content overflowing at the bottom. ## JavaScript Plugin -For full functionality you need to provide JavaScript which will handle toggling of the Modal dialog component. +For full functionality you need to provide JavaScript which will handle the toggling of the Modal dialog component. ```html ``` -Please consult [main package README][web-readme] for how to include JavaScript plugins. +Please consult the [main package README][web-readme] for how to include JavaScript plugins. Or feel free to write controlling scripts yourself.