Sidebar (Alpha)

Jump to Props

Provide a panel that slides in from the right side of the screen.

Import

A sidebar is triggered via React Context. This context is already provided via the VitalityProvider that should be included at the root level of your app.

import { SidebarContext } from "@vitality-ds/components";

Usage

Sidebars can be used to surface up useful and relevant information to support the user's current context. As it appears along side the current page content, the sidebar allows users to maintain focus on their current task whilst retrieving additional information that may help successfully perform the task. Examples include patient details for letter writing, appointment information or even app extensions and third party integrations.

A sidebar can contain internal navigation such as tabs and breadcrumbs, however the internal navigation state should be kept simple as the state will not be maintained as broader page navigation changes.

Opening and closing the sidebar

To present the sidebar to the user, you call openSidebar(content) from the SidebarContext, with content representing the react component you wish to load.

() => {
  const { openSidebar, closeSidebar } = React.useContext(SidebarContext);

  const ExampleContent = () => (
    <>
      <Typography variant="sectionTitle">Admin Notes</Typography>
      <Typography>
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin ut rutrum
        risus. Suspendisse egestas mi eget enim laoreet, sit amet rhoncus tellus
        euismod. Integer sodales justo eget dui tempor, porttitor consequat nibh
        elementum. Nullam lectus lacus, molestie vel auctor eu, hendrerit vel
        sapien. Vivamus ac cursus risus, id efficitur nunc. Pellentesque
        ultrices metus sed luctus vestibulum. Vestibulum lacinia egestas est,
        eget facilisis lectus posuere ac. Integer ut pulvinar tellus.
        Suspendisse potenti. Vestibulum pulvinar tempus magna.
      </Typography>
    </>
  );
  return (
    <Stack direction="horizontal">
      <Button onClick={() => openSidebar(<ExampleContent />)}>Open</Button>
      <Button onClick={() => closeSidebar()}>Close</Button>
    </Stack>
  );
};

Contents

Besides a "close" button, the sidebar itself is intended to be unopinionated of its contents. This leaves the choices about contents and implementation up to the user. Common examples include:

  • simple static content – for instance a "how-to" guide.
  • asynchonous content with a loading state
  • third-party app content and micro frontends (MFEs)

Positioning

When presented to the user, the sidebar will always appear docked to the right of the viewport and it will shift the app content to the left. You don't need to implement any of the styles for this as the VitalityProvider which wraps your app will add a margin-right to the app shell when the sidebar is opened.

The VitalityProvider wraps your app will add a margin-right to the app shell when the sidebar is opened

Accessing state and values

You can access the state of the sidebar by accessing its context value. A common way to have the certain UI elements respond to the Sidebar being open. Below is an example of how to approach this by using the SidebarContext to get the isSidebarOpen prop and conditionally set the style:

() => {
  const {
    isSidebarOpen,
    openSidebar,
    closeSidebar,
    TRANSITION_DURATION,
    SIDEBAR_WIDTH,
  } = React.useContext(SidebarContext);

  const handleClick = isSidebarOpen
    ? closeSidebar
    : () => openSidebar(<>Content</>);
  const style = React.useMemo(
    () => ({
      padding: 32,
      backgroundColor: isSidebarOpen
        ? "rgb(127 255 212 / 21%)"
        : "rgb(255 127 80 / 28%)",
      transition: `all ${TRANSITION_DURATION}ms ease`,
      marginRight: isSidebarOpen ? SIDEBAR_WIDTH : 0,
      "--vitality-sidebar-width": isSidebarOpen ? `${SIDEBAR_WIDTH}px` : "0px",
    }),
    [isSidebarOpen, TRANSITION_DURATION, SIDEBAR_WIDTH]
  );

  return (
    <div style={style}>
      <Button appearance="primary" onClick={handleClick}>
        Toggle
      </Button>
    </div>
  );
};

Offsetting the top value

Unlike a Drawer component, a Sidebar is a global UX pattern that has consistent behaviour throughout a product. Thus, the vertical positioning is set globally. A common reason to use the offset is for instances where you want the app's sidebar to always appear beneath a navigation bar. In that case, you'd set the topOffset value to the nav's height in pixels.

<VitalityProvider config={{ sidebar: { topOffset: 78 } }}>
  {children}
</VitalityProvider>

Responsive behaviour

On @bp1 and below, the Sidebar will mimic the behaviour of a Drawer component – partially covering the content underneath.

Props

SidebarContext

The below table illustrates the values / methods available when accessing the SidebarContext.

© 2025