Special Field

Matrix

A Likert-style grid where each row is a single-choice question sharing one column scale.

stable
matrix likert survey grid rating

Likert-style matrix grid

Demo not found for field: matrix
/**
 * Matrix Field Demo
 */
import { Form, FormBuilder } from '@saastro/forms';
import { FormProvider } from '@/components/FormProvider';
import { TooltipProvider } from '@/components/ui/tooltip';

const config = FormBuilder.create('matrix-demo')
  .layout('manual')
  .columns(12)
  .addField('feedback', (f) =>
    f
      .type('matrix')
      .label('How much do you agree?')
      .helperText('Pick one option per row')
      .prop('rows', [
        { key: 'quality', label: 'Product quality' },
        { key: 'support', label: 'Customer support' },
        { key: 'value', label: 'Value for money' },
      ])
      .options([
        { value: 'agree', label: 'Agree' },
        { value: 'neutral', label: 'Neutral' },
        { value: 'disagree', label: 'Disagree' },
      ])
      .columns({ default: 12 }),
  )
  .addStep('main', ['feedback'])
  .build();

export default function MatrixDemo() {
  const handleSubmit = (data: Record<string, unknown>) => {
    console.log('Form submitted:', data);
  };

  return (
    <TooltipProvider>
      <FormProvider>
        <Form config={config} onSubmit={handleSubmit} className="space-y-6" />
      </FormProvider>
    </TooltipProvider>
  );
}

Overview

matrix renders a table — one row per question, one column per choice on a shared scale. Each row is its own single-choice radiogroup. It’s the classic Likert survey layout (“Agree / Neutral / Disagree” across several statements).

  • Rows come from the rows prop: { key, label }[]. The key identifies the row in the submitted value.
  • Columns are the standard options array: { value, label }[].

Value

The submitted value is an object keyed by row key (valueKind: 'object'), e.g. { quality: 'agree', support: 'neutral' }. Rows the user never touches are simply absent.

Usage

import { FormBuilder } from '@saastro/forms';

const config = FormBuilder.create('survey')
  .addField('feedback', (f) =>
    f
      .type('matrix')
      .label('How much do you agree?')
      .prop('rows', [
        { key: 'quality', label: 'Product quality' },
        { key: 'support', label: 'Customer support' },
      ])
      .options([
        { value: 'agree', label: 'Agree' },
        { value: 'neutral', label: 'Neutral' },
        { value: 'disagree', label: 'Disagree' },
      ]),
  )
  .addStep('main', ['feedback'])
  .build();

rows has no fluent method — set it with .prop('rows', [...]). The columns use the normal .options().

Props

PropTypeDefaultDescription
rowsArray<{ key: string; label: string }>[]One row (question) each; key keys the value
optionsArray<{ value: string; label: string }>[]The shared column scale

The radio accent color reads the --primary CSS variable.