The <dsgn-form-block> component lays out a single-field form: an input, a submit
button beside it, and an optional note underneath. When success flips to
true, the form row fades out and the success slot fades in.
It is the signup row used in a hero or a section CTA — it does not own the
submission itself. Wire your own <form>, or handle the button click, then tell
the block it succeeded.
Usage
<dsgn-form-block alignment="center">
<dsgn-input
slot="input"
type="email"
name="email"
aria-label="Email"
placeholder="you@example.com"
></dsgn-input>
<dsgn-button slot="button" type="submit">Request access</dsgn-button>
<dsgn-text slot="note" size="sm" color="secondary"
>No spam. Unsubscribe anytime.</dsgn-text
>
<dsgn-text slot="success">You're on the list.</dsgn-text>
</dsgn-form-block>
Import the component module in your application entrypoint:
import '@ds-gn/ui/form-block';
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| alignment | 'start' | 'center' |
'start' |
Horizontal alignment of the form row, note, and success content. |
| success | boolean |
false |
Success state. Setting it hides the form row and reveals the success slot. Reflected. |
| surface | 'light' | 'dark' |
'light' |
Semantic token surface to use. |
Slots
| Slot | Description |
|---|---|
input |
Form input control. |
button |
Submission control. |
note |
Supporting note below the row. The region is omitted when empty. |
success |
Content shown after a successful submission. |
There is no default slot — every child needs a slot attribute.
Success state
Two ways to flip it:
// Set the property directly
document.querySelector('dsgn-form-block').success = true;
// Or dispatch dsgn-form-success on the block (or from inside it)
block.dispatchEvent(new CustomEvent('dsgn-form-success', { bubbles: true }));
dsgn-form-success is an event the block listens for, not one it fires — it
exists so a submission handler deeper in your markup can report success without
holding a reference to the block.
Setting success back to false restores the form row immediately, which makes
it easy to reset after an error or a second submission.
If nothing is slotted into success, the form row still disappears — always
supply the success content.
Examples
In a hero
<dsgn-hero layout="centered" content-align="center">
<dsgn-heading-block slot="content" alignment="center">
<dsgn-heading slot="heading" heading-size="hero" surface="dark"
>Join the beta</dsgn-heading
>
</dsgn-heading-block>
<dsgn-form-block slot="form" surface="dark">
<dsgn-input
slot="input"
type="email"
name="email"
aria-label="Email"
></dsgn-input>
<dsgn-button slot="button" type="submit">Request access</dsgn-button>
<dsgn-text slot="success" surface="dark">You're on the list.</dsgn-text>
</dsgn-form-block>
</dsgn-hero>
With a real form submission
<form id="signup">
<dsgn-form-block id="block">
<dsgn-input
slot="input"
type="email"
name="email"
aria-label="Email"
required
></dsgn-input>
<dsgn-button slot="button" type="submit">Subscribe</dsgn-button>
<dsgn-text slot="success">Check your inbox to confirm.</dsgn-text>
</dsgn-form-block>
</form>
signup.addEventListener('submit', async (event) => {
event.preventDefault();
await fetch('/api/signup', { method: 'POST', body: new FormData(signup) });
block.success = true;
});
Accessibility
- The success message replaces the form in the DOM. Move focus to it, or render it in a live region, so the change is announced rather than only seen.
- Give the slotted input a visible
labelor anaria-label; a placeholder is not an accessible name. - Keep the note slot for supporting copy, not for error messages — errors belong
on the input itself, through
<dsgn-input>’serrorprop.