crucıble

Parley

Contact section that routes before it asks: topic chips (Sales / Support / Press / Other) reshape the form with layout animation — fields glide in and out, the submit label and expected-reply line change. Blur validation with a shake, async pending → drawn-check success or an inline error that keeps every value, plus channel cards with copy-to-clipboard and an office card with an abstract SVG street plate and pulsing pin.

motionfree

Installation

CLI

npx shadcn@latest add @crucible/parley

Manual — install dependencies, then copy the source

npm install motion

Props

PropTypeDefaultDescription
eyebrowReact.ReactNode"Contact"Small label above the title.
titleReact.ReactNode"Talk to the right person"Section heading.
subtitleReact.ReactNodeLine under the heading.
topicsParleyTopic[]Topic chips and the form each one routes to. Omit for Sales / Support / Press / Other.
defaultTopicstringfirst topicUncontrolled initial topic id.
topicstringControlled topic id.
onTopicChange(id: string) => voidCalled when the visitor picks a topic.
onSubmit(values: Record<string, string>, topic: string) => void | Promise<unknown>Called with the current topic's values. Return a Promise to hold the button in its pending state — resolve shows the success card, reject keeps every value and shows the rejection's message inline.
channelsParleyChannel[]Side-column channel cards with copy-to-clipboard. Omit for a sample set; [] hides them.
officeParleyOffice | falseOffice card with an abstract location plate, or false to hide it.
accentColorstring"#60a5fa"Accent hex for the active chip, submit button, focus rings and pin.
refReact.Ref<ParleyHandle>Imperative handle (reset(), replay(), setTopic(), focus()). React 19 ref-as-prop.
classNamestringExtra classes for the <section> root.
Also accepts all props of Omit<React.ComponentPropsWithoutRef<"section">, "children" | "title" | "onSubmit"> — they pass through to the underlying element.

Honors prefers-reduced-motion with a designed static fallback, and passes className through.