SettingsSection
One group of settings: a title and description beside or above a bordered card of 1px-ruled rows.
Monitor defaults
Applied to every monitor you create from now on.
Notifications
Each change saves as soon as you flip it.
Members
People who can see and edit this team's monitors.
| Role | |
|---|---|
| ada@acme.dev | Owner |
| grace@acme.dev | Admin |
| linus@acme.dev | Member |
Billing
Your plan and how you pay for it.
Change your plan, update the card on file and download invoices.
Your monitors keep running until the end of the billing period, then stop. Invoices stay available in the billing portal.
View code
<SettingsSection
title="Monitor defaults"
description="Applied to every monitor you create from now on."
save="explicit"
form={{ action: "/settings/monitors" }}
labels={{ save: "Save defaults" }}
>
<SettingsSection.Row label="Check interval" description="How often each URL is requested." htmlFor="interval">
<Select id="interval" name="interval">
<Select.Option value="30">Every 30 seconds</Select.Option>
<Select.Option value="60" selected>Every minute</Select.Option>
<Select.Option value="300">Every 5 minutes</Select.Option>
</Select>
</SettingsSection.Row>
<SettingsSection.Row label="Timeout" description="A check slower than this counts as down." htmlFor="timeout">
<Input id="timeout" name="timeoutMs" type="number" defaultValue="10000" />
</SettingsSection.Row>
<SettingsSection.Row label="Alert email" htmlFor="alert-email" layout="stacked">
<Input id="alert-email" name="alertEmail" type="email" defaultValue="oncall@acme.dev" />
</SettingsSection.Row>
</SettingsSection>
<SettingsSection
title="Notifications"
description="Each change saves as soon as you flip it."
save="instant"
form={{ action: "/settings/notifications" }}
labels={{ save: "Save notifications" }}
>
<SettingsSection.Row layout="inline-switch" label="Email me when a monitor goes down" labelId="down">
<Switch name="emailOnDown" aria-labelledby="down" checked />
</SettingsSection.Row>
<SettingsSection.Row
layout="inline-switch"
label="Weekly uptime report"
description="Sent on Monday at 9:00 in your time zone."
labelId="weekly"
descriptionId="weekly-help"
>
<Switch name="weeklyReport" aria-labelledby="weekly" aria-describedby="weekly-help" />
</SettingsSection.Row>
</SettingsSection>
<SettingsSection
title="Members"
description="People who can see and edit this team's monitors."
save="none"
actions={<Button size="sm" variant="outline">Invite member</Button>}
>
<Table.Container>
<Table aria-label="Members">
<Table.Header>
<Table.Row>
<Table.Column>Email</Table.Column>
<Table.Column>Role</Table.Column>
</Table.Row>
</Table.Header>
<Table.Body>
{MEMBERS.map((member) => (
<Table.Row key={member.email}>
<Table.Cell>{member.email}</Table.Cell>
<Table.Cell>{member.role}</Table.Cell>
</Table.Row>
))}
</Table.Body>
</Table>
</Table.Container>
</SettingsSection>
<SettingsSection title="Billing" description="Your plan and how you pay for it." save="none">
<SettingsSection.Row
layout="action"
label="Subscription & payments"
description="Change your plan, update the card on file and download invoices."
>
<LinkButton href="/billing/portal" size="sm" variant="outline">Open billing portal</LinkButton>
</SettingsSection.Row>
<SettingsSection.Row
layout="action"
actionPlacement="below"
label="Cancel subscription"
description="Your monitors keep running until the end of the billing period, then stop. Invoices stay available in the billing portal."
>
<Button size="sm" variant="outline" color="danger">Cancel subscription</Button>
</SettingsSection.Row>
</SettingsSection>Demo apps
Whole pages built only from @sdxc/ui, each for an invented product with its own palette and type. They open in a new tab.
- CMSInkwellInkwell, a demo CMS built from @sdxc/ui/app: posts with count tabs and quick edit, an editor with a quiet save status and a loud Publish, media and settings./demo/apps/inkwell
- Ops dashboardPulsePulse, an invented ops dashboard: Northwind's services with live filters, a peek sheet and a bulk bar, metrics that switch one chart, incidents, deploys and settings./demo/apps/pulse
- Support inboxRelayRelay, an invented support inbox: mailboxes, conversations and the open conversation on one screen, with contacts, reports and settings./demo/apps/relay
Every demo, landings and docs sites alike, is listed in the demo gallery.
Installation
An ordinary dependency: install it, import the theme once, and import the component where it is used.
npm add @sdxc/ui remiximport "@sdxc/ui/theme.css";Usage
import { SettingsSection } from "@sdxc/ui/app";Renders the section. The card is a <form> when form is set; an explicit section ends
in a footer holding its own Save, which ⌘S presses while focus is in the section, an
instant one submits whenever a control changes, and a "none" one is a plain card.
Composition
The parts the component publishes, each a static property of the host.
SettingsSectionSettingsSection.RowRenders one setting as a label and help beside or above its control.
Examples
<SettingsSection title="Notifications" save="instant" form={{ action: "/settings/notifications" }} labels={{ save: "Save" }}>
<SettingsSection.Row layout="inline-switch" label="Email me when a monitor goes down" labelId="down-label">
<Switch name="emailOnDown" aria-labelledby="down-label" />
</SettingsSection.Row>
</SettingsSection><SettingsSection title="Members" save="none" actions={<Button commandfor="invite" command="show-modal">Invite member</Button>}>
<Table.Container>…</Table.Container>
</SettingsSection>Props
Read from the component's own types, so every prop, every default and every allowed value is listed.
SettingsSection.Row
| Prop | Type | Required | Description |
|---|---|---|---|
label | RemixNode | Yes | |
description | RemixNode | No | Help under the label: what the setting changes, in a sentence. |
htmlFor | string | No | The control's id, which turns the label into a <label for>. |
labelId | string | No | The label's id, for a control named through aria-labelledby, such as a Switch. |
descriptionId | string | No | The description's id, for a control's aria-describedby. |
layout | "split" | "stacked" | "inline-switch" | "action" | No | "split" puts the label at the start and the control at the end, stacking under 32rem; "stacked" puts the control under the label; "inline-switch" keeps a small control at the end at every width; "action" gives the text the row's width and puts a button that acts at once, such as "Open billing portal", where actionPlacement says, stacking under the text below 32rem. |
actionPlacement | ActionPlacement | No | Where an "action" row's control sits on a wide card. |
Also accepts everything in TagProps<"div">.
Types
| Name | Values | What it decides |
|---|---|---|
Save | "explicit" | "instant" | "none" | How the section's changes persist. |
RowLayout | "split" | "stacked" | "inline-switch" | "action" | Where a row's label sits against its control. |