Krizaka UI
Krizaka UI
Components

Schema form

A form drawn from a JSON Schema: typed fields, the schema's own rules, the words of the language (x-i18n) and the rarely needed fields folded (x-advanced).

Web · ✓Mobile · ✗ to buildDesktop · ✓BetaForms
import { SchemaForm, fieldsFromSchema, checkValues, payloadOf } from "@krizaka/ui/schema-form";

Web only — React, from @krizaka/ui/schema-form. Beta: its API may still change in a minor version.

  • Mobile · ✗ to build. The native twin draws the same fieldsFromSchema on the native fields; it follows with the first phone screen that needs it. issue #527

Why it is here. Orazaka's studio run form (replaces RunForm's own schema reading) and Akinaza's shop setup (krizaka/akinaza#104; krizaka-ui#527, B09).

When to use

  • When the fields are data: a studio's input schema, a shop's setup, a product's settings described by a schema.
  • When the host checks the same schema on the server.

When not to use

  • For a form you write field by field, with its own zod schema.Use instead: Form

Installation

Install

npm install @krizaka/ui @krizaka/tailwind @krizaka/tokens tailwindcss

Styles

@import "tailwindcss";
@import "@krizaka/tailwind";
@import "@krizaka/ui/tailwind.css";

Import

import { SchemaForm, fieldsFromSchema, checkValues, payloadOf } from "@krizaka/ui/schema-form";

Examples

From a schema

A title, a closed list, a price in cents, a bounded integer and an advanced note; the payload is shown.

Props

A form from a JSON Schema: typed fields, the schema's rules, x-i18n words, x-advanced folded.

PropTypeDefaultDescription
localerequiredstring—BCP 47 language for the x-i18n words and the money: "fr-CA".
messagesrequiredSchemaFormMessages—The checks' words, passed translated.
onSubmitrequired(payload: Record<string, unknown>) => void—Called with the typed payload once every field passes.
schemarequiredunknown—The JSON Schema object (or its JSON text): properties, required, x-i18n, x-advanced.
wordsrequiredSchemaFormWords—The words, passed translated.
footerReactNode—Beside the submit button: a cost line, a note.
renderField((field: SchemaField, context: SchemaFieldContext) => ReactNode)—Draws a field in the host's way (an upload, a picker); return undefined for the default.
submittingbooleanfalseThe form is being submitted: the fields are blocked and the button shows progress (no second submit).
valuesRecord<string, unknown>—Answers to start from, by field key (over the schema's defaults).

Accessibility

  • Each control is named by its label; the help and the refusal are linked by aria-describedby.
  • A refusal is shown after the field is left, or on submit, never while the person is still typing.
  • Required fields carry aria-required and an asterisk hidden from screen readers.

Keyboard

KeysAction
TabMoves through the fields in the schema's order; the fold of advanced options is a native disclosure.
EnterSubmits; the first failing field takes focus and its message is read.

Best practices

  • Pass the schema as it arrives; unknown or nested properties are left out, never guessed.
  • onSubmit receives a typed payload (numbers, lists, integer cents); empty answers are left out. Re-check it on the server.
  • Keep what is the host's own (an upload, a picker) with renderField: return a node for that field, undefined for the default.
  • Pass submitting while the request runs: the fields are blocked so a second click cannot start a second run.

Generated from the code of @krizaka/ui 3.70.0: its meta.ts, its examples and its types.Edit this documentation on GitHub

On this page