Nasaq
Components

Repeater

A list of rows the user can add, remove, duplicate, reorder by drag or keyboard and collapse, with min and max limits. Bring your own row content.

PreviewOpen ↗

Code

<Repeater<{ name: string }>  defaultValue={[{ name: "Sara" }]}  createItem={() => ({ name: "" })}  rowTitle={(row) => row.name}  min={1}  max={5}  renderRow={(row, { update }) => (    <Input value={row.name} onChange={(e) => update({ name: e.currentTarget.value })} />  )}/>

Form Builders · beta

Live examples and controls: Repeater in the lab.

Install

npx shadcn@latest add https://docs.nasaqui.com/r/repeater.json

The frame for "add another" form sections: phone numbers, line items, team members. It owns the row chrome (drag handle, collapse, duplicate, remove) and the list rules; you render what is inside a row.

When to use

  • A form section where the user decides how many rows there are.

When not to use

  • Rows made of standard fields: use SchemaRepeater, which generates them and validates.
  • A fixed list of options: use checkboxes or a select.

Import

import { Repeater } from "@fadymondy/nasaq/web";

Quick start

<Repeater<{ name: string }>
  defaultValue={[{ name: "Sara" }]}
  createItem={() => ({ name: "" })}
  rowTitle={(row) => row.name}
  min={1}
  max={5}
  renderRow={(row, { update }) => (
    <Input value={row.name} onChange={(e) => update({ name: e.currentTarget.value })} />
  )}
/>

API

PropTypeDefaultDescription
value, defaultValue, onValueChangeT[], (T[]) => void[]The rows. Controlled or not.
createItem() => TrequiredA new row.
cloneItem(T) => TstructuredCloneHow Duplicate copies a row.
renderRow(item, ctx) => ReactNoderequiredRow body. ctx: index, id, count, disabled, update(patch | fn).
rowTitle, rowSummary, rowMetafunctions"Item n"Header title, the line shown while collapsed, and header extras.
min, maxnumbernoneRemove stops at min; Add and Duplicate stop at max.
reorderable, duplicable, collapsiblebooleantrueTurn features off.
defaultCollapsed, disabledbooleanfalse
label, addLabel, empty, labelslocalisedEnglish and Arabic built in; labels overrides any string.

Behaviour

  • Drag the handle (mouse or touch). Keyboard: focus the handle, then ArrowUp / ArrowDown move the row, Home / End jump to the ends. Each move is announced through a polite live region.
  • Rows keep their identity through reorder, so inputs inside keep focus and state.
  • After Add focus goes to the new row; after Remove it goes to a neighbour.

Accessibility

The list is a ul named by label. The collapse toggle has aria-expanded and aria-controls. The handle exposes aria-keyshortcuts and a hint.

RTL

Layout uses logical properties; the handle and chevrons follow the direction. Row content is yours: keep codes and URLs dir="ltr".

On this page