REFERENCE
- Gallery page: https://magpui.com/en/i/dot-matrix-ai-status-pill-40a3dc
- First frame (image): https://dnioievkvxejjbxgwvko.supabase.co/storage/v1/object/public/media/dot-matrix-ai-status-pill-40a3dc/shot.jpg
- Clip (mp4): https://dnioievkvxejjbxgwvko.supabase.co/storage/v1/object/public/media/dot-matrix-ai-status-pill-40a3dc/clip.mp4
- Original post: https://x.com/sucodeee/status/2111410340995199367 by @sucodeee
Before building, download the first frame and look at it. If ffmpeg is available, download the clip and extract frames (ffmpeg -i clip.mp4 -vf fps=2 frame-%02d.png), then study the motion frame by frame. Match what you see; the text below describes it, the frames are the truth.
BUILD: An AI agent status pill that shows what the assistant is doing right now (Thinking, Reading docs, Analysing, Debugging). On the left a small dot-matrix glyph whose dots keep lighting up in shifting patterns; on the right the status word with a soft shimmer sweeping through it. When the status changes, the old word blurs out, the pill smoothly resizes to the new word's width and the new word blurs in. It should feel calm, alive and tactile, like a physical chip sitting on paper.
DESIGN SYSTEM: Page background warm off-white #F1F0EC. Pill: height 44px, padding 0 18px 0 14px, fully rounded (radius 999px). Inner fill #ECEBE6 with a thick 4px white (#FFFFFF) ring around it, plus a soft drop shadow 0 6px 16px rgba(0,0,0,0.06) and a faint inner highlight. Gap 10px between glyph and text. Glyph: 5x5 grid of 2.5px square-ish dots, 1.5px gap, total ~18px; lit dots #1A1A1A, dim dots #C9C7C1. Label: neutral grotesk sans, 16px, weight 600, color #1C1C1C, letter-spacing -0.01em.
MOTION:
- Glyph loop: every 120ms a new frame; each dot transitions opacity 0.25 <-> 1 over 160ms cubic-bezier(0.4,0,0.2,1). Use a different pattern sequence per status (scanning rows for Reading, random sparkle for Thinking, column sweep for Debugging).
- Text shimmer: linear-gradient(90deg, #1C1C1C 0%, #1C1C1C 40%, #9A9893 50%, #1C1C1C 60%, #1C1C1C 100%) clipped to text, background-size 250%, background-position animated from 100% to -100% over 1600ms linear, infinite.
- Status change: old label opacity 1->0, filter blur(0)->blur(6px), translateY 0->-2px over 180ms cubic-bezier(0.4,0,1,1). Pill width animates to the new measured width over 320ms cubic-bezier(0.32,0.72,0,1). New label enters opacity 0->1, blur(6px)->blur(0) over 240ms cubic-bezier(0.22,1,0.36,1), delay 120ms. Glyph briefly blurs (blur 4px) during the swap.
SECTIONS: Parts: outer white ring, inner fill, dot-matrix glyph, status label. States: idle (one status looping), changing (blur crossfade + width morph), done (optional: glyph settles to a checkmark pattern, shimmer stops).
IMPLEMENTATION: React + Motion (framer-motion): AnimatePresence mode="popLayout" for the label swap and layout animation on the pill for the width morph; glyph as a 25-cell CSS grid driven by a setInterval/requestAnimationFrame pattern index; shimmer in pure CSS (background-clip:text). prefers-reduced-motion: stop the shimmer and glyph loop (show a static pattern), swap labels with a 120ms opacity fade only. Accessibility: wrap in role="status" aria-live="polite" so the new status is announced; glyph aria-hidden. Performance: animate only opacity, transform and filter; pause the glyph interval when the pill is off-screen or the tab is hidden.
ADAPT TO THE PROJECT: Reuse the project's existing design tokens, components and fonts; map colors to the closest existing tokens (background, surface, foreground, muted). Never copy logos, brand names or illustrations from the original; use placeholder status labels.
SUCCESS CHECK:
- The glyph changes pattern continuously and the shimmer sweeps across the label without layout shift.
- Changing the status blurs the old word out, resizes the pill smoothly and blurs the new word in, with no width jump.
- With prefers-reduced-motion on, nothing loops and the label swap is a plain fade; a screen reader announces each new status.