Files
clawhub/src/components/ui/dropdown-menu.tsx
T
Patrick Erichsen de29369ba7 feat: adopt shared design system across ClawHub UI (#3026)
* chore: install OpenClaw design system

* feat: adopt shared design system palette

* chore: automate design system updates

* feat: add weekly design system audit

* fix: prevent mobile skills tab overlap

* fix: harden design audit automation

* fix: validate audit changes before execution

* fix: scope design system clone credentials

* fix: align audit with installed design release

* fix: preserve audit artifacts and access

* feat: adopt shared design system on landing page

* fix: align icon geometry with design tokens

* chore: pin design system to v0.0.1

* chore: pin design system to v0.0.1

* chore: pin design system to v0.0.1

* chore: pin design system to v0.0.1

* chore: pin design system to v0.0.1

* fix: migrate ClawHub UI to design tokens

* fix: use public design system installs

* fix: use public design system distribution
2026-07-09 11:05:59 -07:00

97 lines
4.3 KiB
TypeScript

import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
import { Check } from "lucide-react";
import * as React from "react";
import { cn } from "../../lib/utils";
const DropdownMenu = DropdownMenuPrimitive.Root;
const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
const DropdownMenuContent = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>
>(({ className, sideOffset = 8, align = "start", ...props }, ref) => (
<DropdownMenuPrimitive.Portal>
<DropdownMenuPrimitive.Content
ref={ref}
sideOffset={sideOffset}
align={align}
data-slot="dropdown-menu-content"
className={cn(
"z-50 max-h-[var(--radix-dropdown-menu-content-available-height)] min-w-[180px] origin-[var(--radix-dropdown-menu-content-transform-origin)] overflow-x-hidden overflow-y-auto rounded-[var(--oc-radius-surface)] border border-[color:var(--oc-border-subtle)] bg-[color:var(--oc-bg-elevated)] p-2 text-[color:var(--oc-text-primary)] shadow-[var(--oc-shadow-lg)]",
"data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
"data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
className,
)}
{...props}
/>
</DropdownMenuPrimitive.Portal>
));
DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;
const DropdownMenuItem = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {
inset?: boolean;
variant?: "default" | "destructive";
}
>(({ className, inset, variant = "default", ...props }, ref) => (
<DropdownMenuPrimitive.Item
ref={ref}
data-slot="dropdown-menu-item"
data-inset={inset}
data-variant={variant}
className={cn(
"relative flex cursor-pointer select-none items-center gap-2 rounded-[var(--oc-radius-control)] px-3 py-2 text-sm font-semibold text-[color:var(--oc-text-primary)] outline-none transition-colors focus-visible:outline-none data-[highlighted]:bg-[color:var(--oc-surface-interactive)] data-[highlighted]:text-[color:var(--oc-text-primary)] focus:bg-[color:var(--oc-surface-interactive)] data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset=true]:pl-8 data-[variant=destructive]:text-status-error-fg",
className,
)}
{...props}
/>
));
DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;
const DropdownMenuCheckboxItem = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>
>(({ className, children, ...props }, ref) => (
<DropdownMenuPrimitive.CheckboxItem
ref={ref}
data-slot="dropdown-menu-checkbox-item"
className={cn(
"relative flex cursor-pointer select-none items-center rounded-[var(--oc-radius-control)] py-2 pr-3 pl-8 text-sm font-semibold text-[color:var(--oc-text-primary)] outline-none transition-colors focus:bg-[color:var(--oc-surface-interactive)] data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
className,
)}
{...props}
>
<span className="absolute left-2 flex h-4 w-4 items-center justify-center">
<DropdownMenuPrimitive.ItemIndicator>
<Check className="h-4 w-4" aria-hidden="true" />
</DropdownMenuPrimitive.ItemIndicator>
</span>
{children}
</DropdownMenuPrimitive.CheckboxItem>
));
DropdownMenuCheckboxItem.displayName = DropdownMenuPrimitive.CheckboxItem.displayName;
const DropdownMenuSeparator = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.Separator>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>
>(({ className, ...props }, ref) => (
<DropdownMenuPrimitive.Separator
ref={ref}
data-slot="dropdown-menu-separator"
className={cn("my-1 h-px bg-[color:var(--line)]", className)}
{...props}
/>
));
DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;
export {
DropdownMenu,
DropdownMenuTrigger,
DropdownMenuContent,
DropdownMenuCheckboxItem,
DropdownMenuItem,
DropdownMenuSeparator,
};