Skip to content

ActionTools Component

The ActionTools suite provides flexible, responsive, and semantic action menus and toolbars for standardizing interactions across the application. It consists of two main presentational components: PageActions and RowActions.

These components automatically adapt to screen sizes, handle tooltip generation, and construct dropdown menus for nested actions.

Overview

  • PageActions: A responsive toolbar for page-level actions. On desktop, it renders a horizontal button group. On mobile, it collapses into a single "More" dropdown menu. Best used in page headers, toolbars, or detailed forms.
  • RowActions: A lightweight component optimized for dense areas like data grid rows or list items. It renders standalone icon buttons or kebab menus for nested actions. Uses React.memo for zero overhead inside large lists.

Import Statement

tsx
import { PageActions, RowActions, type PageAction, type RowAction } from '@repo/ui/components';

Usage Examples

1. Page Actions (Toolbars & Headers)

PageActions requires a text label (unless the type is divider). You can customize the look using Mantine's button variants and map specific intents for semantic colors.

tsx
import { PageActions, type PageAction } from '@repo/ui/components';
import { Save, Printer, Trash, FileText, CheckCircle } from 'lucide-react';

function PageHeader() {
  const actions: PageAction[] = [
    {
      key: 'save',
      label: 'Save Changes',
      icon: <Save size={16} />,
      intent: 'primary',
      onClick: (key) => console.log('Clicked', key),
    },
    { type: 'divider' },
    {
      key: 'print',
      label: 'Print',
      icon: <Printer size={16} />,
      // Nested actions render as a dropdown menu below the main button
      children: [
        {
          key: 'print-original',
          label: 'Print Original',
          icon: <FileText size={16} />,
          onClick: (k) => console.log(k),
        },
        {
          key: 'print-copy',
          label: 'Print Copy',
          icon: <FileText size={16} />,
          onClick: (k) => console.log(k),
        },
      ],
    },
    {
      key: 'delete',
      label: 'Delete',
      icon: <Trash size={16} />,
      intent: 'destructive',
      onClick: (key) => console.log('Clicked', key),
    },
  ];

  return <PageActions actions={actions} onClose={() => console.log('closed')} />;
}

2. Row Actions (Data Grids & Lists)

RowActions are optimized for density. Text labels are optional and primarily shown inside nested dropdowns. Hover tooltips are supported.

tsx
import { RowActions, type RowAction } from '@repo/ui/components';
import { Edit, CheckCircle, MoreVertical, Trash } from 'lucide-react';
import { Table } from '@repo/ui/components';

function DataTable() {
  const rowActions: RowAction[] = [
    {
      key: 'edit',
      tooltip: 'Edit Record',
      icon: <Edit size={16} />,
      onClick: (key) => console.log('Clicked', key),
    },
    {
      key: 'approve',
      tooltip: 'Approve',
      icon: <CheckCircle size={16} />,
      intent: 'success',
      onClick: (key) => console.log('Clicked', key),
    },
    {
      key: 'more',
      label: 'More Options',
      icon: <MoreVertical size={16} />,
      children: [
        {
          key: 'delete',
          label: 'Delete Record',
          icon: <Trash size={16} />,
          intent: 'destructive',
          onClick: (k) => console.log(k),
        },
      ],
    },
  ];

  return (
    <Table>
      <Table.Tbody>
        <Table.Tr>
          <Table.Td>Invoice #001</Table.Td>
          <Table.Td>
            <RowActions actions={rowActions} />
          </Table.Td>
        </Table.Tr>
      </Table.Tbody>
    </Table>
  );
}

Props API Reference

PageActions Props

PropTypeDefaultDescription
actionsPageAction[]RequiredArray of configured page-level actions.
onClose() => voidundefinedOptional callback triggered when the close (X) button is clicked.

RowActions Props

PropTypeDefaultDescription
actionsRowAction[][]Array of configured row-level actions.
showLabelsbooleanfalseIf true, renders the text label alongside the icon for top-level buttons.

Action Definitions

Both PageAction and RowAction share a common base interface.

Base Action Properties (BaseAction)

PropertyTypeDescription
keystringUnique identifier. Required for 'action', optional for 'divider'.
type'action' | 'divider'Type of action. Defaults to 'action'.
iconReactNodeVisual representation of the action.
disabledbooleanDisables interaction if set to true.
intent'default' | 'success' | 'warning' | 'destructive' | 'primary'Semantic context to determine visual emphasis (color mapping).
onClick(key: string) => voidCallback triggered upon execution.

PageAction Specific Properties

PropertyTypeDescription
labelstringText label displayed on the button. Required for 'action' type.
variant'filled' | 'light' | 'outline' | 'default' | 'subtle' | 'transparent'Specifies the Mantine button variant. Defaults to 'transparent' internally.
childrenPageAction[]Nested actions rendered as a dropdown menu below the main button.

RowAction Specific Properties

PropertyTypeDescription
labelstringText primarily used when rendered inside a nested menu item.
tooltipstringOptional text displayed on hover over the standalone icon.
childrenRowAction[]Nested actions that will be rendered inside a dropdown menu.

Best Practices

  • Semantic Intents: Always map your actions to a specific intent (e.g., intent: 'destructive' for deletions). The components will automatically map these to the appropriate theme colors.
  • Nested Actions (Dropdowns): For actions that trigger sub-actions (like multiple print options), use the children array property. The component automatically manages the dropdown positioning and presentation.
  • Density in Rows: Inside lists and tables, favor RowActions over PageActions and provide a tooltip instead of forcing a full label. This keeps the UI clean and performs efficiently, especially over many rows. Keep showLabels as false (default) for a tighter grid layout unless specifically required.
  • Dividers: Use { type: 'divider' } within your actions array to visually group related buttons together. The component handles both horizontal and vertical divider logic depending on the screen size.