PushDrawer
A panel that contains additional content or controls that can be expanded and collapsed.
The Basics
What it is
PushDrawer is a collapsible container that can contain any form, text, or combination of components. It allows the user to access elements that do not initially appear on a page or show deeper information that is relevant to workflow by clicking on a button or link from the main content area on a page.
PushDrawer has 2 modes:
- Persistent Collapse: Can be opened by any clickable element in the main content area on the page or by clicking the double-arrow icon in the corner of the collapsed drawer. It can be closed by clicking the newly inverted double-arrow icon. However, this version will never collapse completely, like the Hidden Collapse version does. Rather, it will collapse down to a thin strip that will visually persist, retaining the ability to open it back up again.
- Hidden Collapse: Can be opened by any clickable element in the main content area on the page. Once opened, it can be closed using the 'x' close icon in the corner of the expanded drawer
How it works
Persistent Collapse
- The user clicks on a button or other clickable element in the main content area on the screen, or on the double-arrow icon within the visible portion of the collapsed PushDrawer to open it.
- The panel will slide open from where its collapsed form is in the direction of the opposite side of the page until it has reached a width capable of displaying its content.
- Once the user is done with the content in the drawer, they can hide it again either using an element in the main content area, a button within the drawer, or the double-arrow icon that appears within the container. Other than the double-arrow icon, behaviors that can cause it to close are at the discretion of the designer and developer.
- When closed, this variation of the PushDrawer is visible via a thin strip that contains the double-arrow icon.
- In addition to the double-arrow icon, this variation can also have an option Contextual Icon that will give the user an indication of what is contained inside.
Hidden Collapse
- The user clicks on a button or other clickable element in the main content area on the screen to open it.
- The panel will slide open from where its collapsed form is in the direction of the opposite side of the page until it has reached a width capable of displaying its content.
- Once the user is done with the content in the drawer, they can hide it again either using an element in the main content area, a button within the drawer, or the close icon that appears within the container. Other than the close icon, behaviors that can cause it to close are at the discretion of the designer and developer.
- When closed, this variation of the PushDrawer has no visible elements on the screen.
Both Variants
- PushDrawers can have either a white background or a light grey background.
- PushDrawers have a single-pixel dark grey outer edge to help differentiate it from the main content area on the screen.
- PushDrawers can appear on the top, the bottom, the left, or the right. They will move toward the opposite side of the page respective to where they started.
- More than one PushDrawer can appear on a single page. However, it is not recommended to have more than two at one time to avoid user confusion.
When to use
- To afford more details or controls on a page relative to a selection that was made in the main content area
- To keep the main content area of the page cleaner and easier to scan until an element that has more detail is selected
- To help users find specific information in a collection of content
- To make it easier to read long content on mobile devices
- To present a step-by-step flow on a single page, with a content panel for each step (e.g., a questionnaire)
- To group a list of related content items, like FAQ or help content
When not to use
- For important information that users won’t see if they don’t expand a panel
- For screens where a simpler page structure would work instead, like headings and body text
- For a single content item
What to use instead
Use an accordion when it is important to keep the information of an expandable accordion table close to the newly exposed information, for proximity reasons, if the newly exposed information is not intended to refresh the entire section of the main content area, or if the newly shown information is simple and undisruptive in its expanded state.
Use a lightbox when the newly exposed information does not need to be shown as you transition from element to element. For example, if you are clicking on table elements to expose the hidden element, and you know you will be clicking on multiple table elements as part of a larger workflow, it may be inconvenient to use a modal because of the extra clicks it will necessitate.
You may also choose to use a lightbox if the exposed elements are part of a workflow that may not to be done more than once, such as printing or file uploads.
How to use
Mode
Persistent Collapse
- Use this visually persistent variant when your user may want to open the drawer independently from a specific action in the main content area.
Hidden Collapse
- Use this variant when you only need to access the drawer because of an action on the screen, and not by clicking the drawer itself.
Options
- Contextual Icon: On the Persistent Collapse variant, there is the option to have an icon placed with the double-arrow icon to let the user know what the drawer contains. For example, the filter icon can be used to indicate that the drawer contains filter controls.
- Background Color: The background can either be default white or light grey.
- Placement: PushDrawers can appear on any side of the screen and there can be more than one at a time.
Style
Design details
Sizes
- Left and right PushDrawers will stretch the entire height of their container. When open, the width can be either set to a fixed variable or defined by their content.
- Top and bottom PushDrawers will stretch the entire width of their container. When open, the height can be either set to a fixed variable or defined by their content.
Layouts
PushDrawer offers two layout densities:
- Medium: 16px padding, intended for most use cases
- Super Compact: 8px padding, intended for only the most compact use cases.
Header
PushDrawer has an optional but strongly recommended header/title area.
Footer
PushDrawer has an optional footer that supports an array of footer buttons. When used, the footer will stick to the bottom of the PushDrawer container, allowing for scrollable content inside the drawer. All buttons that appear in the footer will be 32px in height.
Note: if a 'sticky' footer is not desired, buttons may be placed directly in the PushDrawer. For details on this, please read our Developer Tips section
Placement and hierarchy
Demos
Coding
Developer tips
children
: This prop takes the content that should be pushed by the drawer. It is a ReactNode, meaning it can be any valid React element or a fragment of elements.
pushDrawerContent
: This is the main content of the drawer itself.
hideDividers
: By default, the hideDividers prop is set to false, meaning the dividers are visible. When you set hideDividers to true, the dividers are hidden, giving the drawer a more seamless and unified appearance.
pushContentAside
: This prop in the PushDrawer component is a boolean prop that controls whether the main content of your application is pushed aside when the drawer is opened. This prop helps in creating a responsive and interactive user experience by shifting the main content to make space for the drawer. By default, the pushContentAside prop is set to true, meaning the main content will be pushed aside when the drawer is opened. You can set it to false if you don’t want your content to be pushed and the drawer opening on top of it
icon
: This prop allows you to specify an icon which is to be displayed when mode='persistent' and the drawer is in the collapsed state, and it accepts a React node, meaning you can pass Forge icons
<PushDrawer...icon={<AppointmentLarge />}/>
PushDrawer width and height
By default, the width and height of a Push Drawer are determined by its content. If you don't set a fixed width and height, the drawer will automatically adjust to fit its content. To set the width and height of a PushDrawer to a fixed value, you can simply add height and width css properties to the pushDrawerContent prop of the PushDrawer component.
const pushDrawerContent = (<div style={{ width: "300px", height: "500px" }}>...</div>);return <PushDrawer pushDrawerContent={pushDrawerContent}>...</PushDrawer>;
Expanded States and Rendering
The isOpen
state can be controlled either through component state or props. To open the drawer on initial render, set the isOpen
prop to true. You can also control the open state explicitly by using the isOpen
and onClose
props to provide the current open state and to set the open state, respectively.
isOpen
and onClose
are required props when the mode='hidden'
Header and Footer
The PushDrawer can include a title and footer. Use the title
prop to set the header title and the footerButtons
prop to include custom footer buttons.
It is a ReactNode and can be passed something like this:
<><Button variant="tertiary" text="Back" /><Button variant="secondary" text="Cancel" /><Button variant="primary" text="OK" /></>
If you want to add action buttons directly to the content of the PushDrawer rather than having them as sticky footer buttons, you can simply include them within the pushDrawerContent prop of the PushDrawer component. This way, the buttons will be part of the drawer's main content and will scroll with the rest of the content.
const pushDrawerContent = (<div>...<Button variant="secondary" text="Cancel" /><Button variant="primary" text="OK" /></div>);return (<PushDrawer mode="persistent" pushDrawerContent={pushDrawerContent}>...</PushDrawer>);
Repository
Implementation links
PushDrawer directory in Bitbucket
Implementation details
It is strongly recommended to familiarize yourself with the Forge source code. While this documentation is a best effort to document the intent and usage of a component, sometimes some features only become clear when looking at the source code. Also, looking at Forge's source code may help identify and fix bugs in either your application or Forge itself.
Storybook files
Forge maintains at least one storybook file per component. While the primary audience for these files is typically the Forge team, these storybook files may cover usages of the component not covered by a demo. The storybook for the latest version of forge can be found at go/forge-storybook-lts.
Testing library
Forge strongly encourages using testing-library to write tests for your application.
"The more your tests resemble the way your software is used, the more confidence they can give you."
If you're having trouble testing a Forge component using testing-library, it would be a good idea to see how Forge tests its own components. For the most part, Forge tries to use screen.getByRole as much as it can, as that API provides the best feedback on a11y compliance. Forge discourages the use of document.querySelector and screen.getByTestId as both APIs encourage using implementation details to test your component, and discourage adding roles to your component.
With that being said, many of Forge's components were not built with accessibility in mind. These components do break the recommendations listed above.
Import statements
In Nimbus applications
athenaOne serves the Forge bundle independently from your application's bundle. Importing Forge components directly from '@athena/forge'
takes advantage of this feature.
import { PushDrawer } from '@athena/forge'
In standalone applications
Importing components using the exact path to the module takes advantage of webpack's tree shaking feature. Webpack will include only that module and its dependencies.
import PushDrawer from '@athena/forge/PushDrawer';
To use this import guidance, Typescript applications must use typescript >= 4.7.3
, and should add this setting to their tsconfig.json file:
{"compilerOptions": {"moduleResolution": "Node16",}}
If this setting doesn't work for your application, use this import statement instead:
import PushDrawer from '@athena/forge/dist/PushDrawer';