Skip to main content
Version: 1.0.3

List With Actions

Overview

The List With Actions component extends the basic list functionality by adding contextual action buttons (like Edit, Delete, View) to each list item. Actions are intelligently revealed on hover or focus on desktop devices, while remaining always visible on mobile for better touch interaction.

Preview

  • Design landing page
  • Implement authentication
  • Review pull requests

Installation

ignix add component list-with-actions

Usage

Import the component:

import { ListWithActions } from './components/ui/list-with-actions';

Basic Usage

The simplest way to use ListWithActions is with the items and actions props:

function BasicList() {
const actions = [
{ id: 'view', label: 'View', onClick: (index) => console.log('View', index) },
{ id: 'edit', label: 'Edit', onClick: (index) => console.log('Edit', index) },
{ id: 'delete', label: 'Delete', onClick: (index) => console.log('Delete', index) },
];

return (
<ListWithActions
items={['Item 1', 'Item 2', 'Item 3']}
actions={actions}
/>
);
}

With Ordered List

To show numbered markers, pass the type prop:

function OrderedList() {
const actions = [
{ id: 'edit', label: 'Edit', onClick: (index) => {} },
{ id: 'delete', label: 'Delete', onClick: (index) => {} },
];

return (
<ListWithActions
type="ordered"
items={['Step 1', 'Step 2', 'Step 3']}
actions={actions}
/>
);
}

Without Markers

If you don't want bullets or numbers, simply omit the type prop:

function NoMarkers() {
return (
<ListWithActions
items={['Task 1', 'Task 2', 'Task 3']}
actions={actions}
/>
);
}

Custom Spacing

Control the spacing between items:

function CustomSpacing() {
return (
<ListWithActions
items={['Item 1', 'Item 2', 'Item 3']}
actions={actions}
spacing="lg" // Options: 'sm', 'md', 'lg'
/>
);
}

Rich Content Items

You can pass complex JSX as items:

function RichContent() {
const items = [
(
<div className="flex flex-col">
<span className="font-medium">Analytics Dashboard</span>
<span className="text-xs text-muted-foreground">Last updated 2 hours ago</span>
</div>
),
(
<div className="flex flex-col">
<span className="font-medium">Marketing Campaign</span>
<span className="text-xs text-muted-foreground">Running · Ends in 3 days</span>
</div>
),
];

return (
<ListWithActions
items={items}
actions={actions}
spacing="lg"
/>
);
}

Interactive Demo

    💡 Hover over items or use Tab to focus them to see the action buttons. On mobile, actions are always visible.

    Variants

    Actions Behavior

    Actions appear on hover/focus on desktop and are always visible on mobile:

    Actions Behavior

    • Task 1
    • Task 2
    • Task 3

    Hover over items or press Tab to focus them. Actions appear on hover/focus on desktop and are always visible on mobile.

    Ordered List

    Use numbered markers for sequential items:

    Ordered List

    1. 1.
      Step 1: Gather requirements
    2. 2.
      Step 2: Design the solution
    3. 3.
      Step 3: Implement features

    Rich Content

    Display complex content in list items:

    Rich Content

    • Analytics DashboardLast updated 2 hours ago
    • Marketing CampaignRunning · Ends in 3 days
    • Billing IntegrationIn review · 4 comments

    Props

    PropTypeDefaultDescription
    itemsReact.ReactNode[]requiredArray of items to display in the list. Can be strings or React nodes.
    actionsListAction[]requiredArray of action definitions. Each action must have id, label, and onClick.
    type'unordered' | 'ordered'undefinedType of list marker. When provided, shows bullets (unordered) or numbers (ordered). When omitted, no markers are shown.
    spacing'sm' | 'md' | 'lg''md'Spacing size between list items. 'sm' (8px), 'md' (12px), 'lg' (16px).
    classNamestringundefinedAdditional CSS classes to apply to the list container.
    itemClassNamestringundefinedAdditional CSS classes to apply to each list row.

    ListAction Interface

    PropertyTypeRequiredDescription
    idstringrequiredUnique identifier for the action (used as React key).
    labelReact.ReactNoderequiredVisible label or icon for the action button.
    ariaLabelstringoptionalAccessible label announced to screen readers.
    onClick(index: number) => voidrequiredCallback fired when the action is clicked. Receives the item's index.

    Examples

    Task Management

    A common use case for managing tasks with actions:

    const tasks = ['Design landing page', 'Implement auth', 'Write tests'];
    const taskActions = [
    { id: 'complete', label: 'Complete', onClick: (i) => markComplete(i) },
    { id: 'edit', label: 'Edit', onClick: (i) => editTask(i) },
    { id: 'delete', label: 'Delete', onClick: (i) => deleteTask(i) },
    ];

    <ListWithActions items={tasks} actions={taskActions} />

    User List

    Displaying users with management actions:

    const users = ['John Doe', 'Jane Smith', 'Bob Johnson'];
    const userActions = [
    { id: 'view', label: 'View Profile', onClick: (i) => viewUser(i) },
    { id: 'edit', label: 'Edit', onClick: (i) => editUser(i) },
    { id: 'delete', label: 'Remove', onClick: (i) => removeUser(i) },
    ];

    <ListWithActions items={users} actions={userActions} spacing="md" />

    Step-by-Step Guide

    Using ordered list for instructions:

    const steps = [
    'Open the application',
    'Navigate to Settings',
    'Select your preferences',
    'Click Save to apply changes',
    ];

    const stepActions = [
    { id: 'view', label: 'View Details', onClick: (i) => showDetails(i) },
    ];

    <ListWithActions
    type="ordered"
    items={steps}
    actions={stepActions}
    spacing="md"
    />

    Accessibility

    The ListWithActions component is designed with accessibility in mind:

    • Keyboard navigation: Each row is focusable (tabIndex={0}), allowing keyboard users to reveal actions by focusing on items
    • Screen reader support: Actions include ariaLabel props for better screen reader announcements
    • Focus management: Actions become visible when a row receives focus, ensuring keyboard users can access all functionality
    • Semantic HTML: Uses proper list semantics (<ul> or <ol>) inherited from ListBasic

    Best Practices

    1. Use memoized callbacks: To prevent unnecessary re-renders, memoize your action handlers with useCallback:

      const handleEdit = useCallback((index: number) => {
      editItem(index);
      }, []);

      const actions = [
      { id: 'edit', label: 'Edit', onClick: handleEdit },
      ];
    2. Provide aria labels: Always include ariaLabel for icon-only actions:

      { id: 'delete', label: <TrashIcon />, ariaLabel: 'Delete item', onClick: handleDelete }
    3. Keep actions concise: Limit the number of actions per item (3-4 max) to avoid cluttering the UI

    4. Mobile-first: Remember that actions are always visible on mobile, so design them to be touch-friendly

    5. Use appropriate spacing: Choose spacing based on content density:

      • sm: For compact lists or when space is limited
      • md: For standard content (default)
      • lg: For better readability with rich content
    6. Consider type prop:

      • Use type="ordered" for sequential steps or ranked items
      • Use type="unordered" for feature lists or options
      • Omit type for clean, marker-free lists

    Performance

    The component is optimized for performance:

    • React.memo: Prevents re-renders when props haven't changed
    • useMemo: Memoizes computed class names
    • useCallback: Memoizes action click handlers

    To maximize performance in your application, ensure your actions array and items array references remain stable between renders.