# Preferences

> An app's Settings window: a tabs switches between General, Appearance and Notifications, each a grouped form of switches, pop-up buttons and a slider.

A shadcn/ui block from the [@cupertinoui](https://www.cupertino-ui.com/?utm_source=shadcn.exchange) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/cupertinoui/preferences-01).

- Page, with a live preview: https://shadcn.exchange/r/cupertinoui/preferences-01
- Screenshot: https://shadcn.exchange/shot/cupertinoui/preferences-01/light.png
- Registry item: https://www.cupertino-ui.com/r/preferences-01.json
- Listed: 2026-11-05, source last changed 2026-11-05

## Install

```bash
npx shadcn@latest add https://shadcn.exchange/r/cupertinoui/preferences-01.json
```

Run it in a project that has shadcn/ui set up. It adds the files below and installs what they depend on.

## Dependencies

- Registry items: `@cupertinoui/macos-theme`, `@cupertinoui/grouped-form`, `@cupertinoui/select`, `@cupertinoui/slider`, `@cupertinoui/switch`, `@cupertinoui/tabs`, `@cupertinoui/window`

## Files

### `registry/macos/blocks/preferences-01/preferences-01.tsx`

```tsx
"use client"

import * as React from "react"

import { cn } from "@/lib/utils"
import {
  GroupedForm,
  GroupedFormGroup,
  GroupedFormRow,
  GroupedFormRowControl,
  GroupedFormRowDescription,
  GroupedFormRowLabel,
  GroupedFormRowTitle,
  GroupedFormSection,
} from "@/registry/macos/ui/grouped-form"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/registry/macos/ui/select"
import { Slider } from "@/registry/macos/ui/slider"
import { Switch } from "@/registry/macos/ui/switch"
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/registry/macos/ui/tabs"
import {
  Window,
  WindowContent,
  WindowControls,
  WindowMain,
  WindowTitle,
  WindowTitlebar,
} from "@/registry/macos/ui/window"

// A pop-up button in a settings row.
function Choice({ label, items, defaultValue }: { label: string; items: Record<string, string>; defaultValue: string }) {
  return (
    <Select defaultValue={defaultValue} items={items}>
      <SelectTrigger variant="borderless" aria-label={label}>
        <SelectValue />
      </SelectTrigger>
      <SelectContent>
        {Object.entries(items).map(([value, text]) => (
          <SelectItem key={value} value={value}>
            {text}
          </SelectItem>
        ))}
      </SelectContent>
    </Select>
  )
}

// A settings row with a title, an optional description and a control.
function Row({ title, description, children }: { title: string; description?: string; children: React.ReactNode }) {
  return (
    <GroupedFormRow className={cn(description && "items-start")}>
      {description ? (
        <GroupedFormRowLabel>
          <GroupedFormRowTitle>{title}</GroupedFormRowTitle>
          <GroupedFormRowDescription>{description}</GroupedFormRowDescription>
        </GroupedFormRowLabel>
      ) : (
        <GroupedFormRowTitle>{title}</GroupedFormRowTitle>
      )}
      <GroupedFormRowControl>{children}</GroupedFormRowControl>
    </GroupedFormRow>
  )
}

// An app's Settings window: a tabs picks General, Appearance
// or Notifications, each a grouped form of switches, pop-up buttons and a
// slider. Replace the rows with your own settings.
export function Preferences01({ className, ...props }: React.ComponentProps<typeof Window>) {
  return (
    <Window className={cn("h-[460px] w-[560px]", className)} {...props}>
      <WindowMain>
        <WindowTitlebar>
          <WindowControls />
          <WindowTitle>Settings</WindowTitle>
        </WindowTitlebar>
        <WindowContent className="flex flex-col">
          <Tabs defaultValue="general" className="flex min-h-0 flex-1 flex-col items-center gap-4 pt-3">
            <TabsList>
              <TabsTrigger value="general">General</TabsTrigger>
              <TabsTrigger value="appearance">Appearance</TabsTrigger>
              <TabsTrigger value="notifications">Notifications</TabsTrigger>
            </TabsList>
            <TabsContent value="general" className="w-full px-5 pb-5">
              <GroupedForm>
                <GroupedFormSection>
                  <GroupedFormGroup>
                    <Row title="Open at login">
                      <Switch size="mini" aria-label="Open at login" />
                    </Row>
                    <Row title="Check for updates automatically">
                      <Switch size="mini" defaultChecked aria-label="Check for updates automatically" />
                    </Row>
                  </GroupedFormGroup>
                </GroupedFormSection>
                <GroupedFormSection>
                  <GroupedFormGroup>
                    <Row title="New documents open in">
                      <Choice label="New documents open in" defaultValue="documents" items={{ documents: "Documents", desktop: "Desktop", icloud: "iCloud Drive" }} />
                    </Row>
                    <Row title="Language">
                      <Choice label="Language" defaultValue="system" items={{ system: "System Language", en: "English", de: "Deutsch", fr: "Français" }} />
                    </Row>
                  </GroupedFormGroup>
                </GroupedFormSection>
              </GroupedForm>
            </TabsContent>
            <TabsContent value="appearance" className="w-full px-5 pb-5">
              <GroupedForm>
                <GroupedFormSection>
                  <GroupedFormGroup>
                    <Row title="Appearance">
                      <Choice label="Appearance" defaultValue="auto" items={{ auto: "Auto", light: "Light", dark: "Dark" }} />
                    </Row>
                    <Row title="Text size">
                      <div className="w-40">
                        <Slider defaultValue={[40]} aria-label="Text size" />
                      </div>
                    </Row>
                    <Row title="Show the sidebar" description="Hide it to make more room for what you’re working on.">
                      <Switch size="mini" defaultChecked aria-label="Show the sidebar" />
                    </Row>
                  </GroupedFormGroup>
                </GroupedFormSection>
              </GroupedForm>
            </TabsContent>
            <TabsContent value="notifications" className="w-full px-5 pb-5">
              <GroupedForm>
                <GroupedFormSection>
                  <GroupedFormGroup>
                    <Row title="Allow notifications">
                      <Switch size="mini" defaultChecked aria-label="Allow notifications" />
                    </Row>
                    <Row title="Sound">
                      <Choice label="Sound" defaultValue="glass" items={{ none: "None", glass: "Glass", ping: "Ping", pop: "Pop" }} />
                    </Row>
                    <Row title="Badge the app icon">
                      <Switch size="mini" defaultChecked aria-label="Badge the app icon" />
                    </Row>
                    <Row title="Show previews">
                      <Choice label="Show previews" defaultValue="always" items={{ always: "Always", never: "Never" }} />
                    </Row>
                  </GroupedFormGroup>
                </GroupedFormSection>
              </GroupedForm>
            </TabsContent>
          </Tabs>
        </WindowContent>
      </WindowMain>
    </Window>
  )
}
```
