Vertical tabs
Used for creating expanding and collapsing vertical navigation menus.
- Install
npm install @pluralsight/ps-design-system-verticaltabs
- Import
import VerticalTabs from '@pluralsight/ps-design-system-verticaltabs'
Examples
App side nav
import VerticalTabs from '@pluralsight/ps-design-system-verticaltabs'import { PlaceholderIcon } from '@pluralsight/ps-design-system-icon'import React from 'react'const FLOW_NAV = [{collapsible: false,header: {href: '#',icon: <PlaceholderIcon />,id: 'reports-home',title: 'Reports Home'},items: []},{collapsible: true,header: {icon: <PlaceholderIcon />,id: 'operational-reports',title: 'Operational Reports'},items: [{href: '#',id: 'work-log',title: 'Work Log'},{href: '#',id: 'project-timeline',title: 'Project Timeline'},{href: '#',id: 'leaderboard',title: 'Leaderboard'},{href: '#',id: 'snapshot',title: 'Snapshot'},{href: '#',id: 'daily-updates',title: 'Daily Updates'},{href: '#',id: 'spot-check',title: 'Spot Check'}]},{collapsible: true,header: {icon: <PlaceholderIcon />,id: 'review-collaborate',title: 'Review & Collaborate'},items: [{href: '#',id: 'review-workflow',title: 'Review Workflow'},{href: '#',id: 'review-collab',title: 'Review Collaboration'},{href: '#',id: 'pr-resolution',title: 'PR Resolution'},{href: '#',id: 'knowledge-sharing',title: 'Knowledge Sharing'},{href: '#',id: 'player-card',title: 'Player Card'}]},{collapsible: true,header: {icon: <PlaceholderIcon />,id: 'delivery',title: 'Delivery'},items: [{href: '#',title: 'Retrospective'}]},{collapsible: true,header: {icon: <PlaceholderIcon />,id: 'fundamentals',title: 'Fundamentals'},items: [{href: '#',id: 'fundamentals-code',title: 'Code'},{href: '#',id: 'fundamentals-submit',title: 'Submit'},{href: '#',id: 'fundamentals-review',title: 'Review'}]}]const Example: React.FC = props => {const [open, setOpen] = React.useState(false)const [activeId, setActiveId] = React.useState('pr-resolution')const isActive = id => activeId === idconst activate = (evt, id) => {evt.preventDefault()setActiveId(id)}return (<divonMouseEnter={() => setOpen(true)}onMouseLeave={() => setOpen(false)}style={{display: 'flex',height: '100%',justifyContent: 'start',minHeight: 500}}><div style={{ width: open ? 240 : 72 }}><VerticalTabs {...props} forceCollapsed={!open} hideLabels={!open}><VerticalTabs.Group>{FLOW_NAV.map((section, sectionKey) => {const sectionHeader = section.header && (<VerticalTabs.Tier1.Header icon={section.header.icon}>{section.header.title}</VerticalTabs.Tier1.Header>)return (<VerticalTabs.Tier1collapsible={section.collapsible}key={sectionKey}header={sectionHeader}>{section.items.map((item, itemKey) => {const active = isActive(item.id)const itemHeader = (<VerticalTabs.Tier2.Headerhref={item.href}onClick={evt => activate(evt, item.id)}>{item.title}</VerticalTabs.Tier2.Header>)return (<VerticalTabs.Tier2active={active}header={itemHeader}key={itemKey}/>)})}</VerticalTabs.Tier1>)})}</VerticalTabs.Group></VerticalTabs></div></div>)}export default Example
Tiers as links
import VerticalTabs from '@pluralsight/ps-design-system-verticaltabs'import React from 'react'function Example() {return (<VerticalTabs><VerticalTabs.Tier1header={<VerticalTabs.Tier1.Header href="#">Tier 1 link</VerticalTabs.Tier1.Header>}/><VerticalTabs.Tier2header={<VerticalTabs.Tier2.Header href="#">Tier 2 link</VerticalTabs.Tier2.Header>}/></VerticalTabs>)}export default Example
Tiers as buttons
import VerticalTabs from '@pluralsight/ps-design-system-verticaltabs'import React from 'react'function Example() {return (<VerticalTabs><VerticalTabs.Tier1header={<VerticalTabs.Tier1.Header onClick={() => {}}>Tier 1 link</VerticalTabs.Tier1.Header>}/><VerticalTabs.Tier2header={<VerticalTabs.Tier2.Header onClick={() => {}}>Tier 2 link</VerticalTabs.Tier2.Header>}/></VerticalTabs>)}export default Example
Tiers w/React Router
Many users of this component are using it in conjunction with react-router
. If you'd like to do the same and use VerticalTabs.Tier1
or VerticalTabs.Tier2
to trigger react-router
links, you can follow this pattern.
import VerticalTabs from '@pluralsight/ps-design-system-verticaltabs'import React from 'react'import { BrowserRouter as Router, withRouter } from 'react-router-dom'const HeaderLink = withRouter(props => {const { history, onClick, to, ...rest } = propsconst handleClick = evt => {evt.preventDefault()if (onClick) onClick(evt)props.history.push(to)}return (<VerticalTabs.Tier1.Headerhref={props.to}onClick={handleClick}{...rest}/>)})function Example() {return (<VerticalTabs><Router><VerticalTabs.Tier1header={<HeaderLink to="/other">React-router Link as DS button</HeaderLink>}/></Router></VerticalTabs>)}export default Example
Start collapsed
Each VerticalTabs.Tier1
item can start collapsed if the collapse
and collapsible
prop are both set.
import { PlaceholderIcon } from '@pluralsight/ps-design-system-icon'import VerticalTabs from '@pluralsight/ps-design-system-verticaltabs'import * as React from 'react'const EXAMPLE_NAV = [{collapsible: true,collapsed: true,header: {icon: <PlaceholderIcon />,title: 'Starts collapsed'},items: [{title: 'See me after opening'}]},{collapsible: true,header: {icon: <PlaceholderIcon />,title: 'Starts open'},items: [{href: '#',title: 'See me on load'}]}]const Example: React.FC = () => {return (<VerticalTabs><VerticalTabs.Group>{EXAMPLE_NAV.map((section, sectionKey) => (<VerticalTabs.Tier1collapsible={section.collapsible}collapsed={section.collapsed}key={sectionKey}header={<VerticalTabs.Tier1.Header icon={section.header.icon}>{section.header.title}</VerticalTabs.Tier1.Header>}>{section.items.map((item, itemKey) => (<VerticalTabs.Tier2header={<VerticalTabs.Tier2.Header href={item.href}>{item.title}</VerticalTabs.Tier2.Header>}key={itemKey}/>))}</VerticalTabs.Tier1>))}</VerticalTabs.Group></VerticalTabs>)}export default Example
Accessibility
WCAG 2.1 AA Compliance
100% axe-core testsManual audit
WAI-ARIA Patterns: Disclosure
Props
VerticalTabs
Name | Type | Description | Default |
---|---|---|---|
forceCollapsed | boolean | force lists to be collapsed | false |
hideLabels | boolean | hide text labels | false |
VerticalTabs.Group
Name | Type | Description | Default |
---|---|---|---|
children | VerticalTabs.Tier1[] | VerticalTabs.Tier1 components |
|
header | VerticalTabs.Group.Header | slot group header into position |
|
VerticalTabs.Group.Header
Name | Type | Description | Default |
---|---|---|---|
children | string | header text |
|
tagName | string | change default tag of header root tag | h2 |
VerticalTabs.CollapsibleGroup
Name | Type | Description | Default |
---|---|---|---|
children | VerticalTabs.Tier1 | VerticalTabs.Tier1 components |
|
header | VerticalTabs.CollapsibleGroup | slot group header into position |
|
startOpen | boolean | group in open is open on first render |
|
groupButtonAriaLabel | string | custom label for collapsible group toggle toggle for screenreaders |
|
VerticalTabs.CollapsibleGroup.Header
Name | Type | Description | Default |
---|---|---|---|
children | string | header text |
|
tagName | string | change default tag of header root tag | h2 |
VerticalTabs.Tier1
Name | Type | Description | Default |
---|---|---|---|
active | boolean | changes visual state to active tab tier | false |
children | VerticalTabs.Tier2 | VerticalTabs.Tier2 components |
|
collapsed | boolean | start item collapsed if collapsible also true | false |
collapsible | boolean | allows collapsing of children | false |
header | VerticalTabs.Tier1.Header | slot tier1 header into position |
|
VerticalTabs.Tier1.Header
Name | Type | Description | Default |
---|---|---|---|
children | string | header text |
|
icon | Icon | Icon component |
|
VerticalTabs.Tier2
Name | Type | Description | Default |
---|---|---|---|
active | boolean | changes visual state to active tab tier |
|
header | VerticalTabs.Tier2.Header | slot tier2 header into position |
|
VerticalTabs.Tier2.Header
Name | Type | Description | Default |
---|---|---|---|
children | string | header text |
|