Modal#

The Modal component inheritely uses Reakit's Modal component and follows the WAI-ARIA Modal Pattern. It is rendered within a Portal & focus is trapped by default.

Note: You may want to consider the Dialog component before this one.

Import#

import { Modal } from 'bumbag';

Usage#

Editable example

Backdrop#

You can hide the backdrop with the hideBackdrop prop.

Editable example

Placement#

Change where your modal is positioned with the placement prop.

Editable example

Animation#

Fade#

Editable example

Slide#

Editable example

Expand#

Editable example

Duration#

Editable example

Placement with animation#

Editable example

Restricting closure#

You can restrict closure with either the hideOnEsc or hideOnClickOutside prop.

Editable example

Controlled#

Editable example

Composition#

The Modal component comes with utilities to compose with other components.

use#

Editable example

Hooks#

Editable example

Render props#

Editable example

Accessing internal state#

Any descendant component of Modal.State can utilise Modal.useContext to access the internal modal state:

function Example() {
const { modal } = Modal.useContext();
return (
<Button onClick={modal.hide}>Hide modal</Button>
)
}

Accessibility#

The <Modal> component follows the WAI ARIA Dialog (Modal) Pattern.

Rules#

  • A Modal must be triggered via <Modal.Disclosure>, or Modal.Disclosure.useProps.

Patterns#

  • Modal has a role of dialog.
  • Modal has the aria-modal attribute set to true, unless the modal prop is set to false.
  • When the modal opens, focus is set to the first focusable element in the modal.
  • Focus is trapped inside the modal, unless the modal prop is set to false.
  • Esc closes the modal unless `hideOnEsc` is `false`.
  • Clicking outside the modal closes it unless hideOnClickOutside is false.
  • When the modal closes, focus returns to the disclosure that triggered it.

References#

Props#

Modal Props#

hideBackdrop boolean

Hides the backdrop.

placement

"top-start"
  | "top"
  | "top-end"
  | "right-start"
  | "right"
  | "right-end"
  | "bottom-end"
  | "bottom"
  | "bottom-start"
  | "left-end"
  | "left"
  | "left-start"
  | "center"

Sets the placement of the modal.

delay string

Delay of the animation (in s/ms).

duration string

Duration of the animation (in s/ms).

expand

boolean
  | "top"
  | "right"
  | "bottom"
  | "left"
  | "center"

Will the component have an expand animation when it is toggled on/off?

fade boolean

Will the component have a fade animation when it is toggled on/off?

slide boolean | "top" | "right" | "bottom" | "left"

Will the component have a slide animation when it is toggled on/off?

timingFunction string

Timing function of the animation

hideOnEsc boolean

When enabled, user can hide the dialog by pressing Escape.

hideOnClickOutside boolean

When enabled, user can hide the dialog by clicking outside it.

preventBodyScroll boolean

When enabled, user can't scroll on body when the dialog is visible. This option doesn't work if the dialog isn't modal.

9 state props
These props are returned by the state hook. You can spread them into this component (...state) or pass them separately. You can also provide these props from your own state logic.

baseId string

ID that will serve as a base for all the items IDs.

visible boolean

Whether it's visible or not.

animating boolean

Whether it's animating or not.

animated number | boolean

If true, animating will be set to true when visible is updated. It'll wait for stopAnimation to be called or a CSS transition ends. If animated is set to a number, stopAnimation will be called only after the same number of milliseconds have passed.

stopAnimation () => void

Stops animation. It's called automatically if there's a CSS transition.

modal boolean

Toggles Dialog's modal state.

  • Non-modal: preventBodyScroll doesn't work and focus is free.
  • Modal: preventBodyScroll is automatically enabled, focus is trapped within the dialog and the dialog is rendered within a Portal by default.

hide () => void

Changes the visible state to false

baseId string Required

ID that will serve as a base for all the items IDs.

Inherits Box props

use

string
  | (ComponentClass<any, any> & { useProps: any; })
  | (FunctionComponent<any> & { useProps: any; })

className string

children

string
  | number
  | boolean
  | {}
  | ReactElement<any, string
  | ((props: any) => ReactElement<any, string
  | ...
  | (new (props: any) => Component<any, any, any>)>)
  | (new (props: any) => Component<...>)>
  | ReactNodeArray
  | ReactPortal
  | ((props: BoxProps) => ReactNode)

alignX "right" | "left" | "center"

alignY "top" | "bottom" | "center"

variant string

colorMode string

disabled boolean

overrides

{
  useCSSVariables?: boolean;
  altitudes?: AltitudesThemeConfig;
  borders?: BordersThemeConfig;
  borderRadii?: BorderRadiiThemeConfig;
  ... 95 more ...;
  Template?: TemplateThemeConfig;
}

elementRef ((instance: any) => void) | RefObject<any>

themeKey string

Modal.Disclosure Props#

disabled boolean

Same as the HTML attribute.

focusable boolean

When an element is disabled, it may still be focusable. It works similarly to readOnly on form elements. In this case, only aria-disabled will be set.

5 state props
These props are returned by the state hook. You can spread them into this component (...state) or pass them separately. You can also provide these props from your own state logic.

visible boolean

Whether it's visible or not.

baseId string Required

ID that will serve as a base for all the items IDs.

toggle () => void Required

Toggles the visible state

toggle () => void Required

Toggles the visible state

Inherits Box props

use

string
  | (ComponentClass<any, any> & { useProps: any; })
  | (FunctionComponent<any> & { useProps: any; })

className string

children

string
  | number
  | boolean
  | {}
  | ReactElement<any, string
  | ((props: any) => ReactElement<any, string
  | ...
  | (new (props: any) => Component<any, any, any>)>)
  | (new (props: any) => Component<...>)>
  | ReactNodeArray
  | ReactPortal
  | ((props: BoxProps) => ReactNode)

alignX "right" | "left" | "center"

alignY "top" | "bottom" | "center"

variant string

colorMode string

overrides

{
  useCSSVariables?: boolean;
  altitudes?: AltitudesThemeConfig;
  borders?: BordersThemeConfig;
  borderRadii?: BorderRadiiThemeConfig;
  ... 95 more ...;
  Template?: TemplateThemeConfig;
}

elementRef ((instance: any) => void) | RefObject<any>

themeKey string

Modal.Backdrop Props#

6 state props
These props are returned by the state hook. You can spread them into this component (...state) or pass them separately. You can also provide these props from your own state logic.

baseId string

ID that will serve as a base for all the items IDs.

visible boolean

Whether it's visible or not.

animating boolean

Whether it's animating or not.

animated number | boolean

If true, animating will be set to true when visible is updated. It'll wait for stopAnimation to be called or a CSS transition ends. If animated is set to a number, stopAnimation will be called only after the same number of milliseconds have passed.

stopAnimation () => void

Stops animation. It's called automatically if there's a CSS transition.

modal boolean

Toggles Dialog's modal state.

  • Non-modal: preventBodyScroll doesn't work and focus is free.
  • Modal: preventBodyScroll is automatically enabled, focus is trapped within the dialog and the dialog is rendered within a Portal by default.
Inherits Box props

use

string
  | (ComponentClass<any, any> & { useProps: any; })
  | (FunctionComponent<any> & { useProps: any; })

className string

children

string
  | number
  | boolean
  | {}
  | ReactElement<any, string
  | ((props: any) => ReactElement<any, string
  | ...
  | (new (props: any) => Component<any, any, any>)>)
  | (new (props: any) => Component<...>)>
  | ReactNodeArray
  | ReactPortal
  | ((props: BoxProps) => ReactNode)

alignX "right" | "left" | "center"

alignY "top" | "bottom" | "center"

variant string

colorMode string

disabled boolean

overrides

{
  useCSSVariables?: boolean;
  altitudes?: AltitudesThemeConfig;
  borders?: BordersThemeConfig;
  borderRadii?: BorderRadiiThemeConfig;
  ... 95 more ...;
  Template?: TemplateThemeConfig;
}

elementRef ((instance: any) => void) | RefObject<any>

themeKey string

State#

Modal.State API#

baseId string

ID that will serve as a base for all the items IDs.

visible boolean

Whether it's visible or not.

animated number | boolean

If true, animating will be set to true when visible is updated. It'll wait for stopAnimation to be called or a CSS transition ends. If animated is set to a number, stopAnimation will be called only after the same number of milliseconds have passed.

modal boolean

Toggles Dialog's modal state.

  • Non-modal: preventBodyScroll doesn't work and focus is free.
  • Modal: preventBodyScroll is automatically enabled, focus is trapped within the dialog and the dialog is rendered within a Portal by default.

Modal.State Return Values#

15 values

baseId string Required

ID that will serve as a base for all the items IDs.

visible boolean Required

Whether it's visible or not.

animated number | boolean Required

If true, animating will be set to true when visible is updated. It'll wait for stopAnimation to be called or a CSS transition ends. If animated is set to a number, stopAnimation will be called only after the same number of milliseconds have passed.

animating boolean Required

Whether it's animating or not.

setBaseId (value: SetStateAction<string>) => void Required

Sets baseId.

show () => void Required

Changes the visible state to true

hide () => void Required

Changes the visible state to false

toggle () => void Required

Toggles the visible state

setVisible (value: SetStateAction<boolean>) => void Required

Sets visible.

setAnimated (value: SetStateAction<number | boolean>) => void Required

Sets animated.

stopAnimation () => void Required

Stops animation. It's called automatically if there's a CSS transition.

modal boolean Required

Toggles Dialog's modal state.

  • Non-modal: preventBodyScroll doesn't work and focus is free.
  • Modal: preventBodyScroll is automatically enabled, focus is trapped within the dialog and the dialog is rendered within a Portal by default.

setModal (value: SetStateAction<boolean>) => void Required

Sets modal.

Modal.useState API#

baseId string

ID that will serve as a base for all the items IDs.

visible boolean

Whether it's visible or not.

animated number | boolean

If true, animating will be set to true when visible is updated. It'll wait for stopAnimation to be called or a CSS transition ends. If animated is set to a number, stopAnimation will be called only after the same number of milliseconds have passed.

modal boolean

Toggles Dialog's modal state.

  • Non-modal: preventBodyScroll doesn't work and focus is free.
  • Modal: preventBodyScroll is automatically enabled, focus is trapped within the dialog and the dialog is rendered within a Portal by default.

Modal.useState Return Values#

15 values

baseId string Required

ID that will serve as a base for all the items IDs.

visible boolean Required

Whether it's visible or not.

animated number | boolean Required

If true, animating will be set to true when visible is updated. It'll wait for stopAnimation to be called or a CSS transition ends. If animated is set to a number, stopAnimation will be called only after the same number of milliseconds have passed.

animating boolean Required

Whether it's animating or not.

setBaseId (value: SetStateAction<string>) => void Required

Sets baseId.

show () => void Required

Changes the visible state to true

hide () => void Required

Changes the visible state to false

toggle () => void Required

Toggles the visible state

setVisible (value: SetStateAction<boolean>) => void Required

Sets visible.

setAnimated (value: SetStateAction<number | boolean>) => void Required

Sets animated.

stopAnimation () => void Required

Stops animation. It's called automatically if there's a CSS transition.

modal boolean Required

Toggles Dialog's modal state.

  • Non-modal: preventBodyScroll doesn't work and focus is free.
  • Modal: preventBodyScroll is automatically enabled, focus is trapped within the dialog and the dialog is rendered within a Portal by default.

setModal (value: SetStateAction<boolean>) => void Required

Sets modal.

Theming#

Modal.styles.base
Modal.styles.placements.center
Modal.styles.placements.left
Modal.styles.placements.right
Modal.styles.placements.top
Modal.styles.placements.bottom
Modal.styles.placements.topStart
Modal.styles.placements.topEnd
Modal.styles.placements.bottomStart
Modal.styles.placements.bottomEnd
Modal.Disclosure.styles.base
Modal.Backdrop.styles.base
Copyright © 2021 Jake Moxey