-
Notifications
You must be signed in to change notification settings - Fork 129
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Consolidate and simplify the modal API (#949)
- Loading branch information
1 parent
bd23429
commit 4e63620
Showing
52 changed files
with
1,290 additions
and
1,165 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
'@sumup/circuit-ui': major | ||
--- | ||
|
||
Removed the exports of the `Modal`, `ModalWrapper`, `ModalHeader`, `ModalFooter`, `ModalContext`, and `ModalConsumer` components. Use the `useModal` hook instead. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,122 +1,66 @@ | ||
import { Status, Props, Story } from '../../../../.storybook/components'; | ||
import { ModalWrapper, ModalHeader, ModalFooter } from '.'; | ||
|
||
# Modal | ||
|
||
<Status.Stable /> | ||
|
||
Modals are floating cards which overlay the primary UI. All content in a single modal should be related to completing one single task. Modals are heavy UI elements which obscure the primary user interface — avoid them where possible. | ||
The modal component displays self-contained tasks in a focused window that overlays the page content. | ||
|
||
<Story id="components-modal--base" /> | ||
<Props of={ModalWrapper} /> | ||
<Props of={ModalHeader} /> | ||
<Props of={ModalFooter} /> | ||
<Props /> | ||
|
||
## When to use it | ||
|
||
Use it when you want the user to focus on a single and perhaps more complex task. | ||
Generally, use the modal component sparingly. Consider displaying more complex tasks and large amounts of information on a separate page instead. | ||
|
||
## Usage guidelines | ||
## Variants | ||
|
||
#### General guidelines | ||
<Story id="components-modal--variants" /> | ||
|
||
- **Do** use modals sparingly. | ||
- **Do** use modals when you want to isolate an action from the primary UI. | ||
- **Do not** draw a modal over another modal. | ||
- **Do not** fill a modal with content which has multiple end results. | ||
- **Do not** present a modal without a user prompting a modal (e.g. as a popup). | ||
### Contextual | ||
|
||
#### Header guidelines | ||
Use this variant when the modal content requires the context of the page underneath to be understood. On small viewports, the modal component opens up from the bottom as a bottom sheet overlay on top of the page content, dimming the uncovered area while giving a visual context of the page underneath. The height of the bottom sheet can be manually adjusted depending on the use case and the amount of content needed to be displayed. | ||
|
||
- **Do** use concise yet descriptive headings that label the function of the specific modal. | ||
- **Do not** exclude headings from modals. | ||
### Immersive | ||
|
||
#### Content guidelines | ||
|
||
- **Do** align text content to the left. | ||
- **Do not** have more than two columns of content. | ||
|
||
#### Footer guidelines | ||
|
||
The modal footer contains CTA's which carry out an action on the entire modal. | ||
|
||
- **Do** align modal CTA's to the right side of the footer. | ||
- **Do not** have more than one "Primary - Major" CTA. | ||
Use this variant to focus the user's attention on the modal content. On small viewports, the modal component opens up from the bottom as a fullscreen overlay on top of the page content and covers it entirely in favor of an immersive experience. | ||
|
||
## Usage in code | ||
|
||
There are a number of ways to use a modal in code. In some codebases, you | ||
may opt to create a helper higher-order component that complements the | ||
`ModalConsumer`. | ||
|
||
### Using the ModalProvider | ||
First, wrap your application in the `ModalProvider` which keeps track of the open modals, prevents scrolling of the page when a modal is open, and ensures the accessibility of the modal. | ||
|
||
The benefit of using the ModalProvider is that it can be declared once at the application root, and you do not need to manage the open/closed state of the modal yourself. | ||
|
||
```js | ||
import { | ||
useModal, | ||
ModalProvider, | ||
ModalWrapper, | ||
ModalHeader, | ||
Button, | ||
} from '@sumup/circuit-ui'; | ||
|
||
const SayHello = ({ name }) => { | ||
const { setModal } = useModal(); | ||
const showModal = () => { | ||
setModal({ | ||
children: ({ onClose }) => ( | ||
<ModalWrapper> | ||
<ModalHeader title="This is a modal" onClose={onClose} /> | ||
Hello {name} | ||
</ModalWrapper> | ||
), | ||
}); | ||
}; | ||
return <Button onClick={showModal}>Say hello</Button>; | ||
}; | ||
```tsx | ||
// _app.tsx for Next.js or App.js for CRA | ||
import { ThemeProvider } from 'emotion-theming'; | ||
import { light } from '@sumup/design-tokens'; | ||
import { ModalProvider, BaseStyles } from '@sumup/circuit-ui'; | ||
|
||
const Page = () => { | ||
export default function App() { | ||
return ( | ||
<ModalProvider> | ||
<SayHello name="World" /> | ||
</ModalProvider> | ||
<ThemeProvider theme={light}> | ||
<BaseStyles /> | ||
<ModalProvider>{/* Your content here... */}</ModalProvider> | ||
</ThemeProvider> | ||
); | ||
}; | ||
} | ||
``` | ||
|
||
- `ModalWrapper` This is the wrapper for the body of a modal. | ||
- `ModalHeader` This contains the title and the `X` close button. | ||
- `ModalFooter` This component aligns its content. | ||
|
||
### Embedding the modal in code | ||
Then, use the `useModal` hook to open a modal from a component: | ||
|
||
If you prefer to embed the code declaratively inside the component, you can do it as such: | ||
```tsx | ||
import { useModal, Button, Body } from '@sumup/circuit-ui'; | ||
|
||
```js | ||
import { Modal, ModalWrapper, ModalHeader, Button } from '@sumup/circuit-ui'; | ||
|
||
const Page = () => { | ||
const [isModalOpen, setModalOpen] = useState(false); | ||
export function SayHello({ name }) { | ||
const { setModal } = useModal(); | ||
|
||
const toggleModal = () => { | ||
setModalOpen((prev) => !prev); | ||
const handleClick = () => { | ||
setModal({ | ||
children: <Body>Hello {name}</Body>, | ||
variant: 'immersive', | ||
closeButtonLabel: 'Close modal', | ||
}); | ||
}; | ||
|
||
return ( | ||
<Fragment> | ||
<Button onClick={toggleModal}>Open modal</Button> | ||
|
||
<Modal isOpen={isModalOpen} onClose={toggleModal}> | ||
{({ onClose }) => ( | ||
<ModalWrapper> | ||
<ModalHeader onClose={onClose} title="Hello" /> | ||
The modal is open! | ||
</ModalWrapper> | ||
)} | ||
</Modal> | ||
</Fragment> | ||
); | ||
}; | ||
return <Button onClick={handleClick}>Say hello</Button>; | ||
} | ||
``` |
Oops, something went wrong.