StealThis .dev

Form — Repeatable field rows (add/remove)

A variable-length team-invite form where each member is a repeatable row of name, work email, and role select. Add appends a fresh row with a smooth height transition, while each row carries its own trash button, per-field validation, aria-invalid error helpers, and success states. Rows renumber on removal, a minimum of one is always enforced, duplicate emails are flagged, and a live seat counter plus an empty-state placeholder keep the whole list keyboard accessible.

Open in Lab
html css vanilla-js
Targets: JS HTML

Code

Repeatable field rows (add/remove)

A team-invite form built around a variable-length list of rows. Each row collects a teammate’s full name, work email, and role (Viewer, Editor, Admin, Owner). The “Add member” button appends a blank row with a smooth enter transition and moves focus into its first field, while every row carries a trash button that collapses the row by animating its height to zero before removing it.

Validation runs per row: required name and email checks with inline helper messages, aria-invalid, and live re-validation as the user fixes a field. On submit the form validates every row, flags duplicate emails across rows, focuses the first problem, and otherwise reveals a success confirmation summarising how many invites were sent by role. A minimum of one row is always enforced — the lone remove button disables itself — and an empty-state placeholder is wired in for the zero-row case.

Rows renumber automatically after any removal, a running member count and a “seats used” meter stay in sync, and an aria-live status plus a small toast helper announce changes. The layout collapses from a desktop grid to fully stacked cards below 520px, and all interactions are keyboard-operable with visible focus rings.