Default
<State initial={false}>
{([opened, setOpen]) => (
<Card>
<Card.Section>
<div className="d-f justify-content-between align-items-center">
Name
<BodyText subdued>(800) 555-1234</BodyText>
{
opened
? <Button primary small onClick={() => setOpen(!opened)}>Save</Button>
: <Button primary small fill="subtle" onClick={() => setOpen(!opened)}>Edit</Button>
}
</div>
<Collapsible open={opened}>
<Form className="m-t-2">
<Form.Input label="First Name" placeholder="First Name" />
<Form.Input label="First Name" placeholder="Last Name" />
<Form.Input label="Phone Number" placeholder="(800) 555-1234" />
</Form>
</Collapsible>
</Card.Section>
</Card>
)}
</State>
Animate
Collapsible can be configured to open and close with a transition effect. This is useful when the area being open is not large or a performance hit on slower computers.
<State initial={true}>
{([opened, setOpen]) => (
<Card>
<Card.Section>
<div className="d-f justify-content-between align-items-center">
Name
<BodyText subdued>(800) 555-1234</BodyText>
{
opened
? <Button primary small onClick={() => setOpen(!opened)}>Save</Button>
: <Button primary small fill="subtle" onClick={() => setOpen(!opened)}>Edit</Button>
}
</div>
<Collapsible animate open={opened}>
<Form className="m-t-2">
<Form.Input label="First Name" placeholder="First Name" />
<Form.Input label="First Name" placeholder="Last Name" />
<Form.Input label="Phone Number" placeholder="(800) 555-1234" />
</Form>
</Collapsible>
</Card.Section>
</Card>
)}
</State>
Examples
Basic
<State initial={false}>
{([opened, setOpen]) => (
<div>
<Button full fill="outline" primary onClick={() => setOpen(!opened)}>
What is Anvil?
</Button>
<Collapsible open={opened}>
<BodyText className="m-t-2">
Design guidelines and development tools for building products at ServiceTitan.
</BodyText>
</Collapsible>
</div>
)}
</State>
Accordion
A variation where only one or no section in a list of collapsible sections is open at a time.
<State initial={false}>
{([opened, setOpened]) => (
<Card>
{[1, 2, 3].map((card) => (
<Card.Section key={card}>
<div className="d-f justify-content-between align-items-center">
<Headline className="m-0">Section Title {card}</Headline>
<Button
iconName={card === opened ? "expand_less" : "expand_more"}
small
fill="subtle"
onClick={() => setOpened(opened === card ? 0 : card)}
/>
</div>
<Collapsible animate open={card === opened}>
<BodyText className="m-t-2">
Collapsible content.
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute
irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia
deserunt mollit anim id est laborum.
</BodyText>
</Collapsible>
</Card.Section>
))}
</Card>
)}
</State>
When to collapse content
In general, content should not be collapsed by default, as it can hide important information and require additional interactions to access it. Some use general use cases of collapsed content include:
- When the content has secondary value on the page, such as viewing details on a single item.
- When space is cramped, particularly on smaller displays.
- When information is not yet relevant, such as in a Flow Card.
- When using, the preferred control for the component is a Button variation.
Importing
import { Collapsible } from '@servicetitan/design-system';