Skip to main content

Design system components

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

ContactInquiryPanel props
PropTypeDefaultDescriptionRequired
initialMode"message" | "book"messageTab to show; defaults to message. The panel switches to it again whenever the prop value changes after mount.No
packageIdstringnoneOptional pricing package id for booking prefill.No
bookingNotesstringnoneOptional note carried into the booking form, such as the calculator choice.No
messagePanelReactNodenoneEditorial contact form slot shown on the message tab.Yes
bookingConfigSiteBookingConfignoneBooking 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 initialMode values: message, book (default message).

Invalid combinations

The contract records no invalid combinations.

Keyboard

ContactInquiryPanel keyboard behaviour
KeyBehaviour
TabMoves focus to the control and on to the next focusable element. (standard)
ArrowLeftMoves focus or the value in that direction. (standard)
ArrowRightMoves focus or the value in that direction. (standard)
EnterActivates 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.

ContactInquiryPanel rules
LevelRuleHow it is checked
MUSTARIA: Tablist with aria-selected tabs.Not yet verified: no evidence record. WCAG 4.1.2.
MUSTARIA: Tabpanels linked via aria-controls.Not yet verified: no evidence record. WCAG 4.1.2.
MUSTARIA: Message form anchor id contact-form.Not yet verified: no evidence record. WCAG 4.1.2.
MUSTRequired stories produce no axe violations at the configured severity.Automated by npm run test:stories:matrix:ci. WCAG 2.5.8.
MUSTThe 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.
MUSTThe component remains legible and operable under a real browser forced-colors: active pass.Automated by npm run test:stories:hc.
MUSTEvery documented keyboard interaction works as specified.Not yet verified: no evidence record. WCAG 2.1.1, 2.1.2.
MUSTA human completed an end-to-end accessibility review of this component.Manual review, last on 2026-11-04.
SHOULDLet 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.
SHOULDDeep-link the message tab through the #contact-form anchor; booking CTAs elsewhere can preselect a package with packageId.Not stated in the contract.
SHOULD NOTDon'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.