formsform
Form
Styled Formisch form that provides its store to Moraine form fields.
Import#
Create the Formisch store with a Valibot schema, then pass it to Form. Moraine fields and
controls bind to the store automatically through FormField.name.
import { createForm, Form, Input, Switch } from 'moraine'
export function NoticationForm() { const form = createForm({ schema, initialInput: { email: '', enabled: false }, }) const save = (output) => {}
return ( <Form of={form} onSubmit={(output) => save(output)}> <FormField name="email" label="Email"> <Input /> </FormField> <FormField name="enabled" label="Enable notifications"> <Switch /> </FormField> </Form> )}For field arrays or custom rendering, import Field, FieldArray, useField, and Formisch
methods directly from @formisch/solid and use the same store.
Examples#
Workspace Provisioning#
Create a new workspace with owner identity, default role, and rollout target.
1function WorkspaceProvisioning() {2 const [submittedWorkspace, setSubmittedWorkspace] = createSignal<string>()3 const form = createForm({4 schema: WorkspaceSchema,5 initialInput: {6 workspaceName: '',7 ownerEmail: '',8 role: 'developer',9 environment: 'staging',10 enableAudit: true,11 },12 })13
14 return (15 <Form16 of={form}17 onSubmit={(output) => setSubmittedWorkspace(`Created ${output.workspaceName}.`)}18 class="mx-auto max-w-2xl w-full space-y-4"19 >20 <FormField<typeof WorkspaceSchema> name="workspaceName" label="Workspace Name" required>21 <Input placeholder="acme-platform" />22 </FormField>23
24 <FormField<typeof WorkspaceSchema> name="ownerEmail" label="Owner Email" required>2526 </FormField>27
28 <FormField<typeof WorkspaceSchema> name="role" label="Default Team Role" required>29 <Select30 options={[31 { label: 'Developer', value: 'developer' },32 { label: 'Designer', value: 'designer' },33 { label: 'Manager', value: 'manager' },34 ]}35 placeholder="Select role"36 />37 </FormField>38
39 <FormField<typeof WorkspaceSchema>40 name="environment"41 label="Initial Deployment Target"42 required43 >44 <RadioGroup45 items={[46 { value: 'staging', label: 'Staging', description: 'Pre-production verification' },47 { value: 'production', label: 'Production', description: 'Public traffic rollout' },48 ]}49 variant="table"50 />51 </FormField>52
53 <FormField<typeof WorkspaceSchema>54 name="enableAudit"55 label="Audit Logging"56 description="Enable immutable audit trail for permissions and deploy actions."57 >58 <Switch checkedIcon="i-lucide-shield-check" uncheckedIcon="i-lucide-shield" />59 </FormField>60
61 <Button type="submit">Create Workspace</Button>62 <Show when={submittedWorkspace()}>63 {(message) => <p class="text-success text-sm">{message()}</p>}64 </Show>65 </Form>66 )67}Release Readiness Checklist#
Validate release metadata, rollout channels, and approval gate with a Formisch schema.
1function ReleaseReadinessChecklist() {2 const [approvedRelease, setApprovedRelease] = createSignal<string>()3 const form = createForm({4 schema: ReleaseReadinessSchema,5 initialInput: {6 releaseVersion: '',7 channels: [],8 approvalLevel: 'peer',9 rolloutConfirmed: false,10 notes: '',11 },12 })13 return (14 <Form15 of={form}16 onSubmit={(output) => setApprovedRelease(`${output.releaseVersion} is ready for rollout.`)}17 class="mx-auto max-w-2xl w-full space-y-4"18 >19 <FormField<typeof ReleaseReadinessSchema>20 name="releaseVersion"21 label="Release Version"22 required23 >24 <Input placeholder="v2.14.0" />25 </FormField>26
27 <FormField<typeof ReleaseReadinessSchema> name="channels" label="Rollout Channels" required>28 <CheckboxGroup29 items={[30 {31 value: 'alpha',32 label: 'Alpha',33 description: 'Internal team first',34 },35 {36 value: 'beta',37 label: 'Beta',38 description: 'Limited external users',39 },40 {41 value: 'stable',42 label: 'Stable',43 description: 'Full production release',44 },45 ]}46 variant="table"47 />48 </FormField>49
50 <FormField<typeof ReleaseReadinessSchema> name="approvalLevel" label="Approval Gate" required>51 <RadioGroup52 items={[53 {54 value: 'peer',55 label: 'Peer Review',56 description: 'One teammate sign-off',57 },58 {59 value: 'lead',60 label: 'Tech Lead',61 description: 'Owner team approval',62 },63 {64 value: 'qa',65 label: 'QA + Lead',66 description: 'Formal release gate',67 },68 ]}69 variant="card"70 />71 </FormField>72
73 <FormField<typeof ReleaseReadinessSchema> name="notes" label="Release Notes" required>74 <Textarea75 placeholder="Summarize risk, migration notes, and rollback strategy..."76 rows={4}77 />78 </FormField>79
80 <FormField<typeof ReleaseReadinessSchema>81 name="rolloutConfirmed"82 label="Rollback Prepared"83 required84 >85 <Checkbox label="I confirmed rollback commands and owner on-call availability." />86 </FormField>87
88 <Button type="submit">Approve Release</Button>89 <Show when={approvedRelease()}>90 {(message) => <p class="text-success text-sm">{message()}</p>}91 </Show>92 </Form>93 )94}Incident Escalation Policy#
Configure nested policy fields for severity routing and automatic rollback behavior.
1function IncidentEscalationPolicy() {2 const [submittedPolicy, setSubmittedPolicy] = createSignal<string>()3 const form = createForm({4 schema: IncidentPolicySchema,5 initialInput: {6 policy: {7 name: '',8 severity: 'p1',9 notifyEmail: '',10 autoRollback: true,11 summary: '',12 },13 },14 })15
16 return (17 <Form18 of={form}19 onSubmit={(output) => setSubmittedPolicy(`Saved ${output.policy.name}.`)}20 class="mx-auto max-w-2xl w-full space-y-4"21 >22 <FormField<typeof IncidentPolicySchema>23 name={['policy', 'name']}24 label="Policy Name"25 required26 >27 <Input placeholder="payments-latency-spike" />28 </FormField>29
30 <FormField<typeof IncidentPolicySchema>31 name={['policy', 'severity']}32 label="Default Severity"33 required34 >35 <Select36 options={[37 { label: 'P1 - Critical', value: 'p1' },38 { label: 'P2 - Major', value: 'p2' },39 { label: 'P3 - Minor', value: 'p3' },40 ]}41 placeholder="Select severity"42 />43 </FormField>44
45 <FormField<typeof IncidentPolicySchema>46 name={['policy', 'notifyEmail']}47 label="Escalation Email"48 required49 >5051 </FormField>52
53 <FormField<typeof IncidentPolicySchema>54 name={['policy', 'autoRollback']}55 label="Auto Rollback"56 description="Trigger rollback when alert duration crosses the policy threshold."57 >58 <Switch />59 </FormField>60
61 <FormField<typeof IncidentPolicySchema>62 name={['policy', 'summary']}63 label="Policy Summary"64 required65 >66 <Textarea67 placeholder="Describe conditions and handoff details for incident response."68 rows={3}69 />70 </FormField>71
72 <Button type="submit">Save Escalation Policy</Button>73 <Show when={submittedPolicy()}>74 {(message) => <p class="text-success text-sm">{message()}</p>}75 </Show>76 </Form>77 )78}Access Request Review#
Review temporary access requests with scoped permissions and required reviewers.
1function AccessRequestReview() {2 const [submittedRequest, setSubmittedRequest] = createSignal<string>()3 const form = createForm({4 schema: AccessRequestSchema,5 initialInput: {6 requester: '',7 reason: '',8 temporary: true,9 scopes: ['repo:read'],10 reviewers: ['security'],11 },12 })13
14 return (15 <Form16 of={form}17 onSubmit={(output) => setSubmittedRequest(`Request submitted for ${output.requester}.`)}18 class="mx-auto max-w-2xl w-full space-y-4"19 >20 <FormField<typeof AccessRequestSchema> name="requester" label="Requester" required>21 <Input placeholder="alex.chen" />22 </FormField>23
24 <FormField<typeof AccessRequestSchema> name="reason" label="Business Reason" required>25 <Textarea26 placeholder="Need short-term access for production incident mitigation."27 rows={3}28 />29 </FormField>30
31 <FormField<typeof AccessRequestSchema>32 name="temporary"33 label="Temporary Access"34 description="Enable automatic expiry for this permission grant."35 >36 <Switch />37 </FormField>38
39 <FormField<typeof AccessRequestSchema> name="scopes" label="Requested Scopes" required>40 <CheckboxGroup41 items={[42 { value: 'repo:read', label: 'Repository Read', description: 'View code and PRs' },43 {44 value: 'repo:write',45 label: 'Repository Write',46 description: 'Push and merge changes',47 },48 {49 value: 'deploy:prod',50 label: 'Production Deploy',51 description: 'Trigger release pipelines',52 },53 ]}54 variant="card"55 />56 </FormField>57
58 <FormField<typeof AccessRequestSchema> name="reviewers" label="Required Reviewers" required>59 <CheckboxGroup60 items={[61 {62 value: 'security',63 label: 'Security Team',64 description: 'Permission boundary review',65 },66 {67 value: 'platform',68 label: 'Platform Team',69 description: 'Infrastructure and ops review',70 },71 { value: 'manager', label: 'Line Manager', description: 'Business ownership approval' },72 ]}73 />74 </FormField>75
76 <Button type="submit">Submit Access Request</Button>77 <Show when={submittedRequest()}>78 {(message) => <p class="text-success text-sm">{message()}</p>}79 </Show>80 </Form>81 )82}API Reference#
Attributes#
Slot
root0 attributesNative form element managed by Formisch.
No attribute metadata for this slot.
Props#
| Prop | Type | Default | Description |
|---|---|---|---|
| class | ClassValue | — | Class applied to the component root or trigger element. |
| classes | FormT.Classes | undefined | — | — |
| onSubmit | SubmitEventHandler<TSchema> | undefined | — | Called with validated schema output and the native submit event. |
| ref | JSX.HTMLElementTags["form"] extends { ref?: infer Ref; } ? Ref : never | undefined | — | — |
| style | JSX.CSSProperties | undefined | — | — |
| styles | FormT.Styles | undefined | — | — |
Inherited#
From @formisch/solid
| Prop | Type | Default | Description |
|---|---|---|---|
| children | JSX.Element | — | The child elements to render within the form. |
| of* | FormStore<TSchema> | — | The form store instance. |