Skip to content
kitn AI/UI

Form

kai-form

Point a JSON Schema at <kai-form> and get a fully themed, accessible, client-validated form — labels, widgets, submit button, and a read-only resolved state — without writing a single input element.

  • Shadow DOM
  • JSON Schema driven
  • Client-side validation
  • Read-only resolved state
  • Card contract events

Assign the form definition in JavaScript — it’s an object, not an HTML attribute:

<kai-form id="my-form"></kai-form>
<script type="module">
import '@kitn.ai/ui/elements';
const form = document.querySelector('#my-form');
form.data = {
type: 'object',
title: 'How did we do?',
required: ['rating'],
'x-kai-submitLabel': 'Send feedback',
properties: {
rating: { type: 'integer', title: 'Overall rating', minimum: 1, maximum: 5, 'x-kai-widget': 'rating' },
comments: { type: 'string', title: 'Comments', 'x-kai-widget': 'textarea' },
},
};
form.addEventListener('kai-card', (e) => {
if (e.detail.kind === 'submit') console.log('submission data', e.detail.data);
if (e.detail.kind === 'action') console.log('secondary action', e.detail.action);
});
</script>
  • Schema → widgets deterministically: string → text; string + enum → radio/select; integer + x-kai-widget: 'rating' → stars; boolean → switch; array → repeater/checkbox group; nested object → fieldset. See the Every widget example for the full mapping.
  • x-kai-* hints in the schema control field order (x-kai-order), submit label (x-kai-submitLabel), secondary buttons (x-kai-actions), placeholder (x-kai-placeholder), and dismissibility (x-kai-dismissible).
  • Events use the Card contractkai-form fires no events of its own; it emits a single bubbling kai-card CustomEvent. Relevant kinds: submit (detail.data is the validated object), action, ready, dismiss, and error.
  • resolution — set el.resolution = { kind: 'submit', data: { … } } to swap the form for a read-only <dl> summary.

Star rating, free-text textarea, enum radio group, boolean switch, and a secondary Skip action.

Exercises the full schema-to-widget mapping: text, email, URL, date, password, select, number, slider, rating, switch, checkbox, tag list, checkbox group, repeater, and nested fieldset.

Required fields, minLength/maxLength, minimum/maximum, and format: 'email' — submit empty to see inline errors.

After a successful submission, set el.resolution to render a read-only <dl> summary with a “Submitted” badge.

Pass a non-object schema to see the inline error state; the element also emits kai-card with kind: 'error'.

PropertyTypeDefaultNotes
data The form definition — a JSON Schema (`type:'object'`) + `x-kai-*` UI hints (the CardEnvelope.data). Set as a JS PROPERTY: `el.data = { type:'object', properties:{…} }`. Import the `FormDefinition` type from `@kitn.ai/ui` for the full shape (it is self-referential, so the element types it loosely).
cardId Stable card id correlating every emitted CardEvent. Attribute: `card-id`.
heading Heading rendered in the card chrome (= CardEnvelope.title). Attribute: `heading`.
resolution Set when the user resolved this card; renders the read-only view. Property: `el.resolution = { kind:'submit', data:{…} }`.

This element wraps these SolidJS components — reach for them directly when you need finer control than the props expose.

Form