Crystal design system · motion
The motion kit.From the showroom floor.
The Artasce showroom's reveals, its chapter light and its test drive now live in Crystal as named parts with explicit dials, so every site composes the same mechanics and none of them looks the same. No animation library: React and one stylesheet.
CrystalReveal
Seven named arrivals. Content reveals once as it scrolls in; with a stagger, each child takes its turn.
<CrystalReveal variant="unveil" delay={90}>…</CrystalReveal>
<CrystalReveal as="ul" variant="rise" stagger={110}>…</CrystalReveal>CrystalHeadline
One line at a time, blur to sharp, so a headline settles instead of snapping in.
<CrystalHeadline as="h1" immediate lines={['Good looks.', <em>Real work.</em>]} />CrystalChapters + CrystalAmbient
The page is told in chapters. The room’s light crossfades to the chapter in view; you are watching it now. The meter reads useCrystalChapter().
<CrystalChapters initial="intro">
<CrystalAmbient layers={{ intro: {…}, forge: {…} }} />
<section data-crystal-chapter="forge">…</section>
</CrystalChapters>CrystalExpandDialog
The test drive opens out of the control you tapped and folds back into it. Escape, the X and a tap outside all close it; focus comes back where it was.
onClick={(e) => setOrigin(expandOriginFrom(e.currentTarget))}
<CrystalExpandDialog origin={origin} onClose={() => setOrigin(null)}>{(close) => …}</CrystalExpandDialog>Idle life
A first screen is never still: a rule with a passing light, a live dot earned only by a verified fact, a photo on its own clock, a slow ticker, a load line.
Operating now · a fact was just read liveChecking…<CrystalDrift cycle={11} offset={4}><Image fill … /></CrystalDrift>
<CrystalLiveDot state={verified ? 'live' : 'checking'}>…</CrystalLiveDot>