Skip to content

Commit

Permalink
Feat(web-react): Introduce optional uniform appearance of Modal #DS…
Browse files Browse the repository at this point in the history
…-1091

Add `spirit-feature-modal-enable-uniform-dialog` feature class to enable
uniform appearance of `Modal` across all breakpoints.

Current mobile design is then accessible using the `isDockedOnMobile` property.
  • Loading branch information
adamkudrna committed Jan 15, 2024
1 parent 23ccda6 commit 531a9d9
Show file tree
Hide file tree
Showing 12 changed files with 126 additions and 22 deletions.
3 changes: 2 additions & 1 deletion packages/web-react/src/components/Modal/ModalDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,15 @@ const ModalDialog = <E extends ElementType = ModalDialogElementType>(
const {
elementType: ElementTag = 'article',
children,
isDockedOnMobile,
isExpandedOnMobile,
maxHeightFromTabletUp,
preferredHeightOnMobile,
preferredHeightFromTabletUp,
...restProps
} = props;

const { classProps } = useModalStyleProps({ isExpandedOnMobile });
const { classProps } = useModalStyleProps({ isDockedOnMobile, isExpandedOnMobile });
const { styleProps, props: otherProps } = useStyleProps(restProps);

const customizedHeightStyle: CustomizedHeightCSSProperties = {
Expand Down
38 changes: 28 additions & 10 deletions packages/web-react/src/components/Modal/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,16 +114,17 @@ You can use the `maxHeightFromTabletUp` option to override the max height on tab

### API

| 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 |
| Name | Type | Default | Required | Description |
| ----------------------------- | --------------------- | --------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `children` | `ReactNode` ||| Children node |
| `elementType` | [`article` \| `form`] | `article` || ModalDialog element type |
| `isDockedOnMobile` | `bool` | `false` || [REQUIRES FEATURE FLAG](#feature-flag-uniform-appearance-on-all-breakpoints): Dock the ModalDialog to the bottom of the screen on mobile |
| `isExpandedOnMobile` | `bool` | `false` || 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 |

Also, all properties of the [`<article>` element][mdn-article] and [`<form>` element][mdn-form] are supported.

Expand Down Expand Up @@ -308,10 +309,27 @@ const handleClose = () => setOpen(false);
</Modal>
```
## Feature Flag: Uniform Appearance on All Breakpoints
The uniform appearance of modal dialog on all breakpoints is disabled by default. To enable it, either set the
`$modal-enable-uniform-dialog` Sass feature flag to `true` or use the `spirit-feature-modal-enable-uniform-dialog` CSS
class on any parent of the modal.
For more info, see main [README][readme-feature-flags].
### ⚠️ DEPRECATION NOTICE
The uniform dialog appearance will replace current behavior in the next major release. Current mobile appearance will
remain accessible via the `isDockedOnMobile` property.
[What are deprecations?][readme-deprecations]
[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
[mdn-article]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/article
[mdn-form]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form
[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
[readme-deprecations]: https://github.com/lmc-eu/spirit-design-system/blob/main/packages/web-react/README.md#deprecations
[readme-feature-flags]: https://github.com/lmc-eu/spirit-design-system/blob/main/packages/web/README.md#feature-flags
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const ModalDefault = () => {
const [isSecondOpen, setSecondOpen] = useState(false);
const [isThirdOpen, setThirdOpen] = useState(false);
const [footerAlign, setFooterAlign] = useState<AlignmentXDictionaryType>('right');
const [isExpanded, setIsExpanded] = useState(false);
const [isExpanded, setIsExpanded] = useState(true);

const toggleFirstModal = () => setFirstOpen(!isFirstOpen);
const toggleSecondModal = () => setSecondOpen(!isSecondOpen);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import React, { useState } from 'react';
import { Button, Modal, ModalBody, ModalDialog, ModalFooter, ModalHeader } from '../..';

const ModalDefault = () => {
const [isFirstOpen, setFirstOpen] = useState(false);
const [isSecondOpen, setSecondOpen] = useState(false);

const toggleFirstModal = () => setFirstOpen(!isFirstOpen);
const toggleSecondModal = () => setSecondOpen(!isSecondOpen);

const handleFirstClose = () => setFirstOpen(false);
const handleSecondClose = () => setSecondOpen(false);

return (
<>
{/* Set `display: contents` to enable parent stack layout. */}
<div className="spirit-feature-modal-enable-uniform-dialog" style={{ display: 'contents' }}>
<Button onClick={toggleFirstModal}>Open Modal</Button>

<Modal id="example-uniform" isOpen={isFirstOpen} onClose={handleFirstClose}>
<ModalDialog>
<ModalHeader>Modal Title</ModalHeader>
<ModalBody>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquam at excepturi laudantium magnam
mollitia mollitia perferendis reprehenderit, voluptate. Cum delectus dicta ducimus eligendi excepturi
natus provident unde. Eveniet, iste, molestiae?
</p>
</ModalBody>
<ModalFooter description="Optional description">
<Button onClick={handleFirstClose}>Primary action</Button>
<Button color="secondary" onClick={handleFirstClose}>
Secondary action
</Button>
</ModalFooter>
</ModalDialog>
</Modal>

<Button onClick={toggleSecondModal}>Open Docked Modal (mobile only)</Button>

<Modal id="example-docked" isOpen={isSecondOpen} onClose={handleSecondClose}>
<ModalDialog isDockedOnMobile isExpandedOnMobile>
<ModalHeader>Modal Title</ModalHeader>
<ModalBody>
<p>
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?
</p>
</ModalBody>
<ModalFooter description="Optional description">
<Button onClick={handleSecondClose}>Primary action</Button>
<Button color="secondary" onClick={handleSecondClose}>
Secondary action
</Button>
</ModalFooter>
</ModalDialog>
</Modal>
</div>
</>
);
};

export default ModalDefault;
4 changes: 4 additions & 0 deletions packages/web-react/src/components/Modal/demo/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import ModalDefault from './ModalDefault';
import ModalScrollingLongContent from './ModalScrollingLongContent';
import ModalStacking from './ModalStacking';
import ModalDisabledBackdropClick from './ModalDisabledBackdropClick';
import ModalUniformModalOnMobile from './ModalUniformModalOnMobile';

ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
<React.StrictMode>
Expand All @@ -27,6 +28,9 @@ ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
<DocsSection title="Disabled Backdrop Click">
<ModalDisabledBackdropClick />
</DocsSection>
<DocsSection title="Feature Flag: Uniform Modal on Mobile">
<ModalUniformModalOnMobile />
</DocsSection>
</IconsProvider>
</React.StrictMode>,
);
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,14 @@ const meta: Meta<typeof ModalDialog> = {
title: 'Components/Modal',
component: ModalDialog,
argTypes: {
isDockedOnMobile: {
control: 'boolean',
description: `**REQUIRES FEATURE FLAG** which is turned on in this demo. To view Modal without feature flag, navigate
to the "Modal" story in the "Components/Modal" section of the sidebar.`,
},
isExpandedOnMobile: {
control: 'boolean',
},
maxHeightFromTabletUp: {
control: 'text',
},
Expand All @@ -20,6 +28,8 @@ const meta: Meta<typeof ModalDialog> = {
},
},
args: {
isDockedOnMobile: false,
isExpandedOnMobile: false,
maxHeightFromTabletUp: '',
preferredHeightOnMobile: '',
preferredHeightFromTabletUp: '',
Expand All @@ -43,7 +53,7 @@ const ModalWithHooks = (
};

return (
<>
<div className="spirit-feature-modal-enable-uniform-dialog">
<Button onClick={toggleModal} aria-expanded={isOpen}>
Open Modal
</Button>
Expand All @@ -61,7 +71,7 @@ const ModalWithHooks = (
</ModalFooter>
</ModalDialog>
</Modal>
</>
</div>
);
};

Expand Down
10 changes: 8 additions & 2 deletions packages/web-react/src/components/Modal/useModalStyleProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useClassNamePrefix } from '../../hooks';

export interface ModalStylesProps {
footerAlignment?: AlignmentXDictionaryType;
isDockedOnMobile?: boolean;
isExpandedOnMobile?: boolean;
}

Expand All @@ -24,13 +25,15 @@ export interface ModalStylesReturn {
}

export function useModalStyleProps(
{ footerAlignment = 'right', isExpandedOnMobile }: ModalStylesProps = {
{ footerAlignment = 'right', isDockedOnMobile, isExpandedOnMobile }: ModalStylesProps = {
footerAlignment: 'right',
isDockedOnMobile: false,
isExpandedOnMobile: false,
},
): ModalStylesReturn {
const modalClass = useClassNamePrefix('Modal');
const modalDialogClass = `${modalClass}Dialog`;
const modalDialogDockedOnMobileClass = `${modalDialogClass}--dockOnMobile`;
const modalDialogExpandedOnMobileClass = `${modalDialogClass}--expandOnMobile`;
const modalHeaderClass = `${modalClass}Header`;
const modalTitleClass = `${modalHeaderClass}__title`;
Expand All @@ -45,7 +48,10 @@ export function useModalStyleProps(
};
const classProps = {
root: modalClass,
dialog: classNames(modalDialogClass, { [modalDialogExpandedOnMobileClass]: isExpandedOnMobile }),
dialog: classNames(modalDialogClass, {
[modalDialogDockedOnMobileClass]: isDockedOnMobile,
[modalDialogExpandedOnMobileClass]: isExpandedOnMobile,
}),
title: modalTitleClass,
header: modalHeaderClass,
body: modalBodyClass,
Expand Down
1 change: 1 addition & 0 deletions packages/web-react/src/types/modal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export interface ModalCloseButtonProps extends ModalDialogHandlingProps {

export type ModalDialogBaseProps<E extends ElementType = ModalDialogElementType> = {
elementType?: E;
isDockedOnMobile?: boolean;
isExpandedOnMobile?: boolean;
} & ChildrenProps &
StyleProps;
Expand Down
4 changes: 2 additions & 2 deletions packages/web-twig/src/Resources/components/Modal/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -325,8 +325,8 @@ When you put it all together:
## Feature Flag: Uniform Appearance on All Breakpoints

The uniform appearance of modal dialog on all breakpoints is disabled by default. To enable it, either set the
`$modal-enable-uniform-dialog` feature flag to `true` or use the `spirit-modal-enable-uniform-dialog` CSS class on any
parent of the modal.
`$modal-enable-uniform-dialog` Sass feature flag to `true` or use the `spirit-feature-modal-enable-uniform-dialog` CSS
class on any parent of the modal.

For more info, see main [README][readme-feature-flags].

Expand Down
2 changes: 1 addition & 1 deletion packages/web/src/scss/components/Dropdown/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ Current class combinations (`Dropdown--top.Dropdown--left`, `.Dropdown--top.Drop
## Feature Flag: Enhanced Shadow

The enhanced shadow feature is disabled by default. To enable it, either set the `$dropdown-enable-enhanced-shadow`
feature flag to `true` or use the `spirit-dropdown-enable-enhanced-shadow` CSS class on any parent of the dropdown.
Sass feature flag to `true` or use the `spirit-dropdown-enable-enhanced-shadow` CSS class on any parent of the dropdown.

For more info, see main [README][readme-feature-flags].

Expand Down
4 changes: 2 additions & 2 deletions packages/web/src/scss/components/Modal/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -355,8 +355,8 @@ Both trigger and close buttons use `data` attributes to open and close the Modal
## Feature Flag: Uniform Appearance on All Breakpoints

The uniform appearance of modal dialog on all breakpoints is disabled by default. To enable it, either set the
`$modal-enable-uniform-dialog` feature flag to `true` or use the `spirit-modal-enable-uniform-dialog` CSS class on any
parent of the modal.
`$modal-enable-uniform-dialog` Sass feature flag to `true` or use the `spirit-feature-modal-enable-uniform-dialog` CSS
class on any parent of the modal.

For more info, see main [README][readme-feature-flags].

Expand Down
2 changes: 1 addition & 1 deletion packages/web/src/scss/components/Tooltip/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Bare Tooltip HTML:

Tooltip placement is currently using CSS modifiers. In the future it will be using `data-spirit-placement`
attribute in order to make the placement independent of the component and compatible with Floating UI.
To enable this behavior now you can use the feature flag, either set the `$tooltip-enable-data-placement`
To enable this behavior now you can use the feature flag, either set the `$tooltip-enable-data-placement` Sass
feature flag to `true` or use the `spirit-feature-tooltip-enable-data-placement` CSS class on any parent of the Tooltip.

For more info, see main [README][readme-feature-flags].
Expand Down

0 comments on commit 531a9d9

Please sign in to comment.