Skip to content
portalbits
Home Docs GitHub(opens in a new tab)

Guides

Get startedFoundationsMotion

Components

All components

Buttons

ButtonIconButton

Inputs

InputSelectTextareaSlider

Selection

CheckboxToggleToggleGroupSwitchRadioGroup

Identity

AvatarBadge

Overlays

DialogPopoverTooltipDropdownMenuAlertDialog

Disclosure

TabsAccordion

Cards

AppCardArticleCardFeatureCard

Content

CarouselSectionHeaderEmptyStateAlertProgressSeparatorRowListRow

Chrome

PortalShellSidebarNavMobileNavTopBarAuthFrameColorSelectorFloatingNav

Carousel

A horizontal collection with native scrolling and named controls.

  • Geometric illustration

    A field guide to small ideas

    Read↗
  • Geometric illustration

    Make space for your next project

    Read↗
  • Geometric illustration

    Find a rhythm that works

    Read↗
Variations
More examples

One item

  • Geometric illustration

    A field guide to small ideas

    Read↗

Source

<script lang="ts">
  import 'portal-bits/styles.css';
  import 'portal-bits/tokens.css';
  import type { Snippet } from 'svelte';

  let { children }: { children: Snippet } = $props();
</script>

{@render children()}
<script lang="ts">
  import CarouselExample from './CarouselExample.svelte';
</script>

<CarouselExample layout={"responsive"} />
<script lang="ts">
  import { ArticleCard, Carousel } from 'portal-bits';
  let { layout = 'responsive' }: { layout?: 'responsive' | 'carousel' } = $props();

  // Synthetic posters as inline SVG data. Pass your own image URLs as `image` instead.
  function poster(word: string, background: string, ink: string) {
    const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="640" height="400" viewBox="0 0 640 400"><rect width="640" height="400" fill="${background}"/><circle cx="440" cy="170" r="120" fill="none" stroke="${ink}" stroke-width="2" opacity=".45"/><text x="32" y="178" fill="${ink}" font-family="Arial,sans-serif" font-size="66" font-weight="500">${word}</text></svg>`;
    return `data:image/svg+xml,${encodeURIComponent(svg)}`;
  }

  const stories = [
    {
      id: 'field',
      label: 'A field guide to small ideas',
      image: poster('field', '#e6ddd0', '#776749'),
      href: '#field-guide',
    },
    {
      id: 'orbit',
      label: 'Make space for your next project',
      image: poster('ORBIT', '#c5d4f6', '#263864'),
      href: '#next-project',
    },
    {
      id: 'tempo',
      label: 'Find a rhythm that works',
      image: poster('tempo', '#ded5f0', '#614984'),
      href: '#rhythm',
    },
  ];
</script>

<Carousel label="Studio journal" items={stories} {layout}>
  {#snippet item(story)}
    <ArticleCard
      title={story.label}
      href={story.href}
      image={story.image}
      imageAlt="Geometric illustration"
    />
  {/snippet}
</Carousel>

API reference

These tables list the props and snippets that Carousel declares. Attributes passed through to an element or primitive are listed under Forwarded attributes, not here.

Props

NameTypeDefaultRequiredBindingDescription
labelstringNoneYesOne-wayNames the carousel region. The viewport and pagination groups add a suffix to it.
itemsT[] where T extends { id: string; label: string }NoneYesOne-wayThe slides. Each `id` must be unique and stable. Each `label` describes the slide for assistive technology.
layout'responsive' | 'carousel'responsiveNoOne-wayResponsive becomes a three-column grid at 48rem of component width. Carousel always scrolls.

Snippets

NameTypeDefaultRequiredBindingDescription
itemSnippet<[T]>NoneYesOne-wayRenders one slide. It receives the item.

Forwarded attributes

None. Carousel forwards no attributes.

No data attributes are documented as stable.

Limits

  • Arrow keys, Home, and End work only while the viewport itself has focus. Nested controls keep their own keys.
  • No autoplay, looping, bound index, or custom drag. Navigation is immediate, including with reduced motion.
  • An empty `items` renders no viewport. One item renders no pagination.
  • Changing item ids or their order resets to the first slide. The 48rem threshold is an adaptation.
  • Keyboard navigation is left to right.

Related

  • ArticleCard
  • FeatureCard
Previous FeatureCard Next SectionHeader

On this page

  • Preview
  • Source
  • API reference
  • Props
  • Snippets
  • Forwarded attributes
  • Limits