Skip to content

Commit 98270c5

Browse files
authored
feat(action-panel): add variant prop to ActionItem for destructive styling (#301)
1 parent f7ad47e commit 98270c5

5 files changed

Lines changed: 31 additions & 9 deletions

File tree

.changeset/red-actions-glow.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@tailor-platform/app-shell": patch
3+
---
4+
5+
Add optional `variant` prop to `ActionItem` for the `ActionPanel` component. Use `variant: "destructive"` to style dangerous actions (e.g., delete) with red text and hover background.

docs/components/action-panel.md

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,14 +47,15 @@ import { ActionPanel } from "@tailor-platform/app-shell";
4747

4848
### ActionItem
4949

50-
| Property | Type | Default | Description |
51-
| ---------- | ----------------------------- | ------------ | ------------------------------------------------- |
52-
| `key` | `string` | **Required** | Unique key for stable rendering |
53-
| `label` | `string` | **Required** | Action label shown to users |
54-
| `icon` | `ReactNode` | **Required** | Icon rendered in a fixed 16px slot |
55-
| `onClick` | `() => void \| Promise<void>` | - | Click handler for the action |
56-
| `disabled` | `boolean` | `false` | Disables interaction and applies disabled styling |
57-
| `loading` | `boolean` | `false` | Shows spinner, disables interaction, sets busy UI |
50+
| Property | Type | Default | Description |
51+
| ---------- | ----------------------------- | ------------ | --------------------------------------------------------------------- |
52+
| `key` | `string` | **Required** | Unique key for stable rendering |
53+
| `label` | `string` | **Required** | Action label shown to users |
54+
| `icon` | `ReactNode` | **Required** | Icon rendered in a fixed 16px slot |
55+
| `onClick` | `() => void \| Promise<void>` | - | Click handler for the action |
56+
| `disabled` | `boolean` | `false` | Disables interaction and applies disabled styling |
57+
| `loading` | `boolean` | `false` | Shows spinner, disables interaction, sets busy UI |
58+
| `variant` | `"default" \| "destructive"` | `"default"` | Visual variant; use `"destructive"` for dangerous actions like delete |
5859

5960
## Behavior
6061

examples/nextjs-app/src/modules/pages/action-panel-demo.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {
33
Receipt as ReceiptIcon,
44
FileText as FileTextIcon,
55
ExternalLink as ExternalLinkIcon,
6+
Trash2 as Trash2Icon,
67
} from "lucide-react";
78

89
const ActionPanelDemoPage = () => {
@@ -49,6 +50,15 @@ const ActionPanelDemoPage = () => {
4950
icon: <ExternalLinkIcon size={16} />,
5051
onClick: () => navigate("/custom-page/purchase-order-demo"),
5152
},
53+
{
54+
key: "delete-result",
55+
label: "Delete Result",
56+
icon: <Trash2Icon size={16} />,
57+
variant: "destructive",
58+
onClick: () => {
59+
toast("Delete result clicked");
60+
},
61+
},
5262
]}
5363
/>
5464
</div>

packages/core/src/components/action-panel/ActionPanel.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,13 @@ const actionRowBaseClasses = cn(
4343
const actionRowInteractiveClasses =
4444
"astw:hover:bg-accent astw:hover:text-accent-foreground astw:outline-none astw:focus-visible:ring-2 astw:focus-visible:ring-ring astw:focus-visible:ring-offset-2";
4545

46+
const actionRowDestructiveClasses =
47+
"astw:text-destructive astw:hover:bg-destructive/10 astw:hover:text-destructive";
48+
4649
const actionRowDisabledClasses = "astw:pointer-events-none astw:opacity-50";
4750

4851
function ActionRow({ action }: { action: ActionItem }) {
49-
const { key, label, icon, onClick, disabled, loading } = action;
52+
const { key, label, icon, onClick, disabled, loading, variant } = action;
5053
const isDisabled = Boolean(disabled) || Boolean(loading);
5154

5255
const content = (
@@ -61,6 +64,7 @@ function ActionRow({ action }: { action: ActionItem }) {
6164
const rowClasses = cn(
6265
actionRowBaseClasses,
6366
isDisabled ? actionRowDisabledClasses : actionRowInteractiveClasses,
67+
variant === "destructive" && !isDisabled && actionRowDestructiveClasses,
6468
);
6569

6670
return (

packages/core/src/components/action-panel/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ export interface ActionItem {
2121
disabled?: boolean;
2222
/** When true, show loading indicator in the row and make it non-interactive */
2323
loading?: boolean;
24+
/** Visual variant. Use "destructive" for dangerous actions like delete. */
25+
variant?: "default" | "destructive";
2426
}
2527

2628
// ============================================================================

0 commit comments

Comments
 (0)