MotionSurface
Indicator context
Lifts, lights and steps its border on hover.
Motion
Every kinetic effect in @luc/ui, driven by one intensity profile — and every one of them resolves to an instant state change under reduced motion.
Change the props and read the result: the preview and the code below it are built from the same values, so what you see is what you copy.
Controls
Presets
Headline
The component animates a change to this string — it is the headline's only content.
Mode
`reveal` assembles the words; `swap` replaces the line in place.
Stagger
Seconds between consecutive words.
Element
The caller owns the type scale, so the tag is a choice rather than a default.
Live region
Announce the new text politely when it changes, for a status line rather than a headline.
Edit the headline: the words re-enter with the mode and the stagger you chose.
import { KineticHeadline } from "@luc/ui/motion";
<KineticHeadline text="Markets reprice in seconds" />Not controllable here
className — Type scale and layout belong to the page that places the headline.style — Colour and spacing come from the type tokens; an inline style would override the system.Implement `KineticHeadline` from Luc UI. It is: A headline that assembles itself per word or per letter, and settles into real text.
Import it with: import { KineticHeadline } from "@luc/ui/motion";
Requires: react ^19.0.0; react-dom ^19.0.0; react-hook-form ^7.0.0 (optional, for @luc/ui/forms/react-hook-form); tailwindcss ^4.0.0; node >= 22 (repository tools). Import the stylesheet once at the app root and wrap the tree in `LucProvider`. Both come from the package that publishes @luc.
Chosen configuration: `text="Markets reprice in seconds"`, `mode="reveal"`, `stagger={0.045}`, `as="h2"`, `live={false}`.
Accessibility: keep the component's own semantics. Do not re-implement its ARIA wiring, do not add roles it does not declare, and make sure every interactive element is reachable and operable from the keyboard with a visible focus state.
Styling: use Luc UI design tokens and the component's own props. Do not restyle with raw colour literals and do not override the component's internal structure with page CSS.
Motion: respect `prefers-reduced-motion`. The component already does, so do not disable it.
Reproduce this state:
```tsx
<KineticHeadline text="Markets reprice in seconds" />
```Everything on this page reads its behaviour from these switches. Reduced motion and the light/dark theme live in the topbar, exactly as they do everywhere else in the system — one control surface, not two.
Controls
Intensity
Pointer effects
Ambient motion
Profile
expressive · pointer=true · ambient=true · depth=1Intensity cascades to every child through React context. `none` is what reduced motion resolves to, so the two paths can never drift.
<MotionIntensityProvider intensity="expressive" pointer={true} ambient={true}>
<YourPage />
</MotionIntensityProvider>Small controls still feel intentional: a magnet, a spring press, a glyph that morphs, a field that answers focus.
Magnetic CTAs, a perimeter beam and a spring press.
Copy → check, sun → moon: one glyph dissolving into the next in a stable box.
The glyph box never changes size, so the toolbar never reflows.
The physical states, with the press spring.
Tilt, glare, spotlight and a border beam — the primitives stay generic; a product composes them.
Move the pointer across the card. Only transform animates, and the release is a spring.
Research card
Prepared evidence, 2015 → 2026. The card leans; the data does not move.
Glare surface
$72,105A sheen across the surface — never over the glyphs.
One pointer tracker drives the interior light, the lit edge and the texture: three readouts, one rAF write.
SpotlightSurface
Border and texture are the same pointer position, rendered three ways.
activeBorderTrail · ambient
A single bright segment travelling the perimeter. One per page.
The interactive shell and the spring press, composed. `featured` is the loudest static Card treatment.
MotionSurface
Lifts, lights and steps its border on hover.
Pressable
Hover lifts · press compresses
Static, but deliberate: accent hairline, deeper shadow, hover lift.
Shared geometry where a real source exists; directional panels where content swaps in place.
Radix owns focus, Escape and scroll lock; Motion owns one shared layout id.
Research card
Open detail
Metric detail
A directional swap inside one fixed slot — the outgoing panel leaves the flow, so the slot never collapses.
Levels
Price, SMA 50 and SMA 200 on one prepared axis.
Numbers and dense data get functional motion: digit-level rolls, semantic flashes, no per-row cascade.
Only the digits that changed move. The width is reserved, so nothing reflows.
BTC · USD
$72,104.87Prepared series
Interaction kinetics on the existing engines. No fabricated history, ever.
Hover a series: it thickens and glows while its peers step back. The latest observation carries a lit core.
Hovering a cell lights its edge, prints its value and lifts it — the grid geometry never moves.
The hovered observation grows, gains a lit border and a halo; every other point stays visible.
Loops are allowed now, but only when they mean something: a grid that answers the pointer, a status that decodes, a completion that sparks.
A low-contrast technical grid that lights up near the pointer, with an optional slow drift.
Move the pointer across the field.
Related