Default Modal

frame: true
noPadding: true
---
<div style={{ height: '400px' }}>
    <Modal
        open={true}
        closable={true}
        title="Grand Moff Tarkin"
        footer={<Button primary>Close</Button>}
        portal={false}
    >
        Don't worry, we'll deal with your rebel friends soon enough!
    </Modal>
</div>

Size

Modals have four sizes depending on the width of content that needs to be displayed. Medium is the default size.

const Example = () => {
    const [open, setOpen] = React.useState(false);
    const [modalWidth, setWidth] = React.useState(Modal.Sizes.S);
    const toggleOpen = () => setOpen(!open);
    const widthValue = (width) => setWidth(width);
    const widths = [Modal.Sizes.XS, Modal.Sizes.S, Modal.Sizes.M, Modal.Sizes.L];

    return (
        <div>
            <ButtonGroup>
                {widths.map( (width, index) => (
                    <Button key={index} onClick={() => { widthValue(width); toggleOpen(); }}><span className="tt-uppercase m-r-half">{width}</span> Modal</Button>
                ))}
            </ButtonGroup>
            <Modal
                open={open}
                size={modalWidth}
                closable={true}
                onClose={toggleOpen}
                title={"Hello"}
                footer={<Button primary onClick={toggleOpen}>Close</Button>}
            >
                Don't worry, we'll deal with your rebel friends soon enough!
            </Modal>
        </div>
    );
};
render (Example);

Scrolling Content

When the content of the modal is larger than the screen supports, it becomes scrollable with consistent spacing between the screen edge and the modal.

frame: true
noPadding: true
---
<div style={{ height: '400px' }}>
    <Modal
        open={true}
        closable={true}
        title="Grand Moff Tarkin"
        footer={<Button primary>Close</Button>}
        portal={false}
    >
        <p style={{marginTop: 0}}>
            Chia cillum etsy pabst, in paleo fashion axe.
            Gastropub pariatur tilde wayfarers chia laboris.
            Salvia cred franzen chambray cillum slow-carb.
            Beard letterpress distillery, knausgaard readymade YOLO in.
            Aesthetic ea aliqua, blog vaporware kombucha gluten-free art party VHS pariatur cray raclette.
        </p>

        <p>
            Pop-up kale chips four dollar toast gastropub you probably haven't heard of them prism tote bag.
            Paleo thundercats godard glossier +1, iceland anim.
            Readymade sriracha occaecat, crucifix bicycle rights retro seitan exercitation craft beer kale
            chips minim.
            Do post-ironic wayfarers, seitan etsy small batch hammock green juice hexagon whatever hoodie
            ipsum fashion axe copper mug.
            Fingerstache put a bird on it palo santo craft beer.
        </p>

        <p>
            Adaptogen officia cred ut enamel pin.
            Man bun fixie blue bottle minim proident franzen raw denim fanny pack, church-key edison bulb
            butcher lumbersexual vaporware ethical YOLO.
            Mlkshk elit austin succulents live-edge poke esse pork belly williamsburg consectetur
            helvetica craft beer put a bird on it pop-up aliqua.
            Viral irure synth laboris laborum.
        </p>

        <p>
            Ut blue bottle activated charcoal pickled meh.
            Forage esse occupy artisan aliquip scenester biodiesel street art actually truffaut succulents
            art party yr nulla ethical.
            Hell of waistcoat aliquip gochujang sunt, fashion axe sed ut photo booth cronut.
            Kogi tattooed semiotics cold-pressed adipisicing taiyaki.
        </p>
    </Modal>
</div>

Non-closable Modals

For mandatory workflows and notifications, we can also remove the close functionality. The close button in the Modal Header does not appear and clicking on the backdrop doesn't do anything.

const Example = () => {
    const [open, setOpen] = React.useState(false);
    const toggleOpen = () => setOpen(!open);

    return (
        <div>
            <Button onClick={toggleOpen}>Open</Button>
            <Modal
                open={open}
                title="Accept Estimate"
                footer={<Button primary onClick={toggleOpen}>I Accept</Button>}
            >
                <Form>
                    <Form.Input value="John Smith" />
                </Form>
                <p>I understand this is a legal representation of my signature.</p>
            </Modal>
        </div>
    );
};
render (Example);

Footer Styles

The Modal Footer can have a few layouts depending on the needs of the Modal. Usually they fall into one of these four layouts.

frame: true
noPadding: true
---
<div style={{ height: '200px' }}>
    <Modal
        open={open}
        footer={<Button primary>Save</Button>}
        portal={false}
    >
        Single Right Aligned Button
    </Modal>
</div>
frame: true
noPadding: true
---
<div style={{ height: '200px' }}>
    <Modal
        open={open}
        footer={<ButtonGroup>
            <Button>Cancel</Button>
            <Button primary>Save</Button>
        </ButtonGroup>}
        portal={false}
    >
        Double Right Aligned Buttons
    </Modal>
</div>
frame: true
noPadding: true
---
<div style={{ height: '200px' }}>
    <Modal
        open={open}
        footer={<Button>Close</Button>}
        footerAlign="center"
        portal={false}
    >
        Centered Button
    </Modal>
</div>
frame: true
noPadding: true
---
<div style={{ height: '200px' }}>
    <Modal
        open={open}
        footer={<React.Fragment>
            <Button>Cancel</Button>
            <Button primary>Save</Button>
        </React.Fragment>}
        footerAlign="space-between"
        portal={false}
    >
        Split Buttons
    </Modal>
</div>

Best Practices

A Modal should:

  • Be used to display critical information or workflows that do not merit full pages
  • Include clear call-to-actions for the user to proceed, cancel, or close
  • Be used sparingly because they are purposefully interruptive

Related Components

  • To completely hide the context of the page, use a Takeover component.
  • For critical information that requires a specific decision, use a Dialog component.
  • For informative or basic actions that do not interrupt the user flow, use a Popover.

Importing

import { Modal } from '@servicetitan/design-system';