<st-contact-form>
JSON type: ContactForm
A contact form for a website: name, work e-mail, company, an optional phone, a topic, a message and a
required consent box. It posts the answers as JSON to endpoint and shows what came back: a success
note (with the reference, when the API gives one), field messages from the server, or a short note when
the message could not be sent. The text the server sends is never shown. Only the component's own
labels and messages, plus the server's per-field messages, appear on the page.
Every rule is checked in the browser first, the same rules the server applies, so a visitor sees the
problem before anything is sent. The server still decides, and a field it rejects is shown with its
message while the visitor's input is kept. A hidden honeypot field (website) must stay empty.
topics lists the choices, grouped by each item's group. The topic is preselected from the page URL:
?product= wins, then ?topic=, each when it names one of the topics. default-topic is the fallback.
An "About:" pill shows when the URL chose the topic.
The form does not clear the message on an error, and the button is disabled while a request is in flight. Removing the element aborts a request that has not finished.
When three or more fields fail, a summary (role="alert") at the top of the form lists each error as a link
to its field, and focus moves to the summary. With one or two failing fields, focus goes to the first one.
The notes for a network failure or a rate limit may contain {mailto}; it becomes a mailto: link to the
mailto address. A message the server sends is shown as plain text and is never given a link.
The message counter appears from 80% of the limit. Screen readers are told when it passes 80%, 90% and the limit.
None of the events carries personal data (no name, e-mail, company, phone or message text).
Usage
import '@sankhyatronics/sankhya-cms/contact-form'; // registers <st-contact-form>
Properties
| Property | Attribute | Type | Default | Description |
|---|---|---|---|---|
endpoint | endpoint | string | '' | Absolute http(s) URL of the contact API. Empty: the form still renders, and submitting shows the error note without sending. |
topics | topics | ContactTopic[] | [] | The choices for the topic select. Also set as the JSON attribute topics. Items with a group are put under that <optgroup>. |
defaultTopic | default-topic | string | '' | The topic to preselect when the page URL does not choose one. Ignored unless it is one of topics. |
showPhone | show-phone | boolean | true | Shows the optional phone field. Set show-phone="false" to hide it. |
locale | locale | string | '' | Language sent with the message. Empty uses the page's lang, or en. |
page | page | string | '' | Page sent with the message. Empty uses the page's path. |
nameLabel | name-label | string | 'Full name' | |
emailLabel | email-label | string | 'Work email' | |
companyLabel | company-label | string | 'Company' | |
phoneLabel | phone-label | string | 'Phone (optional)' | |
topicLabel | topic-label | string | 'Topic' | |
topicPlaceholder | topic-placeholder | string | 'Select a topic' | |
messageLabel | message-label | string | 'Message' | |
namePlaceholder | name-placeholder | string | 'Your name' | |
emailPlaceholder | email-placeholder | string | 'you@company.com' | |
companyPlaceholder | company-placeholder | string | 'Your company' | |
messagePlaceholder | message-placeholder | string | 'Tell us what you need' | |
messageCounter | message-counter | string | '{count} / {max}' | The message counter. {count} and {max} are filled in. |
submitLabel | submit-label | string | 'Send message' | |
sendingLabel | sending-label | string | 'Sending…' | |
requiredLabel | required-label | string | 'required' | Shown in brackets after each required label, for screen readers. |
aboutLabel | about-label | string | 'About:' | The text before the topic in the "About:" pill. |
consentLabel | consent-label | string | 'I agree that Sankhyatronics may use these details to reply to my enquiry.' | |
privacyNote | privacy-note | string | '' | A line of privacy text above the submit button. Empty hides it. |
privacyLinkLabel | privacy-link-label | string | 'Privacy Policy' | |
privacyHref | privacy-href | string | '/privacy-policy' | |
sentNote | sent-note | string | 'Thanks, your message has been sent. We will reply soon.' | |
referenceLabel | reference-label | string | 'Your reference:' | |
errorNote | error-note | string | 'Sorry, your message could not be sent. Please try again later.' | |
rateLimitedNote | rate-limited-note | string | 'You have sent several messages in a short time. Please wait {seconds} seconds and try again.' | Rate-limit note. {seconds} is filled in when the server says how long to wait. |
rateLimitedGenericNote | rate-limited-generic-note | string | 'You have sent several messages in a short time. Please wait a little and try again.' | |
errorSummary | error-summary | string | 'Please fix {count} fields.' | The field-error summary for screen readers, when several fields fail. {count} is filled in. |
errorSummaryOne | error-summary-one | string | 'Please fix {count} field.' | The summary when one field fails. |
requiredNote | required-note | string | '* Required' | The note above the fields. The form's aria-describedby points at it. Empty hides it. |
mailto | mailto | string | '' | Address for {mailto} in the error and rate-limit notes. Empty, or not an address, leaves the placeholder out. |
errorMessages | — | Partial<ContactErrorMessages> | {} | Replaces the English validation messages (required, tooLong, ...). Only the keys given are replaced. |
Events
| Event | Detail | Description |
|---|---|---|
CONTACT_FORM_SUBMIT_EVENT | CustomEvent | |
CONTACT_FORM_SENT_EVENT | CustomEvent | |
CONTACT_FORM_ERROR_EVENT | CustomEvent | |
st-contact-form-submit | Bubbles and is composed. Detail { topic: string } (the chosen topic's value). The checks passed and the request is about to be sent. | |
st-contact-form-sent | Bubbles and is composed. Detail { reference?: string }. The form has been cleared. | |
st-contact-form-error | Bubbles and is composed. Detail { kind: 'validation' | 'rate_limited' | 'unavailable' }. The input is kept. |
See the live examples in Storybook.