Composition & Styling
Takeoff Spar uses compound components when a UI surface has meaningful parts. The parent owns shared state and behavior; child parts preserve semantic DOM, accessibility relationships, and stable styling hooks.
Compose the documented anatomy
import { Accordion } from '@takeoff-ui/react-spar';
<Accordion defaultValue="baggage">
<Accordion.Item value="baggage">
<Accordion.Header>
<Accordion.Trigger>
Baggage allowance
<Accordion.Indicator />
</Accordion.Trigger>
</Accordion.Header>
<Accordion.Content>One cabin bag is included.</Accordion.Content>
</Accordion.Item>
</Accordion>;
This is intentionally more explicit than a single component with many shortcut props. You control composition and placement without rebuilding keyboard or accessibility behavior.
Customization layers
Every DOM-rendering public part can expose these layers:
classNameappends a class to the part's root slot.classNamesappends classes by named slot.slotPropssupplies HTML attributes by named slot.- Provider
componentsentries set shared defaults and slot customization.
<Accordion.Item value="fare" className="fare-item">
<Accordion.Header>
<Accordion.Trigger
classNames={{ root: 'fare-trigger' }}
slotProps={{ root: { 'aria-describedby': 'fare-help' } }}
>
Fare rules
<Accordion.Indicator />
</Accordion.Trigger>
</Accordion.Header>
<Accordion.Content>Changes may include a fee.</Accordion.Content>
</Accordion.Item>
Available slot names differ by component part. Use the API table on each component page rather than guessing a slot name.
Stable selectors
The wrappers preserve two selector families:
- Canonical
tk-*classes connect components to Takeoff token recipes. data-slotidentifies the rendered part, such asroot,indicator, oricon.
Components also expose documented state attributes such as data-size,
data-variant, data-disabled, or data-invalid where applicable.
.booking-form [data-slot='root'][data-invalid] {
outline: 2px solid var(--states-danger-base);
}
Only rely on attributes listed in the component's Data attributes table. Internal DOM structure is not a public styling contract.
Precedence rules
Component props resolve from lowest to highest priority:
- Library-authored defaults
- Provider
componentsdefaults - Instance props
Classes are concatenated rather than replaced: canonical class, provider class,
then instance class. slotProps are shallow-merged, while canonical wrapper
attributes such as data-slot and component-owned state hooks remain
authoritative.
Preserve accessibility behavior
Compound parts are not decorative wrappers. Triggers, labels, content panels, and portal surfaces establish keyboard and ARIA relationships. Keep the documented parts in place, provide visible labels, and use consumer-supplied icons as decorative content unless they carry meaning not present in text.
Component pages describe their specific keyboard model and labeling requirements under Accessibility & Keyboard.
See Theming & tokens for color mode, token bundles, and shared provider defaults.