Signup form
new 4.6 kB<hk-signup-form>A whole signup flow rather than a field: reactive controls, per-field validators, a cross-field confirm check on the group, and SSO offered above the form instead of buried under it. Errors appear on touched or submitted, never on the first keystroke, and the submit button is never disabled by invalidity — a dead button gives no reason, while a rejected submit surfaces every message at once.
#form#signup#reactive#validation#sso#auth
Live demo
Running in this page — interact with it.
Inputs
| Name | Type | Default | Description |
|---|---|---|---|
| providers | SsoProvider[] | ['google', 'github'] | SSO buttons to offer, in order. Empty hides the block and its divider. |
| roles | string[] | [] | Options for the role select. Empty drops the field. |
| minPasswordScore | number | 4 | Rules the password must satisfy before the form validates. |
| requireTerms | boolean | true | Adds the terms checkbox with a requiredTrue validator. |
| busy | boolean | false | Drives the submit spinner and blocks a second submit. |
| error | string | null | null | Server-side failure, rendered above the submit as an alert. |
Outputs
submittedEventEmitter<SignupValue>Fires only when the form is valid.
ssoRequestedEventEmitter<string>Fires with the provider id; the form is skipped entirely.
Methods
reset()() => voidClears every control and the submitted flag.
setServerErrors(map)(map: Record<string, string>) => voidAttaches server messages to named controls, so a taken email lands on the email field.
Keyboard
- Tab Walks SSO, then the fields, then submit — in reading order
- Enter Submits from any field
- Space Toggles the terms and updates checkboxes
Theming
Component tokens, each falling back to a global one:
| Property | Default | Controls |
|---|---|---|
| --hk-form-gap | 1rem | Vertical rhythm between fields. |
| --hk-form-error | #dc2626 | Invalid border and message colour. |
| --hk-sso-columns | 2 | Provider buttons per row. |
Accessibility
- Every field carries aria-invalid, and its message is wired through aria-describedby rather than left as loose text nearby.
- The form is novalidate: the browser’s own bubbles cannot be styled or translated, and would pre-empt the real messages.
- A failed submit moves focus to the first invalid control, so the reason is reachable without hunting.
- The submit summary is role="alert", so the count of remaining problems is announced.
- Submit is never disabled by invalidity — a disabled button explains nothing, while a rejected submit explains everything.