Skip to main content
react-md

Sheet

The Sheet is an extension of the Dialog component that is positioned on the sides of the viewport instead of centered within the viewport.

Simple Example

The Sheet defaults to rendering to the left of the viewport and requires an aria-label or aria-labelledby for accessibility just like the Dialog.

"use client";

import { Button } from "@react-md/core/button/Button";
import { DialogContent } from "@react-md/core/dialog/DialogContent";
import { DialogHeader } from "@react-md/core/dialog/DialogHeader";
import { DialogTitle } from "@react-md/core/dialog/DialogTitle";
import { Sheet } from "@react-md/core/sheet/Sheet";
import { Typography } from "@react-md/core/typography/Typography";
import { useToggle } from "@react-md/core/useToggle";
import { type ReactElement } from "react";

export default function SimpleExample(): ReactElement {
  const { toggled, enable, disable } = useToggle();

  return (
    <>
      <Button onClick={enable}>Show</Button>
      <Sheet aria-label="Example" visible={toggled} onRequestClose={disable}>
        <DialogHeader>
          <DialogTitle>Title</DialogTitle>
        </DialogHeader>
        <DialogContent>
          <Typography>Hello, world!</Typography>
        </DialogContent>
      </Sheet>
    </>
  );
}

Press Enter to start editing.

Sheet Positions

The Sheet can be rendered at the "left" (default), "right", "top", or "bottom" by using the position prop.

"use client";

import { Box } from "@react-md/core/box/Box";
import { Button } from "@react-md/core/button/Button";
import { DialogContent } from "@react-md/core/dialog/DialogContent";
import { DialogHeader } from "@react-md/core/dialog/DialogHeader";
import { DialogTitle } from "@react-md/core/dialog/DialogTitle";
import { Option } from "@react-md/core/form/Option";
import { Select } from "@react-md/core/form/Select";
import { Sheet } from "@react-md/core/sheet/Sheet";
import { type SheetPosition } from "@react-md/core/sheet/styles";
import { Typography } from "@react-md/core/typography/Typography";
import { useToggle } from "@react-md/core/useToggle";
import { type ReactElement, useState } from "react";

export default function SheetPositionsExample(): ReactElement {
  const { toggled, enable, disable } = useToggle();
  const [position, setPosition] = useState<SheetPosition>("left");

  return (
    <Box stacked>
      <Button onClick={enable}>Show</Button>
      <Select
        label="Sheet Position"
        value={position}
        onChange={(event) => {
          setPosition(event.currentTarget.value);
        }}
      >
        {positions.map((position) => (
          <Option key={position} value={position}>
            {position}
          </Option>
        ))}
      </Select>
      <Sheet
        aria-label="Example"
        position={position}
        visible={toggled}
        onRequestClose={disable}
      >
        <DialogHeader>
          <DialogTitle>Title</DialogTitle>
        </DialogHeader>
        <DialogContent>
          <Typography>Hello, world!</Typography>
        </DialogContent>
      </Sheet>
    </Box>
  );
}

const positions: readonly SheetPosition[] = ["left", "right", "top", "bottom"];

Press Enter to start editing.

Horizontal Size

Horizontal sheets support the following sizes:

"use client";

import { Box } from "@react-md/core/box/Box";
import { Button } from "@react-md/core/button/Button";
import { DialogContent } from "@react-md/core/dialog/DialogContent";
import { DialogHeader } from "@react-md/core/dialog/DialogHeader";
import { DialogTitle } from "@react-md/core/dialog/DialogTitle";
import { Option } from "@react-md/core/form/Option";
import { Select } from "@react-md/core/form/Select";
import { Sheet } from "@react-md/core/sheet/Sheet";
import { type SheetHorizontalSize } from "@react-md/core/sheet/styles";
import { Typography } from "@react-md/core/typography/Typography";
import { useToggle } from "@react-md/core/useToggle";
import CloseIcon from "@react-md/material-icons/CloseIcon";
import { type ReactElement, useState } from "react";

export default function HorizontalSizeExample(): ReactElement {
  const { toggled, enable, disable } = useToggle();
  const [horizontalSize, setHorizontalSize] =
    useState<SheetHorizontalSize>("media");

  return (
    <Box stacked>
      <Button onClick={enable}>Show</Button>
      <Select
        label="Sheet Position"
        value={horizontalSize}
        onChange={(event) => {
          setHorizontalSize(event.currentTarget.value);
        }}
      >
        {horizontalSizes.map((size) => (
          <Option key={size} value={size}>
            {size}
          </Option>
        ))}
      </Select>
      <Sheet
        aria-label="Example"
        // position="right"
        horizontalSize={horizontalSize}
        visible={toggled}
        onRequestClose={disable}
      >
        <DialogHeader>
          <DialogTitle>Title</DialogTitle>
          <Button aria-label="Close" buttonType="icon" onClick={disable}>
            <CloseIcon />
          </Button>
        </DialogHeader>
        <DialogContent>
          <Typography>
            Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec
            feugiat diam et mauris dapibus bibendum. Praesent vehicula maximus
            egestas. Mauris lacinia lectus elit, quis placerat massa egestas sit
            amet. Sed massa ex, commodo sed orci nec, accumsan sagittis sem.
            Curabitur malesuada urna sit amet leo vehicula lobortis.
            Pellentesque habitant morbi tristique senectus et netus et malesuada
            fames ac turpis egestas. Integer fringilla tincidunt nunc, in
            efficitur nibh placerat quis. Vivamus a est quis nunc vestibulum
            facilisis. Ut ut massa a ante ultricies imperdiet. Orci varius
            natoque penatibus et magnis dis parturient montes, nascetur
            ridiculus mus. Ut viverra volutpat ex, eu scelerisque tortor
            interdum non. Ut cursus mi id turpis tristique, sed fringilla urna
            fermentum. Suspendisse potenti. Suspendisse hendrerit scelerisque
            porttitor. Duis nisi dolor, ultrices quis fermentum ac, interdum eu
            nisl.
          </Typography>
          <Typography>
            Donec nec ultricies tellus. Suspendisse potenti. Cras condimentum,
            arcu tempus ornare aliquet, purus elit bibendum justo, eu pretium
            mauris leo ac ligula. Sed imperdiet odio in vulputate vestibulum.
            Integer vitae commodo elit. Phasellus gravida eros at dolor varius,
            in tempor metus tincidunt. Nulla dictum nec mi in dignissim. Duis
            non mauris a turpis posuere tempor ut vel eros. Donec volutpat velit
            sapien, et varius velit viverra sit amet. Aenean id magna sit amet
            velit rutrum porta in a tortor. Integer vel feugiat tortor. Nullam
            posuere, nulla ut viverra dignissim, eros quam mattis erat, eget
            pretium felis erat non mi. Proin varius est id pretium volutpat.
            Aliquam erat volutpat.
          </Typography>
          <Typography>
            Mauris porta mauris et feugiat blandit. Sed placerat non mauris at
            ultrices. Fusce malesuada sem ut nulla malesuada aliquam.
            Pellentesque fermentum aliquam lorem, at semper ex facilisis ac.
            Fusce laoreet odio vitae sem dictum, at sagittis erat imperdiet.
            Nullam lacinia tortor at diam tempus malesuada. Aliquam vitae
            euismod mi. Integer ac enim commodo felis sollicitudin condimentum
            id at ex. Mauris lobortis est nunc, et scelerisque eros malesuada
            vel.
          </Typography>
          <Typography>
            Integer vel mi nulla. Pellentesque eu tellus quam. Sed sagittis erat
            neque, quis varius justo mattis sed. Donec ac sollicitudin ante.
            Duis sollicitudin suscipit nulla, sed feugiat felis vehicula quis.
            Nunc ullamcorper hendrerit dolor ut consectetur. Praesent arcu diam,
            placerat non sagittis vel, varius ut turpis. Maecenas id mi at nulla
            dapibus rhoncus ac nec nulla. Donec mattis mi convallis odio
            elementum, at pulvinar leo ornare. Praesent consequat augue in
            tellus sodales fermentum.
          </Typography>
          <Typography>
            Sed ultricies nibh ut leo dapibus, eget volutpat lectus auctor.
            Etiam egestas urna nec neque posuere, eget feugiat lacus aliquet.
            Aliquam nunc nulla, faucibus at libero et, dapibus vulputate nisi.
            Cras sit amet sagittis tortor. Donec nec velit nulla. Mauris dictum
            vel ipsum quis bibendum. Aenean elementum nisi urna, vel finibus
            lacus iaculis ut.
          </Typography>
        </DialogContent>
      </Sheet>
    </Box>
  );
}

const horizontalSizes: readonly SheetHorizontalSize[] = [
  "none",
  "media",
  "touch",
  "static",
];

Press Enter to start editing.

Vertical Size

Vertical sheets support the following sizes:

The "touch" size does not automatically span the entire viewport like the horizontal version. Vertical sheets are normally used for rendering menus in a sheet on mobile devices to increase accessibility.

"use client";

import { Box } from "@react-md/core/box/Box";
import { Button } from "@react-md/core/button/Button";
import { DialogContent } from "@react-md/core/dialog/DialogContent";
import { DialogHeader } from "@react-md/core/dialog/DialogHeader";
import { DialogTitle } from "@react-md/core/dialog/DialogTitle";
import { Option } from "@react-md/core/form/Option";
import { Select } from "@react-md/core/form/Select";
import { Sheet } from "@react-md/core/sheet/Sheet";
import { type SheetVerticalSize } from "@react-md/core/sheet/styles";
import { Typography } from "@react-md/core/typography/Typography";
import { useToggle } from "@react-md/core/useToggle";
import CloseIcon from "@react-md/material-icons/CloseIcon";
import { type ReactElement, useState } from "react";

export default function VerticalSizeExample(): ReactElement {
  const { toggled, enable, disable } = useToggle();
  const [verticalSize, setVertical] =
    useState<SheetVerticalSize>("recommended");

  return (
    <Box stacked>
      <Button onClick={enable}>Show</Button>
      <Select
        label="Vertical Size"
        value={verticalSize}
        onChange={(event) => {
          setVertical(event.currentTarget.value);
        }}
      >
        {verticalSizes.map((size) => (
          <Option key={size} value={size}>
            {size}
          </Option>
        ))}
      </Select>
      <Sheet
        aria-label="Example"
        position="top"
        verticalSize={verticalSize}
        visible={toggled}
        onRequestClose={disable}
      >
        <DialogHeader>
          <DialogTitle>Title</DialogTitle>
          <Button aria-label="Close" buttonType="icon" onClick={disable}>
            <CloseIcon />
          </Button>
        </DialogHeader>
        <DialogContent>
          <LoremIpsum />
        </DialogContent>
      </Sheet>
    </Box>
  );
}

const verticalSizes: readonly SheetVerticalSize[] = [
  "none",
  "touch",
  "recommended",
];

function LoremIpsum(): ReactElement {
  return (
    <>
      <Typography>
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec feugiat
        diam et mauris dapibus bibendum. Praesent vehicula maximus egestas.
        Mauris lacinia lectus elit, quis placerat massa egestas sit amet. Sed
        massa ex, commodo sed orci nec, accumsan sagittis sem. Curabitur
        malesuada urna sit amet leo vehicula lobortis. Pellentesque habitant
        morbi tristique senectus et netus et malesuada fames ac turpis egestas.
        Integer fringilla tincidunt nunc, in efficitur nibh placerat quis.
        Vivamus a est quis nunc vestibulum facilisis. Ut ut massa a ante
        ultricies imperdiet. Orci varius natoque penatibus et magnis dis
        parturient montes, nascetur ridiculus mus. Ut viverra volutpat ex, eu
        scelerisque tortor interdum non. Ut cursus mi id turpis tristique, sed
        fringilla urna fermentum. Suspendisse potenti. Suspendisse hendrerit
        scelerisque porttitor. Duis nisi dolor, ultrices quis fermentum ac,
        interdum eu nisl.
      </Typography>
      <Typography>
        Donec nec ultricies tellus. Suspendisse potenti. Cras condimentum, arcu
        tempus ornare aliquet, purus elit bibendum justo, eu pretium mauris leo
        ac ligula. Sed imperdiet odio in vulputate vestibulum. Integer vitae
        commodo elit. Phasellus gravida eros at dolor varius, in tempor metus
        tincidunt. Nulla dictum nec mi in dignissim. Duis non mauris a turpis
        posuere tempor ut vel eros. Donec volutpat velit sapien, et varius velit
        viverra sit amet. Aenean id magna sit amet velit rutrum porta in a
        tortor. Integer vel feugiat tortor. Nullam posuere, nulla ut viverra
        dignissim, eros quam mattis erat, eget pretium felis erat non mi. Proin
        varius est id pretium volutpat. Aliquam erat volutpat.
      </Typography>
      <Typography>
        Mauris porta mauris et feugiat blandit. Sed placerat non mauris at
        ultrices. Fusce malesuada sem ut nulla malesuada aliquam. Pellentesque
        fermentum aliquam lorem, at semper ex facilisis ac. Fusce laoreet odio
        vitae sem dictum, at sagittis erat imperdiet. Nullam lacinia tortor at
        diam tempus malesuada. Aliquam vitae euismod mi. Integer ac enim commodo
        felis sollicitudin condimentum id at ex. Mauris lobortis est nunc, et
        scelerisque eros malesuada vel.
      </Typography>
      <Typography>
        Integer vel mi nulla. Pellentesque eu tellus quam. Sed sagittis erat
        neque, quis varius justo mattis sed. Donec ac sollicitudin ante. Duis
        sollicitudin suscipit nulla, sed feugiat felis vehicula quis. Nunc
        ullamcorper hendrerit dolor ut consectetur. Praesent arcu diam, placerat
        non sagittis vel, varius ut turpis. Maecenas id mi at nulla dapibus
        rhoncus ac nec nulla. Donec mattis mi convallis odio elementum, at
        pulvinar leo ornare. Praesent consequat augue in tellus sodales
        fermentum.
      </Typography>
      <Typography>
        Sed ultricies nibh ut leo dapibus, eget volutpat lectus auctor. Etiam
        egestas urna nec neque posuere, eget feugiat lacus aliquet. Aliquam nunc
        nulla, faucibus at libero et, dapibus vulputate nisi. Cras sit amet
        sagittis tortor. Donec nec velit nulla. Mauris dictum vel ipsum quis
        bibendum. Aenean elementum nisi urna, vel finibus lacus iaculis ut.
      </Typography>
      <Typography>
        Interdum et malesuada fames ac ante ipsum primis in faucibus.
        Pellentesque eget mattis erat. Etiam vitae tellus ipsum. Morbi vitae
        sapien eu lacus cursus vehicula. Nunc varius hendrerit nibh et finibus.
        Nullam mollis pharetra dolor, eu laoreet dui sodales vitae. Donec
        molestie ac massa non dapibus. Suspendisse volutpat ligula vitae
        fermentum aliquam. Nullam eu congue urna. Nulla a libero quis risus
        pharetra ornare.
      </Typography>
      <Typography>
        In interdum lectus et neque mollis, ut gravida mauris sagittis. Nunc
        pellentesque lacus sem, vel lacinia neque hendrerit eu. Nulla facilisi.
        Vivamus eleifend ligula erat, sit amet iaculis est feugiat ut. Aliquam
        mauris nisi, lobortis et tempor eu, cursus vel justo. Curabitur sit amet
        aliquam urna. Nulla eget mi ac tortor condimentum sodales at facilisis
        tellus. Curabitur viverra elementum arcu, non scelerisque tortor congue
        ac. Sed suscipit quam rhoncus, rhoncus dolor malesuada, auctor dui.
        Vestibulum nec iaculis risus. Etiam scelerisque maximus mattis.
        Vestibulum et felis id felis gravida sagittis sed non metus. In sed mi
        rhoncus, tempor nibh non, elementum nulla.
      </Typography>
      <Typography>
        Proin auctor pellentesque orci, sed dapibus libero tempus vel. Cras
        venenatis ex in ipsum tempor ultricies. Etiam dapibus commodo dolor, ut
        pretium purus sagittis et. Fusce nunc turpis, porta non tortor
        scelerisque, egestas iaculis turpis. Nullam eget ultrices mauris, sit
        amet lobortis ipsum. Proin commodo, eros eu facilisis laoreet, sapien
        lectus viverra mi, eget congue felis turpis a orci. Integer condimentum
        vehicula volutpat. Nam id mauris quis nisl pharetra vulputate eget
        accumsan nulla. Nam rutrum ante orci, vitae tincidunt velit aliquet
        vitae. Cras mattis dignissim consectetur. Sed sapien velit, consectetur
        sed nibh a, venenatis rhoncus dui. Donec vitae hendrerit augue, eget
        venenatis nisi.
      </Typography>
      <Typography>
        Duis tincidunt justo ut magna ullamcorper euismod. Aliquam ultricies,
        libero a mollis convallis, neque libero rutrum dolor, at blandit justo
        turpis at ex. Pellentesque ullamcorper urna in tempor feugiat. Praesent
        eget ligula eget tortor mattis suscipit. Aenean volutpat nisi ac
        vestibulum congue. Nulla in tellus quis mauris facilisis tempor.
        Pellentesque malesuada at tellus sed bibendum. Donec ultricies vitae
        dolor a sodales. Sed non justo ac nibh euismod pulvinar. Duis vel risus
        in risus luctus pulvinar et nec mauris. Aliquam blandit tellus nunc, sit
        amet feugiat diam facilisis vitae. Aliquam nisi elit, scelerisque et
        luctus a, mollis eu ex. Pellentesque eget fringilla metus. Ut molestie
        commodo odio finibus consectetur.
      </Typography>
      <Typography>
        Pellentesque molestie ipsum ac felis bibendum vehicula. Aliquam accumsan
        augue ac sapien iaculis fringilla. Sed feugiat est vitae ornare
        consectetur. Nulla lacinia quam nisl, ut mollis lacus placerat at.
        Vivamus non consectetur sapien. Ut ac mollis ante, id ultricies mi.
        Mauris tincidunt at erat sed vestibulum. Curabitur eget tellus venenatis
        sem tincidunt molestie. Morbi tellus sem, accumsan non vestibulum
        fermentum, tristique ac magna. Curabitur congue consectetur nibh quis
        placerat. Integer ultrices orci nisi, vel ornare mauris fringilla at.
      </Typography>
    </>
  );
}

Press Enter to start editing.