mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-03-22 03:08:23 +00:00
132 lines
3.1 KiB
TypeScript
132 lines
3.1 KiB
TypeScript
"use client";
|
|
|
|
import { MoreHorizontal } from "lucide-react";
|
|
import { ComponentProps, ReactNode } from "react";
|
|
|
|
import { cn } from "@/lib/utils";
|
|
|
|
import {
|
|
DropdownMenu,
|
|
DropdownMenuContent,
|
|
DropdownMenuItem,
|
|
DropdownMenuSeparator,
|
|
DropdownMenuTrigger,
|
|
} from "./dropdown";
|
|
|
|
interface ActionDropdownProps {
|
|
/** The dropdown trigger element. Defaults to a vertical dots icon button */
|
|
trigger?: ReactNode;
|
|
/** Alignment of the dropdown content */
|
|
align?: "start" | "center" | "end";
|
|
/** Additional className for the content */
|
|
className?: string;
|
|
/** Accessible label for the trigger */
|
|
ariaLabel?: string;
|
|
children: ReactNode;
|
|
}
|
|
|
|
export function ActionDropdown({
|
|
trigger,
|
|
align = "end",
|
|
className,
|
|
ariaLabel = "Open actions menu",
|
|
children,
|
|
}: ActionDropdownProps) {
|
|
return (
|
|
<DropdownMenu modal={false}>
|
|
<DropdownMenuTrigger asChild>
|
|
{trigger ?? (
|
|
<button
|
|
type="button"
|
|
aria-label={ariaLabel}
|
|
className="hover:bg-bg-neutral-tertiary rounded-md p-1 transition-colors"
|
|
>
|
|
<MoreHorizontal className="text-text-neutral-secondary size-5" />
|
|
</button>
|
|
)}
|
|
</DropdownMenuTrigger>
|
|
<DropdownMenuContent
|
|
align={align}
|
|
className={cn(
|
|
"border-border-neutral-secondary bg-bg-neutral-secondary w-56 rounded-xl",
|
|
className,
|
|
)}
|
|
>
|
|
{children}
|
|
</DropdownMenuContent>
|
|
</DropdownMenu>
|
|
);
|
|
}
|
|
|
|
interface ActionDropdownItemProps
|
|
extends Omit<ComponentProps<typeof DropdownMenuItem>, "children"> {
|
|
/** Icon displayed before the label */
|
|
icon?: ReactNode;
|
|
/** Main label text */
|
|
label: ReactNode;
|
|
/** Optional description text below the label */
|
|
description?: string;
|
|
/** Whether the item is destructive (danger styling) */
|
|
destructive?: boolean;
|
|
}
|
|
|
|
export function ActionDropdownItem({
|
|
icon,
|
|
label,
|
|
description,
|
|
destructive = false,
|
|
className,
|
|
...props
|
|
}: ActionDropdownItemProps) {
|
|
return (
|
|
<DropdownMenuItem
|
|
className={cn(
|
|
"flex cursor-pointer items-start gap-2",
|
|
destructive && "text-text-error-primary focus:text-text-error-primary",
|
|
className,
|
|
)}
|
|
{...props}
|
|
>
|
|
{icon && (
|
|
<span
|
|
className={cn(
|
|
"text-muted-foreground mt-0.5 shrink-0 [&>svg]:size-4",
|
|
destructive && "text-text-error-primary",
|
|
)}
|
|
>
|
|
{icon}
|
|
</span>
|
|
)}
|
|
<div className="flex flex-col">
|
|
<span>{label}</span>
|
|
{description && (
|
|
<span
|
|
className={cn(
|
|
"text-muted-foreground text-xs",
|
|
destructive && "text-text-error-primary/70",
|
|
)}
|
|
>
|
|
{description}
|
|
</span>
|
|
)}
|
|
</div>
|
|
</DropdownMenuItem>
|
|
);
|
|
}
|
|
|
|
export function ActionDropdownDangerZone({
|
|
children,
|
|
}: {
|
|
children: ReactNode;
|
|
}) {
|
|
return (
|
|
<>
|
|
<DropdownMenuSeparator />
|
|
<span className="text-text-neutral-tertiary px-2 py-1.5 text-xs">
|
|
Danger zone
|
|
</span>
|
|
{children}
|
|
</>
|
|
);
|
|
}
|