Components

Modal

Modals are used to overlay content above an interface. They are intended to capture the user's attention in order to inform or shift focus to a pertinent task.

Always specify a appElementSelector property to trap keyboard focus in the modal and hide the rest of the app content temporarily.

import { Modal } from '@sproutsocial/racine'
() => {
const [open, setOpen] = useState(false)
const toggleModal = () => setOpen(!open)
return (
<Box>
<Button appearance="secondary" onClick={toggleModal} width={1}>
Open modal
</Button>
<Modal
//appElementSelector='___gatsby'
isOpen={open}
onClose={toggleModal}
closeButtonLabel="Close this modal"
label="Assign Chatbot"
zIndex={900}
>
<Modal.Header
title="Assign Chatbot"
subtitle="The chatbot will respond to customers from this profile."
/>
<Modal.Content>
<Text fontSize={300} color="text.body">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Lorem
ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Lorem ipsum
dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua.
</Text>
</Modal.Content>
<Modal.Footer>
<Box display="flex" justifyContent="flex-end">
<Button appearance="unstyled" onClick={toggleModal} mr={400}>
Go back
</Button>
<Button appearance="primary" onClick={toggleModal} px={500}>
Submit
</Button>
</Box>
</Modal.Footer>
</Modal>
</Box>
)
}

Properties

NameTypeDefaultDescriptionRequired?
appElementSelectorstring
section of app to aria hide for the modal
isOpenboolean
trigger to open or close the modal
labelstring
label for screen readers to announce the modal
childrenReact.ReactNode
body content of the modal
onClose() => void
callback for close
closeButtonLabelstring
aria-label for modal X
zIndexnumber6
Controls the z-index CSS property
width
string
number
"800px"
The max width of the modal container
data
string
string | boolean | number
Custom attributes to be added to the modals container Each key will be prepended with "data-" when rendered in the DOM

Subcomponents

The Modal.Header subcomponent is optional (not all Modals have to have headers), but if a header is present it should always be rendered as the first child of the Modal.

The following example shows a Modal header with a title and subtitle. Note: when rendered within an actual Modal, a close button will also be shown.

<Modal.Header
title="Assign Chatbot"
subtitle="The chatbot will respond to customers from this profile."
/>

This title and subtitle configuration is the default, but if you would like to create your own header you can do so by passing children:

<Modal.Header bordered>
<Box
display="flex"
alignItems="center"
justifyContent="space-between"
width={1}
>
<Text as="div" fontSize={400} fontWeight="semibold">
Custom header
</Text>
<Button appearance="primary">Some action</Button>
</Box>
</Modal.Header>

Note that the bordered prop is needed on a custom header if the bottom border is desired. If children are provided, the title and subtitle props are ignored.

The Modal.CloseButton subcomponent renders an icon button (using the icon) that will close the parent Modal when clicked.

The Modal.Content subcomponent is a simple wrapper used to contain the content of a Modal (any items not within the header or footer), and ensures that the contents scroll when appropriate.

The Modal.Footer subcomponent renders it's children with the appropriate padding and border for the footer of a Modal. This component should always be rendered after an instance of Modal.Content.

<Modal.Footer>Footer content</Modal.Footer>

Recipes

Modal headers can be omitted altogether, or they can render only a close button if neither a title, subtitle, or children prop is passed to the Modal.Header subcomponent.

This should only be done with the first item in the modal body is an image or illustration. If the modal body begins with text, a bordered header with a title or subtitle should be used.

The following example shows a modal rendering an empty header, which displays only a close button in the upper right corner.

() => {
const [open, setOpen] = useState(false)
const toggleModal = () => setOpen(!open)
return (
<Box>
<Button appearance="secondary" onClick={toggleModal} width={1}>
Open modal
</Button>
<Modal
//appElementSelector='___gatsby'
isOpen={open}
onClose={toggleModal}
closeButtonLabel="Close this modal"
label="Example Modal"
zIndex={900}
>
<Modal.Header />
<Modal.Content>
<Box
mb={500}
display="flex"
alignItems="center"
flexDirection="column"
>
<Box width="400px" height="400px" bg="neutral.200" />
<Text
fontSize={400}
fontWeight="bold"
color="text.headline"
pt={600}
>
Some headline
</Text>
<Text
fontSize={300}
textAlign="center"
color="text.body"
pt={450}
px={500}
>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Lorem
ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua.
</Text>
</Box>
</Modal.Content>
<Modal.Footer>
<Box display="flex" justifyContent="flex-end">
<Button appearance="primary" onClick={toggleModal}>
Close modal
</Button>
</Box>
</Modal.Footer>
</Modal>
</Box>
)
}

Expressive modal

() => {
const [open, setOpen] = useState(false)
const toggleModal = () => setOpen(!open)
return (
<Box>
<Button appearance="secondary" onClick={toggleModal} width={1}>
Open modal
</Button>
<Modal
isOpen={open}
onClose={toggleModal}
closeButtonLabel="Close this modal"
label="Example Modal"
zIndex={900}
bg="blue.400"
width="30%"
>
<Modal.Header>
<Box display="flex" flexDirection="row-reverse" width={1}>
<Modal.CloseButton color="neutral.0" />
</Box>
</Modal.Header>
<Image
alt="expressive illustration"
mb={600}
src={withPrefix('/illus.svg')}
/>
<Box
width="100%"
bg="neutral.0"
p={600}
display="flex"
flexDirection="column"
>
<Text
fontSize={400}
color="text.headline"
fontWeight={700}
textAlign="center"
pb={400}
>
Engagement makes the world go 'round.
</Text>
<Text fontSize={200} textAlign="center" color="text.body">
We care about how you engage with your customers and we’re here to
make that experience as smooth and seamless as possible.
</Text>
</Box>
<Modal.Footer>
<Box display="flex" justifyContent="flex-end">
<Button appearance="primary" onClick={toggleModal} minWidth={120}>
Thanks
</Button>
</Box>
</Modal.Footer>
</Modal>
</Box>
)
}

Destructive confirmation

() => {
const [open, setOpen] = useState(false)
const toggleModal = () => setOpen(!open)
return (
<Box>
<Button appearance="secondary" onClick={toggleModal} width={1}>
Open modal
</Button>
<Modal
isOpen={open}
onClose={toggleModal}
closeButtonLabel="Close this modal"
label="Example Modal"
zIndex={900}
width="30%"
>
<Modal.Header
title="Delete profiles?"
subtitle="This action can not be undone."
></Modal.Header>
<Modal.Content>
<Text as='div' py={300} fontSize={300} color="text.body">
Deleting this profile will remove it from all groups as well as
remove any messages associated with this profile. Are you sure you
want to proceed?
</Text>
</Modal.Content>
<Modal.Footer>
<Box display="flex" justifyContent="flex-end">
<Button appearance="unstyled" onClick={toggleModal} mr={400}>
Cancel
</Button>
<Button
appearance="destructive"
onClick={toggleModal}
minWidth="120px"
>
Confirm
</Button>
</Box>
</Modal.Footer>
</Modal>
</Box>
)
}

Free form modal

This example showcases the freedom and flexibility we have within Modal.Content

() => {
const [open, setOpen] = useState(false)
const toggleModal = () => setOpen(!open)
return (
<Box>
<Button appearance="secondary" onClick={toggleModal} width={1}>
Open modal
</Button>
<Modal
isOpen={open}
onClose={toggleModal}
closeButtonLabel="Close this modal"
label="Example Modal"
zIndex={900}
>
<Modal.Header bordered>
<Box
display="flex"
alignItems="center"
justifyContent="space-between"
width={1}
>
<Box display="flex" flexDirection="column">
<Text fontSize={400} fontWeight="bold" color="text.headline">
Free form experience
</Text>
<Text fontSize={200} color="text.subtext">
Browse and select things from the list as you please, nothing is
required.
</Text>
</Box>
<Box display="flex">
<Button mr={350} appearance="unstyled" onClick={toggleModal}>
Cancel
</Button>
<Button
minWidth="120px"
appearance="primary"
onClick={toggleModal}
>
Complete
</Button>
</Box>
</Box>
</Modal.Header>
<Modal.Content display="flex">
<Box width={1 / 2} display="flex" flexDirection="column" pr={450}>
<Text
fontWeight={700}
fontSize={300}
color="text.headline"
mb={400}
>
An informational headline
</Text>
<Text fontSize={200} color="text.body" mb={350}>
Authoritatively integrate installed base deliverables without
worldwide intellectual capital. Progressively promote functional
markets before mission-critical potentialities.
</Text>
<Text fontSize={200} color="text.body" mb={350}>
Assertively incentivize 2.0 communities with quality technologies.
Globally benchmark accurate sources for go forward systems.
Energistically develop out-of-the-box ideas and quality services.
</Text>
</Box>
<Box width={1 / 2}>
<ModalListExample />
</Box>
</Modal.Content>
</Modal>
</Box>
)
}