LoadingIndicator
Loading indicator
Determinate morphs between a circle and a soft-burst shape as progress advances; indeterminate loops continuously through seven Material 3 Expressive shapes with a real polygon-morph animation, precomputed offline from the pinned source's own shape-matching algorithm.
import { LoadingIndicator, Surface, Text } from '@language-lit/material3-expressive'
export function LoadingIndicatorExample() {
return (
<Surface
as="section"
aria-labelledby="loading-indicator-example-title"
color="surface-container-low"
shape="extra-large"
className="loading-indicator-example"
>
<Text as="h2" id="loading-indicator-example-title" variant="titleLarge" emphasis="emphasized">
Loading indicator
</Text>
<Text as="p" variant="bodyMedium">
Determinate morphs between a circle and a soft-burst shape as
progress advances; indeterminate loops continuously through seven
Material 3 Expressive shapes with a real polygon-morph animation,
precomputed offline from the pinned source's own shape-matching
algorithm.
</Text>
<div className="loading-indicator-example__row">
<LoadingIndicator aria-label="Loading, empty" value={0} />
<LoadingIndicator aria-label="Loading, low" value={0.05} />
<LoadingIndicator aria-label="Loading, mid" value={0.45} />
<LoadingIndicator aria-label="Loading, high" value={0.98} />
<LoadingIndicator aria-label="Loading, complete" value={1} />
<LoadingIndicator aria-label="Loading, custom max" value={150} max={200} />
<LoadingIndicator aria-label="Loading" />
</div>
</Surface>
)
}LoadingIndicator renders the Material 3 Expressive shape-morphing
loading indicator. Pass value for determinate progress (morphing between
a circle and a soft-burst shape), or omit it entirely for a continuously
animating indeterminate loop through seven shapes — the same
determinate/indeterminate contract a native <progress> element uses.
import { LoadingIndicator } from '@language-lit/material3-expressive'
import '@language-lit/material3-expressive/styles.css'
<LoadingIndicator aria-label="Loading" value={0.4} />
<LoadingIndicator aria-label="Loading" />Contract
value(a number in[0, max]) renders determinate progress with an accuratearia-valuenow, morphing between a circle and a soft-burst shape as it advances. Omittingvaluerenders indeterminate mode: a continuously morphing, rotating loop through seven shapes, with noaria-valuenowat all, signaling a busy/indeterminate state to assistive technology.maxdefaults to1.aria-label/aria-labelledbyprovide the required accessible name —LoadingIndicatorhas no visible label of its own.- Fixed
48pxintrinsic size; override--m3e-comp-loading-indicator-container-width/-container-heightto resize. - Only the uncontained treatment is covered — there is no colored-container variant.
Tokens and boundaries
Color and layout come entirely from --m3e-comp-loading-indicator-* CSS
custom properties, scoped by Material3Provider. LoadingIndicator
injects no runtime styles and uses no requestAnimationFrame loop —
determinate motion is a plain function of the value prop (the same
polygon-morph interpolation the source performs every frame, computed
synchronously at render time), and indeterminate motion is pure CSS
@keyframes, using a spring-shaped linear() easing function to
reproduce the source's own morph spring exactly. The shape geometry itself
is precomputed offline from a faithful port of the source's
RoundedPolygon/Morph shape-matching algorithm — see ADR 0022 for the
full technique.