Airframe GitHub Storybook
Component

ba-carousel

Provides a horizontally scrollable content component that allows users to browse through a set of items one at a time.

Airframe

Active
Figma

Web Components

Active
Storybook GitHub

React

Active
Storybook GitHub

React Native

Planned
Design Code Accessibility QA
A

Scrollable viewport

The visible area that displays one or more carousel items at a time

B

Navigation controls

Previous and next buttons that allow users to navigate between carousel items

C

Progress bar

Shows the current position within the carousel and the total number of items

The carousel component should only be used when needing to show 3 or more items that benefit from horizontal scrolling instead of vertical.

If you only need to show 2 items use a standard layout pattern instead: stacked on mobile, side by side on desktop.

For 1 item, display as a standard content block with no navigation.

There is no limit to how many items can be shown on desktop as long as each item is no smaller than 264px. The default amount is 2 items.

<ba-carousel>
  <ba-card tag-text="tag text">
    <ba-image
      alt="Description of image"
      src="ba-card-live-demo.jpg"
      slot="media"
      aspect-ratio="16-9"
    ></ba-image>
    <ba-content>
      <h4>Example heading 1</h4>
      <p>Example content</p>
    </ba-content>
    <ba-link href="/link" slot="action">Action</ba-link>
  </ba-card>
  <ba-card tag-text="tag text">
    <ba-image
      alt="Description of image"
      src="ba-card-live-demo.jpg"
      slot="media"
      aspect-ratio="16-9"
    ></ba-image>
    <ba-content>
      <h4>Example heading 2</h4>
      <p>Example content</p>
    </ba-content>
    <ba-link href="/link" slot="action">Action</ba-link>
  </ba-card>
  <ba-card tag-text="tag text">
    <ba-image
      alt="Description of image"
      src="ba-card-live-demo.jpg"
      slot="media"
      aspect-ratio="16-9"
    ></ba-image>
    <ba-content>
      <h4>Example heading 3</h4>
      <p>Example content</p>
    </ba-content>
    <ba-link href="/link" slot="action">Action</ba-link>
  </ba-card>
  <ba-card tag-text="tag text">
    <ba-image
      alt="Description of image"
      src="ba-card-live-demo.jpg"
      slot="media"
      aspect-ratio="16-9"
    ></ba-image>
    <ba-content>
      <h4>Example heading 4</h4>
      <p>Example content</p>
    </ba-content>
    <ba-link href="/link" slot="action">Action</ba-link>
  </ba-card>
  <ba-card tag-text="tag text">
    <ba-image
      alt="Description of image"
      src="ba-card-live-demo.jpg"
      slot="media"
      aspect-ratio="16-9"
    ></ba-image>
    <ba-content>
      <h4>Example heading 5</h4>
      <p>Example content</p>
    </ba-content>
    <ba-link href="/link" slot="action">Action</ba-link>
  </ba-card>
</ba-carousel>
Property Attribute Description Type Default
desktopSlides desktop-slides The amount of slides to show on desktop. Defaults to 2 number | undefined 2
  • None
Slot Description Permitted elements
Unnamed slot Elements will render in the body of the component <ba‑card>, <ba‑card‑promo>, <ba‑link‑tile>

ba-carousel can be slotted into:

A carousel with cards for the items

A carousel with cards for the items
<ba-carousel>
  <ba-card tag-text="tag text">
    <ba-image
      alt="Description of image"
      src="ba-card-live-demo.jpg"
      slot="media"
      aspect-ratio="16-9"
    ></ba-image>
    <ba-content>
      <h4>Example heading 1</h4>
      <p>Example content</p>
    </ba-content>
    <ba-link href="/link" slot="action">Action</ba-link>
  </ba-card>
  <ba-card tag-text="tag text">
    <ba-image
      alt="Description of image"
      src="ba-card-live-demo.jpg"
      slot="media"
      aspect-ratio="16-9"
    ></ba-image>
    <ba-content>
      <h4>Example heading 2</h4>
      <p>Example content</p>
    </ba-content>
    <ba-link href="/link" slot="action">Action</ba-link>
  </ba-card>
  <ba-card tag-text="tag text">
    <ba-image
      alt="Description of image"
      src="ba-card-live-demo.jpg"
      slot="media"
      aspect-ratio="16-9"
    ></ba-image>
    <ba-content>
      <h4>Example heading 3</h4>
      <p>Example content</p>
    </ba-content>
    <ba-link href="/link" slot="action">Action</ba-link>
  </ba-card>
  <ba-card tag-text="tag text">
    <ba-image
      alt="Description of image"
      src="ba-card-live-demo.jpg"
      slot="media"
      aspect-ratio="16-9"
    ></ba-image>
    <ba-content>
      <h4>Example heading 4</h4>
      <p>Example content</p>
    </ba-content>
    <ba-link href="/link" slot="action">Action</ba-link>
  </ba-card>
  <ba-card tag-text="tag text">
    <ba-image
      alt="Description of image"
      src="ba-card-live-demo.jpg"
      slot="media"
      aspect-ratio="16-9"
    ></ba-image>
    <ba-content>
      <h4>Example heading 5</h4>
      <p>Example content</p>
    </ba-content>
    <ba-link href="/link" slot="action">Action</ba-link>
  </ba-card>
</ba-carousel>

The number of items can be set on desktop using the desktop-slides attribute

A carousel with the number of desktop items set
<ba-carousel desktop-slides="3">
  <ba-card tag-text="tag text">
    <ba-image
      alt="Description of image"
      src="ba-card-live-demo.jpg"
      slot="media"
      aspect-ratio="16-9"
    ></ba-image>
    <ba-content>
      <h4>Example heading 1</h4>
      <p>Example content</p>
    </ba-content>
    <ba-link href="/link" slot="action">Action</ba-link>
  </ba-card>
  <ba-card tag-text="tag text">
    <ba-image
      alt="Description of image"
      src="ba-card-live-demo.jpg"
      slot="media"
      aspect-ratio="16-9"
    ></ba-image>
    <ba-content>
      <h4>Example heading 2</h4>
      <p>Example content</p>
    </ba-content>
    <ba-link href="/link" slot="action">Action</ba-link>
  </ba-card>
  <ba-card tag-text="tag text">
    <ba-image
      alt="Description of image"
      src="ba-card-live-demo.jpg"
      slot="media"
      aspect-ratio="16-9"
    ></ba-image>
    <ba-content>
      <h4>Example heading 3</h4>
      <p>Example content</p>
    </ba-content>
    <ba-link href="/link" slot="action">Action</ba-link>
  </ba-card>
</ba-carousel>
Prop Description Type Default
desktopSlides The amount of slides to show on desktop. Defaults to 2 number | undefined 2
children Elements will render in the body of the component <ba‑card>, <ba‑card‑promo>, <ba‑link‑tile>

None

BaCarousel can be slotted into:

A carousel with cards for the items

A carousel with cards for the items
<BaCarousel>
  <BaCard
    media={<BaImage
      alt="Description of image"
      src="BaCard-live-demo.jpg"
      aspectRatio="16-9"
    />}
    action={<BaLink href="/link">Action</BaLink>}>
    <BaContent>
      <h4>Example heading 1</h4>
      <p>Example content</p>
    </BaContent>
  </BaCard>
  <BaCard
    media={<BaImage
      alt="Description of image"
      src="BaCard-live-demo.jpg"
      aspectRatio="16-9"
    />}
    action={<BaLink href="/link">Action</BaLink>}>
    <BaContent>
      <h4>Example heading 2</h4>
      <p>Example content</p>
    </BaContent>
  </BaCard>
  <BaCard
    media={<BaImage
      alt="Description of image"
      src="BaCard-live-demo.jpg"
      aspectRatio="16-9"
    />}
    action={<BaLink href="/link">Action</BaLink>}>
    <BaContent>
      <h4>Example heading 3</h4>
      <p>Example content</p>
    </BaContent>
  </BaCard>
  <BaCard
    media={<BaImage
      alt="Description of image"
      src="BaCard-live-demo.jpg"
      aspectRatio="16-9"
    />}
    action={<BaLink href="/link">Action</BaLink>}>
    <BaContent>
      <h4>Example heading 4</h4>
      <p>Example content</p>
    </BaContent>
  </BaCard>
  <BaCard
    media={<BaImage
      alt="Description of image"
      src="BaCard-live-demo.jpg"
      aspectRatio="16-9"
    />}
    action={<BaLink href="/link">Action</BaLink>}>
    <BaContent>
      <h4>Example heading 5</h4>
      <p>Example content</p>
    </BaContent>
  </BaCard>
</BaCarousel>

The number of items can be set on desktop using the desktopSlides attribute

A carousel with the number of desktop items set
<BaCarousel desktopSlides="3">
  <BaCard
    media={<BaImage
      alt="Description of image"
      src="BaCard-live-demo.jpg"
      aspectRatio="16-9"
    />}
    action={<BaLink href="/link">Action</BaLink>}>
    <BaContent>
      <h4>Example heading 1</h4>
      <p>Example content</p>
    </BaContent>
  </BaCard>
  <BaCard
    media={<BaImage
      alt="Description of image"
      src="BaCard-live-demo.jpg"
      aspectRatio="16-9"
    />}
    action={<BaLink href="/link">Action</BaLink>}>
    <BaContent>
      <h4>Example heading 2</h4>
      <p>Example content</p>
    </BaContent>
  </BaCard>
  <BaCard
    media={<BaImage
      alt="Description of image"
      src="BaCard-live-demo.jpg"
      aspectRatio="16-9"
    />}
    action={<BaLink href="/link">Action</BaLink>}>
    <BaContent>
      <h4>Example heading 3</h4>
      <p>Example content</p>
    </BaContent>
  </BaCard>
</BaCarousel>

React Native documentation coming soon.

Due to the carousel items being accessible via the keyboard, the controls to move forward and backward in the carousel have been removed from the tab flow. This makes the behaviour less confusing for screen reader users as it stops duplication.

This enables screen reader users to know how many items are in the carousel, and gives a running count of which item they are on when moving through the carousel.

State: Previous element in the DOM has focus

⇥ Tab

Focus moves to the carousel container

State: Carousel container has focus

⇥ Tab

Focus moves to the first focusable element within the carousel, or the next focusable element in the DOM if no focusable elements are present

← Arrow Left

The carousel moves to the previous item

→ Arrow Right

The carousel moves to the next item

State: Focusable element within carousel item has focus

⇥ Tab

Focus moves to the next focusable element within the carousel items in sequential order, or to the next focusable element in the DOM if there are no more focusable elements within the carousel items

← Arrow Left

The carousel moves to the previous item, focus remains on the same focusable element

→ Arrow Right

The carousel moves to the next item, focus remains on the same focusable element

Use this checklist to confirm the component has been configured and used correctly.

  • ba-carousel is only used when displaying 3 or more items that benefit from horizontal scrolling
  • ba-carousel items are no smaller than 264px wide on desktop
  • The desktop-slides attribute is configured appropriately for the content being displayed
  • On mobile, carousel displays one item at a time with horizontal scrolling
  • Navigation controls are visible and positioned consistently
  • Carousel items maintain consistent sizing and spacing
  • Focus indicator has not been obscured on all sides of focusable elements within carousel items
  • Carousel items are accessible via keyboard navigation
  • All interactive elements within carousel items are keyboard accessible

These checks are handled by the component and do not need to be repeated each time it is used.

  • Screen reader announces the total number of items and current position
  • ba-carousel items have role='listitem' automatically added
  • Carousel respects prefers-reduced-motion for smooth scrolling animations
  • Carousel items maintain minimum width of 264px on desktop
  • Focus management works correctly when navigating between items
  • Navigation controls are removed from keyboard tab flow to prevent duplication
  • Carousel responds appropriately to different viewport sizes
  • Color contrast meets WCAG AA standards for all text and controls
Designing Developing Components BAgel helper QA process britishairways.com Careers Cookie policy