A lightweight, CDN-ready form Web Component — built-in fields, validation, multi-step mode, themes, and i18n. No framework required.

Basic usage

A single <neiki-forms> tag, fed with a schema through setSchema(). Fields, labels, validation and layout are all driven by plain JavaScript objects.

<neiki-forms id="fm"></neiki-forms>

fm.setSchema({
  fields: [
    { type: 'text', name: 'name', label: 'Full name', required: true, width: 'half' },
    { type: 'email', name: 'email', label: 'Email', required: true, width: 'half' },
    { type: 'textarea', name: 'message', label: 'Message', rows: 4 }
  ],
  submitLabel: 'Send message'
});

fm.addEventListener('neiki-forms:submit', function (event) {
  console.log(event.detail.values);
});

Field types & validation

Text, email, password (with show/hide toggle), number, date, select, checkboxes, switches, radio groups, range and file — each with built-in validation rules (required, pattern, min/max length, matching fields, custom validators).

Multi-step mode

Pass steps instead of fields to get a wizard with a progress indicator. Each step validates before advancing, and previously completed steps stay clickable.

Themes & accents

Each instance resolves light / dark / auto independently, and any of six accent colors (blue, violet, emerald, rose, amber, slate).

light · violet
dark · emerald
auto (follows OS) · rose

Internationalization (i18n)

Built-in translations for English, Czech, German, Spanish, French, Polish, Slovak and Ukrainian — switch with setLang() or the lang attribute. Add your own with addTranslations().

fm.setLang('cs');

fm.addTranslations('en', {
  nav: { submit: 'Send it' }
});

JavaScript API & events

The submit event is cancelable — call event.preventDefault() and use event.detail.values to wire up your own API. Without an action attribute and without canceling, the component simply emits success.

Event log

CDN-style usage

<script src="https://cdn.neikiri.dev/neiki-forms/neiki-forms.min.js"></script>

<neiki-forms id="fm"></neiki-forms>
<script>
  document.getElementById('fm').setSchema({
    fields: [
      { type: 'email', name: 'email', label: 'Email', required: true }
    ]
  });
</script>