Manual single-slide carousel with controlled or uncontrolled selection and accessible navigation controls.
Install @wyrd-company/react or the Flutter package and use it directly —
your DESIGN.md does the styling.
catalog/contracts/carousel.ymlsource of truth · verbatim
$schema: https://thewyrdingway.dev/schemas/component-contract.schema.ymlcontractVersion: 0.1.0identity:name: Carouseltag: wyrd-carouselpackage: wyrd.component.carouseltitle: Carouselsummary: Manual single-slide carousel with controlled or uncontrolled selection and accessible navigation controls.relationships:related-to: - quality-parity-and-gates - l10n-formatting-runtimeclassification:category: data-displaycomposition: collectioninteractive: truetarget-strategy:react: requiredflutter: requiredsurface:properties: - name: labeltype:kind: stringrequired: trueserializable: truesummary: Accessible name for the carousel region. - name: valuetype:kind: stringrequired: falsecontrolled: trueserializable: truesummary: Controlled active slide value. - name: default-valuetype:kind: stringrequired: falseserializable: truesummary: Initial uncontrolled active slide value; the first enabled item is used when absent. - name: itemstype:kind: arrayitem:kind: objectfields:value:kind: stringlabel:kind: stringdisabled:kind: booleanrequired: falsedefault: []serializable: truesummary: Ordered slides; disabled slides remain mounted but are skipped by navigation. - name: looptype:kind: booleanrequired: falsedefault: falsereflects: trueserializable: truesummary: Allows previous and next navigation to wrap between the first and last enabled slides.slots: - name: contentcontent: truerequired: truecardinality: one-or-manyaccepts: - component - contentsummary: Index-matched slide content; the Nth child belongs to the Nth item.events: - name: value-changepayload:value:kind: stringbubbles: truecomposed: truecancelable: falsesummary: Emitted when manual navigation activates a different enabled slide.states: - name: defaultsource: platformsummary: One slide is active and manual controls are available. - name: activesource: propertysummary: Active slide state derived from value or default-value. - name: boundarysource: propertysummary: A non-looping carousel is at its first or last enabled slide. - name: focus-visiblesource: platformsummary: Keyboard-visible focus on a navigation control.parts: - name: rootsummary: Named carousel region.slots: - content - name: viewportsummary: Visible slide viewport. - name: slidesummary: Repeated index-matched slide container.slots: - content - name: controlssummary: Previous, position, and next control row. - name: previoussummary: Previous-slide button. - name: positionsummary: Localized active slide position. - name: nextsummary: Next-slide button.tokens:root:gap: spacing.smviewport:background: color.surfaceforeground: color.on-surfaceradius: rounded.mdcontrol:background: color.surfaceforeground: color.on-surfacehover-background: color.secondaryradius: rounded.smpadding-x: spacing.mdpadding-y: spacing.smposition:foreground: color.on-surface-varianttext: typography.label-mdmessages: - key: carousel.previousdescription: Accessible label for moving to the previous slide. - key: carousel.nextdescription: Accessible label for moving to the next slide. - key: carousel.positiondescription: Announces the active slide position and total slide count.params:current: numbertotal: numberobligations:accessibility:role: regionname: Label property provides the carousel region's accessible name.keyboard: - Tab reaches the previous and next buttons in document order. - Enter and Space activate a focused navigation button. - ArrowLeft and ArrowRight move to the spatially previous and next enabled slides while focus is within the carousel. - Spatial arrow direction reverses in right-to-left text direction.semantics: - Web projections expose a named region with aria-roledescription=carousel and each slide as a group with aria-roledescription=slide. - Each slide uses its item label when present, otherwise the localized position message. - Inactive slides stay mounted but are hidden visually and from assistive technology. - Previous and next controls expose component-owned localized names and disabled boundary state. - Flutter exposes an equivalent named container, active slide label, and button semantics.behavior:model: collectioninteractions: - value ?? default-value ?? first enabled item determines the active slide. - Manual button and arrow-key navigation skips disabled slides. - Navigation stops at boundaries unless loop is true. - Carousel never advances automatically in v1. - All slide children remain mounted so slide-local state survives navigation.hostEffects: - Dispatch value-change when manual navigation activates a different slide. - Format component-owned previous, next, and position messages through the l10n runtime.conditions: - rtl - reduced-motion - cvd-deuteranopia - density-compact - text-expansionsdui:status: serializableserializableProperties: - label - value - default-value - items - loopserializableSlots: - contenteventBindings: - value-changenotes: Carousel serializes ordered items and index-matched slide content; hosts preserve order and keep all slides mounted.examples: - name: product-tourstate: activeproperties:label: Product tourdefault-value: foundationsitems: - value: foundationslabel: Foundations - value: componentslabel: Components - value: toolinglabel: Toolingslots:content: - Semantic foundations. - Cross-target components. - Authoring and validation tooling. - name: loopingstate: activeproperties:label: Featured componentsdefault-value: date-time-pickerloop: trueitems: - value: date-time-pickerlabel: Date and time picker - value: graph-viewerlabel: Graph viewerslots:content: - Locale-aware segmented entry and calendar selection. - Read-only exploration of typed behavior graphs. - name: disabled-slidestate: boundaryproperties:label: Release readinessitems: - value: stablelabel: Stable - value: blockedlabel: Blockeddisabled: true - value: plannedlabel: Plannedslots:content: - Available to downstream applications. - Waiting for a required runtime capability. - Accepted for a future catalog increment.overrides:react:slots:content: childrenflutter:slots:content: child
01
Examples
Generated from the contract's examples block.
Previews are the published @wyrd-company/react component, themed by the
brand's role tokens — flip the site's light/dark toggle and they follow.
import { WyrdCarousel } from"@wyrd-company/react";
<WyrdCarousel label="Featured components" defaultValue="date-time-picker" loop items={[{"value":"date-time-picker","label":"Date and time picker"},{"value":"graph-viewer","label":"Graph viewer"}]}>
Locale-aware segmented entry and calendar selection.
Read-only exploration of typed behavior graphs.
</WyrdCarousel>
// events: onValueChange
import'package:wyrd_flutter/wyrd_flutter.dart';
WyrdCarousel(
label: 'Featured components',
initialValue: 'date-time-picker',
loop: true,
items: [{"value":"date-time-picker","label":"Date and time picker"},{"value":"graph-viewer","label":"Graph viewer"}],
child: Text('Locale-aware segmented entry and calendar selection. Read-only exploration of typed behavior graphs.'),
)
// events: onChanged
disabled-slidestate: boundary
Usage
import { WyrdCarousel } from"@wyrd-company/react";
<WyrdCarousel label="Release readiness" items={[{"value":"stable","label":"Stable"},{"value":"blocked","label":"Blocked","disabled":true},{"value":"planned","label":"Planned"}]}>
Available to downstream applications.
Waiting for a required runtime capability.
Accepted for a future catalog increment.
</WyrdCarousel>
// events: onValueChange
import'package:wyrd_flutter/wyrd_flutter.dart';
WyrdCarousel(
label: 'Release readiness',
items: [{"value":"stable","label":"Stable"},{"value":"blocked","label":"Blocked","disabled":true},{"value":"planned","label":"Planned"}],
child: Text('Available to downstream applications. Waiting for a required runtime capability. Accepted for a future catalog increment.'),
)
// events: onChanged
02
Properties
Name
Type
Default
Summary
label
string
undefined
Accessible name for the carousel region.
value
string
undefined
Controlled active slide value.
default-value
string
undefined
Initial uncontrolled active slide value; the first enabled item is used when absent.
items
array
Ordered slides; disabled slides remain mounted but are skipped by navigation.
loop
boolean
false
Allows previous and next navigation to wrap between the first and last enabled slides.
03
Slots & events
Slot
Cardinality
Accepts
Summary
content
one-or-many
component, content
Index-matched slide content; the Nth child belongs to the Nth item.
Event
Payload
Summary
value-change
value
Emitted when manual navigation activates a different enabled slide.
04
Tokens
The contract's token bindings. Open the shared contextual sidebar from any example;
primary swatches reflect the color you pick there. Error swatches show the active
preset's values; editing any knob switches to custom and resets error to TWW · Ink.
Binding
Token
root.gap
spacing.sm
viewport.background
color.surface
viewport.foreground
color.on-surface
viewport.radius
rounded.md
control.background
color.surface
control.foreground
color.on-surface
control.hover-background
color.secondary
control.radius
rounded.sm
control.padding-x
spacing.md
control.padding-y
spacing.sm
position.foreground
color.on-surface-variant
position.text
typography.label-md
05
States
State
Source
Summary
default
platform
One slide is active and manual controls are available.
active
property
Active slide state derived from value or default-value.
boundary
property
A non-looping carousel is at its first or last enabled slide.
focus-visible
platform
Keyboard-visible focus on a navigation control.
06
Accessibility
From the contract's accessibility obligations. Role region; Label property provides the carousel region's accessible name.
Tab reaches the previous and next buttons in document order.
Enter and Space activate a focused navigation button.
ArrowLeft and ArrowRight move to the spatially previous and next enabled slides while focus is within the carousel.
Spatial arrow direction reverses in right-to-left text direction.
Web projections expose a named region with aria-roledescription=carousel and each slide as a group with aria-roledescription=slide.
Each slide uses its item label when present, otherwise the localized position message.
Inactive slides stay mounted but are hidden visually and from assistive technology.
Previous and next controls expose component-owned localized names and disabled boundary state.
Flutter exposes an equivalent named container, active slide label, and button semantics.