@kiwicom/orbit-components
Version:
Orbit-components is a React component library which provides developers with the easiest possible way of building Kiwi.com’s products.
242 lines (184 loc) • 11.4 kB
Markdown
# Modal
To implement Modal component into your project you'll need to the import at least the Modal and the [ModalSection](#modalsection):
```jsx
import Modal, { ModalSection } from "@kiwicom/orbit-components/lib/Modal";
```
> You might need the Portal also. See it's [docs](https://orbit.kiwi/utilities/portal/).
After adding import into your project you can use it simply like:
```jsx
<Modal>
<ModalSection>Hello World!</ModalSection>
</Modal>
```
The Modal component has big variety of usage, please check examples for usage [below](#use-cases).
## Props
Table below contains all types of the props available in the Modal component.
| Name | Type | Default | Description |
| :------------------ | :------------------------- | :--------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| children | `React.Node` | | The content of the Modal. [See Subcomponents](#subcomponents) |
| lockScrolling | `boolean` | `true` | Whether to prevent scrolling of the rest of the page while Modal is open. This is on by default to provide a better user experience. |
| scrollingElementRef | ref (object or function) | | The scrolling element, which depends on the viewport |
| dataTest | `string` | | Optional prop for testing purposes. |
| id | `string` | | Set `id` for `Modal` |
| fixedFooter | `boolean` | `false` | If `true` the ModalFooter will be fixed to the bottom of window. |
| isMobileFullPage | `boolean` | `false` | If `true` the Modal will look like a page on mobile devices. |
| size | [`enum`](#modal-enum) | `"normal"` | The maximum width of the Modal on desktop viewport. |
| onClose | `event => void \| Promise` | | Function for handling onClose event. If you don't pass any function the Close button will not be displayed and it will not be possible to close the Modal. [See Functional specs](#functional-specs) |
| preventOverlayClose | `boolean` | | Property for preventing closing of modal when there is a action on overlay. BEWARE: This should be used only in very specials edge-cases! It breaks user experience. |
| hasCloseButton | `boolean` | `true` | Defines whether the Modal displays a close button. If you disable this, we recommend adding some kind of an alternative. |
| autoFocus | `boolean` | `true` | The autofocus attribute of the Modal, see [this docs](https://www.w3schools.com/tags/att_autofocus.asp). |
| disableAnimation | `boolean` | `false` | Defines whether the Modal performs the slide in animation on mobile. If you want to improve your [CLS](https://web.dev/cls/) score, you might want to set this to `true`. |
| mobileHeader | `boolean` | `true` | If `false` the ModalHeader will not have MobileHeader and CloseContainer |
### Modal enum
| size |
| :------------- |
| `"extraSmall"` |
| `"small"` |
| `"normal"` |
| `"large` |
| `"extraLarge"` |
### Functional specs
- To select the Close Button element for testing purposes, use [data-test="ModalCloseButton"] selector.
- To type a reference you're passing to a modal, use the following example:
```jsx
const modalRef = React.useRef<React.ElementRef<typeof Modal> | null>(null)
```
- You might want to get the current scroll position of a Modal component, which might change based on media queries. Reading it constantly would degrade performance. Instead, get it on demand by using the `getScrollPosition` method in a Modal instance like this:
```jsx
class Component extends React.Component {
const modalRef = React.useRef<React.ElementRef<typeof Modal> | null>(null)
const getScroll = () => {
if (modalRef.current) {
setLocalScrollPosition(modalRef.current.getScrollPosition());
}
};
render() {
return (
<Modal ref={modalRef}>
Some content.
</Modal>
);
}
}
```
- To set the scroll position of a Modal component, use the `setScrollPosition` method in a Modal instance like this:
```jsx
class Component extends React.Component {
const modalRef = React.useRef<React.ElementRef<typeof Modal> | null>(null)
setScroll = () => {
if (modalRef.current) {
modalRef.current.setScrollPosition(100);
}
};
render() {
return (
<Modal ref={modalRef}>
<ModalSection>Example usage of setting up the scrollTop position</ModalSection>
<ModalFooter>
<Button onClick={this.setScroll}>Change scrollTop</Button>
</ModalFooter>
</Modal>
);
}
}
```
---
## Subcomponents
Modal component offers a good flexibility and many variations in its usage. There are three subcomponents which you might use.
### ModalSection
```jsx
import Modal, { ModalSection } from "@kiwicom/orbit-components/lib/Modal";
```
#### Usage
```jsx
<Modal>
<ModalSection suppressed>Hello World!</ModalSection>
</Modal>
```
#### Props
Table below contains all types of the props in the ModalSection component.
| Name | Type | Default | Description |
| :----------- | :----------- | :------ | :------------------------------------------------------ |
| **children** | `React.Node` | | Content of the ModalSection component. |
| dataTest | `string` | | Optional prop for testing purposes. |
| suppressed | `boolean` | `false` | If `true` the ModalSection will have cloudy background. |
### ModalHeader
```jsx
import Modal, { ModalHeader } from "@kiwicom/orbit-components/lib/Modal";
```
#### Usage
```jsx
<Modal>
<ModalHeader title="Orbit design system">Hello World!</ModalHeader>
</Modal>
```
#### Props
Table below contains all types of the props in the ModalHeader component.
| Name | Type | Default | Description |
| :----------- | :----------------------------------- | :------ | :----------------------------------------------------- |
| children | `React.Node` | | The content of the ModalHeader. |
| dataTest | `string` | | Optional prop for testing purposes. |
| description | `React.Node` | | The displayed description of the ModalHeader. |
| illustration | `React.Element<typeof Illustration>` | | The displayed Illustration of the ModalHeader. |
| suppressed | `boolean` | `false` | If `true` the ModalHeader will have cloudy background. |
| title | `React.Node` | | The displayed title of the ModalHeader. |
### ModalFooter
```jsx
import Modal, { ModalFooter } from "@kiwicom/orbit-components/lib/Modal";
// and probably Button
import Button from "@kiwicom/orbit-components/lib/Button";
```
#### Usage:
```jsx
<Modal fixedFooter>
<ModalFooter flex={["0 0 auto", "1 1 100%"]}>
<Button type="secondary" iconLeft={<ChevronLeft />}>
Back
</Button>
<Button block>Continue to Payment</Button>
</ModalFooter>
</Modal>
```
#### Props
Table below contains all types of the props in the ModalFooter component.
| Name | Type | Default | Description |
| :----------- | :-------------------------- | :---------- | :----------------------------------------------------------------------------------------------- |
| **children** | `React.Node` | | The content of the ModalFooter. |
| dataTest | `string` | | Optional prop for testing purposes. |
| flex | `string` or `Array<string>` | `"0 1 auto` | The flex attribute(s) for children of the ModalFooter. [See Functional specs](#functional-specs) |
#### ModalFooter Functional specs
- You can set up different `flex` attribute for every children, or use one for all. See [flex property docs](https://www.w3schools.com/cssref/css3_pr_flex.asp) for more information.
## Use cases
Although this component offers good flexibility of usage, there are tiny limitations for usage.
### Wrapper ModalSections
If you need to wrap the children into custom component, wrap all of the children into **one wrapper**, e.g.:
```jsx
// good
<Modal fixedFooter>
<CustomWrapper>
<ModalHeader />
<ModalSection>
My content
</ModalSection>
<ModalSection>
My content
</ModalSection>
<ModalFooter />
</CustomWrapper>
</Modal>
// bad, the CSS styles will be broken
<Modal fixedFooter>
<ModalHeader />
<CustomWrapper>
<ModalSection>
My content
</ModalSection>
<ModalSection>
My content
</ModalSection>
</CustomWrapper>
<ModalFooter />
</Modal>
```
## Accessibility
- When Modal is closed return focus to the element that opened the modal. You can use `onClose` callback function to achieve this.