{
  "$schema": "https://shadcn-vue.com/schema/registry-item.json",
  "name": "settings-page",
  "title": "Settings Page",
  "type": "registry:page",
  "files": [
    {
      "path": "packages/registry-vue/blocks/settings-page/SettingsPage.vue",
      "content": "<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\nimport type { Component, HTMLAttributes } from 'vue'\nimport { Bell, Building2, CreditCard, Palette, TriangleAlert, User } from 'lucide-vue-next'\nimport { cn } from '@/lib/utils'\nimport { Button } from '@/components/ui/button'\nimport { Input } from '@/components/ui/input'\nimport { Label } from '@/components/ui/label'\nimport { SectionCard } from '@/components/ui/section-card'\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'\nimport { Separator } from '@/components/ui/separator'\nimport { Switch } from '@/components/ui/switch'\nimport { Textarea } from '@/components/ui/textarea'\nimport {\n  Dialog,\n  DialogContent,\n  DialogDescription,\n  DialogFooter,\n  DialogHeader,\n  DialogTitle,\n} from '@/components/ui/dialog'\n\ntype SectionId = 'profile' | 'notifications' | 'appearance' | 'workspace' | 'billing' | 'danger'\n\ninterface SettingsSection {\n  id: SectionId\n  label: string\n  icon: Component\n}\n\nconst props = withDefaults(\n  defineProps<{\n    /** Override the nav. Ids must still match the built-in panels. */\n    sections?: SettingsSection[]\n    /** Initially active section id. */\n    initialSection?: SectionId\n    class?: HTMLAttributes['class']\n  }>(),\n  {\n    sections: undefined,\n    initialSection: 'profile',\n  },\n)\n\nconst defaultSections: SettingsSection[] = [\n  { id: 'profile', label: 'Profile', icon: User },\n  { id: 'notifications', label: 'Notifications', icon: Bell },\n  { id: 'appearance', label: 'Appearance', icon: Palette },\n  { id: 'workspace', label: 'Workspace', icon: Building2 },\n  { id: 'billing', label: 'Billing', icon: CreditCard },\n  { id: 'danger', label: 'Danger zone', icon: TriangleAlert },\n]\n\nconst sections = computed(() => props.sections ?? defaultSections)\nconst active = ref<SectionId>(props.initialSection)\n\nconst notifyEmail = ref(true)\nconst notifyPush = ref(false)\nconst notifyDigest = ref(true)\nconst themeChoice = ref<'light' | 'dark' | 'system'>('system')\nconst deleteOpen = ref(false)\nconst deleteConfirm = ref('')\n\nfunction switchPanel(id: SectionId) {\n  active.value = id\n}\n</script>\n\n<template>\n  <div\n    data-slot=\"settings-page\"\n    :class=\"cn('bg-background border-border flex min-h-svh flex-col rounded-xl border lg:flex-row', props.class)\"\n  >\n    <!-- Nav rail -->\n    <nav class=\"border-border shrink-0 border-b p-3 lg:w-56 lg:border-r lg:border-b-0\" aria-label=\"Settings sections\">\n      <div\n        class=\"flex [scrollbar-width:none] gap-1 overflow-x-auto lg:flex-col lg:overflow-visible [&::-webkit-scrollbar]:hidden\"\n      >\n        <button\n          v-for=\"section in sections\"\n          :key=\"section.id\"\n          type=\"button\"\n          class=\"focus-visible:ring-ring flex shrink-0 items-center gap-2 rounded-md px-3 py-2 text-sm font-medium transition-colors focus-visible:ring-2 focus-visible:outline-none\"\n          :class=\"\n            active === section.id\n              ? section.id === 'danger'\n                ? 'text-destructive bg-destructive/10'\n                : 'bg-accent text-accent-foreground'\n              : 'text-muted-foreground hover:bg-accent/50 hover:text-foreground'\n          \"\n          :aria-current=\"active === section.id ? 'page' : undefined\"\n          @click=\"switchPanel(section.id)\"\n        >\n          <component :is=\"section.icon\" class=\"size-4\" aria-hidden=\"true\" />\n          {{ section.label }}\n        </button>\n      </div>\n    </nav>\n\n    <!-- Content pane -->\n    <div class=\"flex min-w-0 flex-1 flex-col\">\n      <!-- Profile -->\n      <section v-if=\"active === 'profile'\" class=\"flex flex-1 flex-col\">\n        <div class=\"flex-1 space-y-6 p-6\">\n          <SectionCard title=\"Public profile\" description=\"How teammates see you across the workspace.\">\n            <div class=\"space-y-4\">\n              <div class=\"space-y-2\">\n                <Label for=\"sp-name\">Display name</Label>\n                <Input id=\"sp-name\" model-value=\"Amara Osei\" />\n              </div>\n              <div class=\"space-y-2\">\n                <Label for=\"sp-email\">Email</Label>\n                <Input id=\"sp-email\" model-value=\"amara@acme.com\" type=\"email\" />\n              </div>\n              <div class=\"space-y-2\">\n                <Label for=\"sp-bio\">Bio</Label>\n                <Textarea id=\"sp-bio\" model-value=\"Design engineer. Builds systems, breaks assumptions.\" :rows=\"3\" />\n              </div>\n              <div class=\"space-y-2\">\n                <Label for=\"sp-role\">Role</Label>\n                <Select model-value=\"editor\">\n                  <SelectTrigger id=\"sp-role\" class=\"w-full sm:w-56\">\n                    <SelectValue />\n                  </SelectTrigger>\n                  <SelectContent>\n                    <SelectItem value=\"admin\">Admin</SelectItem>\n                    <SelectItem value=\"editor\">Editor</SelectItem>\n                    <SelectItem value=\"viewer\">Viewer</SelectItem>\n                  </SelectContent>\n                </Select>\n              </div>\n            </div>\n          </SectionCard>\n        </div>\n        <div class=\"border-border flex items-center justify-end gap-2 border-t p-4\">\n          <Button variant=\"ghost\" size=\"sm\">Discard</Button>\n          <Button size=\"sm\">Save changes</Button>\n        </div>\n      </section>\n\n      <!-- Notifications -->\n      <section v-else-if=\"active === 'notifications'\" class=\"flex-1 p-6\">\n        <SectionCard title=\"Notifications\" description=\"Choose what reaches you and where.\">\n          <ul class=\"-my-4 divide-y\">\n            <li class=\"flex items-center justify-between gap-4 py-4\">\n              <div>\n                <p class=\"text-sm font-medium\">Email notifications</p>\n                <p class=\"text-muted-foreground text-xs\">Mentions, assignments and approvals.</p>\n              </div>\n              <Switch v-model=\"notifyEmail\" aria-label=\"Toggle email notifications\" />\n            </li>\n            <li class=\"flex items-center justify-between gap-4 py-4\">\n              <div>\n                <p class=\"text-sm font-medium\">Push notifications</p>\n                <p class=\"text-muted-foreground text-xs\">Real-time browser alerts while you work.</p>\n              </div>\n              <Switch v-model=\"notifyPush\" aria-label=\"Toggle push notifications\" />\n            </li>\n            <li class=\"flex items-center justify-between gap-4 py-4\">\n              <div>\n                <p class=\"text-sm font-medium\">Weekly digest</p>\n                <p class=\"text-muted-foreground text-xs\">A summary of everything, every Monday.</p>\n              </div>\n              <Switch v-model=\"notifyDigest\" aria-label=\"Toggle weekly digest\" />\n            </li>\n          </ul>\n        </SectionCard>\n      </section>\n\n      <!-- Appearance -->\n      <section v-else-if=\"active === 'appearance'\" class=\"flex-1 p-6\">\n        <SectionCard title=\"Appearance\" description=\"Theme follows your system by default.\">\n          <div class=\"space-y-5\">\n            <div class=\"grid grid-cols-3 gap-3\">\n              <button\n                v-for=\"theme in ['light', 'dark', 'system'] as const\"\n                :key=\"theme\"\n                type=\"button\"\n                class=\"focus-visible:ring-ring rounded-lg border p-3 text-left transition-colors focus-visible:ring-2 focus-visible:outline-none\"\n                :class=\"themeChoice === theme ? 'border-primary ring-primary/20 ring-2' : 'hover:bg-accent/50'\"\n                @click=\"themeChoice = theme\"\n              >\n                <span class=\"block text-sm font-medium capitalize\">{{ theme }}</span>\n                <span class=\"text-muted-foreground block text-xs\">\n                  {{ theme === 'light' ? 'Bright surfaces' : theme === 'dark' ? 'Low-light friendly' : 'Match device' }}\n                </span>\n              </button>\n            </div>\n            <Separator />\n            <div class=\"flex items-center justify-between\">\n              <div>\n                <p class=\"text-sm font-medium\">Reduced motion</p>\n                <p class=\"text-muted-foreground text-xs\">Collapse animations to instant transitions.</p>\n              </div>\n              <Switch :model-value=\"false\" aria-label=\"Toggle reduced motion\" />\n            </div>\n          </div>\n        </SectionCard>\n      </section>\n\n      <!-- Workspace -->\n      <section v-else-if=\"active === 'workspace'\" class=\"flex-1 p-6\">\n        <SectionCard title=\"Workspace\" description=\"Identity and defaults for everyone here.\">\n          <div class=\"space-y-4\">\n            <div class=\"space-y-2\">\n              <Label for=\"sp-ws-name\">Workspace name</Label>\n              <Input id=\"sp-ws-name\" model-value=\"Acme Inc\" />\n            </div>\n            <div class=\"space-y-2\">\n              <Label for=\"sp-ws-url\">URL slug</Label>\n              <div class=\"flex\">\n                <span\n                  class=\"border-border bg-muted text-muted-foreground flex items-center rounded-l-md border px-3 font-mono text-xs\"\n                >\n                  acme.uipkge.app\n                </span>\n                <Input id=\"sp-ws-url\" model-value=\"acme\" class=\"rounded-l-none font-mono text-xs\" />\n              </div>\n            </div>\n            <p class=\"text-muted-foreground text-xs\">16 members · 4 pending invites</p>\n          </div>\n        </SectionCard>\n      </section>\n\n      <!-- Billing -->\n      <section v-else-if=\"active === 'billing'\" class=\"flex-1 p-6\">\n        <SectionCard title=\"Billing\" description=\"Plan, seats and invoices.\">\n          <div class=\"flex items-center justify-between gap-4\">\n            <div>\n              <p class=\"text-sm font-medium\">Team plan · $12 / seat / month</p>\n              <p class=\"text-muted-foreground mt-1 text-xs\">Next invoice Sep 1, 2026 · 18 seats</p>\n            </div>\n            <Button variant=\"outline\" size=\"sm\">Manage billing</Button>\n          </div>\n        </SectionCard>\n      </section>\n\n      <!-- Danger zone -->\n      <section v-else class=\"flex-1 p-6\">\n        <div class=\"border-destructive/40 rounded-xl border p-6\">\n          <div class=\"flex items-center justify-between gap-4\">\n            <div>\n              <p class=\"text-destructive text-sm font-medium\">Delete this workspace</p>\n              <p class=\"text-muted-foreground mt-1 text-xs\">\n                All projects, members and data will be permanently removed.\n              </p>\n            </div>\n            <Button variant=\"destructive\" size=\"sm\" @click=\"deleteOpen = true\">Delete…</Button>\n          </div>\n        </div>\n      </section>\n    </div>\n\n    <Dialog v-model:open=\"deleteOpen\">\n      <DialogContent class=\"max-w-sm\">\n        <DialogHeader>\n          <DialogTitle>Delete workspace?</DialogTitle>\n          <DialogDescription>\n            This removes Acme Inc and all of its data for every member. This cannot be undone.\n          </DialogDescription>\n        </DialogHeader>\n        <Input v-model=\"deleteConfirm\" placeholder='Type \"DELETE\" to confirm' />\n        <DialogFooter>\n          <Button variant=\"outline\" size=\"sm\" @click=\"deleteOpen = false\">Cancel</Button>\n          <Button variant=\"destructive\" size=\"sm\" :disabled=\"deleteConfirm !== 'DELETE'\" @click=\"deleteOpen = false\">\n            Delete forever\n          </Button>\n        </DialogFooter>\n      </DialogContent>\n    </Dialog>\n  </div>\n</template>\n",
      "type": "registry:page",
      "target": "~/app/components/blocks/SettingsPage.vue"
    }
  ],
  "dependencies": [
    "lucide-vue-next"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/vue/button.json",
    "https://uipkge.dev/r/vue/dialog.json",
    "https://uipkge.dev/r/vue/input.json",
    "https://uipkge.dev/r/vue/label.json",
    "https://uipkge.dev/r/vue/section-card.json",
    "https://uipkge.dev/r/vue/select.json",
    "https://uipkge.dev/r/vue/separator.json",
    "https://uipkge.dev/r/vue/switch.json",
    "https://uipkge.dev/r/vue/textarea.json"
  ],
  "description": "Linear-style settings shell: a nav rail of icon sections (collapses to a horizontal tab strip on narrow screens) switching between fully composed panels — profile form with sticky save bar, notification switches, theme picker, workspace identity, billing summary, and a type-to-confirm danger zone. Swap the panel internals for your own forms.",
  "categories": [
    "layout",
    "dashboard"
  ]
}