# Settings Page

> A responsive settings page block with profile, notification, and security sections.

A shadcn/ui block from the [@corr](https://ui.corr.sh) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/corr/settings-page).

- Page, with a live preview: https://shadcn.exchange/r/corr/settings-page
- Screenshot: https://abzjhwgwpdpz7ua5.public.blob.vercel-storage.com/shots/corr/settings-page-light-2e602da2a418689c.png
- Registry item: https://ui.corr.sh/r/settings-page.json
- Listed: 2026-10-13, source last changed 2026-10-13

## Install

```bash
npx shadcn@latest add https://ui.corr.sh/r/settings-page.json
```

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

## Dependencies

- npm packages: `lucide-react`, `motion`
- Registry items: `button`, `card`, `field`, `input`, `separator`, `switch`, `tabs`

## Files

### `registry/corr/components/settings-page.tsx`

```tsx
"use client"

import * as React from "react"
import { BellIcon, ShieldIcon, UserIcon } from "lucide-react"
import { motion, useReducedMotion } from "motion/react"

import { Button } from "@/components/ui/button"
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "@/components/ui/card"
import { Field, FieldLabel } from "@/components/ui/field"
import { Input } from "@/components/ui/input"
import { Separator } from "@/components/ui/separator"
import { Switch } from "@/components/ui/switch"
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"

export function SettingsPage({
  defaultTab = "profile",
}: {
  defaultTab?: "profile" | "notifications" | "security"
}) {
  const reduceMotion = useReducedMotion()

  const MotionSection = ({ children }: { children: React.ReactNode }) => (
    <motion.div
      initial={{ opacity: 0, y: reduceMotion ? 0 : 8 }}
      animate={{ opacity: 1, y: 0 }}
      transition={{ duration: reduceMotion ? 0 : 0.18 }}
    >
      {children}
    </motion.div>
  )

  return (
    <div className="rounded-md border bg-card">
      <div className="border-b p-4">
        <h2 className="text-lg font-semibold">Settings</h2>
        <p className="mt-1 text-sm text-muted-foreground">
          Manage account details, notifications, and access controls.
        </p>
      </div>
      <Tabs
        defaultValue={defaultTab}
        orientation="vertical"
        className="grid gap-0 md:grid-cols-[14rem_minmax(0,1fr)]"
      >
        <div className="border-b p-3 md:border-r md:border-b-0">
          <TabsList className="grid h-auto w-full grid-cols-3 md:grid-cols-1">
            <TabsTrigger value="profile" className="justify-start">
              <UserIcon className="size-4" />
              Profile
            </TabsTrigger>
            <TabsTrigger value="notifications" className="justify-start">
              <BellIcon className="size-4" />
              Alerts
            </TabsTrigger>
            <TabsTrigger value="security" className="justify-start">
              <ShieldIcon className="size-4" />
              Security
            </TabsTrigger>
          </TabsList>
        </div>
        <div className="min-w-0 p-4">
          <TabsContent value="profile" className="mt-0">
            <MotionSection>
              <Card>
                <CardHeader>
                  <CardTitle>Profile</CardTitle>
                  <CardDescription>
                    Keep public account information up to date.
                  </CardDescription>
                </CardHeader>
                <CardContent className="grid gap-4 sm:grid-cols-2">
                  <Field>
                    <FieldLabel>Name</FieldLabel>
                    <Input defaultValue="Liam Corrigan" />
                  </Field>
                  <Field>
                    <FieldLabel>Email</FieldLabel>
                    <Input defaultValue="liam@example.com" />
                  </Field>
                  <div className="sm:col-span-2">
                    <Button>Save profile</Button>
                  </div>
                </CardContent>
              </Card>
            </MotionSection>
          </TabsContent>
          <TabsContent value="notifications" className="mt-0">
            <MotionSection>
              <SettingsPanel
                title="Notifications"
                description="Choose which operational events should reach you."
                rows={[
                  ["Build updates", "Registry build status and failures."],
                  ["Install events", "Notify when a component is installed."],
                  ["Weekly summary", "A digest of usage and changes."],
                ]}
              />
            </MotionSection>
          </TabsContent>
          <TabsContent value="security" className="mt-0">
            <MotionSection>
              <SettingsPanel
                title="Security"
                description="Control account protection and review prompts."
                rows={[
                  ["Two-factor authentication", "Require a second factor."],
                  ["Session alerts", "Email when a new device signs in."],
                  ["Destructive confirmations", "Confirm risky workspace actions."],
                ]}
              />
            </MotionSection>
          </TabsContent>
        </div>
      </Tabs>
    </div>
  )
}

function SettingsPanel({
  title,
  description,
  rows,
}: {
  title: string
  description: string
  rows: [string, string][]
}) {
  return (
    <Card>
      <CardHeader>
        <CardTitle>{title}</CardTitle>
        <CardDescription>{description}</CardDescription>
      </CardHeader>
      <CardContent>
        <div className="space-y-4">
          {rows.map(([label, helper], index) => (
            <React.Fragment key={label}>
              {index > 0 ? <Separator /> : null}
              <div className="flex items-center justify-between gap-4">
                <div className="min-w-0">
                  <div className="text-sm font-medium">{label}</div>
                  <div className="mt-1 text-xs text-muted-foreground">
                    {helper}
                  </div>
                </div>
                <Switch defaultChecked={index !== rows.length - 1} />
              </div>
            </React.Fragment>
          ))}
        </div>
      </CardContent>
    </Card>
  )
}
```
