Developer mode
Opens components on the React tab by default.
Your bookmarks

Accordion

Groups related long content into sections shown one at a time.

import Accordion from "@kiwicom/orbit-components/lib/Accordion";
import AccordionSection from "@kiwicom/orbit-components/lib/AccordionSection";
import ButtonLink from "@kiwicom/orbit-components/lib/ButtonLink";
import Heading from "@kiwicom/orbit-components/lib/Heading";
import Seat from "@kiwicom/orbit-components/lib/Seat";
import Stack from "@kiwicom/orbit-components/lib/Stack";
import Text from "@kiwicom/orbit-components/lib/Text";
(): React.Node => {
  const [expandedSection, setExpandedSection] = React.useState("")
  const [selectedOutboundSeat, setSelectedOutboundSeat] = React.useState("1A")
  const [selectedInboundSeat, setSelectedInboundSeat] = React.useState("1A")

  const seatType = (currentSeat, direction) => {
    if (direction === "outbound") {
      return selectedOutboundSeat === currentSeat ? "legroom" : "default"
    }

    return selectedInboundSeat === currentSeat ? "legroom" : "default"
  }

  const SeatButton = ({ currentSeat, direction }) => (
    <ButtonLink
      compact
      onClick={() =>
        direction === "outbound"
          ? setSelectedOutboundSeat(currentSeat)
          : setSelectedInboundSeat(currentSeat)
      }
    >
      <Seat type={seatType(currentSeat, direction)} />
    </ButtonLink>
  )

  const SeatRow = ({ direction, rowNumber }) => (
    <Stack direction="row" align="center">
      <SeatButton direction={direction} currentSeat={`${rowNumber}A`} />
      <SeatButton direction={direction} currentSeat={`${rowNumber}B`} />
      <Text>{rowNumber}</Text>
      <SeatButton direction={direction} currentSeat={`${rowNumber}C`} />
      <SeatButton direction={direction} currentSeat={`${rowNumber}D`} />
    </Stack>
  )

  const SeatMap = ({ direction }) => (
    <Stack>
      <Stack direction="row" align="center">
        <Stack inline grow={false} align="center" direction="column">
          <Text>A</Text>
          <SeatButton direction={direction} currentSeat="1A" />
        </Stack>
        <Stack inline grow={false} align="center" direction="column">
          <Text>B</Text>
          <SeatButton direction={direction} currentSeat="1B" />
        </Stack>
        <Stack inline grow={false} align="center" direction="column">
          <Text> </Text>
          <Text> </Text>
          <Text>1</Text>
        </Stack>
        <Stack inline grow={false} align="center" direction="column">
          <Text>C</Text>
          <SeatButton direction={direction} currentSeat="1C" />
        </Stack>
        <Stack inline grow={false} align="center" direction="column">
          <Text>D</Text>
          <SeatButton direction={direction} currentSeat="1D" />
        </Stack>
      </Stack>
      <SeatRow direction={direction} rowNumber={2} />
      <SeatRow direction={direction} rowNumber={3} />
      <SeatRow direction={direction} rowNumber={4} />
      <SeatRow direction={direction} rowNumber={5} />
      <SeatRow direction={direction} rowNumber={6} />
      <SeatRow direction={direction} rowNumber={7} />
    </Stack>
  )

  return (
    <Accordion
      expandedSection={expandedSection}
      onExpand={(id) => setExpandedSection(id)}
    >
      <AccordionSection
        id="outbound"
        header={
          <Heading as="h3" type="title3">
            Seating for Barcelona
            <FlightDirect ariaLabel=" to " />
            Boston
          </Heading>
        }
      >
        <SeatMap direction="outbound" />
      </AccordionSection>
      <AccordionSection
        id="inbound"
        header={
          <Heading as="h3" type="title3">
            Seating for Boston
            <FlightDirect ariaLabel=" to " />
            Barcelona
          </Heading>
        }
      >
        <SeatMap direction="inbound" />
      </AccordionSection>
    </Accordion>
  )
}

When to use

  • You have long sections of content with similar structure, such as seat maps for various parts of a trip.
  • You want to show only one section at a time (to keep users from being overwhelmed using progressive disclosure).

When not to use

  • You want to display all content on the screen at once—use a card.
  • Each section has a single associated action—use a tile.
  • The information to hide is simple and doesn’t have a repeating structure—use a collapse.

Content structure

Section header: sets the context for the section; section actions: optionally creates actions associated with a section; collapse section: supports progressive disclosure by hiding additional info; expanded section: shows additional info one section at a time; section content: shows one version of content with similar structure; section footer: optionally presents sticky actions for the section.

Behavior

Make actions clear

Accordions make content appear an disappear on the screen. If you’re not careful, users may start feeling lost.

Offer clear, persistent actions that make it clear how to get from one section to the next. And how to get back anything that has disappeared.

import Accordion from "@kiwicom/orbit-components/lib/Accordion";
import AccordionSection from "@kiwicom/orbit-components/lib/AccordionSection";
import ButtonLink from "@kiwicom/orbit-components/lib/ButtonLink";
import Heading from "@kiwicom/orbit-components/lib/Heading";
import Seat from "@kiwicom/orbit-components/lib/Seat";
import Stack from "@kiwicom/orbit-components/lib/Stack";
import Text from "@kiwicom/orbit-components/lib/Text";
(): React.Node => {
  const [expandedSection, setExpandedSection] = React.useState("outbound")
  const [selectedOutboundSeat, setSelectedOutboundSeat] = React.useState("1A")
  const [selectedInboundSeat, setSelectedInboundSeat] = React.useState("1A")

  const seatType = (currentSeat, direction) => {
    if (direction === "outbound") {
      return selectedOutboundSeat === currentSeat ? "legroom" : "default"
    }

    return selectedInboundSeat === currentSeat ? "legroom" : "default"
  }

  const SeatButton = ({ currentSeat, direction }) => (
    <ButtonLink
      compact
      onClick={() =>
        direction === "outbound"
          ? setSelectedOutboundSeat(currentSeat)
          : setSelectedInboundSeat(currentSeat)
      }
    >
      <Seat type={seatType(currentSeat, direction)} />
    </ButtonLink>
  )

  const SeatRow = ({ direction, rowNumber }) => (
    <Stack direction="row" align="center">
      <SeatButton direction={direction} currentSeat={`${rowNumber}A`} />
      <SeatButton direction={direction} currentSeat={`${rowNumber}B`} />
      <Text>{rowNumber}</Text>
      <SeatButton direction={direction} currentSeat={`${rowNumber}C`} />
      <SeatButton direction={direction} currentSeat={`${rowNumber}D`} />
    </Stack>
  )

  const SeatMap = ({ direction }) => (
    <Stack>
      <Stack direction="row" align="center">
        <Stack inline grow={false} align="center" direction="column">
          <Text>A</Text>
          <SeatButton direction={direction} currentSeat="1A" />
        </Stack>
        <Stack inline grow={false} align="center" direction="column">
          <Text>B</Text>
          <SeatButton direction={direction} currentSeat="1B" />
        </Stack>
        <Stack inline grow={false} align="center" direction="column">
          <Text> </Text>
          <Text> </Text>
          <Text>1</Text>
        </Stack>
        <Stack inline grow={false} align="center" direction="column">
          <Text>C</Text>
          <SeatButton direction={direction} currentSeat="1C" />
        </Stack>
        <Stack inline grow={false} align="center" direction="column">
          <Text>D</Text>
          <SeatButton direction={direction} currentSeat="1D" />
        </Stack>
      </Stack>
      <SeatRow direction={direction} rowNumber={2} />
      <SeatRow direction={direction} rowNumber={3} />
      <SeatRow direction={direction} rowNumber={4} />
      <SeatRow direction={direction} rowNumber={5} />
      <SeatRow direction={direction} rowNumber={6} />
      <SeatRow direction={direction} rowNumber={7} />
    </Stack>
  )

  return (
    <Accordion
      expandedSection={expandedSection}
      onExpand={(id) => setExpandedSection(id)}
    >
      <AccordionSection
        footer={
          <Stack justify="center">
            <ButtonLink
              type="primary"
              onClick={() => setExpandedSection("inbound")}
            >
              Continue to next segment
            </ButtonLink>
          </Stack>
        }
        id="outbound"
        header={
          <Heading as="h3" type="title3">
            Seating for Barcelona
            <FlightDirect ariaLabel=" to " />
            Boston
          </Heading>
        }
      >
        <SeatMap direction="outbound" />
      </AccordionSection>
      <AccordionSection
        footer={
          <Stack justify="center">
            <ButtonLink
              type="secondary"
              onClick={() => setExpandedSection("outbound")}
            >
              Back to previous segment
            </ButtonLink>
          </Stack>
        }
        id="inbound"
        header={
          <Heading as="h3" type="title3">
            Seating for Boston
            <FlightDirect ariaLabel=" to " />
            Barcelona
          </Heading>
        }
      >
        <SeatMap direction="inbound" />
      </AccordionSection>
    </Accordion>
  )
}

Content

Use for similar content

Accordion sections aren’t visible all of the time. Users may experience navigating between them as switching context.

Keep users comfortable by offering similar content in each section. This helps users scan for what they need among all their options.

Offer concrete headings

Section headings offer context for what each section contains. Use specific nouns to make it clear what users can expect on opening the section.

Visual style

Maintain visual hierarchy

Accordions are open to any content you want to put into them. Make sure to use a consistent style of heading to keep the overall visual hierarchy.

Using different styles can create conflicting visual messages.