# Section Nav Settings Layout

> Settings layout with a left section nav (Profile, Account, Notifications, Billing) that swaps the active section's form cards beside it.

A shadcn/ui block from the [@7ovr](https://7ovr.com) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/7ovr/settings-4).

- Page, with a live preview: https://shadcn.exchange/r/7ovr/settings-4
- Screenshot: https://abzjhwgwpdpz7ua5.public.blob.vercel-storage.com/shots/7ovr/settings-4-light-a3af9c17dff6790b.png
- Registry item: https://7ovr.com/r/settings-4.json
- Categories: settings
- Listed: 2026-10-13, source last changed 2026-10-13

## Install

```bash
npx shadcn@latest add https://7ovr.com/r/settings-4.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: `@base-ui/react`
- Registry items: `avatar`, `button`, `field`, `input`, `separator`, `switch`

## Files

### `registry/blocks/settings/4/settings-block.tsx`

```tsx
"use client"

import { useState } from "react"
import { cn } from "@/lib/utils"
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
import { Button } from "@/components/ui/button"
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 { IconPlaceholder } from "@/components/icons/icon-placeholder"

type IconProps = { className?: string; size?: number | string }

const sections = [
  {
    id: "profile",
    label: "Profile",
    icon: (p: IconProps) => (
      <IconPlaceholder
        lucide="User"
        tabler="IconUser"
        hugeicons="UserIcon"
        phosphor="User"
        remixicon="RiUser3Line"
        {...p}
      />
    ),
  },
  {
    id: "account",
    label: "Account",
    icon: (p: IconProps) => (
      <IconPlaceholder
        lucide="Shield"
        tabler="IconShieldLock"
        hugeicons="ShieldKeyIcon"
        phosphor="ShieldChevron"
        remixicon="RiShieldKeyholeLine"
        {...p}
      />
    ),
  },
  {
    id: "notifications",
    label: "Notifications",
    icon: (p: IconProps) => (
      <IconPlaceholder
        lucide="Bell"
        tabler="IconNotification"
        hugeicons="NotificationIcon"
        phosphor="Notification"
        remixicon="RiNotification3Line"
        {...p}
      />
    ),
  },
  {
    id: "billing",
    label: "Billing",
    icon: (p: IconProps) => (
      <IconPlaceholder
        lucide="CreditCard"
        tabler="IconCreditCard"
        hugeicons="CreditCardIcon"
        phosphor="CreditCard"
        remixicon="RiBankCardLine"
        {...p}
      />
    ),
  },
]

export default function SettingsBlock() {
  const [active, setActive] = useState("profile")

  return (
    <section className="flex min-h-svh w-full items-start justify-center bg-background px-6 py-12 text-foreground">
      <div className="w-full max-w-3xl">
        <h1 className="font-heading text-2xl font-bold tracking-tight">
          Settings
        </h1>
        <p className="mt-1 text-sm text-muted-foreground">
          Manage your account and workspace preferences.
        </p>

        <div className="mt-8 grid grid-cols-1 gap-8 md:grid-cols-[12rem_1fr]">
          <nav className="flex flex-col gap-1">
            {sections.map((section) => {
              const Icon = section.icon
              return (
                <button
                  key={section.id}
                  type="button"
                  onClick={() => setActive(section.id)}
                  aria-current={active === section.id}
                  className={cn(
                    "flex items-center gap-2.5 rounded-md px-3 py-2 text-left text-sm transition-colors",
                    active === section.id
                      ? "bg-muted font-medium text-foreground"
                      : "text-muted-foreground hover:bg-muted/60 hover:text-foreground"
                  )}
                >
                  <Icon className="size-4 shrink-0" aria-hidden="true" />
                  {section.label}
                </button>
              )
            })}
          </nav>

          <div className="min-w-0">
            {active === "profile" && (
              <div className="flex flex-col gap-6">
                <div className="flex items-center gap-4">
                  <Avatar className="size-14 border border-border">
                    <AvatarImage
                      src="https://i.pravatar.cc/80?img=45"
                      alt="Elena Duarte"
                      className="grayscale"
                    />
                    <AvatarFallback>ED</AvatarFallback>
                  </Avatar>
                  <Button variant="outline" size="sm">
                    Change avatar
                  </Button>
                </div>
                <Field>
                  <FieldLabel htmlFor="name">Full name</FieldLabel>
                  <Input id="name" defaultValue="Elena Duarte" />
                </Field>
                <Field>
                  <FieldLabel htmlFor="email">Email</FieldLabel>
                  <Input
                    id="email"
                    type="email"
                    defaultValue="elena@acme.com"
                  />
                </Field>
              </div>
            )}

            {active === "notifications" && (
              <div className="flex flex-col gap-4">
                {["Product updates", "Weekly digest", "Security alerts"].map(
                  (label, index) => (
                    <div key={label} className="flex flex-col gap-4">
                      {index > 0 && <Separator />}
                      <div className="flex items-center justify-between">
                        <span className="text-sm font-medium">{label}</span>
                        <Switch
                          defaultChecked={index !== 1}
                          aria-label={label}
                        />
                      </div>
                    </div>
                  )
                )}
              </div>
            )}

            {active === "account" && (
              <div className="flex flex-col gap-6">
                <div className="flex flex-col gap-4">
                  <h2 className="font-heading text-sm font-semibold tracking-tight">
                    Password
                  </h2>
                  <Field>
                    <FieldLabel htmlFor="current">Current password</FieldLabel>
                    <Input
                      id="current"
                      type="password"
                      placeholder="••••••••"
                    />
                  </Field>
                  <Field>
                    <FieldLabel htmlFor="new-password">New password</FieldLabel>
                    <Input
                      id="new-password"
                      type="password"
                      placeholder="••••••••"
                    />
                  </Field>
                </div>
                <Separator />
                <div className="flex items-center justify-between gap-4">
                  <div className="flex flex-col gap-0.5">
                    <span className="text-sm font-medium">
                      Two-factor authentication
                    </span>
                    <span className="text-xs text-muted-foreground">
                      Add an extra layer of security to your account.
                    </span>
                  </div>
                  <Switch aria-label="Two-factor authentication" />
                </div>
              </div>
            )}

            {active === "billing" && (
              <div className="flex flex-col gap-6">
                <div className="flex items-center justify-between gap-4 rounded-lg border border-border p-4">
                  <div className="flex flex-col gap-0.5">
                    <span className="text-sm font-medium">Pro plan</span>
                    <span className="text-xs text-muted-foreground">
                      $29 / month, renews Aug 1, 2026
                    </span>
                  </div>
                  <Button variant="outline" size="sm">
                    Change plan
                  </Button>
                </div>
                <Separator />
                <div className="flex items-center justify-between gap-4">
                  <div className="flex flex-col gap-0.5">
                    <span className="text-sm font-medium">Payment method</span>
                    <span className="text-xs text-muted-foreground tabular-nums">
                      Visa •••• 4242, expires 08/27
                    </span>
                  </div>
                  <Button variant="outline" size="sm">
                    Update
                  </Button>
                </div>
              </div>
            )}

            <div className="mt-8 flex justify-end gap-2 border-t border-border pt-5">
              <Button variant="outline">Cancel</Button>
              <Button>Save changes</Button>
            </div>
          </div>
        </div>
      </div>
    </section>
  )
}
```
