Skip to content
Compositions

SettingsCard

Vercel-style settings card with a per-card save action. Each card represents a cohesive group of related settings; pair rows inside it with SettingsRow for the standard label/description/control layout.

Sample delivery
Where your samples ship.

Usage

import { SettingsCard, settingsCardAnatomy, SettingsCardProps, SettingsRow, SettingsRowProps } from "@instruments/materia-ui/compositions/settings-card";

Best practices

  • Fill it with SettingsRow children for the standard label/description/control layout; use SettingsCard for grouped form settings, not Card, when you want the built-in per-card save footer.

  • The footer only renders when onSave is passed, and the Save button is gated on dirty (and disabled while loading) - wire form dirty state through, or the button stays disabled.

  • Give each card one cohesive group of settings with its own save; don't nest multiple SettingsCards or share one across unrelated sections.

Props

SettingsCard

PropTypeDefaultDescription
children(required)React.ReactNode

Row content - typically SettingsRow / Field compositions.

descriptionstring

Subheading shown under the title.

dirtyboolean

Whether the form has unsaved changes. Gates the save button.

loadingboolean

Whether a save is in flight. Disables and animates the save button.

onSave() => void

Called when the save button is pressed. Omit to render no footer.

saveLabelstring

Save button label. Defaults to "Save".

title(required)string

Card title.

borderBorderStyle
inset"none" | LayoutResponsiveValue<"base" | "2xs" | "xs" | "sm" | "lg" | "xl" | "2xl" | "3xl">"xl" (24px)

Padding around the card's CardHeader and CardContent, and the gap between its parts. Parts pick it up from the root, so they need no matching prop. CardFooter is not affected: it keeps its own 16px padding. "none" removes the padding and the gaps, so header and content run to the card's edges, for tables and code blocks. Accepts a per-breakpoint responsive object; an object without base falls back to the default rather than inheriting an ancestor card's inset.

responsiveModeResponsiveMode"screen"

Whether responsive values resolve against the viewport ("screen") or nearest container ("container").

shadowboolean

Whether the card casts a shadow. Defaults to true (each variant's own shadow). Set to false for flat cards on a shaded canvas - e.g. several cards stacked on a muted-background page/panel, where the colour contrast alone separates them and a shadow on every one would be redundant.

testIdstring
variant"muted" | "ghost" | "accent" | "card" | null | undefined

SettingsRow

PropTypeDefaultDescription
children(required)React.ReactNode

Row control(s) - inputs, selects, switches, and their FieldError.

descriptionReact.ReactNode

Helper text shown below the control.

htmlForstring

Associates the label with the control's id for a11y.

idstring

Shared id passed to the underlying Field (drives FieldError/FieldDescription auto-association).

label(required)React.ReactNode

Row label.

orientationResponsiveOrientation

Layout orientation. Defaults to "vertical".

Also exports

  • constsettingsCardAnatomy
  • interfaceSettingsCardProps
  • interfaceSettingsRowProps

Anatomy

SettingsCard

card

Settings section with a per-card save action

CardHeader

card-header

Title and optional description

CardContent

card-content

Stacked SettingsRow (or other) content

SettingsRow

field

Label + control row (label/description/children)

CardFooter

card-footer

Save button, rendered only when onSave is provided

Composition

Builds on

Button, Card, Field, Flex