Form section, save bar and unsaved guard
Long sectioned forms: a numbered section with the 180px label column at compact (stacked on phone), the dark pending-changes bar (dirty · saving · saved · validation summary that jumps to fields · conflict “someone else changed this” with Compare / Reload / Keep mine), and the unsaved-changes guard on shell nav and tab close.
Covers: form-section primitive, form-section designer, save-bar primitive, save-bar designer, unsaved-guard designer. Exports: FormSection, SaveBar, UnsavedGuard.
Anatomy
The component as it sits in the product: English, compact, real data shapes.
Production
Long form in place
Section nav (step-rail long-form mode) on the left, sections on the right, the dark pending-changes bar Frank praised in the Access console.
Production
States
7 states, left to right, top to bottom. A mock poll never finishes, so each state is drawn on purpose.
Production
Production
Production
Production
Production
1 errorProduction
Leave without saving?
You have 3 unsaved changes on Design 1287 (Notch lapel). They are lost if you leave.
Density
Compact (2b ultra, the default) and comfortable, side by side. Same markup, only the density tokens change.
Production
Production
English · 中文
Staff pick en or cn (T001 Q25). Labels arrive localised; CJK falls back to PingFang SC / Noto Sans SC.
Production
生产
Long string · permission denied
The long-string case (PL-063) and what a role without the permission sees (the server decides; T003).
Production
Production
Both apps
One @rj/admin-kit component, two themes: the Laravel admin (navy pinned) and the DTC admin (kit v4 Midnight green), by token swap only.
Production
Production
Contract
The @rj/admin-kit API for this family. Mirrored in CONTRACT.md.
- Export
FormSection·@rj/admin-kit- Props
id·n·title·errors·layoutinline|stack ·repeatable- States
- clean · error
- shadcn / Radix
- none (fieldset)
- Package underneath
- react-hook-form
- Accessibility
- fieldset + legend; error count in the legend
- Export
SaveBar·@rj/admin-kit- Props
dirtyFields·onSave·onDiscard·conflict{by, at, version}- States
- hidden · dirty · saving · saved · error (summary) · conflict
- Package underneath
- react-hook-form formState · motion
- Accessibility
- status region; Save is ⌘S
- API operations
- any update; conflict from 409 version_conflict (If-Match / expected_version) e.g. admin.orders.measurements.update
- Phone variant
- full-width bar at the bottom
- Export
UnsavedGuard·@rj/admin-kit- Props
when(isDirty)- States
- closed · open
- shadcn / Radix
- AlertDialog
- Package underneath
- beforeunload + Next router guard
- Accessibility
- focus lands on Stay