Back to Evergreen

Introduction

docs/documentation/components/side-sheet.mdx

7.1.95.9 KB
Original Source

Introduction

The SideSheet component is a panel overlaying the screen on the right side. It is used to show more details about a certain object or person. A SideSheet is often triggered by clicking a row in a table.

Use cases

  • Showing a profile view of a user
  • Showing detailed information about a transaction (such as a sync or run)
  • Showing configuration settings that don‘t need to be accessible by a URL

When not to use a side sheet

Side Sheets are a great way to cheat creating a new page. As a general rule of thumb, a SideSheet should not be used as a replacement of a new page when the page needs to be accessible by a URL. Avoid showing a SideSheet based on a URL.

Implementation details

The SideSheet component does not have any opinion about the contents of the SideSheet. In the examples below are some recipes to make sure usage of the SideSheet is consistent. It is recommended to compose more opinionated Side Sheets in the consuming application.

Side sheets close on

  • Backdrop click
  • Close icon button click
  • Escape key
  • The close function being called

Focus management

When opening the SideSheet, focus will be brought inside the SideSheet by looking for elements with [autofocus] first, [tabindex] second and button last.

When closing the SideSheet, focus will be brought back to the element that was focused before opening the SideSheet. This is normally the button that triggered the SideSheet.

Basic example

jsx
function BasicSidesheetExample() {
  const [isShown, setIsShown] = React.useState(false)
  return (
    <React.Fragment>
      <SideSheet isShown={isShown} onCloseComplete={() => setIsShown(false)}>
        <Paragraph margin={40}>Basic Example</Paragraph>
      </SideSheet>
      <Button onClick={() => setIsShown(true)}>Show Basic Side Sheet</Button>
    </React.Fragment>
  )
}

Change position

The SideSheet component can appearn on all side of the screens.

  • Position.TOP
  • Position.RIGHT
  • Position.BOTTOM
  • Position.LEFT
jsx
function CustomPositionSidesheetExample() {
  const [isShown, setIsShown] = React.useState(false)
  return (
    <React.Fragment>
      <SideSheet
        position={Position.BOTTOM}
        isShown={isShown}
        onCloseComplete={() => setIsShown(false)}
      >
        <Paragraph margin={40}>Basic Example</Paragraph>
      </SideSheet>
      <Button onClick={() => setIsShown(true)}>Show Basic Side Sheet</Button>
    </React.Fragment>
  )
}

Full featured example

Full featured example with a header with a title, subtitle and a tab bar. Content is a simple card.

jsx
function FullyFeaturedSidesheetExample() {
  const [isShown, setIsShown] = React.useState(false)
  const [selectedIndex, setSelectedIndex] = React.useState(0)
  return (
    <React.Fragment>
      <SideSheet
        isShown={isShown}
        onCloseComplete={() => setIsShown(false)}
        containerProps={{
          display: 'flex',
          flex: '1',
          flexDirection: 'column'
        }}
      >
        <Pane zIndex={1} flexShrink={0} elevation={0} backgroundColor="white">
          <Pane padding={16} borderBottom="muted">
            <Heading size={600}>Title</Heading>
            <Paragraph size={400} color="muted">
              Optional description or sub title
            </Paragraph>
          </Pane>
          <Pane display="flex" padding={8}>
            <Tablist>
              {['Traits', 'Event History', 'Identities'].map((tab, index) => (
                <Tab
                  key={tab}
                  isSelected={selectedIndex === index}
                  onSelect={() => setSelectedIndex(index)}
                >
                  {tab}
                </Tab>
              ))}
            </Tablist>
          </Pane>
        </Pane>
        <Pane flex="1" overflowY="scroll" background="tint1" padding={16}>
          <Card
            backgroundColor="white"
            elevation={0}
            height={240}
            display="flex"
            alignItems="center"
            justifyContent="center"
          >
            <Heading>Some content</Heading>
          </Card>
        </Pane>
      </SideSheet>
      <Button onClick={() => setIsShown(true)}>Show Basic Side Sheet</Button>
    </React.Fragment>
  )
}

Title only

Example with a header with a title. Content is a simple card.

jsx
function TitleOnlySideSheet() {
  const [isShown, setIsShown] = React.useState(false)

  return (
    <React.Fragment>
      <SideSheet
        isShown={isShown}
        onCloseComplete={() => setIsShown(false)}
        containerProps={{
          display: 'flex',
          flex: '1',
          flexDirection: 'column'
        }}
      >
        <Pane zIndex={1} flexShrink={0} elevation={0} backgroundColor="white">
          <Pane padding={16}>
            <Heading size={600}>Title</Heading>
          </Pane>
        </Pane>
        <Pane flex="1" overflowY="scroll" background="tint1" padding={16}>
          <Card
            backgroundColor="white"
            elevation={0}
            height={240}
            display="flex"
            alignItems="center"
            justifyContent="center"
          >
            <Heading>Some content</Heading>
          </Card>
        </Pane>
      </SideSheet>
      <Button onClick={() => setIsShown(true)}>Show Basic Side Sheet</Button>
    </React.Fragment>
  )
}

Preserve scroll position and prevent body scrolling

Use the preventBodyScrolling prop to disable scrolling outside the side sheet.

jsx
function PreventBodyScrollingSidesheetExample() {
  const [isShown, setIsShown] = React.useState(false)
  return (
    <React.Fragment>
      <SideSheet
        isShown={isShown}
        onCloseComplete={() => setIsShown(false)}
        preventBodyScrolling
      >
        <Paragraph margin={40}>Basic Example</Paragraph>
      </SideSheet>
      <Button onClick={() => setIsShown(true)}>Show Basic Side Sheet</Button>
    </React.Fragment>
  )
}