Files
gridpilot.gg/apps/website/components/admin/BulkActionBar.tsx
2026-01-17 15:46:55 +01:00

94 lines
2.5 KiB
TypeScript

'use client';
import React from 'react';
import { Stack } from '@/ui/Stack';
import { Box } from '@/ui/Box';
import { Text } from '@/ui/Text';
import { Button } from '@/ui/Button';
import { motion, AnimatePresence } from 'framer-motion';
interface BulkActionBarProps {
selectedCount: number;
actions: {
label: string;
onClick: () => void;
variant?: 'primary' | 'secondary' | 'danger';
icon?: React.ReactNode;
}[];
onClearSelection: () => void;
}
/**
* BulkActionBar
*
* Floating action bar that appears when items are selected in a table.
*/
export function BulkActionBar({
selectedCount,
actions,
onClearSelection
}: BulkActionBarProps) {
return (
<AnimatePresence>
{selectedCount > 0 && (
<Box
as={motion.div}
initial={{ y: 100, opacity: 0 }}
animate={{ y: 0, opacity: 1 }}
exit={{ y: 100, opacity: 0 }}
position="fixed"
bottom="8"
left="1/2"
translateX="-1/2"
zIndex={50}
bg="bg-surface-charcoal"
border
borderColor="border-primary-blue/50"
rounded="xl"
shadow="xl"
px={6}
py={4}
bgOpacity={0.9}
blur="md"
>
<Stack direction="row" align="center" gap={8}>
<Stack direction="row" align="center" gap={3}>
<Box bg="bg-primary-blue" rounded="full" px={2} py={0.5}>
<Text size="xs" weight="bold" color="text-white">
{selectedCount}
</Text>
</Box>
<Text size="sm" weight="medium" color="text-white">
Items Selected
</Text>
</Stack>
<Box w="px" h="6" bg="bg-charcoal-outline" />
<Stack direction="row" align="center" gap={3}>
{actions.map((action) => (
<Button
key={action.label}
size="sm"
variant={action.variant === 'danger' ? 'secondary' : (action.variant || 'primary')}
onClick={action.onClick}
icon={action.icon}
>
{action.label}
</Button>
))}
<Button
size="sm"
variant="ghost"
onClick={onClearSelection}
>
Cancel
</Button>
</Stack>
</Stack>
</Box>
)}
</AnimatePresence>
);
}