Skip to content
Site volume
Colourway

Components

QuoteForm

The site's inquiry form: name, email, website, tier and budget keys, a message, and the one action key.

Import from@maxgrits/overprint-react/quote-form
On this page

Example#

Look of this example
What do you need?
Budget (optional)

Prefer email? Write to studio@example.com

Live render of examples/quote-form/basic.tsx

Usage#

QuoteForm is the site's lead funnel: name, email, the current website, what they need, the budget and a message, with the honeypot and timestamp built in. Pass action (a URL or a server action) and the tiers; everything else has a literal default.

  • Intents. quote (the full form), product (name, email, message) and release-note (name, email and an optional message, "Ask for the note").
  • Tiers and budgets print as toggle keys; appTierId hides the budget for the tier that does not need one. defaults pre-fill from the query, such as ?tier=.
  • States. Sending keeps the fields editable; sent replaces the form with a success plate and moves focus to it; a failure shows the error above Send with "Email it instead", a mailto link built from what was typed.
  • In a drawer the Send row is the drawer's sticky footer.

Anatomy#

What do you need?
Budget (optional)

Prefer email? Write to studio@example.com

The parts of examples/quote-form/basic.tsx, numbered:
  1. Name and emailSide by side from the sm width..mk-quote-form-pair
  2. Tier keysWhat do you need, as toggle keys..mk-radio-group
  3. Send rowThe action key, the view's one action..mk-quote-form-send
  4. FallbackThe email address, always visible..mk-quote-form-fallback

Volume#

Reading layer: identical at every volume, so the most important form on the site never gets louder than its labels.

  • Quiet

    What do you need?
    Budget (optional)

    Prefer email? Write to studio@example.com

    Docs, forms, legal and long reads. Flat inks, no art in motion.

  • Studio

    What do you need?
    Budget (optional)

    Prefer email? Write to studio@example.com

    The site default. Art on its own plates, one display moment per view.

  • Press

    What do you need?
    Budget (optional)

    Prefer email? Write to studio@example.com

    Hero moments, covers and campaigns. Halftone fields and the second ink.

  • Rave

    What do you need?
    Budget (optional)

    Prefer email? Write to studio@example.com

    Launches, posters and the 404. Every ink, and the words still win.

Content#

  • Every label, hint and message is literal and kind: "Add your email, so I can reply."
  • The fallback email is always on the page: "Prefer email? Write to studio@example.com".
  • The success plate says what happens next and when.

Do and don't#

Do

What do you need?
Budget (optional)

Prefer email? Write to studio@example.com

Six questions that price the job.

Don't

A quote form with twelve fields, three of them about the company's founding year.

A questionnaire before a hello.

Each extra field loses some people. Ask what you need to reply with a price, and ask the rest on the call.

Accessibility#

  • Every field is labelled; required ones are not marked, optional ones are.
  • Sending keeps the fields editable; success replaces the form with a plate whose title takes focus and is announced politely.
  • A failed send keeps every value and offers "Email it instead", a mailto link built from the fields.
KeysWhat happens
TabName, email, website, the tier and budget groups, message, Send, the email fallback
Arrow keys in a groupPick a tier or a budget
EnterSends; a failed check moves focus to the first field to fix

The colour pairs it prints, with their contrast on both papers:

TextSurfaceRoleBoneNight
--mk-text--mk-surfaceuinot in this looknot in this look
--mk-text-2--mk-surfaceuinot in this looknot in this look
--mk-link--mk-surfaceuinot in this looknot in this look
--mk-on-action--mk-actioncontrol-sm 14.44:1 · Lc 89.2, passes 14.76:1 · Lc 89.4, passes

Process at Studio, normal contrast. Every look: the press check.

Props#

PropTypeDefaultDescription
action requiredstring | ((data: FormData) => Promise<QuoteFormResult>)none
intent"product" | "quote" | "release-note"quoteThe site's three variants (default `quote`).
tiersreadonly { readonly id: string; readonly label: string; readonly time?: string; }[]noneRequired for `quote`.
appTierIdstringnoneHides the budget keys for that tier.
budgetsreadonly string[]none
defaultsPartial<Record<"budget" | "message" | "tier" | "website", string>>noneFrom `?tier=`, `?budget=` …
sourcestringnoneA hidden input, ≤ 40 characters.
fallbackEmail requiredstringnoneShown always; used for the mailto fallback.
copyPartial<QuoteFormCopy>none
successReactNodenoneReplaces the default success plate (the comic kit can pass a radio balloon).
idPrefixstringnone
messageCopyReadonly<Record<string, { readonly label?: string; readonly placeholder?: string; }>>noneThe message field's label and placeholder per tier id (20 §8: they follow the tier); falls back to `copy`.
stickySendbooleannoneKeeps the Send row in reach while a scrolling parent (a Drawer body) scrolls.

Generated from QuoteFormProps in packages/overprint-react/src/reading/quote-form/types.ts.

Tokens#

Changelog#

Arrived in 0.1.0.

0.1.024 October 2026

  • MinorreactThe reading layer's controls, overlays, forms and visitor prefs (P2-T1 to P2-T5): every Button is the comic hit key, with IconButton, Link and Tooltip; Input, Textarea, Select, Checkbox and CheckboxGroup, Radio and RadioGroup, Switch, Slider with the ruler, RulerReadout and SegmentedControl; Dialog, Drawer, NavSheet, Tabs, Disclosure, Faq and faqJsonLd on Base UI 1.9 where the platform falls short; Field, Fieldset, Form with the site's inline validation, ErrorSummary, Callout, Honeypot, FormTimestamp and QuoteForm; PrefsScript under 1 KB, usePref and setPref with cross-tab sync, ThemeToggle and the visitor VolumeDial; VisuallyHidden.