import { memo, Fragment } from 'react'; import { Group, Button, Menu, Divider, ActionIcon, Box, ButtonProps, Tooltip, MantineSpacing } from '@mantine/core'; import { ChevronDown, MoreVertical } from 'lucide-react'; import { PageActionProps } from './types'; import { getIntentColor } from './utils'; export interface PageActionsProps { /** Array of configured page-level actions. */ actions?: PageActionProps[]; customButtonProps?: (action: PageActionProps) => ButtonProps; gapActionDesktop?: MantineSpacing; gapActionMobile?: MantineSpacing; } /** * A responsive and flexible presentational component for page-level actions. * Automatically adapts layout based on screen size. */ export const PageActions = memo(function PageActions(props: PageActionsProps) { const { actions = [], customButtonProps, gapActionDesktop = 'xs', gapActionMobile = 'sm' } = props; if (!actions || actions?.length === 0) { return null; } function defaultButtonStyle(isPremiumGlow: boolean) { return { size: 'sm', radius: 'md', fw: 500, style: isPremiumGlow ? { boxShadow: '0 4px 14px 0 color-mix(in srgb, var(--mantine-primary-color-filled) 40%, transparent)' } : undefined, }; } return ( {/* --- DESKTOP VIEW --- */} {actions.map((action, index) => { if (action.type === 'divider') { return ; } const isPremiumGlow = action.intent === 'primary' && action.variant === 'filled'; const showLabel = action.showLabel !== false; const tooltipContent = action.tooltipLabel || (!showLabel ? action.label : undefined); // 1. Button with Dropdown (Menu.Target) if (action.children && action.children.length > 0) { const ButtonWithDropdown = showLabel ? ( ) : ( {action.icon} ); return ( {tooltipContent ? ( {ButtonWithDropdown} ) : ( ButtonWithDropdown )} {action.children.map((child, childIndex) => { if (child.type === 'divider') { return ; } return ( child.onClick?.(child.key || '')} > {child.label} ); })} ); } // 2. Regular Button (Standalone) const StandaloneButton = showLabel ? ( ) : ( action.onClick?.(action.key || '')} size="lg" style={isPremiumGlow ? defaultButtonStyle(true).style : undefined} > {action.icon} ); return tooltipContent ? ( {StandaloneButton} ) : ( {StandaloneButton} ); })} {/* --- MOBILE VIEW --- */} {actions.map((action, index) => { if (action.type === 'divider') { return ; } if (action.children && action.children.length > 0) { return ( {action.label} {action.children.map((child, childIndex) => { if (child.type === 'divider') { return ; } return ( child.onClick?.(child.key || '')} style={{ paddingLeft: '1.5rem' }} mt="sm" mb="sm" > {child.label} ); })} ); } const color = action?.color ? action.color : getIntentColor(action.intent); const realColor = color === undefined ? 'brand' : color; return ( action.onClick?.(action.key || '')} mt="sm" mb="sm" > {action.label} ); })} ); });