{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "dropdown-menu",
  "type": "registry:ui",
  "title": "Dropdown Menu",
  "description": "Grows from its trigger, with one highlight that glides after the pointer.",
  "categories": [
    "menus"
  ],
  "dependencies": [
    "@base-ui/react",
    "motion"
  ],
  "registryDependencies": [
    "https://www.stealth.pm/r/tokens.json",
    "https://www.stealth.pm/r/cn.json",
    "https://www.stealth.pm/r/icons.json",
    "https://www.stealth.pm/r/motion.json"
  ],
  "files": [
    {
      "path": "components/ui/dropdown-menu.tsx",
      "content": "\"use client\";\nimport { Menu } from \"@base-ui/react/menu\";\nimport { animate, motion, useMotionValue, useReducedMotion } from \"motion/react\";\nimport { createContext, useContext, useEffect, useId, useRef } from \"react\";\nimport { cn } from \"@/lib/cn\";\nimport { ChevronDown, ChevronRight } from \"@/lib/icons\";\nimport { spring } from \"@/lib/motion\";\n\n/* -------------------------------------------------------------------------------------------------\n * Root and trigger\n * -----------------------------------------------------------------------------------------------*/\n\nexport type DropdownMenuProps = Menu.Root.Props;\n\n/** Groups a trigger and its menu. Uncontrolled by default; pass `open` + `onOpenChange` to control it. */\nexport function DropdownMenu(props: DropdownMenuProps) {\n  return <Menu.Root {...props} />;\n}\n\nexport type DropdownMenuTriggerProps = Menu.Trigger.Props & {\n  variant?: \"secondary\" | \"ghost\";\n  size?: \"sm\" | \"md\";\n  /** Square button with only an icon. Give it an aria-label. */\n  iconOnly?: boolean;\n  /** A chevron after the label that turns over while the menu is open. */\n  chevron?: boolean;\n};\n\n/** A button that opens the menu. Styled by default; pass `render` to put the behavior on your own button. */\nexport function DropdownMenuTrigger({\n  variant = \"secondary\",\n  size = \"md\",\n  iconOnly = false,\n  chevron = false,\n  className,\n  children,\n  ...rest\n}: DropdownMenuTriggerProps) {\n  return (\n    <Menu.Trigger\n      data-variant={variant}\n      data-size={size}\n      className={(state) => cn(\n        \"group/trigger relative inline-flex shrink-0 select-none items-center justify-center font-medium tracking-[-0.005em] outline-none\",\n        \"touch-manipulation [-webkit-tap-highlight-color:transparent]\",\n        \"focus-visible:outline-solid focus-visible:outline-1 focus-visible:outline-offset-2 focus-visible:outline-fg-3\",\n        \"transition-[background-color,border-color,color,scale] duration-150 ease-out active:scale-[0.97] active:duration-75\",\n        \"data-disabled:pointer-events-none data-disabled:opacity-50\",\n        size === \"sm\" ? \"h-7 gap-1.5 rounded-md text-[12px] [&_svg]:size-3.5\" : \"h-8 gap-1.5 rounded-lg text-[12.5px] [&_svg]:size-4\",\n        iconOnly ? (size === \"sm\" ? \"w-7 active:scale-[0.94]\" : \"w-8 active:scale-[0.94]\") : size === \"sm\" ? \"px-2\" : \"px-2.5\",\n        iconOnly && !chevron && \"before:absolute before:-inset-2 before:content-[''] pointer-fine:before:hidden\",\n        chevron && !iconOnly && (size === \"sm\" ? \"pe-1.5\" : \"pe-2\"),\n        variant === \"secondary\"\n          ? \"border border-line-2 bg-raised text-fg shadow-[var(--shadow)] hover:border-fg-4 hover:bg-hover data-popup-open:border-fg-4 data-popup-open:bg-hover\"\n          : \"text-fg-2 hover:bg-hover hover:text-fg data-popup-open:bg-hover data-popup-open:text-fg\",\n        typeof className === \"function\" ? className(state) : className,\n      )}\n      {...rest}\n    >\n      {children}\n      {chevron && (\n        <ChevronDown className=\"text-fg-3 transition-transform duration-200 ease-out-expo group-data-popup-open/trigger:rotate-180 motion-reduce:transition-none\" />\n      )}\n    </Menu.Trigger>\n  );\n}\n\n/* -------------------------------------------------------------------------------------------------\n * Popup: the surface, its entrance, and the one highlight that glides between rows\n * -----------------------------------------------------------------------------------------------*/\n\n// The popup grows out of whatever opened it (Base UI sets --transform-origin to the\n// trigger edge, or to the pointer for context menus) and drifts 4px away from it.\n// data-instant is set when the menu was opened or closed from the keyboard, or when\n// a menubar hands off between menus: those render on the same frame.\nconst popupClass = cn(\n  \"group/menu relative isolate max-h-(--available-height) min-w-[max(12rem,var(--anchor-width))] max-w-[min(20rem,var(--available-width))]\",\n  \"overflow-y-auto overscroll-contain rounded-xl border border-line-2 bg-raised p-1 text-fg shadow-pop outline-none\",\n  \"[scrollbar-width:none] has-[[data-lead]]:[--menu-lead:26px]\",\n  \"origin-(--transform-origin) transition-[opacity,scale,translate] duration-180 ease-out-expo\",\n  \"data-starting-style:scale-96 data-starting-style:opacity-0\",\n  \"data-[side=bottom]:data-starting-style:-translate-y-1 data-[side=top]:data-starting-style:translate-y-1\",\n  \"data-[side=right]:data-starting-style:-translate-x-1 data-[side=inline-end]:data-starting-style:-translate-x-1\",\n  \"data-[side=left]:data-starting-style:translate-x-1 data-[side=inline-start]:data-starting-style:translate-x-1\",\n  \"data-ending-style:scale-98 data-ending-style:opacity-0 data-ending-style:duration-120\",\n  \"data-instant:duration-0 motion-reduce:scale-100 motion-reduce:translate-none\",\n);\n\nexport type DropdownMenuPopupProps = Menu.Popup.Props;\n\n/**\n * The styled menu surface. DropdownMenuContent wraps it in a portal and positioner;\n * use it directly inside another positioner (a context menu, a menubar).\n */\nexport function DropdownMenuPopup({ className, children, ref, ...rest }: DropdownMenuPopupProps) {\n  const popupRef = useRef<HTMLDivElement | null>(null);\n  const highlightRef = useRef<HTMLDivElement>(null);\n  const style = useGlidingHighlight(popupRef, highlightRef);\n\n  return (\n    <Menu.Popup\n      ref={(node: HTMLDivElement | null) => {\n        popupRef.current = node;\n        if (typeof ref === \"function\") ref(node);\n        else if (ref) ref.current = node;\n      }}\n      className={(state) => cn(popupClass, typeof className === \"function\" ? className(state) : className)}\n      {...rest}\n    >\n      <motion.div\n        ref={highlightRef}\n        aria-hidden\n        data-tone=\"default\"\n        style={style}\n        className={cn(\n          \"pointer-events-none absolute inset-x-1 top-0 -z-10 rounded-lg bg-fg/[0.06] transition-[background-color] duration-100\",\n          \"data-[tone=danger]:bg-danger-soft data-[tone=open]:bg-fg/[0.04] data-pressed:bg-fg/[0.1] data-[tone=danger]:data-pressed:bg-danger/[0.18]\",\n        )}\n      />\n      {children}\n    </Menu.Popup>\n  );\n}\n\n// One highlight for the whole list, moved to whichever row Base UI marks as\n// highlighted. It springs after the pointer, jumps for arrow keys (keyboard\n// navigation never animates), and fades rather than slides when it first appears\n// so it never sweeps in from the top of the menu. Motion values keep all of this\n// off React's render path.\nfunction useGlidingHighlight(popupRef: React.RefObject<HTMLDivElement | null>, highlightRef: React.RefObject<HTMLDivElement | null>) {\n  const reduce = useReducedMotion();\n  const y = useMotionValue(0);\n  const height = useMotionValue(0);\n  const opacity = useMotionValue(0);\n\n  useEffect(() => {\n    const popup = popupRef.current;\n    const hl = highlightRef.current;\n    if (!popup || !hl) return;\n    let input: \"pointer\" | \"keyboard\" = \"pointer\";\n    let shown = false;\n\n    const sync = () => {\n      // Only rows that belong to this popup; submenus are portaled, so a plain query is enough.\n      const row =\n        popup.querySelector<HTMLElement>(\"[data-highlighted]\") ??\n        popup.querySelector<HTMLElement>(\"[data-popup-open][role=menuitem]\");\n      if (!row) {\n        if (shown) animate(opacity, 0, { duration: 0.12 });\n        shown = false;\n        delete hl.dataset.pressed;\n        return;\n      }\n      hl.dataset.tone = row.dataset.variant === \"danger\" ? \"danger\" : row.hasAttribute(\"data-highlighted\") ? \"default\" : \"open\";\n      const top = row.offsetTop;\n      const h = row.offsetHeight;\n      if (!shown || input === \"keyboard\" || reduce) {\n        y.jump(top);\n        height.jump(h);\n      } else {\n        animate(y, top, spring.follow);\n        animate(height, h, spring.follow);\n      }\n      animate(opacity, row.hasAttribute(\"data-disabled\") ? 0.5 : 1, { duration: shown ? 0.08 : 0.1 });\n      shown = true;\n    };\n\n    const onKey = () => (input = \"keyboard\");\n    const onMove = () => (input = \"pointer\");\n    const onDown = (e: PointerEvent) => {\n      if ((e.target as HTMLElement).closest(\"[role^=menuitem]:not([data-disabled])\")) hl.dataset.pressed = \"\";\n    };\n    const onUp = () => delete hl.dataset.pressed;\n\n    const observer = new MutationObserver(sync);\n    observer.observe(popup, { subtree: true, attributes: true, attributeFilter: [\"data-highlighted\", \"data-popup-open\"] });\n    popup.addEventListener(\"keydown\", onKey, true);\n    popup.addEventListener(\"pointermove\", onMove, true);\n    popup.addEventListener(\"pointerdown\", onDown);\n    window.addEventListener(\"pointerup\", onUp);\n    window.addEventListener(\"pointercancel\", onUp);\n    sync();\n    return () => {\n      observer.disconnect();\n      popup.removeEventListener(\"keydown\", onKey, true);\n      popup.removeEventListener(\"pointermove\", onMove, true);\n      popup.removeEventListener(\"pointerdown\", onDown);\n      window.removeEventListener(\"pointerup\", onUp);\n      window.removeEventListener(\"pointercancel\", onUp);\n    };\n  }, [popupRef, highlightRef, reduce, y, height, opacity]);\n\n  return { y, height, opacity };\n}\n\nexport type DropdownMenuContentProps = DropdownMenuPopupProps & {\n  side?: Menu.Positioner.Props[\"side\"];\n  align?: Menu.Positioner.Props[\"align\"];\n  sideOffset?: number;\n  alignOffset?: number;\n  collisionPadding?: Menu.Positioner.Props[\"collisionPadding\"];\n  /** Position against this element instead of the trigger. */\n  anchor?: Menu.Positioner.Props[\"anchor\"];\n  /** Where the menu is portaled. Defaults to the body. */\n  container?: Menu.Portal.Props[\"container\"];\n};\n\n/** The menu itself: portaled, positioned against the trigger, and grown out of it. */\nexport function DropdownMenuContent({\n  side = \"bottom\",\n  align = \"start\",\n  sideOffset = 6,\n  alignOffset = 0,\n  collisionPadding = 8,\n  anchor,\n  container,\n  ...rest\n}: DropdownMenuContentProps) {\n  return (\n    <Menu.Portal container={container}>\n      <Menu.Positioner\n        side={side}\n        align={align}\n        sideOffset={sideOffset}\n        alignOffset={alignOffset}\n        collisionPadding={collisionPadding}\n        anchor={anchor}\n        className=\"z-(--z-dropdown) outline-none\"\n      >\n        <DropdownMenuPopup {...rest} />\n      </Menu.Positioner>\n    </Menu.Portal>\n  );\n}\n\n/* -------------------------------------------------------------------------------------------------\n * Rows\n * -----------------------------------------------------------------------------------------------*/\n\n// Rows carry no background of their own: the shared highlight paints it. Labels line\n// up across the whole menu: once any row has a leading icon or indicator, rows\n// without one are indented by the same 26px (--menu-lead, set on the popup).\nconst rowClass = cn(\n  \"group/item relative flex min-h-8 cursor-default select-none items-center gap-2.5 rounded-lg pe-2 text-[13px] leading-[18px] outline-none\",\n  \"ps-[calc(0.5rem+var(--menu-lead,0px))] has-[[data-lead]]:ps-2 pointer-coarse:min-h-10\",\n  \"data-disabled:opacity-50 data-[variant=danger]:text-danger\",\n);\n\nconst leadClass =\n  \"grid size-4 shrink-0 place-items-center text-fg-3 transition-colors duration-100 group-data-highlighted/item:text-fg-2 group-data-[variant=danger]/item:text-danger [&_svg]:size-4\";\n// Checkbox and radio indicators carry state, so they stay at full strength.\nconst indicatorClass = \"grid size-4 shrink-0 place-items-center text-fg\";\n// With a description the row grows; the icon and keys stay on the first line.\nconst firstLine = \"self-start mt-[7px]\";\n\ntype RowContent = {\n  /** A 16px icon before the label. */\n  icon?: React.ReactNode;\n  /** Keys shown at the end of the row, as glyphs: \"⌘D\", \"⇧⌘C\", \"⌫\". Display only. */\n  shortcut?: string;\n  /** A second, quieter line under the label. */\n  description?: React.ReactNode;\n};\n\nfunction RowBody({ icon, shortcut, description, children }: RowContent & { children?: React.ReactNode }) {\n  return (\n    <>\n      {icon && (\n        <span data-lead aria-hidden className={cn(leadClass, description ? firstLine : undefined)}>\n          {icon}\n        </span>\n      )}\n      {description ? (\n        <span className=\"flex min-w-0 flex-1 flex-col py-1.5\">\n          <span className=\"truncate\">{children}</span>\n          <span className=\"line-clamp-2 text-[12px] leading-4 text-fg-3\">{description}</span>\n        </span>\n      ) : (\n        <span className=\"min-w-0 flex-1 truncate\">{children}</span>\n      )}\n      {shortcut && <DropdownMenuShortcut keys={shortcut} className={description ? \"self-start mt-[10px]\" : undefined} />}\n    </>\n  );\n}\n\nconst textOf = (node: React.ReactNode) => (typeof node === \"string\" ? node : undefined);\n\nexport type DropdownMenuItemProps = Menu.Item.Props &\n  RowContent & {\n    /** Destructive: danger text, and the highlight turns danger when it lands here. */\n    variant?: \"default\" | \"danger\";\n  };\n\nexport function DropdownMenuItem({ icon, shortcut, description, variant = \"default\", className, children, label, ...rest }: DropdownMenuItemProps) {\n  return (\n    <Menu.Item\n      data-variant={variant}\n      label={label ?? textOf(children)}\n      aria-keyshortcuts={toAriaShortcut(shortcut)}\n      className={(state) => cn(rowClass, typeof className === \"function\" ? className(state) : className)}\n      {...rest}\n    >\n      <RowBody icon={icon} shortcut={shortcut} description={description}>\n        {children}\n      </RowBody>\n    </Menu.Item>\n  );\n}\n\nexport type DropdownMenuLinkItemProps = Menu.LinkItem.Props & RowContent;\n\n/** A row that navigates. Renders an anchor, so it opens in a new tab like any link. */\nexport function DropdownMenuLinkItem({ icon, shortcut, description, className, children, label, ...rest }: DropdownMenuLinkItemProps) {\n  return (\n    <Menu.LinkItem\n      label={label ?? textOf(children)}\n      className={(state) => cn(rowClass, \"text-fg no-underline\", typeof className === \"function\" ? className(state) : className)}\n      {...rest}\n    >\n      <RowBody icon={icon} shortcut={shortcut} description={description}>\n        {children}\n      </RowBody>\n    </Menu.LinkItem>\n  );\n}\n\nexport type DropdownMenuCheckboxItemProps = Menu.CheckboxItem.Props & Omit<RowContent, \"icon\">;\n\n/** Toggles a setting. The menu stays open and the tick draws itself in. */\nexport function DropdownMenuCheckboxItem({ shortcut, description, className, children, label, ...rest }: DropdownMenuCheckboxItemProps) {\n  return (\n    <Menu.CheckboxItem\n      label={label ?? textOf(children)}\n      aria-keyshortcuts={toAriaShortcut(shortcut)}\n      className={(state) => cn(rowClass, typeof className === \"function\" ? className(state) : className)}\n      {...rest}\n    >\n      <Menu.CheckboxItemIndicator keepMounted data-lead className={cn(indicatorClass, description ? firstLine : undefined)}>\n        <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" strokeWidth={1.5} strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\n          <path\n            d=\"M3.5 8.5 6.5 11.5 12.5 4.5\"\n            pathLength={1}\n            className=\"[stroke-dasharray:1] [stroke-dashoffset:1] transition-[stroke-dashoffset] duration-120 ease-out in-data-checked:[stroke-dashoffset:0] in-data-checked:duration-280 in-data-checked:ease-out-expo motion-reduce:transition-none\"\n          />\n        </svg>\n      </Menu.CheckboxItemIndicator>\n      <RowBody shortcut={shortcut} description={description}>\n        {children}\n      </RowBody>\n    </Menu.CheckboxItem>\n  );\n}\n\nconst RadioDot = createContext<string | null>(null);\n\nexport type DropdownMenuRadioGroupProps = Menu.RadioGroup.Props;\n\n/** One choice out of several. Controlled with value + onValueChange, or defaultValue. */\nexport function DropdownMenuRadioGroup(props: DropdownMenuRadioGroupProps) {\n  const id = useId();\n  return (\n    <RadioDot.Provider value={id}>\n      <Menu.RadioGroup {...props} />\n    </RadioDot.Provider>\n  );\n}\n\nexport type DropdownMenuRadioItemProps = Menu.RadioItem.Props & Omit<RowContent, \"icon\">;\n\n/** One option in a radio group. The dot glides from the old choice to the new one. */\nexport function DropdownMenuRadioItem({ shortcut, description, className, children, label, ...rest }: DropdownMenuRadioItemProps) {\n  const dot = useContext(RadioDot);\n  const reduce = useReducedMotion();\n  return (\n    <Menu.RadioItem\n      label={label ?? textOf(children)}\n      aria-keyshortcuts={toAriaShortcut(shortcut)}\n      className={(state) => cn(rowClass, typeof className === \"function\" ? className(state) : className)}\n      {...rest}\n    >\n      <Menu.RadioItemIndicator\n        keepMounted\n        data-lead\n        className={cn(indicatorClass, description ? firstLine : undefined)}\n        render={(props, state) => (\n          <span {...props}>\n            {state.checked && (\n              <motion.span\n                layoutId={dot ? `menu-radio-${dot}` : undefined}\n                transition={reduce ? { duration: 0 } : spring.snappy}\n                className=\"size-1.5 rounded-full bg-current\"\n              />\n            )}\n          </span>\n        )}\n      />\n      <RowBody shortcut={shortcut} description={description}>\n        {children}\n      </RowBody>\n    </Menu.RadioItem>\n  );\n}\n\nexport type DropdownMenuGroupProps = Menu.Group.Props;\n\nexport function DropdownMenuGroup(props: DropdownMenuGroupProps) {\n  return <Menu.Group {...props} />;\n}\n\nexport type DropdownMenuLabelProps = Menu.GroupLabel.Props;\n\n/** A quiet heading for the group it sits in; screen readers announce it with the group. */\nexport function DropdownMenuLabel({ className, ...rest }: DropdownMenuLabelProps) {\n  return (\n    <Menu.GroupLabel\n      className={(state) =>\n        cn(\n          \"select-none pe-2 pb-1 pt-2 font-mono text-2xs uppercase tracking-[0.08em] text-fg-3\",\n          \"ps-[calc(0.5rem+var(--menu-lead,0px))]\",\n          typeof className === \"function\" ? className(state) : className,\n        )\n      }\n      {...rest}\n    />\n  );\n}\n\nexport type DropdownMenuSeparatorProps = Menu.Separator.Props;\n\nexport function DropdownMenuSeparator({ className, ...rest }: DropdownMenuSeparatorProps) {\n  return <Menu.Separator className={(state) => cn(\"-mx-1 my-1 h-px bg-line\", typeof className === \"function\" ? className(state) : className)} {...rest} />;\n}\n\n/* -------------------------------------------------------------------------------------------------\n * Submenus\n * -----------------------------------------------------------------------------------------------*/\n\nexport type DropdownMenuSubProps = Menu.SubmenuRoot.Props;\n\nexport function DropdownMenuSub(props: DropdownMenuSubProps) {\n  return <Menu.SubmenuRoot {...props} />;\n}\n\nexport type DropdownMenuSubTriggerProps = Menu.SubmenuTrigger.Props & Omit<RowContent, \"shortcut\">;\n\n/** A row that opens a submenu on hover, click, or the right arrow key. */\nexport function DropdownMenuSubTrigger({ icon, description, className, children, label, ...rest }: DropdownMenuSubTriggerProps) {\n  return (\n    <Menu.SubmenuTrigger\n      label={label ?? textOf(children)}\n      className={(state) => cn(rowClass, typeof className === \"function\" ? className(state) : className)}\n      {...rest}\n    >\n      <RowBody icon={icon} description={description}>\n        {children}\n      </RowBody>\n      <ChevronRight\n        size={14}\n        className=\"-me-0.5 shrink-0 text-fg-3 transition-[translate,color] duration-150 ease-out group-data-highlighted/item:translate-x-0.5 group-data-highlighted/item:text-fg-2 group-data-popup-open/item:translate-x-0.5 motion-reduce:transition-none\"\n      />\n    </Menu.SubmenuTrigger>\n  );\n}\n\nexport type DropdownMenuSubContentProps = DropdownMenuPopupProps & {\n  sideOffset?: number;\n  alignOffset?: number;\n  container?: Menu.Portal.Props[\"container\"];\n};\n\n/** The submenu surface. Its first row lines up with the row that opened it. */\nexport function DropdownMenuSubContent({ sideOffset = 6, alignOffset = -5, container, ...rest }: DropdownMenuSubContentProps) {\n  return (\n    <Menu.Portal container={container}>\n      <Menu.Positioner side=\"inline-end\" align=\"start\" sideOffset={sideOffset} alignOffset={alignOffset} collisionPadding={8} className=\"z-(--z-dropdown) outline-none\">\n        <DropdownMenuPopup {...rest} />\n      </Menu.Positioner>\n    </Menu.Portal>\n  );\n}\n\n/* -------------------------------------------------------------------------------------------------\n * Shortcut\n * -----------------------------------------------------------------------------------------------*/\n\nconst MODIFIERS = \"⌃⌥⇧⌘\";\nconst MODIFIER_NAMES: Record<string, string> = { \"⌃\": \"Control\", \"⌥\": \"Alt\", \"⇧\": \"Shift\", \"⌘\": \"Meta\" };\n\nfunction splitKeys(keys: string) {\n  let i = 0;\n  while (i < keys.length && MODIFIERS.includes(keys[i])) i++;\n  return [keys.slice(0, i), keys.slice(i)] as const;\n}\n\nfunction toAriaShortcut(keys?: string) {\n  if (!keys) return undefined;\n  const [mods, key] = splitKeys(keys);\n  return [...[...mods].map((m) => MODIFIER_NAMES[m]), key.length === 1 ? key.toUpperCase() : key].join(\"+\");\n}\n\nexport type DropdownMenuShortcutProps = Omit<React.ComponentProps<\"kbd\">, \"children\"> & {\n  /** Modifier glyphs then the key: \"⇧⌘S\". */\n  keys: string;\n};\n\n/**\n * Keys at the end of a row. The key sits in its own column and modifiers stack\n * to its left, so ⌘S and ⇧⌘S line up on the S the way native menus do. Hidden on\n * touch screens, where there is no keyboard to press them on.\n */\nexport function DropdownMenuShortcut({ keys, className, ...rest }: DropdownMenuShortcutProps) {\n  const [mods, key] = splitKeys(keys);\n  return (\n    <kbd\n      aria-hidden\n      className={cn(\n        \"ms-auto flex shrink-0 items-center ps-6 font-sans text-[12px] leading-none text-fg-3 tabular pointer-coarse:hidden\",\n        \"group-data-highlighted/item:text-fg-2 group-data-[variant=danger]/item:text-danger/70\",\n        className,\n      )}\n      {...rest}\n    >\n      <span className=\"tracking-[0.04em]\">{mods}</span>\n      <span className=\"min-w-[1em] text-start\">{key}</span>\n    </kbd>\n  );\n}\n\n",
      "type": "registry:ui"
    }
  ],
  "docs": "https://www.stealth.pm/ui/dropdown-menu"
}
