# Settings screen

> A complete settings screen in inset grouped sections: account, notification switches that flip optimistically, a light, dark and system appearance switch, privacy, storage with a cache size that rolls down to zero when cleared, about, and a destructive sign out confirmed in an alert that runs it.

- Type: Component (screens)
- Access: Pro
- Page: https://goodui.dev/native/components/settings-screen
- Markdown: https://goodui.dev/native/components/settings-screen.md
- Registry item: https://goodui.dev/native/r/settings-screen.json
- Dependencies: react-native-svg
- Keywords: react native settings screen, expo settings page template, app preferences screen, dark mode toggle settings, notification settings switches, sign out confirmation, inset grouped list

## When to use

- The settings tab or screen of a consumer app with an account, notifications and appearance.
- A starting point you trim: every navigation row only shows a chevron when you pass onNavigate.

## When not to use

- Editing profile fields (name, username, bio): use edit-profile-screen and link to it from the Edit profile row.
- Settings with dozens of rows or search: compose ListSection and ListRow in a sticky-header-list or your own sections.

## Installation

With the shadcn CLI (needs a components.json in the Expo app), then `npx expo install --fix` so native dependencies match your Expo SDK. The foundation comes along the first time.

```bash
npx shadcn@latest add @goodui-native-pro/settings-screen
npx expo install --fix
```

Pro: add `"@goodui-native-pro": { "url": "https://goodui.dev/native/r/pro/{name}.json", "headers": { "Authorization": "Bearer ${GOODUI_LICENSE_KEY}" } }` to the `registries` of components.json and put your license key in .env.local.

The component lands in `components/goodui-native/settings-screen/` and imports the foundation from `components/goodui-native/foundation/` with relative paths; it also installs alert-dialog, avatar, badge, large-title-header, list-row, rolling-number, segmented-control.

### Setup

- Wrap the app in GestureHandlerRootView and ThemeProvider (the alert renders in its overlay layer).

## Usage

```tsx
// app/(tabs)/settings.tsx
import { Stack, router } from "expo-router";
import { SettingsScreen } from "@/components/goodui-native/settings-screen/settings-screen";
import { api, useAccount } from "@/lib/account";
import { useColorSchemeSetting } from "@/lib/theme"; // your store behind ThemeProvider colorScheme

export default function SettingsRoute() {
  const account = useAccount();
  const [appearance, setAppearance] = useColorSchemeSetting();
  return (
    <>
      <Stack.Screen options={{ headerShown: false }} />
      <SettingsScreen
        account={{ name: account.name, email: account.email, avatar: account.photoUrl, plan: account.plan }}
        appearance={appearance}
        onAppearanceChange={setAppearance}
        notifications={account.notifications}
        onNotificationChange={(key, value) => api.updateNotifications({ [key]: value })}
        privateAccount={account.isPrivate}
        onPrivateAccountChange={(value) => api.updatePrivacy({ isPrivate: value })}
        cacheSize={account.cacheMegabytes}
        onClearCache={() => api.clearCache()}
        onNavigate={(route) => router.push(`/settings/${route}`)}
        onSignOut={async () => {
          await api.signOut();
          router.replace("/sign-in");
        }}
      />
    </>
  );
}
```

## Examples

### On its own, with a sample account

```tsx
<SettingsScreen />
```

### Drive the app theme from the appearance switch

```tsx
const [scheme, setScheme] = useState<"light" | "dark" | "system">("system");

<ThemeProvider colorScheme={scheme}>
  <SettingsScreen appearance={scheme} onAppearanceChange={setScheme} />
</ThemeProvider>
```

## API reference

### SettingsScreen

`import { SettingsScreen } from "@/components/goodui-native/settings-screen/settings-screen";`

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `account` | `SettingsAccount` | `sampleAccount` | – |
| `appearance` | `"light" \| "dark" \| "system"` | – | Appearance (controlled). Pair it with `onAppearanceChange`. |
| `defaultAppearance` | `"light" \| "dark" \| "system"` | `"system"` | Starting appearance when uncontrolled. Default "system". |
| `onAppearanceChange` | `(appearance: SettingsAppearance) => void` | – | Called with light, dark or system. Wire it to ThemeProvider's colorScheme. |
| `notifications` | `SettingsNotifications` | `{ push: true, email: false, sounds: true }` | Starting notification switches. |
| `onNotificationChange` | `(key: keyof SettingsNotifications, value: boolean) => unknown` | – | A notification switch changed. Return a promise: the switch flips at once and flips back if it rejects. |
| `privateAccount` | `boolean` | `false` | Starting state of the private account switch. |
| `onPrivateAccountChange` | `(value: boolean) => unknown` | – | The private account switch changed. Return a promise for an optimistic switch with rollback. |
| `quietHours` | `{ start: string; end: string } \| null` | `{ start: "22:00", end: "07:00" }` | Quiet hours as 24 h "HH:mm" start and end, shown with the device's time format. |
| `blockedCount` | `number` | `3` | Number of blocked accounts shown in its row. |
| `twoFactor` | `boolean` | `true` | Shows two-factor authentication as on or off. |
| `cacheSize` | `number` | `248.6` | Cache size in megabytes. |
| `onClearCache` | `() => unknown` | – | Clear cache was tapped. Return a promise: the row spins, then the size rolls down to zero. |
| `version` | `string` | `"2.4.1 (318)"` | Version shown in About, for example "2.4.1 (318)". |
| `onNavigate` | `(route: SettingsRoute) => void` | – | A navigation row was tapped. |
| `onSignOut` | `() => unknown` | – | Sign out was confirmed in the alert. Return a promise and the alert keeps a spinner on Sign out until it settles; it closes on success and shakes with an error on failure. |
| `title` | `string` | `"Settings"` | Large title. Default "Settings". |
| `onBack` | `() => void` | – | Shows a back button in the bar. |
| `locale` | `string` | – | BCP 47 locale for numbers and times. Defaults to the device locale. |
| `testID` | `string` | – | Identifier for end-to-end tests. |

## Accessibility

- Section headers are headers; navigation rows are buttons named by their title and value; switch rows hand the title to the switch.
- Appearance is a tab list named 'Appearance' with the selected option marked.
- The cache row reads 'Cache, 248.6 MB' on native; on the web its visible text names it. 'Cache cleared' is announced when the size reaches zero.
- Clear cache reports busy while it runs and is disabled at zero.
- Sign out opens an alert dialog that needs an answer: Cancel or Sign out, with the error announced if signing out fails.

## Motion

- Clearing the cache: the row spins, then the size rolls down digit by digit to zero.
- The large title collapses into the bar as you scroll; the appearance highlight stretches between segments and can be dragged.
- Switches squash and stretch as they flip and flip back with a shake if their promise rejects.
- Sign out: the alert springs in, keeps a spinner on Sign out while it runs and shakes on failure.
- Reduced motion: the size changes in place, the title cross-fades without moving, the highlight moves without stretching and the alert fades.

## Haptics

- toggle-on or toggle-off on a switch flip, select on an appearance change, error when a switch's promise rejects
- error when Clear cache rejects
- success or error when the sign out promise settles (AlertDialog)

## Performance

- Switches, the segment highlight, the digit roll and the title collapse run on the UI thread.
- Rows are plain views; the whole screen renders once and only rows whose state changes update.

## Notes for AI

- Pass appearance and onAppearanceChange and feed the value to ThemeProvider colorScheme; 'system' follows the device.
- Switch values are starting states; the switches keep their own state and call onNotificationChange(key, value) or onPrivateAccountChange(value). Return a promise for a server setting and a rejection flips the switch back.
- onClearCache and onSignOut may return promises; the screen shows pending and error states itself. Navigate after sign out inside your onSignOut.
- Navigation rows only become pressable when onNavigate is passed; route keys are edit-profile, subscription, password, quiet-hours, blocked, two-factor, help, terms and privacy-policy.
- quietHours takes 24 h 'HH:mm' strings and shows them in the device's time format; pass null for Off.
- Render it full-bleed with the navigator header hidden (headerShown: false).

## Related

- [List row](https://goodui.dev/native/components/list-row.md): Settings and navigation cells with a token-colored icon tile, title, subtitle and a trailing value, switch, badge, check or chevron, grouped in inset sections with headers and footers. On touch down the highlight floods in, the tile sinks and the chevron leans forward; on release the highlight lingers and fades.
- [Switch](https://goodui.dev/native/components/switch.md): An iOS-style switch with squash and stretch: the thumb stretches toward where it is going on touch down, then travels on a spring while the track color follows. Settings-row layout, tones, sizes and optimistic async changes.
- [Segmented control](https://goodui.dev/native/components/segmented-control.md): Two to five views of the same thing with an elastic highlight that stretches toward the new segment, can be dragged, and ticks at every boundary. Includes a billing toggle.
- [Alert dialog](https://goodui.dev/native/components/alert-dialog.md): A centered alert that springs in from slightly larger; touch an action and slide across the others with a tick per action, tap outside and it nudges, and async actions keep it open with a spinner until they settle.
- [Rolling number](https://goodui.dev/native/components/rolling-number.md): A number whose digits roll in the direction of change, with digits that open and close in place and currency signs that glide instead of jumping.
- [Edit profile screen](https://goodui.dev/native/components/edit-profile-screen.md): Edit your own profile: change the photo from an action sheet (take, choose, remove) and watch the new one spring in, fields that validate as you leave them, Save with its own pending, saved and error states riding on the keyboard, and an alert that guards unsaved changes on back.
- [Large title header](https://goodui.dev/native/components/large-title-header.md): An iOS large title that collapses into a compact bar as the content scrolls: the titles cross-fade, the bar fades in, the title stretches when pulled past the top and a half-finished collapse settles on either state.

## Guidance for AI tools

Settings screen: A complete settings screen in inset grouped sections: account, notification switches that flip optimistically, a light, dark and system appearance switch, privacy, storage with a cache size that rolls down to zero when cleared, about, and a destructive sign out confirmed in an alert that runs it. Use only the documented props. Keep accessibility, reduced motion and both color schemes intact when adapting it.

Full library index: https://goodui.dev/native/llms.txt
