{"$schema":"https://ui.shadcn.com/schema/registry.json","name":"hairline","homepage":"https://hairlineui.com/ui","items":[{"name":"text-morph","type":"registry:component","title":"Text morph","description":"Text that changes the way it should: shared letters slide over, new ones rise out of a blur, the width eases.","dependencies":[],"files":[{"path":"registry/text-morph.tsx","type":"registry:component"}],"css":{}},{"name":"status-button","type":"registry:component","title":"Status button","description":"Save, Saving, Saved: the spinner opens in, the check draws itself, errors shake, and the label morphs between them.","dependencies":[],"registryDependencies":["https://hairlineui.com/r/text-morph.json"],"files":[{"path":"registry/status-button.tsx","type":"registry:component"}],"css":{}},{"name":"number-roll","type":"registry:component","title":"Number roll","description":"Numbers that change like an odometer: every digit rolls in the direction the number moved.","dependencies":[],"files":[{"path":"registry/number-roll.tsx","type":"registry:component"}],"css":{"@keyframes ui-col-in":{"from":{"max-width":"0","opacity":"0"},"to":{"max-width":"1em","opacity":"1"}},"@keyframes ui-col-out":{"from":{"max-width":"1em","opacity":"1"},"to":{"max-width":"0","opacity":"0"}}}},{"name":"pricing-toggle","type":"registry:component","title":"Pricing toggle","description":"Monthly or yearly: the thumb slides with a little give, and every price on the page rolls to its new amount.","dependencies":[],"registryDependencies":["https://hairlineui.com/r/number-roll.json"],"files":[{"path":"registry/pricing-toggle.tsx","type":"registry:component"}],"css":{"@keyframes ui-note-in":{"from":{"opacity":"0","transform":"translateY(var(--ui-from))"},"to":{"opacity":"1","transform":"none"}},"@keyframes ui-col-in":{"from":{"max-width":"0","opacity":"0"},"to":{"max-width":"1em","opacity":"1"}},"@keyframes ui-col-out":{"from":{"max-width":"1em","opacity":"1"},"to":{"max-width":"0","opacity":"0"}}}},{"name":"waitlist-field","type":"registry:component","title":"Waitlist field","description":"An email field that becomes its own answer: the button stretches across it, then settles as \"You’re on the list · #1,248\".","dependencies":[],"registryDependencies":["https://hairlineui.com/r/number-roll.json","https://hairlineui.com/r/text-morph.json"],"files":[{"path":"registry/waitlist-field.tsx","type":"registry:component"}],"css":{"@keyframes ui-scan":{"from":{"transform":"translateX(-100%)"},"to":{"transform":"translateX(250%)"}},"@keyframes ui-fade-in":{"from":{"opacity":"0"},"to":{"opacity":"1"}}}},{"name":"code-input","type":"registry:component","title":"Code input","description":"The six boxes, done properly: digits rise in, a paste cascades, a wrong code shakes and clears, the right one becomes a pill with a check.","dependencies":[],"registryDependencies":["https://hairlineui.com/r/number-roll.json","https://hairlineui.com/r/status-button.json","https://hairlineui.com/r/text-morph.json"],"files":[{"path":"registry/code-input.tsx","type":"registry:component"}],"css":{"@keyframes ui-blink":{"0%, 100%":{"opacity":"1"},"50%":{"opacity":"0"}},"@keyframes ui-sheen":{"from":{"mask-position":"150% 0"},"to":{"mask-position":"-50% 0"}}}},{"name":"steps-form","type":"registry:component","title":"Steps form","description":"A multi-step form in one card that changes shape: steps slide in from the way you’re going, checks shake and explain, and Create turns into what comes next.","dependencies":["lucide-react"],"registryDependencies":["https://hairlineui.com/r/number-roll.json","https://hairlineui.com/r/status-button.json","https://hairlineui.com/r/text-morph.json"],"files":[{"path":"registry/steps-form.tsx","type":"registry:component"}],"css":{}},{"name":"date-range-picker","type":"registry:component","title":"Date range picker","description":"A range is one liquid band: it follows your pointer between days, presets flow it to their span, and the dates morph as it moves.","dependencies":["lucide-react"],"registryDependencies":["https://hairlineui.com/r/number-roll.json","https://hairlineui.com/r/text-morph.json"],"files":[{"path":"registry/date-range-picker.tsx","type":"registry:component"}],"css":{}},{"name":"morphing-nav","type":"registry:component","title":"Morphing nav","description":"One dropdown that follows you along the menu, gliding and resizing to each item’s content.","dependencies":[],"files":[{"path":"registry/morphing-nav.tsx","type":"registry:component"}],"css":{"@keyframes ui-pop-in":{"from":{"opacity":"0","transform":"translateY(-4px) scale(0.96)"},"to":{"opacity":"1","transform":"none"}}}},{"name":"feature-tabs","type":"registry:component","title":"Feature tabs","description":"One panel, many features: the line slides between tabs, fills as autoplay runs, and the panel eases to each.","dependencies":[],"files":[{"path":"registry/feature-tabs.tsx","type":"registry:component"}],"css":{"@keyframes ui-progress":{"from":{"transform":"scaleX(0)"},"to":{"transform":"scaleX(1)"}}}},{"name":"scroll-story","type":"registry:component","title":"Scroll story","description":"A how-it-works section that tells itself as you scroll: steps light up at the middle, a rail fills, and one card reshapes into each step’s picture.","dependencies":[],"registryDependencies":["https://hairlineui.com/r/number-roll.json"],"files":[{"path":"registry/scroll-story.tsx","type":"registry:component"}],"css":{}},{"name":"stats-band","type":"registry:component","title":"Stats band","description":"Numbers that arrive when you do: hairlines draw themselves, then each figure rolls up from zero in turn.","dependencies":[],"registryDependencies":["https://hairlineui.com/r/number-roll.json"],"files":[{"path":"registry/stats-band.tsx","type":"registry:component"}],"css":{}},{"name":"announcement-pill","type":"registry:component","title":"Announcement pill","description":"\"New: …\" above your headline that opens into the news: the pill itself grows into a changelog card.","dependencies":[],"files":[{"path":"registry/announcement-pill.tsx","type":"registry:component"}],"css":{}},{"name":"testimonials","type":"registry:component","title":"Testimonials","description":"One quote, chosen by its people: faces step forward, the words cross-fade through a blur, a ring keeps time.","dependencies":[],"registryDependencies":["https://hairlineui.com/r/text-morph.json"],"files":[{"path":"registry/testimonials.tsx","type":"registry:component"}],"css":{"@keyframes ui-fade-in":{"from":{"opacity":"0"},"to":{"opacity":"1"}},"@keyframes ui-ring-fill":{"from":{"stroke-dashoffset":"var(--ui-ring)"},"to":{"stroke-dashoffset":"0"}}}},{"name":"faq-accordion","type":"registry:component","title":"FAQ accordion","description":"Questions on hairlines that open like they mean it: the answer eases to its height, the plus folds into a minus.","dependencies":[],"files":[{"path":"registry/faq-accordion.tsx","type":"registry:component"}],"css":{}},{"name":"logo-marquee","type":"registry:component","title":"Logo marquee","description":"A quiet strip of logos that notices you: it eases to a stop on hover and the logo you point at stays bright.","dependencies":[],"files":[{"path":"registry/logo-marquee.tsx","type":"registry:component"}],"css":{}},{"name":"command-palette","type":"registry:component","title":"Command palette","description":"⌘K that grows out of the search pill: fuzzy search, nested lists, and commands that run in place.","dependencies":[],"registryDependencies":["https://hairlineui.com/r/text-morph.json"],"files":[{"path":"registry/command-palette.tsx","type":"registry:component"}],"css":{}},{"name":"toast-stack","type":"registry:component","title":"Toast stack","description":"Notifications that stack, fan out on hover, follow a promise in one toast, and swipe away.","dependencies":[],"registryDependencies":["https://hairlineui.com/r/text-morph.json"],"files":[{"path":"registry/toast-stack.tsx","type":"registry:component"}],"css":{"@keyframes ui-progress":{"from":{"transform":"scaleX(0)"},"to":{"transform":"scaleX(1)"}}}},{"name":"live-activity","type":"registry:component","title":"Live activity","description":"One pill for whatever is happening now: it updates in place, tap it and it grows into a panel, done blurs into a check.","dependencies":[],"registryDependencies":["https://hairlineui.com/r/number-roll.json","https://hairlineui.com/r/text-morph.json"],"files":[{"path":"registry/live-activity.tsx","type":"registry:component"}],"css":{}},{"name":"live-cursors","type":"registry:component","title":"Live cursors","description":"Other people’s cursors gliding over the same page: names that turn into speech bubbles, click ripples, and selections that follow them around.","dependencies":[],"files":[{"path":"registry/live-cursors.tsx","type":"registry:component"}],"css":{}},{"name":"live-map","type":"registry:component","title":"Live map","description":"The world as dots, lighting up where things happen: pings ripple, the light lingers, and one card follows the newest event from city to city.","dependencies":[],"registryDependencies":["https://hairlineui.com/r/text-morph.json"],"files":[{"path":"registry/live-map.tsx","type":"registry:component"}],"css":{}},{"name":"theme-toggle","type":"registry:component","title":"Theme toggle","description":"The sun sets into a moon, and the new theme spreads from the button in a circle.","dependencies":[],"registryDependencies":["https://hairlineui.com/r/text-morph.json"],"files":[{"path":"registry/theme-toggle.tsx","type":"registry:component"}],"css":{}},{"name":"pricing-calculator","type":"registry:component","title":"Pricing calculator","description":"Drag to your size and watch the price roll, the plan morph and, at the top, “Let’s talk”.","dependencies":[],"registryDependencies":["https://hairlineui.com/r/number-roll.json","https://hairlineui.com/r/text-morph.json","https://hairlineui.com/r/pricing-toggle.json"],"files":[{"path":"registry/pricing-calculator.tsx","type":"registry:component"}],"css":{}},{"name":"comparison-table","type":"registry:component","title":"Comparison table","description":"Plans side by side, with a column that glides to the plan under your pointer and prices that roll.","dependencies":[],"registryDependencies":["https://hairlineui.com/r/pricing-toggle.json"],"files":[{"path":"registry/comparison-table.tsx","type":"registry:component"}],"css":{"@keyframes ui-slide-from-right":{"from":{"opacity":"0","transform":"translateX(8px)"},"to":{"opacity":"1","transform":"none"}},"@keyframes ui-slide-from-left":{"from":{"opacity":"0","transform":"translateX(-8px)"},"to":{"opacity":"1","transform":"none"}}}},{"name":"onboarding-checklist","type":"registry:component","title":"Onboarding checklist","description":"The first five things, ticked off in place: a ring that fills, checks that draw, and a finish worth seeing.","dependencies":[],"registryDependencies":["https://hairlineui.com/r/number-roll.json","https://hairlineui.com/r/text-morph.json"],"files":[{"path":"registry/onboarding-checklist.tsx","type":"registry:component"}],"css":{"@keyframes ui-fade-in":{"from":{"opacity":"0"},"to":{"opacity":"1"}}}},{"name":"sortable-list","type":"registry:component","title":"Sortable list","description":"Drag to reorder and everything moves: rows slide out of the way, the dropped one settles, every rank rolls, and presets re-sort the lot.","dependencies":[],"registryDependencies":["https://hairlineui.com/r/number-roll.json"],"files":[{"path":"registry/sortable-list.tsx","type":"registry:component"}],"css":{}},{"name":"changelog-timeline","type":"registry:component","title":"Changelog timeline","description":"What shipped, drawn as you read: a rail that fills, dots that light, filters that fold the rest away.","dependencies":[],"registryDependencies":["https://hairlineui.com/r/number-roll.json","https://hairlineui.com/r/text-morph.json"],"files":[{"path":"registry/changelog-timeline.tsx","type":"registry:component"}],"css":{}},{"name":"changelog-trace","type":"registry:component","title":"Changelog trace","description":"What shipped, routed like a circuit: the line steps aside between releases, and a bead runs down it as you read.","dependencies":[],"registryDependencies":["https://hairlineui.com/r/number-roll.json","https://hairlineui.com/r/text-morph.json"],"files":[{"path":"registry/changelog-trace.tsx","type":"registry:component"}],"css":{}},{"name":"changelog-scrubber","type":"registry:component","title":"Changelog scrubber","description":"Your release history on a ruler you scrub: drag the playhead, or press play and watch the product ship.","dependencies":[],"registryDependencies":["https://hairlineui.com/r/number-roll.json","https://hairlineui.com/r/text-morph.json"],"files":[{"path":"registry/changelog-scrubber.tsx","type":"registry:component"}],"css":{}},{"name":"cookie-banner","type":"registry:component","title":"Cookie banner","description":"Asks once, plainly, then folds into a small cookie button in the corner that grows back into the preferences.","dependencies":[],"registryDependencies":["https://hairlineui.com/r/text-morph.json"],"files":[{"path":"registry/cookie-banner.tsx","type":"registry:component"}],"css":{}},{"name":"newsletter-footer","type":"registry:component","title":"Newsletter footer","description":"A footer that’s still alive: a signup that becomes its own confirmation, drawn link underlines and your name in outline.","dependencies":[],"registryDependencies":["https://hairlineui.com/r/number-roll.json","https://hairlineui.com/r/text-morph.json"],"files":[{"path":"registry/newsletter-footer.tsx","type":"registry:component"}],"css":{"@keyframes ui-breathe":{"0%, 100%":{"transform":"scale(0.82)","opacity":"0.55"},"50%":{"transform":"scale(1)","opacity":"1"}}}},{"name":"prompt-composer","type":"registry:component","title":"Prompt composer","description":"The input that starts it all: grows as you type, takes files, and turns Send into Stop while answering.","dependencies":["lucide-react"],"registryDependencies":["https://hairlineui.com/r/number-roll.json"],"files":[{"path":"registry/prompt-composer.tsx","type":"registry:component"}],"css":{}},{"name":"agent-composer","type":"registry:component","title":"Agent composer","description":"The taller composer for agent surfaces: branch, folder and context on a tab above, permissions and model as pills that grow into their lists.","dependencies":["lucide-react"],"registryDependencies":["https://hairlineui.com/r/model-picker.json","https://hairlineui.com/r/number-roll.json","https://hairlineui.com/r/text-morph.json"],"files":[{"path":"registry/agent-composer.tsx","type":"registry:component"}],"css":{"@keyframes ui-breathe":{"0%, 100%":{"transform":"scale(0.82)","opacity":"0.55"},"50%":{"transform":"scale(1)","opacity":"1"}}}},{"name":"mention-menu","type":"registry:component","title":"Mentions and commands","description":"Type @ to pull in context or / for a command. The menu grows from the caret and your text becomes a chip.","dependencies":[],"registryDependencies":["https://hairlineui.com/r/text-morph.json"],"files":[{"path":"registry/mention-menu.tsx","type":"registry:component"}],"css":{"@keyframes ui-sheen":{"from":{"mask-position":"150% 0"},"to":{"mask-position":"-50% 0"}},"@keyframes ui-pop-in":{"from":{"opacity":"0","transform":"translateY(-4px) scale(0.96)"},"to":{"opacity":"1","transform":"none"}},"@keyframes ui-chip-in":{"from":{"opacity":"0.35","transform":"scale(0.9)"},"to":{"opacity":"1","transform":"none"}}}},{"name":"attachment-chip","type":"registry:component","title":"Attachment chip","description":"A file on its way into a prompt: uploading, being read, ready or failed.","dependencies":["lucide-react"],"registryDependencies":["https://hairlineui.com/r/number-roll.json","https://hairlineui.com/r/text-morph.json"],"files":[{"path":"registry/attachment-chip.tsx","type":"registry:component"}],"css":{"@keyframes ui-sheen":{"from":{"mask-position":"150% 0"},"to":{"mask-position":"-50% 0"}},"@keyframes ui-fade-up":{"from":{"opacity":"0","transform":"translateY(4px)"},"to":{"opacity":"1","transform":"none"}}}},{"name":"mode-switcher","type":"registry:component","title":"Mode switcher","description":"Fast, Thinking, Research: a segmented switch with a sliding pill and locked paid modes.","dependencies":["lucide-react"],"registryDependencies":["https://hairlineui.com/r/text-morph.json"],"files":[{"path":"registry/mode-switcher.tsx","type":"registry:component"}],"css":{}},{"name":"model-picker","type":"registry:component","title":"Model picker","description":"The model pill in your composer grows into the menu: what each model is for, speed, smarts and thinking effort.","dependencies":["lucide-react"],"registryDependencies":["https://hairlineui.com/r/text-morph.json"],"files":[{"path":"registry/model-picker.tsx","type":"registry:component"}],"css":{"@keyframes ui-fade-in":{"from":{"opacity":"0"},"to":{"opacity":"1"}}}},{"name":"voice-input","type":"registry:component","title":"Voice input","description":"Dictate a prompt: a waveform from your real mic level, a timer, then transcribing.","dependencies":["lucide-react"],"registryDependencies":["https://hairlineui.com/r/number-roll.json","https://hairlineui.com/r/text-morph.json"],"files":[{"path":"registry/voice-input.tsx","type":"registry:component"}],"css":{"@keyframes ui-sheen":{"from":{"mask-position":"150% 0"},"to":{"mask-position":"-50% 0"}},"@keyframes ui-wave":{"0%, 100%":{"transform":"scaleY(0.35)"},"50%":{"transform":"scaleY(1)"}}}},{"name":"voice-note","type":"registry:component","title":"Voice note","description":"A voice message you can scrub and read along with: the waveform fills, the time rolls, and the transcript highlights each word as it’s said.","dependencies":["lucide-react"],"registryDependencies":["https://hairlineui.com/r/number-roll.json"],"files":[{"path":"registry/voice-note.tsx","type":"registry:component"}],"css":{}},{"name":"thinking-indicator","type":"registry:component","title":"Thinking indicator","description":"Four quiet loaders for the gap before the first token, with a label, a rolling timer and a finish that draws itself.","dependencies":[],"registryDependencies":["https://hairlineui.com/r/number-roll.json","https://hairlineui.com/r/text-morph.json"],"files":[{"path":"registry/thinking-indicator.tsx","type":"registry:component"}],"css":{"@keyframes ui-sheen":{"from":{"mask-position":"150% 0"},"to":{"mask-position":"-50% 0"}},"@keyframes ui-bounce":{"0%, 80%, 100%":{"transform":"translateY(0)","opacity":"0.35"},"40%":{"transform":"translateY(-3px)","opacity":"1"}},"@keyframes ui-breathe":{"0%, 100%":{"transform":"scale(0.82)","opacity":"0.55"},"50%":{"transform":"scale(1)","opacity":"1"}},"@keyframes ui-scan":{"from":{"transform":"translateX(-100%)"},"to":{"transform":"translateX(250%)"}}}},{"name":"thinking-trace","type":"registry:component","title":"Thinking trace","description":"An expandable record of what an agent did: steps, reasoning, search or tool calls.","dependencies":["lucide-react"],"registryDependencies":["https://hairlineui.com/r/number-roll.json","https://hairlineui.com/r/text-morph.json"],"files":[{"path":"registry/thinking-trace.tsx","type":"registry:component"}],"css":{"@keyframes ui-sheen":{"from":{"mask-position":"150% 0"},"to":{"mask-position":"-50% 0"}},"@keyframes ui-fade-up":{"from":{"opacity":"0","transform":"translateY(4px)"},"to":{"opacity":"1","transform":"none"}},"@keyframes ui-fade-in":{"from":{"opacity":"0"},"to":{"opacity":"1"}}}},{"name":"tool-call","type":"registry:component","title":"Tool call","description":"One tool invocation from arguments to result: preparing, running, done, failed or denied.","dependencies":["lucide-react"],"registryDependencies":["https://hairlineui.com/r/number-roll.json","https://hairlineui.com/r/text-morph.json"],"files":[{"path":"registry/tool-call.tsx","type":"registry:component"}],"css":{"@keyframes ui-sheen":{"from":{"mask-position":"150% 0"},"to":{"mask-position":"-50% 0"}},"@keyframes ui-fade-up":{"from":{"opacity":"0","transform":"translateY(4px)"},"to":{"opacity":"1","transform":"none"}}}},{"name":"clarifying-question","type":"registry:component","title":"Clarifying question","description":"The agent pauses to ask. Pick with a click or a number key, or type your own; it folds into a one-line receipt.","dependencies":["lucide-react"],"registryDependencies":["https://hairlineui.com/r/number-roll.json","https://hairlineui.com/r/text-morph.json"],"files":[{"path":"registry/clarifying-question.tsx","type":"registry:component"}],"css":{"@keyframes ui-fade-in":{"from":{"opacity":"0"},"to":{"opacity":"1"}},"@keyframes ui-ping":{"from":{"transform":"scale(1)","opacity":"0.55"},"to":{"transform":"scale(2.6)","opacity":"0"}}}},{"name":"approval-card","type":"registry:component","title":"Approval card","description":"The agent asks before it acts: what it wants to do, the details, Approve or Deny.","dependencies":["lucide-react"],"registryDependencies":["https://hairlineui.com/r/number-roll.json","https://hairlineui.com/r/text-morph.json"],"files":[{"path":"registry/approval-card.tsx","type":"registry:component"}],"css":{"@keyframes ui-fade-up":{"from":{"opacity":"0","transform":"translateY(4px)"},"to":{"opacity":"1","transform":"none"}}}},{"name":"plan","type":"registry:component","title":"Plan","description":"An agent’s checklist that ticks itself off: pending, in progress, done, skipped or failed.","dependencies":["lucide-react"],"registryDependencies":["https://hairlineui.com/r/number-roll.json"],"files":[{"path":"registry/plan.tsx","type":"registry:component"}],"css":{}},{"name":"web-research","type":"registry:component","title":"Web research","description":"Watch the agent search: the query types in, page icons stack up as it reads, then it folds into a trail of searches and the pages each one found.","dependencies":["lucide-react"],"registryDependencies":["https://hairlineui.com/r/number-roll.json","https://hairlineui.com/r/text-morph.json"],"files":[{"path":"registry/web-research.tsx","type":"registry:component"}],"css":{"@keyframes ui-sheen":{"from":{"mask-position":"150% 0"},"to":{"mask-position":"-50% 0"}},"@keyframes ui-breathe":{"0%, 100%":{"transform":"scale(0.82)","opacity":"0.55"},"50%":{"transform":"scale(1)","opacity":"1"}},"@keyframes ui-drop-in":{"from":{"opacity":"0","transform":"translateY(-8px) scale(0.6)"},"to":{"opacity":"1","transform":"none"}}}},{"name":"command-output","type":"registry:component","title":"Command output","description":"A command the agent runs: the log streams in, folds away on success, and stays open on failure.","dependencies":["lucide-react"],"registryDependencies":["https://hairlineui.com/r/number-roll.json","https://hairlineui.com/r/text-morph.json"],"files":[{"path":"registry/command-output.tsx","type":"registry:component"}],"css":{"@keyframes ui-fade-in":{"from":{"opacity":"0"},"to":{"opacity":"1"}},"@keyframes ui-blink":{"0%, 100%":{"opacity":"1"},"50%":{"opacity":"0"}}}},{"name":"task-progress","type":"registry:component","title":"Task progress","description":"For work that takes minutes: phases, a live timer, stats, cancel, and the result when it’s done.","dependencies":["lucide-react"],"registryDependencies":["https://hairlineui.com/r/number-roll.json","https://hairlineui.com/r/text-morph.json"],"files":[{"path":"registry/task-progress.tsx","type":"registry:component"}],"css":{"@keyframes ui-scan":{"from":{"transform":"translateX(-100%)"},"to":{"transform":"translateX(250%)"}},"@keyframes ui-sheen":{"from":{"mask-position":"150% 0"},"to":{"mask-position":"-50% 0"}}}},{"name":"task-log","type":"registry:component","title":"Task log","description":"What the agent did, task by task, as it does it: steps arrive on a hairline trail, files sit in chips, titles turn past tense.","dependencies":["lucide-react"],"registryDependencies":["https://hairlineui.com/r/text-morph.json"],"files":[{"path":"registry/task-log.tsx","type":"registry:component"}],"css":{"@keyframes ui-sheen":{"from":{"mask-position":"150% 0"},"to":{"mask-position":"-50% 0"}}}},{"name":"streaming-answer","type":"registry:component","title":"Streaming answer","description":"An answer as it arrives, with inline citations, actions, sources and follow-ups.","dependencies":["lucide-react"],"registryDependencies":["https://hairlineui.com/r/number-roll.json"],"files":[{"path":"registry/streaming-answer.tsx","type":"registry:component"}],"css":{"@keyframes ui-fade-up":{"from":{"opacity":"0","transform":"translateY(4px)"},"to":{"opacity":"1","transform":"none"}},"@keyframes ui-fade-in":{"from":{"opacity":"0"},"to":{"opacity":"1"}},"@keyframes ui-blink":{"0%, 100%":{"opacity":"1"},"50%":{"opacity":"0"}}}},{"name":"code-block","type":"registry:component","title":"Code block","description":"Code in an answer: highlighted as it streams, copy and wrap, long files folded, and an optional Apply.","dependencies":["lucide-react"],"registryDependencies":["https://hairlineui.com/r/status-button.json","https://hairlineui.com/r/text-morph.json"],"files":[{"path":"registry/code-block.tsx","type":"registry:component"}],"css":{"@keyframes ui-blink":{"0%, 100%":{"opacity":"1"},"50%":{"opacity":"0"}}}},{"name":"citation","type":"registry:component","title":"Citation","description":"An inline numbered source that previews the site, title and snippet on hover or focus.","dependencies":["lucide-react"],"files":[{"path":"registry/citation.tsx","type":"registry:component"}],"css":{}},{"name":"response-versions","type":"registry:component","title":"Response versions","description":"Step between regenerated answers with \"2 / 3\", and regenerate without losing the old ones.","dependencies":["lucide-react"],"registryDependencies":["https://hairlineui.com/r/number-roll.json"],"files":[{"path":"registry/response-versions.tsx","type":"registry:component"}],"css":{}},{"name":"selection-actions","type":"registry:component","title":"Selection actions","description":"Select text and a pill appears under it. Pick an action or describe an edit, and the rewrite streams in place.","dependencies":["lucide-react"],"files":[{"path":"registry/selection-actions.tsx","type":"registry:component"}],"css":{"@keyframes ui-shimmer":{"0%":{"background-position":"150% 0"},"100%":{"background-position":"-50% 0"}},"@keyframes ui-fade-in":{"from":{"opacity":"0"},"to":{"opacity":"1"}},"@keyframes ui-pop-in":{"from":{"opacity":"0","transform":"translateY(-4px) scale(0.96)"},"to":{"opacity":"1","transform":"none"}},"@layer base":{"::highlight(ui-selection)":{"background-color":"color-mix(in oklab, var(--primary) 18%, transparent)"}}}},{"name":"inline-rewrite","type":"registry:component","title":"Inline rewrite","description":"Drag a dial and the paragraph rewrites itself in place: shared words glide, the rest blur out and rise in.","dependencies":[],"registryDependencies":["https://hairlineui.com/r/number-roll.json","https://hairlineui.com/r/text-morph.json"],"files":[{"path":"registry/inline-rewrite.tsx","type":"registry:component"}],"css":{"@keyframes ui-sheen":{"from":{"mask-position":"150% 0"},"to":{"mask-position":"-50% 0"}}}},{"name":"diff-review","type":"registry:component","title":"Diff review","description":"Accept or reject what the AI changed, word by word for prose or line by line for code.","dependencies":["lucide-react"],"registryDependencies":["https://hairlineui.com/r/number-roll.json","https://hairlineui.com/r/text-morph.json"],"files":[{"path":"registry/diff-review.tsx","type":"registry:component"}],"css":{}},{"name":"action-receipt","type":"registry:component","title":"Action receipts","description":"What the agent actually did, one quiet line each, with Undo while a ring drains. Several stack into one.","dependencies":["lucide-react"],"registryDependencies":["https://hairlineui.com/r/number-roll.json","https://hairlineui.com/r/text-morph.json"],"files":[{"path":"registry/action-receipt.tsx","type":"registry:component"}],"css":{"@keyframes ui-fade-up":{"from":{"opacity":"0","transform":"translateY(4px)"},"to":{"opacity":"1","transform":"none"}},"@keyframes ui-drain":{"from":{"stroke-dashoffset":"0"},"to":{"stroke-dashoffset":"var(--ui-ring)"}}}},{"name":"chat-notice","type":"registry:component","title":"Error and limit states","description":"Calm, specific notices for failed answers, being offline, rate limits and chats that grow too long.","dependencies":["lucide-react"],"registryDependencies":["https://hairlineui.com/r/number-roll.json","https://hairlineui.com/r/status-button.json","https://hairlineui.com/r/text-morph.json"],"files":[{"path":"registry/chat-notice.tsx","type":"registry:component"}],"css":{"@keyframes ui-fade-up":{"from":{"opacity":"0","transform":"translateY(4px)"},"to":{"opacity":"1","transform":"none"}},"@keyframes ui-breathe":{"0%, 100%":{"transform":"scale(0.82)","opacity":"0.55"},"50%":{"transform":"scale(1)","opacity":"1"}}}},{"name":"usage-meter","type":"registry:component","title":"Usage meter","description":"Credits, messages or context left: quiet when there’s plenty, clear before it runs out.","dependencies":[],"registryDependencies":["https://hairlineui.com/r/number-roll.json","https://hairlineui.com/r/text-morph.json"],"files":[{"path":"registry/usage-meter.tsx","type":"registry:component"}],"css":{}},{"name":"usage-limits","type":"registry:component","title":"Usage limits","description":"What an agent has left: the context window split by what fills it, and each plan limit with its share and a live reset countdown.","dependencies":["lucide-react"],"registryDependencies":["https://hairlineui.com/r/number-roll.json"],"files":[{"path":"registry/usage-limits.tsx","type":"registry:component"}],"css":{}},{"name":"chat-scroll","type":"registry:component","title":"Jump to latest","description":"A chat that follows the answer as it streams, lets go the moment you scroll up, and brings you back.","dependencies":["lucide-react"],"registryDependencies":["https://hairlineui.com/r/text-morph.json"],"files":[{"path":"registry/chat-scroll.tsx","type":"registry:component"}],"css":{"@keyframes ui-sheen":{"from":{"mask-position":"150% 0"},"to":{"mask-position":"-50% 0"}},"@keyframes ui-ping":{"from":{"transform":"scale(1)","opacity":"0.55"},"to":{"transform":"scale(2.6)","opacity":"0"}}}},{"name":"message-edit","type":"registry:component","title":"Edit and resend","description":"Fix a sent message where it sits. The bubble grows into an editor, then folds back and branches the reply.","dependencies":["lucide-react"],"registryDependencies":["https://hairlineui.com/r/number-roll.json"],"files":[{"path":"registry/message-edit.tsx","type":"registry:component"}],"css":{"@keyframes ui-fade-in":{"from":{"opacity":"0"},"to":{"opacity":"1"}}}},{"name":"chat-history","type":"registry:component","title":"Chat history","description":"Past chats grouped by day, searchable, with titles that write themselves, rename in place and delete with Undo.","dependencies":["lucide-react"],"files":[{"path":"registry/chat-history.tsx","type":"registry:component"}],"css":{"@keyframes ui-shimmer":{"0%":{"background-position":"150% 0"},"100%":{"background-position":"-50% 0"}},"@keyframes ui-fade-up":{"from":{"opacity":"0","transform":"translateY(4px)"},"to":{"opacity":"1","transform":"none"}}}},{"name":"earnings-chart","type":"registry:component","title":"Earnings chart","description":"A bar chart that changes instead of redrawing: bars glide between periods, the scale and the total roll, a readout follows the pointer.","dependencies":[],"registryDependencies":["https://hairlineui.com/r/number-roll.json","https://hairlineui.com/r/text-morph.json"],"files":[{"path":"registry/earnings-chart.tsx","type":"registry:component"}],"css":{}},{"name":"steps-chart","type":"registry:component","title":"Steps chart","description":"A week against a daily goal: days that make it fill in, a wave runs the way you step through the weeks, the totals roll.","dependencies":[],"registryDependencies":["https://hairlineui.com/r/number-roll.json","https://hairlineui.com/r/text-morph.json"],"files":[{"path":"registry/steps-chart.tsx","type":"registry:component"}],"css":{}},{"name":"revenue-chart","type":"registry:component","title":"Revenue chart","description":"This year as an area, last year behind it; point at a month and the header becomes the readout, switch the measure and the lines reshape.","dependencies":[],"registryDependencies":["https://hairlineui.com/r/number-roll.json","https://hairlineui.com/r/text-morph.json"],"files":[{"path":"registry/revenue-chart.tsx","type":"registry:component"}],"css":{}},{"name":"area-chart","type":"registry:component","title":"Area chart","description":"Several series stacked, overlapping or as shares: every band morphs between layouts, and the tiles are the legend, the switches and the readout.","dependencies":[],"registryDependencies":["https://hairlineui.com/r/number-roll.json","https://hairlineui.com/r/text-morph.json"],"files":[{"path":"registry/area-chart.tsx","type":"registry:component"}],"css":{}},{"name":"combo-chart","type":"registry:component","title":"Combo chart","description":"Every day as a bar and the trend as a line on one scale: point at a day and the header becomes its readout while the line’s dot pings where it lands.","dependencies":[],"registryDependencies":["https://hairlineui.com/r/number-roll.json","https://hairlineui.com/r/text-morph.json"],"files":[{"path":"registry/combo-chart.tsx","type":"registry:component"}],"css":{}},{"name":"stage-bars","type":"registry:component","title":"Stage bars","description":"A funnel you can read at a glance: every stage as a bar against the first, the drop-off between them, and widths that ease when the period changes.","dependencies":[],"registryDependencies":["https://hairlineui.com/r/number-roll.json"],"files":[{"path":"registry/stage-bars.tsx","type":"registry:component"}],"css":{}},{"name":"activity-rings","type":"registry:component","title":"Activity rings","description":"Three daily goals as concentric rings beside a tight legend, with the week underneath: pick a day and the rings sweep to it.","dependencies":[],"registryDependencies":["https://hairlineui.com/r/number-roll.json","https://hairlineui.com/r/text-morph.json"],"files":[{"path":"registry/activity-rings.tsx","type":"registry:component"}],"css":{}},{"name":"agent-playback","type":"registry:component","title":"Agent playback","description":"Your AI product working, hands-off and on a loop: the hero demo built from the real components.","dependencies":["lucide-react"],"registryDependencies":["https://hairlineui.com/r/prompt-composer.json","https://hairlineui.com/r/thinking-trace.json","https://hairlineui.com/r/web-research.json","https://hairlineui.com/r/tool-call.json","https://hairlineui.com/r/streaming-answer.json"],"files":[{"path":"registry/agent-playback.tsx","type":"registry:component"}],"css":{}}]}