pelagia-portal/App/components/ui/row-actions-menu.tsx
Hardik d27ec9152c feat(admin): collapse row actions into ⋯ dropdown menu
Replace per-row inline action buttons (Edit, Activate/Deactivate, Delete,
Grant SuperUser) across all six admin tables with a Radix DropdownMenu
triggered by a ⋯ button. Introduces RowActionsMenu/Item/DestructiveItem/
Separator primitives and a DeleteConfirmDialog modal. Each Edit*Button
gains controlled open/onOpenChange props so the dialog can be driven from
the table's per-row ActionsMenu sub-component. Toggle and delete actions
use useTransition + router.refresh() directly in the table.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 02:58:54 +05:30

78 lines
2.1 KiB
TypeScript

"use client";
import * as DropdownMenu from "@radix-ui/react-dropdown-menu";
import { MoreHorizontal } from "lucide-react";
export function RowActionsMenu({ children }: { children: React.ReactNode }) {
return (
<DropdownMenu.Root>
<DropdownMenu.Trigger asChild>
<button
className="rounded p-1.5 text-neutral-400 hover:text-neutral-600 hover:bg-neutral-100 transition-colors"
aria-label="Row actions"
>
<MoreHorizontal className="h-4 w-4" />
</button>
</DropdownMenu.Trigger>
<DropdownMenu.Portal>
<DropdownMenu.Content
align="end"
sideOffset={4}
className="min-w-[160px] rounded-lg border border-neutral-200 bg-white shadow-lg py-1 z-50"
>
{children}
</DropdownMenu.Content>
</DropdownMenu.Portal>
</DropdownMenu.Root>
);
}
export function RowActionsItem({
children,
onClick,
disabled,
}: {
children: React.ReactNode;
onClick?: () => void;
disabled?: boolean;
}) {
return (
<DropdownMenu.Item
onSelect={(e) => {
e.preventDefault();
onClick?.();
}}
disabled={disabled}
className="flex items-center gap-2 px-3 py-2 text-sm cursor-pointer hover:bg-neutral-50 transition-colors text-neutral-700 outline-none data-[disabled]:opacity-50 data-[disabled]:cursor-not-allowed"
>
{children}
</DropdownMenu.Item>
);
}
export function RowActionsDestructiveItem({
children,
onClick,
disabled,
}: {
children: React.ReactNode;
onClick?: () => void;
disabled?: boolean;
}) {
return (
<DropdownMenu.Item
onSelect={(e) => {
e.preventDefault();
onClick?.();
}}
disabled={disabled}
className="flex items-center gap-2 px-3 py-2 text-sm cursor-pointer hover:bg-danger-50 transition-colors text-danger-600 outline-none data-[disabled]:opacity-50 data-[disabled]:cursor-not-allowed"
>
{children}
</DropdownMenu.Item>
);
}
export function RowActionsSeparator() {
return <DropdownMenu.Separator className="my-1 h-px bg-neutral-100" />;
}