ContactInquiryPanel
Contact page inquiry panel with message and book-a-call tabs wrapping the editorial form.
Status: stable. Group: form. Markdown version: /design-system/components/contact-inquiry-panel.md
When to use
ContactInquiryPanel is the contact page's inquiry column: a two-tab switcher between writing a message and booking a call. The parent owns the form and its submit state, passing it in as messagePanel (ContactPage passes ContactFormEditorial); packageId preselects a pricing package for booking CTAs deep-linked from /pricing. The message panel anchors at #contact-form for deep links. A ref exposes scrollToMessageForm(), which switches to the message tab, smooth-scrolls to #contact-form and focuses its first enabled field.
When not to use
- Do not mount without messagePanel slot.
- Do not duplicate tablist landmarks on the same page.
- Don't use it for a standalone form without tab chrome; mount ContactFormEditorial directly.
Look-alikes
The contract names no look-alike with a deciding condition.
Props
| Prop | Type | Default | Description | Required |
|---|---|---|---|---|
initialMode | "message" | "book" | message | Tab to show; defaults to message. The panel switches to it again whenever the prop value changes after mount. | No |
packageId | string | none | Optional pricing package id for booking prefill. | No |
bookingNotes | string | none | Optional note carried into the booking form, such as the calculator choice. | No |
messagePanel | ReactNode | none | Editorial contact form slot shown on the message tab. | Yes |
bookingConfig | SiteBookingConfig | none | Booking config used only when packageId is not set; packageId wins and this prop is then ignored. Without either, the site default booking config applies. | No |
Variants
- Allowed
initialModevalues:message,book(defaultmessage).
Invalid combinations
The contract records no invalid combinations.
Keyboard
| Key | Behaviour |
|---|---|
| Tab | Moves focus to the control and on to the next focusable element. (standard) |
| ArrowLeft | Moves focus or the value in that direction. (standard) |
| ArrowRight | Moves focus or the value in that direction. (standard) |
| Enter | Activates the focused control. (standard) |
Rows marked (standard) name a key the contract lists without a description; the behaviour shown is the usual one for that key.
Rules
Every item under When not to use is a MUST NOT. MUST and SHOULD follow RFC 2119.
| Level | Rule | How it is checked |
|---|---|---|
| MUST | ARIA: Tablist with aria-selected tabs. | Not yet verified: no evidence record. WCAG 4.1.2. |
| MUST | ARIA: Tabpanels linked via aria-controls. | Not yet verified: no evidence record. WCAG 4.1.2. |
| MUST | ARIA: Message form anchor id contact-form. | Not yet verified: no evidence record. WCAG 4.1.2. |
| MUST | Required stories produce no axe violations at the configured severity. | Automated by npm run test:stories:matrix:ci. WCAG 2.5.8. |
| MUST | The accessibility tree (role, name, state) matches the committed snapshot for every required story. | Automated by npm run test:stories:matrix:ci. WCAG 1.3.1, 4.1.2. |
| MUST | The component remains legible and operable under a real browser forced-colors: active pass. | Automated by npm run test:stories:hc. |
| MUST | Every documented keyboard interaction works as specified. | Not yet verified: no evidence record. WCAG 2.1.1, 2.1.2. |
| MUST | A human completed an end-to-end accessibility review of this component. | Manual review, last on 2026-11-04. |
| SHOULD | Let the parent own form submit state and pass the editorial form in via messagePanel; the panel only owns the tab chrome. | Not stated in the contract. |
| SHOULD | Deep-link the message tab through the #contact-form anchor; booking CTAs elsewhere can preselect a package with packageId. | Not stated in the contract. |
| SHOULD NOT | Don't rebuild pricing package cards inside the panel; that's PricingPageContent's job. | Not stated in the contract. |
Install and import
- In-repo only. ContactInquiryPanel is not exported from
@digitaltableteur/react, so there is no public import path.
Links
- Machine-readable contract (Design System Contract 1.0)
- Markdown version of this page
- Component index as JSON
- All components
- Source: The implementation lives in a private repository. This page, its Markdown twin and the contract are generated from it at build time and are the public source of truth.