{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"form-section","type":"registry:ui","title":"Form Section","description":"One group of a settings page: a title and description beside its fields.","dependencies":[],"registryDependencies":["https://dashral.com/r/utils.json"],"files":[{"path":"registry/dashral/form-section.tsx","type":"registry:file","target":"components/dashral/form-section.tsx","content":"import * as React from \"react\"\n\nimport { cn } from \"./lib/utils\"\n\ntype FormSectionProps = Omit<React.ComponentProps<\"section\">, \"title\"> & {\n  /** What the fields are about: \"Profile\", \"Notifications\", \"Danger zone\". */\n  title: React.ReactNode\n  /** A line or two on what changing them does. */\n  description?: React.ReactNode\n  /** The heading's level, to fit the page's outline. */\n  titleAs?: \"h2\" | \"h3\"\n  /** The fields. */\n  children: React.ReactNode\n  /** Under the fields: the section's buttons, e.g. Save. With variant=\"card\", a bar along the card's foot. */\n  footer?: React.ReactNode\n  /** split (default): the title at the side and the fields beside it, from the md breakpoint (stacked below). stacked: the title above. */\n  layout?: \"split\" | \"stacked\"\n  /** plain: the fields on the page; card: in a bordered card with the footer as its bottom bar. */\n  variant?: \"plain\" | \"card\"\n  /** A line above the section, to part it from the one before. */\n  divided?: boolean\n  classNames?: { header?: string; title?: string; description?: string; content?: string; footer?: string }\n}\n\n/**\n * One group of a settings page, in one tag: `<FormSection title=\"Profile\" description=\"…\" footer={<Button>Save</Button>}>`.\n * The title and description sit at the side with the fields beside them, as settings pages do, and stack on a phone.\n * Wrap the page's sections in a form, or give each its own.\n */\nfunction FormSection({\n  title,\n  description,\n  titleAs: Title = \"h2\",\n  children,\n  footer,\n  layout = \"split\",\n  variant = \"plain\",\n  divided = false,\n  className,\n  classNames,\n  id,\n  ...props\n}: FormSectionProps) {\n  const generatedId = React.useId()\n  const titleId = `${id ?? generatedId}-title`\n  const card = variant === \"card\"\n\n  return (\n    <section\n      id={id}\n      data-slot=\"form-section\"\n      aria-labelledby={titleId}\n      className={cn(\n        \"grid gap-x-10 gap-y-5\",\n        layout === \"split\" && \"md:grid-cols-[minmax(0,1fr)_minmax(0,2fr)]\",\n        divided && \"border-t pt-8\",\n        className\n      )}\n      {...props}\n    >\n      <div className={cn(\"grid content-start gap-1.5\", classNames?.header)}>\n        <Title id={titleId} className={cn(\"font-heading text-base font-medium tracking-tight text-balance\", classNames?.title)}>\n          {title}\n        </Title>\n        {description && <p className={cn(\"max-w-prose text-sm leading-relaxed text-pretty text-muted-foreground\", classNames?.description)}>{description}</p>}\n      </div>\n      <div className={cn(card && \"overflow-hidden rounded-xl border bg-card text-card-foreground shadow-xs\")}>\n        <div className={cn(\"grid gap-5\", card && \"p-5 sm:p-6\", classNames?.content)}>{children}</div>\n        {footer && (\n          <div\n            className={cn(\n              \"flex flex-wrap items-center justify-end gap-2\",\n              card ? \"border-t bg-muted/40 px-5 py-3 sm:px-6\" : \"mt-5\",\n              classNames?.footer\n            )}\n          >\n            {footer}\n          </div>\n        )}\n      </div>\n    </section>\n  )\n}\n\nexport { FormSection, type FormSectionProps }\n"}],"cssVars":{"theme":{"font-heading":"var(--font-geist, \"Geist\"), var(--font-inter, \"Inter\"), var(--font-arabic, \"IBM Plex Sans Arabic\"), ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", Roboto, sans-serif"},"light":{},"dark":{}}}