{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "sort-by-heading",
  "title": "Sort-by heading",
  "description": "An editorial heading that reads “Top landlords by [platform fee]”, followed by a direction toggle.",
  "dependencies": [
    "radix-ui"
  ],
  "registryDependencies": [],
  "files": [
    {
      "path": "registry/items/sort-by-heading/sort-by-heading.tsx",
      "content": "\"use client\";\nimport { useState } from \"react\";\nimport { DropdownMenu } from \"radix-ui\";\nexport type SortChoice = { value: string; label: string };\nexport type SortByHeadingProps = {\n  prefix?: string; options: readonly SortChoice[]; value?: string; defaultValue?: string;\n  onValueChange?: (value: string) => void; direction?: \"asc\" | \"desc\";\n  defaultDirection?: \"asc\" | \"desc\"; onDirectionChange?: (direction: \"asc\" | \"desc\") => void;\n};\nexport function SortByHeading({ prefix = \"Top landlords by\", options, value, defaultValue, onValueChange, direction, defaultDirection = \"desc\", onDirectionChange }: SortByHeadingProps) {\n  const [internal, setInternal] = useState(defaultValue ?? options[0]?.value ?? \"\");\n  const [internalDirection, setInternalDirection] = useState(defaultDirection);\n  const selected = value ?? internal;\n  const dir = direction ?? internalDirection;\n  const active = options.find(option => option.value === selected) ?? options[0];\n  return <div className=\"flex w-full flex-wrap items-center gap-2 font-body text-ink\">\n    <h2 className=\"font-heading text-xl\">{prefix}</h2>\n    <DropdownMenu.Root>\n      <DropdownMenu.Trigger {...{ asChild: true }} disabled={!options.length}>\n        <button type=\"button\" aria-label={`Rank by ${active?.label ?? \"a measure\"}`} className=\"inline-flex min-h-11 cursor-pointer items-center gap-2 rounded-inset border border-rule px-2.5 font-heading text-xl leading-none text-lead hover:border-lead focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-lead disabled:cursor-default disabled:opacity-50\">\n          {active?.label ?? \"Choose a measure\"}<span aria-hidden=\"true\" className=\"text-xs\">▾</span>\n        </button>\n      </DropdownMenu.Trigger>\n      <DropdownMenu.Content align=\"start\" sideOffset={4} collisionPadding={16} className=\"z-50 min-w-40 overflow-hidden rounded-panel border border-rule bg-popover py-1 font-body text-sm text-popover-foreground shadow-lg outline-none\">\n        <DropdownMenu.RadioGroup value={active?.value ?? \"\"} onValueChange={next => { setInternal(next); onValueChange?.(next); }}>\n          {options.map(option => (\n            <DropdownMenu.RadioItem key={option.value} value={option.value} className=\"flex min-h-11 cursor-pointer items-center justify-between gap-4 px-3 py-2 outline-none data-[highlighted]:bg-paper data-[state=checked]:text-lead\">\n              {option.label}\n              <DropdownMenu.ItemIndicator aria-hidden=\"true\" className=\"text-xs\">✓</DropdownMenu.ItemIndicator>\n            </DropdownMenu.RadioItem>\n          ))}\n        </DropdownMenu.RadioGroup>\n      </DropdownMenu.Content>\n    </DropdownMenu.Root>\n    <button type=\"button\" onClick={() => { const next = dir === \"desc\" ? \"asc\" : \"desc\"; setInternalDirection(next); onDirectionChange?.(next); }} className=\"min-h-11 cursor-pointer rounded-inset border border-rule px-2.5 py-1.5 text-xs text-dim transition-colors hover:border-lead hover:text-ink focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-lead\" title={dir === \"desc\" ? \"Highest first\" : \"Lowest first\"}>{dir === \"desc\" ? \"Descending ↓\" : \"Ascending ↑\"}</button>\n  </div>;\n}\n",
      "type": "registry:component"
    }
  ],
  "meta": {
    "kind": "widget",
    "whenToUse": "Use when the ranking criterion belongs in the heading. A custom dropdown preserves the sentence-like appearance, with keyboard selection, a checked item, Escape and click-away dismissal.",
    "origin": {
      "project": "Ledge",
      "path": "src/components/admin/top-landlords.tsx"
    },
    "credits": []
  },
  "type": "registry:component"
}
