This animation is built on the following libraries. expo install pins the versions that match your SDK, and the CLI tells you exactly which ones are missing when you add the component.
import { CardExpand, ExpandCard } from '@/components/ui/CardExpand';const CARDS: ExpandCard[] = [ { id: 'focus', label: 'Featured', title: 'Deep Focus', subtitle: 'One line under the title.', body: 'The long text revealed once the card is fullscreen.', colors: ['#3b2f2a', '#8a5a3b'], },];<CardExpand cards={CARDS} />;
Measure the card. On tap, measureInWindow gives the card's rect in window coordinates. That rect is the entire shared element contract: the clone starts there and must land back there.
One progress drives everything. An overlay renders the same card face and a single progress value interpolates its rect from the slot to fullscreen, on a calm Apple-style bezier (0.32, 0.72, 0, 1), no spring. The body fade, the label offset and the background list zoom all read the same value, so nothing can desync.
Drag to dismiss. A pan shrinks the sheet while held. Past 140pt or a 900pt/s flick it releases into the close animation, reversed on the same curve.
Coordinate space. The overlay lives inside the component's container, translated by the container's window offset, so the sheet covers the whole screen even when mounted below a header.