How to Use Table.ShowAction, Table.EditAction, and Table.DeleteAction in refine-shadcn

Use Table.ShowAction, Table.EditAction, and Table.DeleteAction inside Table.Actions to add permission-aware row-level actions to any refine-shadcn table; these components automatically handle URL generation, access control via useCan, and delete confirmations through DeleteProvider.

The refine-shadcn library provides a composable Table component that simplifies building data grids with integrated CRUD operations. These action sub-components abstract away routing logic and permission checks, letting you declare row actions declaratively while the library handles navigation, disabling unauthorized actions, and modal confirmations.

Understanding the Action Components

The Table component exposes three specialized action wrappers that render as dropdown menu items. Each wraps the shared RowAction UI element and integrates with Refine’s access-control system.

Table.ShowAction

Table.ShowAction generates a navigation link to the resource’s show page. In packages/theme/src/table/actions/show.tsx, the component calls the useGetShowUrl hook to construct the URL and check permissions via Refine’s useCan. If the user lacks view permission, the button disables automatically and displays the restriction reason as a tooltip.

Table.EditAction

Table.EditAction functions identically to ShowAction but targets the edit route. Located in packages/theme/src/table/actions/edit.tsx, it uses useGetEditUrl to generate the edit path (e.g., /users/edit/:id) and applies the same permission-based disabling logic.

Table.DeleteAction

Table.DeleteAction differs from the navigation actions—it triggers a confirmation modal rather than a route change. Implemented in packages/theme/src/table/actions/delete.tsx, it leverages useDeleteHelper to verify delete permissions and communicates with DeleteProvider (defined in packages/theme/src/providers/deleteProvider.tsx) to open the confirmation dialog. Upon confirmation, it executes the delete request and optionally runs an onAfterHandle callback.

RowAction Shared UI

All three actions render through RowAction, defined in packages/theme/src/table/actions/index.tsx. This component renders a DropdownMenuItem that adapts based on props: it renders as a <Link> when a to URL is provided (Show/Edit) or as a button with an onClick handler (Delete).

Basic Implementation

Import Table from @ferdiunal/refine-shadcn and render the actions inside a column’s cell function wrapped by Table.Actions.

import { ListPage, Table } from "@ferdiunal/refine-shadcn";
import { Eye, Edit, Trash2 } from "lucide-react";

export const UserList = () => (
  <ListPage>
    <Table enableSorting enableFilters>
      <Table.Column
        accessorKey="id"
        header="Actions"
        cell={({ row: { original } }) => (
          <Table.Actions>
            <Table.ShowAction
              title="View Details"
              row={original}
              resource="users"
              icon={<Eye size={16} />}
            />
            <Table.EditAction
              title="Edit User"
              row={original}
              resource="users"
              icon={<Edit size={16} />}
            />
            <Table.DeleteAction
              title="Delete User"
              row={original}
              resource="users"
              icon={<Trash2 size={16} />}
            />
          </Table.Actions>
        )}
      />
    </Table>
  </ListPage>
);

The row prop receives the current row data, and resource specifies the Refine resource name for URL generation and permission checks.

Permission Handling and Architecture

Each action follows a consistent three-step flow defined in the source hooks:

  1. Permission check – useGetShowUrl, useGetEditUrl, and useDeleteHelper (located in packages/theme/src/hooks/) internally call useCan to verify access.
  2. Conditional rendering – The hook returns { can, reason, url }. If can is false, RowAction receives disabled={true} and displays reason as a tooltip.
  3. Navigation or modal – Show and Edit actions render as links to the generated url. DeleteAction calls DeleteContext.updateData to open the modal from DeleteProvider.

The Table component automatically wraps its children with DeleteProvider (see lines 166-168 of packages/theme/src/table/index.tsx), so you do not need to manually provide the context to use Table.DeleteAction.

Advanced Usage Patterns

Custom Post-Delete Callbacks

Pass onAfterHandle to Table.DeleteAction to run logic after successful deletion, such as invalidating queries or showing toast notifications.

<Table.DeleteAction
  title="Remove Comment"
  row={original}
  resource="comments"
  icon={<Trash2 size={16} />}
  onAfterHandle={() => {
    toast.success("Comment deleted successfully");
    queryClient.invalidateQueries({ queryKey: ["comments"] });
  }}
/>

Overriding Default Icons and Labels

Each action accepts standard props to customize appearance. The title prop sets the tooltip text and accessible label, while icon accepts any React element.

<Table.ShowAction
  title="Preview"
  row={original}
  resource="posts"
  icon={<EyeOff size={16} />}  // Custom icon
/>

Key Source Files

Reference these locations in the ferdiunal/refine-shadcn repository for implementation details:

Summary

  • Table.ShowAction and Table.EditAction generate permission-aware navigation links to show and edit routes using useGetShowUrl and useGetEditUrl.
  • Table.DeleteAction triggers a confirmation modal via DeleteProvider and handles deletion through useDeleteHelper.
  • All actions disable automatically when the user lacks permission, showing the restriction reason as a tooltip.
  • Wrap actions inside Table.Actions within a Table.Column cell to render a dropdown menu of row operations.
  • The DeleteProvider context is included automatically in the Table component, requiring no manual setup.

Frequently Asked Questions

How do I disable an action manually regardless of permissions?

Pass the disabled prop directly to any action component. While the components automatically disable based on useCan results, you can force a disabled state by setting disabled={true}, which takes precedence in the RowAction component.

Why is my DeleteAction not opening a modal?

Ensure you are using the Table component from @ferdiunal/refine-shadcn and not a raw table. The Table component internally renders DeleteProvider (as seen in packages/theme/src/table/index.tsx). If you extract the actions for use outside of Table, you must manually wrap your application with DeleteProvider from the same package.

Can I use these actions outside of a Table component?

Technically yes, but you lose automatic context integration. The actions expect a row object and resource name. For standalone usage, import RowAction directly from packages/theme/src/table/actions/index.tsx and provide your own onClick or to props, though you must manually handle permission checks using Refine’s useCan hook.

How do I customize the delete confirmation modal text?

The modal content is controlled by DeleteProvider in packages/theme/src/providers/deleteProvider.tsx. To customize the confirmation text, you would need to shadow or fork the provider component, as the current implementation does not expose props for modal text customization through the action components themselves.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →