Expandable Container

Expandable Container hides and shows information to create a focused experience for our users.

yarn add @workday/canvas-kit-labs-react
Install
yarn add @workday/canvas-kit-labs-react

Anatomy

Image of an Expandable Container in its collapsed and expanded states.

  1. Chevron Icon: This is part of the header to indicate the opened or closed state of the container. This icon could be placed on the left or right side of the header. When the chevron is on the left of the Title, it shows Chevron Right for 'collapsed' and Chevron Down for 'expanded.' When the chevron is on the right of the Title, it shows Chevron Down for 'collapsed' and Chevron Up for 'expanded.'
  2. Avatar Indicator (Optional): This is used to display a user photo for containers that are user related. If there is no user photo available, it shows the default user icon.
  3. Title: The heading text for the information being shown in the content section.
  4. Content Section: This section is where users can find more information and details about the container's subject.

Usage Guidance

  • This component highlights the most important details of a section and reveals more when a user taps or clicks on the header part of the container.
  • Enabling users to hide and show information ensures the design remains focused and relevant to their expectations.
  • Scanning through the most critical information first makes processing more efficient without compromising the ability to access additional information.

When to Use

Use an Expandable Container when there is a lot of information to be shown on a page, but some details can initially be hidden from view.

When to Use Something Else

Be cautious of hiding critical information or burdening the user with an extra click if they are likely to read all the content. There is a chance that content hidden within the collapsed state will not be read or immediately noticed by users.

Examples

Start Icon

For a basic expandable container with a chevron icon before the title, placeExpandable.Icon before Expandable.Title as children of Expandable.Target and pass the iconPosition prop to Expandable.Icon with a value of start. Expandable.Icon will use a right chevron icon when collapsed and a down chevron icon when expanded.

End Icon

For an expandable container with a chevron icon after the title, place Expandable.Title before Expandable.Icon as children of Expandable.Target and pass the iconPosition prop to Expandable.Icon with a value of end. Expandable.Icon will use a down chevron icon when collapsed and an up chevron icon when expanded.

With Avatar

To include an avatar image, Expandable.Avatar should be placed between Expandable.Icon and Expandable.Title. An iconPosition prop with a value of either start or end should be passed to Expandable.Icon depending on whether the Expandable.Icon is placed before or after Expandable.Title.

Right to Left (RTL)

Expandable container has bidirectional support and should function as expected with RTL languages as long as the content direction is set in your Canvas theme.

Depth

The depth prop passed to Expandable allows you to adjust the visual elevation of a component using our depth tokens.

Title Wrap

Long titles will wrap to the next line and increase the height of the container.

You can also have direct access to the model if

Hoisted Model

If you you need direct access to the model, you can hoist it with the useExpandableModel hook. In the example below, we're hoisting the models to expand and collapse all three containers at once.

Component API

Expandable

Expandable wraps an Expandable.Target and an Expandable.Content. By default, it provides a DisclosureModel for its subcomponents. Alternatively, a model may be passed in using the hoisted model pattern.

Layout Component

Expandable supports all props from thelayout component.

Props

Props extend from div. Changing the as prop will change the element interface.

Props extend from . If a model is passed, props from ExpandableModelConfig are ignored.

NameTypeDescriptionDefault
childrenReactNode

The children of the Expandable container. This should contain Expandable.Target and Expandable.Container

cs

The cs prop takes in a single value or an array of values. You can pass the CSS class name returned by , or the result of and . If you're extending a component already using cs, you can merge that prop in as well. Any style that is passed to the cs prop will override style props. If you wish to have styles that are overridden by the css prop, or styles added via the styled API, use wherever elemProps is used. If your component needs to also handle style props, use instead.

import {handleCsProp} from '@workday/canvas-kit-styling';
import {mergeStyles} from '@workday/canvas-kit-react/layout';
// ...
// `handleCsProp` handles compat mode with Emotion's runtime APIs. `mergeStyles` has the same
// function signature, but adds support for style props.
return (
<Element
{...handleCsProp(elemProps, [
myStyles,
myModifiers({ size: 'medium' }),
myVars({ backgroundColor: 'red' })
])}
>
{children}
</Element>
)
asReact.ElementType

Optional override of the default element used by the component. Any valid tag or Component. If you provided a Component, this component should forward the ref using React.forwardRefand spread extra props to a root element.

Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care.

div
refReact.Ref<R = div>

Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If as is set to an element, it will be that element. If as is a component, the reference will be to that component (or element if the component uses React.forwardRef).

model

Optional model to pass to the component. This will override the default model created for the component. This can be useful if you want to access to the state and events of the model, or if you have nested components of the same type and you need to override the model provided by React Context.

elemPropsHook(
  model: ,
  elemProps: TProps
) => HTML Attributes

Optional hook that receives the model and all props to be applied to the element. If you use this, it is your responsibility to return props, merging as appropriate. For example, returning an empty object will disable all elemProps hooks associated with this component. This allows finer control over a component without creating a new one.

Expandable.Target

Expandable.Target creates a heading and a button. The heading is a semantic heading to describe the associated content. The button provides users the ability to toggle the associated content.

As according to the W3 disclosure specification, the button has aria-expanded and aria-controls attributes set by default

This component should hold an Expandable.Icon, an optional Expandable.Avatar, and an Expandable.Title.

Layout Component

Expandable.Target supports all props from thelayout component.

Props

Props extend from button. Changing the as prop will change the element interface.

NameTypeDescriptionDefault
childrenReactNode

Children of the Expandable.Target. Should contain Target.Title, an optional Target.Avatar and Target.Icon with an iconPosition prop that takes a value of either start or end. Target.Icon with start is meant to be placed before the Target.Title and Target.Icon end should be placed after.

headingLevel
  'h1'
  'h2'
  'h3'
  'h4'
  'h5'
  'h6'

This specifies the semantic heading level that will wrap the Expandable.Target's button. If not defined, then nothing will wrap the button.

cs

The cs prop takes in a single value or an array of values. You can pass the CSS class name returned by , or the result of and . If you're extending a component already using cs, you can merge that prop in as well. Any style that is passed to the cs prop will override style props. If you wish to have styles that are overridden by the css prop, or styles added via the styled API, use wherever elemProps is used. If your component needs to also handle style props, use instead.

import {handleCsProp} from '@workday/canvas-kit-styling';
import {mergeStyles} from '@workday/canvas-kit-react/layout';
// ...
// `handleCsProp` handles compat mode with Emotion's runtime APIs. `mergeStyles` has the same
// function signature, but adds support for style props.
return (
<Element
{...handleCsProp(elemProps, [
myStyles,
myModifiers({ size: 'medium' }),
myVars({ backgroundColor: 'red' })
])}
>
{children}
</Element>
)
asReact.ElementType

Optional override of the default element used by the component. Any valid tag or Component. If you provided a Component, this component should forward the ref using React.forwardRefand spread extra props to a root element.

Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care.

button
refReact.Ref<R = button>

Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If as is set to an element, it will be that element. If as is a component, the reference will be to that component (or element if the component uses React.forwardRef).

model

Optional model to pass to the component. This will override the default model created for the component. This can be useful if you want to access to the state and events of the model, or if you have nested components of the same type and you need to override the model provided by React Context.

elemPropsHook(
  model: ,
  elemProps: TProps
) => HTML Attributes

Optional hook that receives the model and all props to be applied to the element. If you use this, it is your responsibility to return props, merging as appropriate. For example, returning an empty object will disable all elemProps hooks associated with this component. This allows finer control over a component without creating a new one.

useExpandableTarget

(
  model: ,
  elemProps: {},
  ref: React.Ref
) => {
  aria-controls: string;
  aria-expanded: boolean;
  onClick: (event: ) => void;
}

Expandable.Title

Expandable.Title styles the target text that describes the content.

Layout Component

Expandable.Title supports all props from thelayout component.

Props

Props extend from div. Changing the as prop will change the element interface.

NameTypeDescriptionDefault
childrenReactNode

Children of the Expandable.Title. This should contain a string for the title

cs

The cs prop takes in a single value or an array of values. You can pass the CSS class name returned by , or the result of and . If you're extending a component already using cs, you can merge that prop in as well. Any style that is passed to the cs prop will override style props. If you wish to have styles that are overridden by the css prop, or styles added via the styled API, use wherever elemProps is used. If your component needs to also handle style props, use instead.

import {handleCsProp} from '@workday/canvas-kit-styling';
import {mergeStyles} from '@workday/canvas-kit-react/layout';
// ...
// `handleCsProp` handles compat mode with Emotion's runtime APIs. `mergeStyles` has the same
// function signature, but adds support for style props.
return (
<Element
{...handleCsProp(elemProps, [
myStyles,
myModifiers({ size: 'medium' }),
myVars({ backgroundColor: 'red' })
])}
>
{children}
</Element>
)
asReact.ElementType

Optional override of the default element used by the component. Any valid tag or Component. If you provided a Component, this component should forward the ref using React.forwardRefand spread extra props to a root element.

Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care.

div
refReact.Ref<R = div>

Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If as is set to an element, it will be that element. If as is a component, the reference will be to that component (or element if the component uses React.forwardRef).

Expandable.Icon

Expandable.Icon creates an icon to visually indicate the state of the content. It takes an iconPosition prop to determine which chevron icon to use.

Layout Component

Expandable.Icon supports all props from thelayout component.

Props

Props extend from span. Changing the as prop will change the element interface.

NameTypeDescriptionDefault
icon

Icon to display from @workday/canvas-accent-icons-web

iconPosition

Button icon positions can either be start or end. If no value is provided, it defaults to start.

'start'
fill

The fill color of the SystemIcon. This overrides color.

color

The color of the SystemIcon. This defines accent and fill. color may be overriden by accent and fill.

size number string undefined

The size of the SystemIcon in px.

styles
shouldMirrorboolean

If set to true, transform the SVG's x-axis to mirror the graphic

false
background

The background color of the SystemIcon.

cs

The cs prop takes in a single value or an array of values. You can pass the CSS class name returned by , or the result of and . If you're extending a component already using cs, you can merge that prop in as well. Any style that is passed to the cs prop will override style props. If you wish to have styles that are overridden by the css prop, or styles added via the styled API, use wherever elemProps is used. If your component needs to also handle style props, use instead.

import {handleCsProp} from '@workday/canvas-kit-styling';
import {mergeStyles} from '@workday/canvas-kit-react/layout';
// ...
// `handleCsProp` handles compat mode with Emotion's runtime APIs. `mergeStyles` has the same
// function signature, but adds support for style props.
return (
<Element
{...handleCsProp(elemProps, [
myStyles,
myModifiers({ size: 'medium' }),
myVars({ backgroundColor: 'red' })
])}
>
{children}
</Element>
)
childrenReactNode
accent

The accent color of the SystemIcon. This overrides color.

accentHover

The accent color of the SystemIcon on hover. This overrides colorHover.

backgroundHover

The background color of the SystemIcon on hover.

colorHover

The hover color of the SystemIcon. This defines accentHover and fillHover. colorHover may be overriden by accentHover and fillHover.

fillHover

The fill color of the SystemIcon on hover. This overrides colorHover.

asReact.ElementType

Optional override of the default element used by the component. Any valid tag or Component. If you provided a Component, this component should forward the ref using React.forwardRefand spread extra props to a root element.

Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care.

span
refReact.Ref<R = span>

Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If as is set to an element, it will be that element. If as is a component, the reference will be to that component (or element if the component uses React.forwardRef).

model

Optional model to pass to the component. This will override the default model created for the component. This can be useful if you want to access to the state and events of the model, or if you have nested components of the same type and you need to override the model provided by React Context.

elemPropsHook(
  model: ,
  elemProps: TProps
) => HTML Attributes

Optional hook that receives the model and all props to be applied to the element. If you use this, it is your responsibility to return props, merging as appropriate. For example, returning an empty object will disable all elemProps hooks associated with this component. This allows finer control over a component without creating a new one.

useExpandableIcon

(
  model: ,
  elemProps: {},
  ref: React.Ref
) => {
  visible: boolean;
}

Expandable.Avatar

Expandable.Avatar is an optional component that creates an Avatar to display a decorative image.

Props

Props extend from button. Changing the as prop will change the element interface.

NameTypeDescriptionDefault
variant

The variant of the Avatar default state. Accepts Light or Dark.

refRef<>
size number

The size of the Avatar.

objectFitProperty.ObjectFit

The object-fit CSS property sets how the content of a replaced element, such as an <img> or <video>, should be resized to fit its container. See object-fit. If your image is not a square, you can use this property to ensure the image is rendered properly.

altTextstring

The alt text of the Avatar image. This prop is also used for the aria-label

urlstring

The url of the Avatar image.

childrenReact.ReactNode
asReact.ElementType

Optional override of the default element used by the component. Any valid tag or Component. If you provided a Component, this component should forward the ref using React.forwardRefand spread extra props to a root element.

Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care.

button
refReact.Ref<R = button>

Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If as is set to an element, it will be that element. If as is a component, the reference will be to that component (or element if the component uses React.forwardRef).

Expandable.Content

Expandable.Content holds the content that will be conditionally expanded and collapsed. It has an id to ensure the Expandable.Target properly set it to the aria-controls attribute.

Layout Component

Expandable.Content supports all props from thelayout component.

Props

Props extend from div. Changing the as prop will change the element interface.

NameTypeDescriptionDefault
childrenReactNode

The children of the Expandable.Content whose visibility is controlled by the associated Expandable.Target

cs

The cs prop takes in a single value or an array of values. You can pass the CSS class name returned by , or the result of and . If you're extending a component already using cs, you can merge that prop in as well. Any style that is passed to the cs prop will override style props. If you wish to have styles that are overridden by the css prop, or styles added via the styled API, use wherever elemProps is used. If your component needs to also handle style props, use instead.

import {handleCsProp} from '@workday/canvas-kit-styling';
import {mergeStyles} from '@workday/canvas-kit-react/layout';
// ...
// `handleCsProp` handles compat mode with Emotion's runtime APIs. `mergeStyles` has the same
// function signature, but adds support for style props.
return (
<Element
{...handleCsProp(elemProps, [
myStyles,
myModifiers({ size: 'medium' }),
myVars({ backgroundColor: 'red' })
])}
>
{children}
</Element>
)
asReact.ElementType

Optional override of the default element used by the component. Any valid tag or Component. If you provided a Component, this component should forward the ref using React.forwardRefand spread extra props to a root element.

Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care.

div
refReact.Ref<R = div>

Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If as is set to an element, it will be that element. If as is a component, the reference will be to that component (or element if the component uses React.forwardRef).

model

Optional model to pass to the component. This will override the default model created for the component. This can be useful if you want to access to the state and events of the model, or if you have nested components of the same type and you need to override the model provided by React Context.

elemPropsHook(
  model: ,
  elemProps: TProps
) => HTML Attributes

Optional hook that receives the model and all props to be applied to the element. If you use this, it is your responsibility to return props, merging as appropriate. For example, returning an empty object will disable all elemProps hooks associated with this component. This allows finer control over a component without creating a new one.

useExpandableContent

(
  model: ,
  elemProps: {},
  ref: React.Ref
) => {
  style:  {
      display: undefined;
    } {
      display: string;
    };
  id: string;
}

Model

useExpandableModel

The ExpandableModel extends the DisclosureModel

useExpandableModel (config: ):

Accessibility Guidelines

How Expandable Containers Impact the Accessible Experience

Any pattern that can show and hide content in a design must support the non-visual screen reading experience. Users must be able to perceive whether the content is expanded or collapsed, and users need to know where they can find the new expanded content.

The reading order of the expanded content must logically follow the target button controlling the content’s visibility for non-visual users to find and understand the content change. A non-visual screen reading experience is fundamentally linear, like reading a book.

Keyboard Interaction

Each Expandable Container must have a focus indicator that is highly visible against the background and against the non-focused state. Refer to Accessible Colors for more information.

Expandable Container must support the following keyboard interactions:

  • Tab: focus the Expandable Container expandable button
  • Enter or Space: Expand or collapse the content

Screen Reader Interaction

Expandable Container must communicate the following to users:

  • The Expandable Container title is an interactive button
  • The “expanded” or “collapsed” state of the content

Design Annotations Needed

  • Specify the heading level for the Expandable Container title

Implementation Markup Needed

  • Use the headingLevel prop to assign an appropriate heading level based on the context of the page content.
  • When using multiple Expandable Containers on a complex screen, use the as prop to render the Expandable.Content sub-component as a <section> element. Use aria-labelledby to reference the unique id of the Expandable.Target button to create a landmark region for screen readers with the expanded content.
  • [Included in component] Set the aria-expanded property onto the <button> element controlling the content.

Content Guidelines

  • Titles should be short and concise, yet long enough to explain what the user would expect to see when the content is expanded.
  • If titles must be long, make sure it doesn't wrap more than two lines.

Can't Find What You Need?

Check out our FAQ section which may help you find the information you're looking for.

FAQ Section