Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BREAKING CHANGE(web-twig): Rename height and maxHeight ModalDialog props and enhance them #DS-1134 #1434

Merged
merged 1 commit into from
May 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions docs/migrations/web-twig/MIGRATION-v3.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Introducing version 3 of the _spirit-web-twig_ package
- [Grid: GridSpan Component](#grid-gridspan-component)
- [Header: Abstracts Class and Style](#header-abstracts-class-and-style)
- [Modal: ModalDialog `isScrollable` Prop](#modal-modaldialog-isscrollable-prop)
- [Modal: ModalDialog Custom Height](#modal-modaldialog-custom-height)
- [Modal: ModalDialog Uniform Appearance](#modal-modaldialog-uniform-appearance)
- [Tabs: TabLink `target` Prop](#tabs-tablink-target-prop)
- [Tooltip: Composition](#tooltip-composition)
Expand Down Expand Up @@ -193,6 +194,27 @@ Add `isScrollable` prop to the `ModalDialog` component.
If you use `ScrollView` for scrolling the content of your modal, you must also make the
`ModalDialog` scrollable by setting the `isScrollable` prop.

### Modal: ModalDialog Custom Height

The `preferredHeightOnMobile` and `preferredHeightFromTabletUp` props were removed and
replaced with one prop `height` which accepts either a single value or
object with breakpoint keys and values.

Also, the prop `maxHeightFromTabletUp` was removed and replaced with the `maxHeight` prop,
which also accepts either a single value or object with breakpoint keys and values.

#### Migration Guide

Update the `preferredHeightOnMobile` and `preferredHeightFromTabletUp` props to the new `height` prop.

- `<ModalDialog preferredHeightOnMobile="333px" … />` → `<ModalDialog height="333px" … />`
- `<ModalDialog preferredHeightFromTabletUp="444px" … />` → `<ModalDialog height="{{ { tablet: '444px' } }}" … />`
- `<ModalDialog preferredHeightOnMobile="333px" preferredHeightFromTabletUp="444px" … />` → `<ModalDialog height="{{ { mobile: '333px', tablet: '444px' } }}" … />`

Update the `maxHeightFromTabletUp` prop to the new `maxHeight` prop.

- `<ModalDialog maxHeightFromTabletUp="555px" … />` → `<ModalDialog maxHeight="{{ { tablet: '555px' } }}" … />`

### Modal: ModalDialog Uniform Appearance

The uniform `ModalDialog` appearance replaced the current behavior. Current mobile appearance
Expand Down
35 changes: 23 additions & 12 deletions packages/web-twig/src/Resources/components/Modal/ModalDialog.twig
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
{# API #}
{%- set props = props | default([]) -%}
{%- set _elementType = props.elementType | default('article') -%}
{%- set _height = props.height | default(null) -%}
{%- set _isDockedOnMobile = props.isDockedOnMobile | default(false) -%}
{%- set _isExpandedOnMobile = props.isExpandedOnMobile | default(false) -%}
{%- set _isScrollable = props.isScrollable | default(false) -%}
{%- set _maxHeightFromTabletUp = props.maxHeightFromTabletUp | default(null) -%}
{%- set _preferredHeightOnMobile = props.preferredHeightOnMobile | default(null) -%}
{%- set _preferredHeightFromTabletUp = props.preferredHeightFromTabletUp | default(null) -%}
{%- set _maxHeight = props.maxHeight | default(null) -%}

{# Class names #}
{%- set _rootClassName = _spiritClassPrefix ~ 'ModalDialog' -%}
Expand All @@ -30,15 +29,27 @@
] : [] -%}

{%- set _style = '' -%}
{%- if _maxHeightFromTabletUp -%}
{% set _style = _style ~ '--modal-max-height-tablet: ' ~ _maxHeightFromTabletUp ~ ';' %}
{%- endif -%}
{%- if _preferredHeightOnMobile -%}
{% set _style = _style ~ '--modal-preferred-height-mobile: ' ~ _preferredHeightOnMobile ~ ';' %}
{%- endif -%}
{%- if _preferredHeightFromTabletUp -%}
{% set _style = _style ~ '--modal-preferred-height-tablet: ' ~ _preferredHeightFromTabletUp ~ ';' %}
{%- endif -%}
{%- set heightProps = {
'maxHeight': _maxHeight,
'height': _height
} -%}
{%- for key, value in heightProps -%}
{%- if value -%}
{%- set infix = (key == 'maxHeight') ? 'max-' : '' -%}
{%- set styleVariable = 'modal-dialog-' ~ infix ~ 'height' -%}

{%- if value is iterable -%}
{%- for breakpoint, breakpointValue in value -%}
{%- if breakpointValue -%}
{%- set suffix = (breakpoint == 'mobile') ? '' : '-' ~ breakpoint -%}
{%- set _style = _style ~ '--' ~ styleVariable ~ suffix ~ ': ' ~ breakpointValue ~ ';' -%}
{%- endif -%}
{%- endfor -%}
{%- else -%}
{%- set _style = _style ~ '--' ~ styleVariable ~ ': ' ~ value ~ ';' -%}
{%- endif -%}
{%- endif -%}
{% endfor %}

{# Attributes #}
{%- set _styleAttr = _style or (_styleProps.style is not same as(null)) ? 'style="' ~ _style ~ _styleProps.style | join() ~ '"' -%}
Expand Down
60 changes: 35 additions & 25 deletions packages/web-twig/src/Resources/components/Modal/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,24 +107,23 @@ By default, the docked dialog on mobile screens shrinks to fit the height of its

### API

| Name | Type | Default | Required | Description |
| ----------------------------- | ----------------------------- | --------- | -------- | -------------------------------------------------------------------------------------------------------------------------- |
| `accept-charset` | `string` | `null` | ✕ | `elementType="form"` only: Character encodings to use for form submission (intentionally in kebab-case) |
| `action` | `string` | `null` | ✕ | `elementType="form"` only: URL to use for form submission |
| `autocomplete` | `string` | `null` | ✕ | `elementType="form"` only: [Automated assistance in filling][autocomplete-attr] |
| `elementType` | `string` | `article` | ✕ | HTML tag to render |
| `enctype` | `string` | `null` | ✕ | `elementType="form"` only: Encoding to use for form submission |
| `isDockedOnMobile` | `bool` | `false` | ✕ | Dock the ModalDialog to the bottom of the screen on mobile |
| `isExpandedOnMobile` | `bool` | `false` | ✕ | If the ModalDialog should expand on mobile. Overrides any height defined by `preferredHeightOnMobile`. |
| `isScrollable` | `bool` | `true` | ✕ | If the ModalDialog should be scrollable. If set to `false`, the dialog will not scroll and will expand to fit the content. |
| `maxHeightFromTabletUp` | `string` | `null` | ✕ | Max height of the modal. Accepts any valid CSS value. |
| `method` | [`get` \| `post` \| `dialog`] | `null` | ✕ | `elementType="form"` only: HTTP method to use for form submission |
| `name` | `string` | `null` | ✕ | `elementType="form"` only: Name of the form |
| `novalidate` | `void` | `null` | ✕ | `elementType="form"` only: [If the dialog should have validation disabled][novalidate-attr] |
| `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. |
| `rel` | `string` | `null` | ✕ | `elementType="form"` only: Relationship between the current document and the linked resource |
| `target` | `string` | `null` | ✕ | `elementType="form"` only: Browsing context for form submission |
| Name | Type | Default | Required | Description |
| -------------------- | ----------------------------- | --------- | -------- | -------------------------------------------------------------------------------------------------------------------------- |
| `accept-charset` | `string` | `null` | ✕ | `elementType="form"` only: Character encodings to use for form submission (intentionally in kebab-case) |
| `action` | `string` | `null` | ✕ | `elementType="form"` only: URL to use for form submission |
| `autocomplete` | `string` | `null` | ✕ | `elementType="form"` only: [Automated assistance in filling][autocomplete-attr] |
| `elementType` | `string` | `article` | ✕ | HTML tag to render |
| `enctype` | `string` | `null` | ✕ | `elementType="form"` only: Encoding to use for form submission |
| `height` | [`string` \| `object`] | `null` | ✕ | Preferred height of the modal. Accepts any valid CSS value, either as a string or an object with breakpoints as keys. |
| `isDockedOnMobile` | `bool` | `false` | ✕ | Dock the ModalDialog to the bottom of the screen on mobile |
| `isExpandedOnMobile` | `bool` | `false` | ✕ | If the ModalDialog should expand on mobile. Overrides any height defined by `preferredHeightOnMobile`. |
| `isScrollable` | `bool` | `true` | ✕ | If the ModalDialog should be scrollable. If set to `false`, the dialog will not scroll and will expand to fit the content. |
| `maxHeight` | [`string` \| `object`] | `null` | ✕ | Max height of the modal. Accepts any valid CSS value. |
| `method` | [`get` \| `post` \| `dialog`] | `null` | ✕ | `elementType="form"` only: HTTP method to use for form submission |
| `name` | `string` | `null` | ✕ | `elementType="form"` only: Name of the form |
| `novalidate` | `void` | `null` | ✕ | `elementType="form"` only: [If the dialog should have validation disabled][novalidate-attr] |
| `rel` | `string` | `null` | ✕ | `elementType="form"` only: Relationship between the current document and the linked resource |
| `target` | `string` | `null` | ✕ | `elementType="form"` only: Browsing context for form submission |

On top of the API options, the components accept [additional attributes][readme-additional-attributes].
If you need more control over the styling of a component, you can use [style props][readme-style-props]
Expand Down Expand Up @@ -302,15 +301,20 @@ takes over the responsibility for scrolling and provides visual overflow decorat
By default, ModalDialog grows to the height of its content until it reaches the [maximum height](#custom-max-height)
limit.

You can set a custom preferred height of ModalDialog using a custom property:
You can set a custom preferred height of ModalDialog using the `height` prop.
The prop accepts any valid CSS value, either as a string or an object with breakpoints as keys.

- `preferredHeightOnMobile` for mobile screens, and
- `preferredHeightFromTabletUp` for tablet screens and up.
The custom properties fall back to the previous breakpoint using the mobile-first approach. For example, if you set
`height="{{ { tablet: '500px' } }}"` while not setting the `desktop` breakpoint, the value will be used for
both tablet and desktop screens. The single non-object value will be used for all breakpoints.

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
<ModalDialog isScrollable preferredHeightOnMobile="400px" preferredHeightFromTabletUp="500px">
<ModalDialog isScrollable height="500px">
</ModalDialog>
<ModalDialog isScrollable height="{{ { mobile: '300px', tablet: '500px', desktop: '600px' } }}">
</ModalDialog>
```
Expand All @@ -327,11 +331,17 @@ The default maximum height of a scrollable ModalDialog is **600 px**, as long as
If the viewport is smaller, scrollable ModalDialog will shrink to fit the viewport. In such case, the ModalDialog height
will calculate as "viewport height (`100dvh`) minus 1100 spacing".

You can use the prop `maxHeightFromTabletUp` to override the default maximum height limit on tablet
screens and up:
You can use the prop `maxHeight` to override the default maximum height limit.

The custom properties fall back to the previous breakpoint using the mobile-first approach. For example, if you set
`maxHeight="{{ { tablet: '500px' } }}"` while not setting the `desktop` breakpoint, the value will be used for
both tablet and desktop screens. The single non-object value will be used for all breakpoints.

```twig
<ModalDialog isScrollable maxHeightFromTabletUp="700px">
<ModalDialog isScrollable maxHeight="700px">
</ModalDialog>
<ModalDialog isScrollable maxHeight="{{ { mobile: '500px', tablet: '700px', desktop: '800px' } }}">
</ModalDialog>
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,26 +36,40 @@
</ModalDialog>
</Modal>

<!-- Render with scrollable and simple custom height -->
<Modal id="modal-example-custom-height" aria-label="Modal Title">
<ModalDialog isScrollable height="100px" maxHeight="200px">
<ModalHeader modalId="modal-example-custom-height" />
<ModalBody>
<p>Modal Body</p>
</ModalBody>
<ModalFooter>
<Button color="primary">
Submit
</Button>
</ModalFooter>
</ModalDialog>
</Modal>

<!-- Render with all props -->
<Modal alignmentY="top" id="modal-example-2" titleId="modal-example-2-title">
<Modal alignmentY="top" id="modal-example-all" titleId="modal-example-all-title">
<ModalDialog
autocomplete="on"
elementType="form"
height="{{ { mobile: '400px', tablet: '500px', desktop: '600px' } }}"
isDockedOnMobile
isExpandedOnMobile
isScrollable
maxHeightFromTabletUp="700px"
maxHeight="{{ { tablet: '700px' } }}"
method="dialog"
preferredHeightOnMobile="400px"
preferredHeightFromTabletUp="500px"
UNSAFE_className="custom-class"
UNSAFE_style="outline: 5px solid blue; outline-offset: -5px;"
>
<ModalHeader
closeLabel="Close form"
enableDismiss={ false }
modalId="modal-example-2"
titleId="modal-example-2-title"
modalId="modal-example-all"
titleId="modal-example-all-title"
>
Title of the Modal
</ModalHeader>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,38 @@ <h2 class="ModalHeader__title" id="modal-example-title">
</footer>
</article>
</dialog>
<!-- Render with scrollable and simple custom height -->

<dialog aria-label="Modal Title" class="Modal Modal--center" id="modal-example-custom-height">
<article class="ModalDialog ModalDialog--scrollable" style="--modal-dialog-max-height: 200px;--modal-dialog-height: 100px;">
<header class="ModalHeader">
<button aria-controls="modal-example-custom-height" aria-expanded="false" data-spirit-dismiss="modal" data-spirit-target="#modal-example-custom-height" class="Button Button--tertiary Button--medium Button--square" type="button"><svg width="24" height="24" fill="none" viewbox="0 0 24 24" aria-hidden="true">
<use href="#a79dff7a255f69bbe6e39d594aa2275b">
</use></svg> <span class="accessibility-hidden">Close</span></button>
</header>

<div class="ModalBody">
<p>
Modal Body
</p>
</div>

<footer class="ModalFooter ModalFooter--right">
<div class="ModalFooter__actions">
<button class="Button Button--primary Button--medium" type="button">Submit</button>
</div>
</footer>
</article>
</dialog>
<!-- Render with all props -->

<dialog class="Modal Modal--top" id="modal-example-2" aria-labelledby="modal-example-2-title">
<form autocomplete="on" method="dialog" class="ModalDialog ModalDialog--dockOnMobile ModalDialog--expandOnMobile ModalDialog--scrollable custom-class" style="--modal-max-height-tablet: 700px;--modal-preferred-height-mobile: 400px;--modal-preferred-height-tablet: 500px;outline: 5px solid blue; outline-offset: -5px;">
<dialog class="Modal Modal--top" id="modal-example-all" aria-labelledby="modal-example-all-title">
<form autocomplete="on" method="dialog" class="ModalDialog ModalDialog--dockOnMobile ModalDialog--expandOnMobile ModalDialog--scrollable custom-class" style="--modal-dialog-max-height-tablet: 700px;--modal-dialog-height: 400px;--modal-dialog-height-tablet: 500px;--modal-dialog-height-desktop: 600px;outline: 5px solid blue; outline-offset: -5px;">
<header class="ModalHeader">
<h2 class="ModalHeader__title" id="modal-example-2-title">
<h2 class="ModalHeader__title" id="modal-example-all-title">
Title of the Modal
</h2>
<button aria-controls="modal-example-2" aria-expanded="false" class="Button Button--tertiary Button--medium Button--square" type="button"><svg width="24" height="24" fill="none" viewbox="0 0 24 24" aria-hidden="true">
<button aria-controls="modal-example-all" aria-expanded="false" class="Button Button--tertiary Button--medium Button--square" type="button"><svg width="24" height="24" fill="none" viewbox="0 0 24 24" aria-hidden="true">
<use href="#a79dff7a255f69bbe6e39d594aa2275b">
</use></svg> <span class="accessibility-hidden">Close form</span></button>
</header>
Expand Down
Loading
Loading