defuss-shadcn / Forms & Inputs / form
FormMOL
Consistent field layout for forms. Built on native <form> with .form-field spacing, .form-field-inline for checkbox/switch rows, .form-field-row for notification-style items, and .form-fieldset for grouped fields.
On this page (9)
§Consistent field heights
Every field control renders the same box height for the same data-size - the Input ladder is the standard (40 / 28 / 32 / 36 / 44 / 52px for default / xs / sm / md / lg / xl), so mixed fields sit on one baseline. The rows below use the shipped grid helpers (grid + grid-cols-4 + gap-4) directly.
§Switch rows (notifications)
Notification-style rows with label, description, and switch - stacked in a .form-group for the gap between them.
§CSS view file
/* -- Form component --------------------------------------------- */@layer components { .form { display: flex; flex-direction: column; gap: 1.5rem; } /* -- Form field -------------------------------------------- */ .form-field { display: flex; flex-direction: column; gap: 0; /* -- Horizontal orientation (label beside control) ------- */ &[data-orientation="horizontal"] { flex-direction: row; align-items: start; gap: 1rem; & > .label { margin-bottom: 0; padding-top: 0.5rem; min-width: 8rem; flex-shrink: 0; } } /* -- Invalid state -------------------------------------- */ &[data-invalid] { & > .field-description { color: var(--destructive); } } } /* -- Inline field (checkbox, switch, radio inline) -------- */ .form-field-inline { display: flex; align-items: center; gap: 0.5rem; & > .label { margin-bottom: 0; } } /* -- Notification / switch row layout --------------------- */ .form-field-row { display: flex; flex-direction: row; align-items: start; justify-content: space-between; gap: 1rem; border: 1px solid var(--border); border-radius: var(--radius-lg); padding: 1rem; box-shadow: var(--shadow-xs); & > div { display: flex; flex-direction: column; gap: 0.125rem; } & > div > .label { margin-bottom: 0; line-height: 1.4; } & > div > .field-description { margin: 0; } &[data-disabled] { opacity: 0.6; } } /* -- Button actions row ----------------------------------- */ .form-actions { display: flex; gap: 0.5rem; align-items: center; padding-top: 0.5rem; } /* -- Fieldset --------------------------------------------- */ .form-fieldset { border: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 1rem; & > legend { font-size: 0.875rem; font-weight: 500; font-family: var(--font-sans); color: var(--foreground); padding: 0; margin-bottom: 0.25rem; } & > .field-description { margin: -0.25rem 0 0.5rem; } } /* -- Form group (vertical stack of fields) ---------------- */ .form-group { display: flex; flex-direction: column; gap: 0.75rem; } /* -- Accessibility ---------------------------------------- */ @media (prefers-contrast: more) { .form-field-row { border-width: 2px; } } @media (forced-colors: active) { .form-field-row { border-color: ButtonBorder; } .form-fieldset > legend { color: LinkText; } }}Comments, ideas or improvements? Edit this page's source on GitHub