# Settings Pages

> Two complete settings screens: an organization console with a tabbed sidebar, members table, AI feature switches and a save bar that springs up when anything changes, and a personal workspace page with profile, billing and a notification matrix.

- Collection: Pages
- Tier: pro
- Docs: https://geturui.com/docs/settings-pages
- Install: `npx shadcn@latest add @geturui-pro/settings-pages`
- Dependencies: motion, lucide-react

## Variants

### Organization

Sidebar tabs for general, members (search, invite, role selects), AI features and publishing, with a save bar that slides up while there are unsaved changes.

Install: `npx shadcn@latest add @geturui-pro/settings-pages-organization`

```tsx
import { OrganizationSettings } from "@/components/pages/settings-pages/organization";

export default async function Page() {
  const org = await getOrg();
  return (
    <OrganizationSettings
      defaultValue={org}
      baseUrl="acme.app/"
      onSave={async (value) => {
        await fetch("/api/org", { method: "PUT", body: JSON.stringify(value) });
      }}
    />
  );
}
```

| Prop | Type | Default | Description |
|---|---|---|---|
| defaultValue | `OrgSettings` | — | { name, slug, description, members, ai, publishing }. The save bar appears once anything differs. |
| onSave | `(value: OrgSettings) => void | Promise<void>` | — | Runs after validation. Throw to show the error in the save bar. |
| baseUrl | `string` | "kestrel.app/" | Prefix shown before the slug. |
| className | `string` | — | Classes for the outer container. |

### Workspace

Underline tabs for profile, billing (plan card with usage meters, drawn payment card, plan picker, invoices) and a notification channel matrix, each with its own save row.

Install: `npx shadcn@latest add @geturui-pro/settings-pages-workspace`

```tsx
import { WorkspaceSettings } from "@/components/pages/settings-pages/workspace";

export default function Account() {
  return (
    <WorkspaceSettings
      defaultTab="billing"
      onSaveProfile={(p) => api.me.update(p)}
      onSaveBilling={(b) => api.billing.update(b)}
      onSaveNotifications={(n) => api.notifications.update(n)}
      onDownloadInvoice={(id) => window.open("/invoices/" + id)}
    />
  );
}
```

| Prop | Type | Default | Description |
|---|---|---|---|
| defaultTab | `"profile" | "billing" | "notifications"` | "profile" | Tab shown first. |
| profile | `{ name; email; timezone; bio }` | — | Starting profile values. |
| billing | `{ planId; billingEmail; taxId }` | — | Starting billing values. |
| notifications | `{ matrix; digest; quietHours }` | — | Starting notification preferences. |
| plans | `{ id; name; price; blurb }[]` | — | Plans in the picker; price is per month billed yearly. |
| invoices | `{ id; date; amount; status: "Paid" | "Due" }[]` | — | Invoice rows. |
| card | `{ brand; last4; expires }` | — | Card on file. |
| usage | `{ label; used; limit; unit? }[]` | — | Meters on the plan card. |
| onSaveProfile / onSaveBilling / onSaveNotifications | `(value) => void | Promise<void>` | — | Per-section save handlers. Throw to show an error in that section. |
| onDownloadInvoice | `(id: string) => void` | — | Invoice download handler. |
| onUpdateCard | `() => void` | — | Update-card button handler. |
| className | `string` | — | Classes for the outer container. |

## Accessibility

- Section navigation is a tablist with arrow-key, Home and End support, tied to its tabpanel.
- Tables use captions, column headers and labelled per-row controls; owner-protection disables controls with an explanation.
- Save status (unsaved, saved, error) is announced through polite live regions; ⌘S / Ctrl+S saves the organization page.

## Source

Pro item — send `Authorization: Bearer <registry token>` to include the source.
