Drawer

Use for expanding and collapsing content.

  • Install
    npm install @pluralsight/ps-design-system-drawer
  • Import
    import Drawer from '@pluralsight/ps-design-system-drawer'

Examples

The Drawer can be used as an uncontrolled or controlled component. It consist of two subcomponents Summary and Details. The top-level component Drawer is headless. It's puporse is to supply context and cordinate the subcomponents.

Basic usage

Use when there is no need to modify open state or hook into onToggle callback.

import Button from '@pluralsight/ps-design-system-button'
import { colorsBackgroundDark, layout } from '@pluralsight/ps-design-system-core'
import Drawer from '@pluralsight/ps-design-system-drawer'
import { BookmarkIcon } from '@pluralsight/ps-design-system-icon'
import Row from '@pluralsight/ps-design-system-row'
import React from 'react'
function Example() {
return (
<Drawer>
<Drawer.Summary>
<ExampleDrawerSummary />
</Drawer.Summary>
<Drawer.Details>
<ExampleDrawerDetails />
</Drawer.Details>
</Drawer>
)
}
export default Example
const ExampleDrawerSummary = () => (
<>
<Row
title="Building a Web App with ASP.NET Core"
progress={18}
metadata1={['Joe Eames', 'Intermediate', 'Jul 21, 2016']}
image={<div className="image-placeholder" />}
/>
<style>{`
.image-placeholder {
width: 100%;
height: 100%;
background: ${colorsBackgroundDark[3]};
}
`}</style>
</>
)
const ExampleDrawerDetails = () => (
<div className="drawer-panel-example">
<Row
title="Course Overview"
metadata1={['1m 46s']}
actionBar={[
<Button
size={Button.sizes.small}
appearance={Button.appearances.flat}
icon={<BookmarkIcon />}
key="bookmark"
/>
]}
size={Row.sizes.small}
actionBarVisible
/>
<Row
title="What is ASP.NET Core?"
metadata1={['39m 28s']}
actionBar={[
<Button
size={Button.sizes.small}
appearance={Button.appearances.flat}
icon={<BookmarkIcon />}
key="bookmark"
/>
]}
size={Row.sizes.small}
actionBarVisible
/>
<style>{`
.drawer-panel-example {
padding: ${layout.spacingXLarge} ${layout.spacingXLarge}
${layout.spacingMedium} ${layout.spacingXLarge};
}
`}</style>
</div>
)

Drawer subcomponents

Styles can be overridden with inline styles or by passing it a new className to either node

Drawer.Summary

  • Default display is inline-flex.
    • To center align a child to the right pass it margin-left: auto style.

Drawer.Details

  • Default display is block
import { colorsPink, type } from '@pluralsight/ps-design-system-core'
import Drawer from '@pluralsight/ps-design-system-drawer'
import { BookmarkIcon } from '@pluralsight/ps-design-system-icon'
import Row from '@pluralsight/ps-design-system-row'
import React from 'react'
function Example() {
return (
<Drawer>
<Drawer.Summary>
<PinkBox>Drawer Summary</PinkBox>
</Drawer.Summary>
<Drawer.Details>
<div style={{ height: 128 }} />
</Drawer.Details>
</Drawer>
)
}
export default Example
const PinkBox = props => (
<div className="pink-box">
<span>{`<${props.children}>`}</span>
<style>{`
.pink-box {
display: flex;
align-items: center;
justify-content: center;
border: 2px dashed ${colorsPink[6]};
color: ${colorsPink[6]};
font-size: 16px;
font-family: ${type.fontFamilyCode};
margin-left: auto
}
`}</style>
</div>
)

Custom layout

If you wish to for example customize the header or body you can make use of the useDrawerContext hook to provide your own Drawer sub-components.

import Drawer, { useDrawerContext } from '@pluralsight/ps-design-system-drawer'
import { Heading } from '@pluralsight/ps-design-system-text'
import React from 'react'
const CustomSummary = ({ children }) => {
const { isOpen, onToggle } = useDrawerContext()
return (
<Heading size={Heading.sizes.medium}>
<h2 onClick={onToggle} style={{ marginBottom: 0, paddingBottom: 16 }}>
{children}
</h2>
</Heading>
)
}
function Example() {
return (
<Drawer>
<CustomSummary>Click to open</CustomSummary>
<Drawer.Details>
<div style={{ height: 128 }} />
</Drawer.Details>
</Drawer>
)
}
export default Example

Controlled mount drawer open (AKA startOpen)

When there is a need to modify/observe open state or hook into onToggle callback it's best to use the Drawer as a controlled component. The Drawer only takes two props which allow one to take control of toggle microinteraction, (onToggle, isOpen).

import Drawer from '@pluralsight/ps-design-system-drawer'
import { P } from '@pluralsight/ps-design-system-text'
import React from 'react'
const Example = () => {
const [open, setOpen] = useState(true)
const handleToggle = e => {
/** custom logic **/
setOpen(!open)
}
return (
<Drawer onToggle={handleToggle} isOpen={open}>
<Drawer.Summary>
<P style={{ padding: '10px 0', margin: 0 }}>Click me to open</P>
</Drawer.Summary>
<Drawer.Details>
<P style={{ padding: '10px 0', margin: 0 }}>Drawer Content here</P>
</Drawer.Details>
</Drawer>
)
}
export default Example

Controlled prevent clicking on <Drawer.Summary /> from opening <Drawer />

import Drawer from '@pluralsight/ps-design-system-drawer'
import { P } from '@pluralsight/ps-design-system-text'
import React from 'react'
const Example = () => {
const [open, setOpen] = useState(false)
const handleToggle = e => {
/** custom logic **/
setOpen(!open)
}
return (
<>
<button onClick={handleToggle}>toggle drawer</button>
<Drawer isOpen={open}>
<Drawer.Summary>
<P style={{ padding: '10px 0', margin: 0 }}>
Clicking me won't toggle drawer
</P>
</Drawer.Summary>
<Drawer.Details>
<P style={{ padding: '10px 0', margin: 0 }}>Drawer Content here</P>
</Drawer.Details>
</Drawer>
</>
)
}
export default Example

Accessibility

WCAG 2.1 AA Compliance

100% axe-core tests
Manual audit

WAI-ARIA Patterns: Disclosure

Props

Drawer

Name
Type
Description
Default
childrenReact.ReactNodecontent inside the drawer
onToggle() => voidtriggered when the drawer opens or closes