Container for a custom actionable region that the toolkit does not already provide, such as a tappable status widget, a bespoke tile, or a media destination. For a standard row, prefer ListItem; for a standard action, prefer Button so the application stays consistent with the toolkit’s patterns.Container is the toolkit’s primary interactive building block. It combines InteractableBase with a material. The component owns focus, press, activation, tooltips, and partial-focus feedback. It renders a ContainerMaterial behind and in front of its content and clips those layers to the shape provider’s geometry. Most interactive toolkit components build on this behavior.children. Container does not provide title, subtitle, or icon convenience props, which keeps custom layouts flexible without changing the component’s interaction behavior.import {Container, TextView, TextStyle, TextColor} from '@wearables-ui-toolkit/mrbd';
function ForecastTile() {
return (
<Container clickable onActivate={openForecast} ariaLabel="Today's forecast">
<div className="forecast-tile">
<TextView textStyle={TextStyle.BODY1}>Today's forecast</TextView>
<TextView textStyle={TextStyle.META1} textColor={TextColor.SECONDARY}>
CLEAR
</TextView>
</div>
</Container>
);
}
.forecast-tile {
display: grid;
gap: var(--uit-spacing-med-lg);
padding: var(--uit-spacing-large);
}
import {useMemo} from 'react';
import {
Container,
CornerRadius,
MaterialLibrary,
RoundedRectangleShapeProvider,
} from '@wearables-ui-toolkit/mrbd';
// A shape provider is immutable, so a single instance can be shared.
const CARD_SHAPE = new RoundedRectangleShapeProvider(CornerRadius.MEDIUM);
function MediaCard() {
// A material carries its own visual state, so each mounted container needs
// an instance of its own.
const material = useMemo(() => MaterialLibrary.card(), []);
return (
<Container clickable material={material} shapeProvider={CARD_SHAPE}>
<CardBody />
</Container>
);
}
useMemo for the material rather than a module constant. Shape providers are immutable, so callers can share them safely.Button, ListItem, ControlTile, and QuickReplyButton also expose a material prop. A material factory can therefore provide a consistent custom theme across several component types while each component retains its own layout, shape, interaction behavior, and accessibility. Create a fresh material instance for every mounted component, even when all of the instances come from the same factory. A material owns mutable visual state, so mounting one instance in multiple hosts violates its single-owner contract and throws. See Custom materials for layer composition patterns.as prop to preserve native element semantics. Container forwards the ref to the rendered element:import {Link} from 'react-router-dom';
import {Container} from '@wearables-ui-toolkit/mrbd';
<Container as={Link} to="/media/library" ariaLabel="Media library">
<LibraryPreview />
</Container>;
Container is also available from its own subpath:import {Container} from '@wearables-ui-toolkit/foundation/components/Container';
Container extends InteractableBase. See InteractableBase for the complete interaction, tooltip, and focus API; notable inherited props appear below. The as prop makes Container polymorphic, and the component forwards remaining props to the rendered element. The full prop type is ContainerProps.| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | — | Content, stacked above the background layers and below the foreground layers. |
material | ContainerMaterial | the default interactive material | Draws the background and foreground layers for each visual state. One instance may be mounted by only one container at a time. |
shapeProvider | ShapeProvider | rounded rectangle at the large corner radius | Geometry used for content clipping and for every material fill and stroke path. |
width | number \| string | 'auto' | CSS width. A number is treated as pixels and lets the shape path be computed before measurement. |
height | number \| string | 'auto' | CSS height, same rules as width. |
clipContent | boolean | true | Clips the content subtree to the shape. Material layers are positioned independently and are not clipped by this. |
interactionStateOverride | InteractionState | — | Sets the interaction state used for visuals and state-change animations. Use when a composite control needs the container to reflect another interaction target. |
visualStateOverride | VisualState | — | Forces the rendered visual state instead of deriving it from interaction, and drives the material to that state. |
materialTransition | ContainerMaterialTransition | — | Externally drives a material cross-fade as {from, to, progress}. progress is clamped to the 0–1 range, and a transition whose from and to match is ignored. When set, the internal transition is suppressed. |
visualStateForInteractionStateFn | (state: InteractionState) => VisualState | default mapping | Overrides how interaction state maps to the rendered visual state. |
contentScaleForStateFn | (state: State, size: {width: number; height: number}) => number | app platform profile | Overrides the content “breathing” scale for each state. |
onScaleChange | (scale: number) => void | — | Called with the interaction scale whenever it changes, including once with the resting scale after mount. This is the interaction scale only; customScaleX and customScaleY are not folded in. |
customScaleX | number | 1 | Multiplied into the horizontal scale. |
customScaleY | number | 1 | Multiplied into the vertical scale. |
customAlpha | number | 1 | Multiplied into the root opacity. |
stateChangeAnimations | (context: ContainerStateChangeAnimationContext) => ContainerStateChangeAnimation[] | — | Extra animation participants driven on the same clock as the built-in state change, so custom motion stays in lockstep with the material. |
ContainerMaterialTransition, ContainerStateChangeAnimation, and ContainerStateChangeAnimationContext are exported from the @wearables-ui-toolkit/foundation/components/Container subpath.stateChangeAnimations context includes prevInteraction, newInteraction, animated (false when the toolkit snaps the change), the selected transition duration and interpolator, and the measured containerSize. Each returned participant provides a duration, an optional startDelay, and onStart, onFrame, onComplete, and onCancel callbacks. onFrame receives elapsed milliseconds and linear progress.| Prop | Type | Default | Description |
|---|---|---|---|
as | ElementType | 'div' | Render as another element or component, such as a router link. |
interactive | boolean | true | Default for focusable, pressable, and clickable. |
focusable | boolean | value of interactive | Whether the container takes focus. |
pressable | boolean | value of interactive | Whether the container shows press feedback. |
clickable | boolean | value of interactive | Whether activation runs. |
disabled | boolean | false | Blocks activation and fades the root; stays focusable. |
initialFocusEligible | boolean | true | When false, the container and its subtree are skipped by automatic initial focus. |
onActivate | (event: InteractableActivationEvent) => void | — | The action. Fires once per activation. |
onStateChange | (prev: InteractionState, next: InteractionState) => void | — | Called after Container has applied its own state change. |
ariaLabel | string | — | Accessible name. |
tooltipMode | TooltipMode | TooltipMode.NONE | Enables the tooltip. The rest of the tooltip* props behave exactly as on the base. |
partialFocusSupportedAxis | PartialFocusSupportedAxis | PartialFocusSupportedAxis.XY | Which axes get handoff and rubber-band feedback. |
isRubberbandTranslationEnabled | boolean | true | Whether the rubber band moves the element or only the material origin. |
onInvalidFocusDirection | (direction: InvalidFocusDirection) => void | — | Called in addition to the built-in rubber band. |
onPartialFocusHandoff | (detail) => void | — | Called in addition to the built-in handoff feedback. |
Container asks the material to render one of the four VisualState values. The default mapping translates interaction state, and visualStateForInteractionStateFn can customize that mapping.Container cross-fades from the previous material state to the next. It uses the same clock for material, scale, and opacity changes, which keeps the element’s motion coordinated.interactionStateOverride makes the supplied value the source for focused, pressed, and disabled visuals. The container keeps its standard material, scale, opacity, and transition behavior.Container applies material opacity only to material layers. Translucent materials therefore preserve content opacity; only disabled and customAlpha change root opacity.Container positions the layers inside the element box and regenerates the shape path at the smaller size so strokes remain within the edge.Container establishes a stacking context so background layers paint behind content and foreground layers paint in front. When a material declares backdrop blending, Container marks the root with data-uit-background-blends-with-backdrop and omits both the stacking context and a redundant identity transform. This lets the material blend with content behind it.Container removes its layers from the tree instead of rendering invisible layers.Container scales content slightly inward at rest, expands it to full size on focus, and insets it again on press. This feedback rhythm has no hover state.Container reads the platform profile supplied by App and uses it for the default content scale. Applications do not pass a platform value to individual containers. Use contentScaleForStateFn only when a component needs a different curve.customScaleX, customScaleY, and customAlpha, which multiply the toolkit’s interaction values. Providing transform through style gives the caller ownership of the transform and disables the built-in scale animation.disabled fades the root between enabled and disabled opacities on the same state-change animation.stateChangeAnimations with animated: false, but it does not schedule returned participants. Callers must read this flag and place custom visuals directly in their end state so reduced-motion and transition behavior remain correct.width and height values or measurement—the shape provider generates the smooth rounded path for content clipping and every material fill and stroke. Until then, the toolkit uses the provider’s plain CSS border radius as a fallback.transform therefore leaves material paths at full size.clipContent clips only the content subtree. Material effects such as glow strokes and drop shadows can remain visible outside the shape.Container springs the partial-focus origin toward the other element and back. Materials use that value to shift their gradient origin, and the incoming element begins offset toward the previous focus. The element itself does not translate during handoff; only the material origin moves.Container plays a two-stage rubber-band nudge toward the blocked direction and back. This is the only case where the element translates. isRubberbandTranslationEnabled={false} keeps the element still while the material origin continues to shift.partialFocusSupportedAxis. For example, a horizontal rail set to X ignores vertical boundaries.partialFocusSupportedAxis to None disables both effects and keeps the origin centered.Container is an inline flex box with intrinsic sizing by default. Prefer to let content and the surrounding responsive layout determine its size instead of hardcoding pixel dimensions.width and height when the shape path must exist before the first measurement, such as for a fixed-size tile.Container inherits the accessibility behavior of InteractableBase: a button role for clickable div roots, tab index management, aria-disabled, the ariaLabel alias, and a suppressed native focus outline. The material’s focused treatment provides the visible focus indicator.role and matching ARIA state props. Prefer as when a native element provides the appropriate semantics.interactive={false}) adds no role, tab index, or aria-disabled. The application must provide appropriate semantics within its content so assistive technology can interpret it.var(--uit-spacing-large). Let full-bleed media use the container’s clipping.useMemo. Immutable shape providers can be shared.interactionStateOverride only when a composite control needs its Container to reflect another interaction target’s focused, pressed, or disabled state.visualStateOverride and materialTransition for coordinated behavior such as a driven preview or scrubbed transition.as to preserve native navigation semantics.stateChangeAnimations when custom motion must stay synchronized with the material cross-fade. Avoid a separate timer because it can drift from the toolkit’s interaction state.Container, StaticContainer, Surface, Button, Chip, Tag, or Header inside a Container; these compositions are unsupported.visualStateOverride to imitate focus. Drive focus visuals from real interaction so the visible state matches accessibility focus.Container internals or targeting generated class names because the toolkit owns their structure and styling.Container. If no component fits, consider requesting the missing library pattern.