Skip to content

Commit 0c02977

Browse files
committed
feat(action-panel): add variant prop to ActionItem for destructive styling
1 parent 26c4ecc commit 0c02977

7 files changed

Lines changed: 35 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/__snapshots__/src__components__combobox.test.tsx.snap

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
22

3+
exports[`Combobox.Parts > opens popup when the input is focused and typed into 1`] = `"<div data-base-ui-inert=""><span role="button" aria-label="Dismiss" style="clip-path: inset(50%); overflow: hidden; white-space: nowrap; border: 0px; padding: 0px; width: 1px; height: 1px; margin: -1px; position: absolute;"></span><input data-list-empty="" autocomplete="off" spellcheck="false" autocorrect="off" autocapitalize="none" role="combobox" aria-expanded="true" aria-haspopup="listbox" aria-autocomplete="list" id="base-ui-_r_i_" data-slot="combobox-input" data-testid="input" placeholder="Search fruits..." class="astw:border-input astw:bg-background astw:text-foreground astw:placeholder:text-muted-foreground astw:flex astw:h-9 astw:w-full astw:rounded-md astw:border astw:px-3 astw:py-1 astw:text-sm astw:shadow-xs astw:outline-none astw:transition-colors astw:focus-visible:border-ring astw:focus-visible:ring-ring/50 astw:focus-visible:ring-[3px] astw:disabled:cursor-not-allowed astw:disabled:opacity-50" type="text" value="" data-popup-open="" data-pressed="" data-popup-side="bottom" aria-controls="_r_j_"><input id="base-ui-_r_i_-hidden-input" style="clip-path: inset(50%); overflow: hidden; white-space: nowrap; border: 0px; padding: 0px; width: 1px; height: 1px; margin: -1px; position: fixed; top: 0px; left: 0px;" tabindex="-1" aria-hidden="true" value=""></div><div id="_r_l_" data-base-ui-portal="" style="position: relative; z-index: var(--z-popup);"><div data-open="" data-side="bottom" data-align="center" data-empty="" role="presentation" style="position: absolute; left: 0px; top: 0px; transform: translate(0px, 0px); --available-width: -10px; --available-height: -11px; --anchor-width: 0px; --anchor-height: 0px; --transform-origin: 0px 0px;" data-anchor-hidden=""><div data-open="" data-side="bottom" data-align="center" data-empty="" role="presentation" tabindex="-1" data-slot="combobox-content" class="astw:bg-popover astw:text-popover-foreground astw:data-open:animate-in astw:data-ending-style:animate-out astw:data-ending-style:fade-out-0 astw:data-open:fade-in-0 astw:data-ending-style:zoom-out-95 astw:data-open:zoom-in-95 astw:z-(--z-popup) astw:w-[var(--anchor-width)] astw:min-w-32 astw:origin-(--transform-origin) astw:overflow-hidden astw:rounded-md astw:border astw:shadow-md" data-anchor-hidden=""><div data-empty="" tabindex="-1" data-base-ui-focusable="" aria-orientation="vertical" role="listbox" id="_r_j_" data-slot="combobox-list" class="astw:max-h-60 astw:overflow-y-auto astw:p-1"><div role="option" id="base-ui-_r_i_-0" aria-selected="false" data-slot="combobox-item" class="astw:relative astw:flex astw:w-full astw:cursor-default astw:items-center astw:gap-2 astw:rounded-sm astw:py-1.5 astw:pr-8 astw:pl-2 astw:text-sm astw:outline-hidden astw:select-none astw:data-highlighted:bg-accent astw:data-highlighted:text-accent-foreground astw:data-disabled:pointer-events-none astw:data-disabled:opacity-50"><span class="astw:absolute astw:right-2 astw:flex astw:size-3.5 astw:items-center astw:justify-center"></span>Apple</div><div role="option" id="base-ui-_r_i_-1" aria-selected="false" data-slot="combobox-item" class="astw:relative astw:flex astw:w-full astw:cursor-default astw:items-center astw:gap-2 astw:rounded-sm astw:py-1.5 astw:pr-8 astw:pl-2 astw:text-sm astw:outline-hidden astw:select-none astw:data-highlighted:bg-accent astw:data-highlighted:text-accent-foreground astw:data-disabled:pointer-events-none astw:data-disabled:opacity-50"><span class="astw:absolute astw:right-2 astw:flex astw:size-3.5 astw:items-center astw:justify-center"></span>Banana</div><div role="option" id="base-ui-_r_i_-2" aria-selected="false" data-slot="combobox-item" class="astw:relative astw:flex astw:w-full astw:cursor-default astw:items-center astw:gap-2 astw:rounded-sm astw:py-1.5 astw:pr-8 astw:pl-2 astw:text-sm astw:outline-hidden astw:select-none astw:data-highlighted:bg-accent astw:data-highlighted:text-accent-foreground astw:data-disabled:pointer-events-none astw:data-disabled:opacity-50"><span class="astw:absolute astw:right-2 astw:flex astw:size-3.5 astw:items-center astw:justify-center"></span>Cherry</div><div role="option" id="base-ui-_r_i_-3" aria-selected="false" data-slot="combobox-item" class="astw:relative astw:flex astw:w-full astw:cursor-default astw:items-center astw:gap-2 astw:rounded-sm astw:py-1.5 astw:pr-8 astw:pl-2 astw:text-sm astw:outline-hidden astw:select-none astw:data-highlighted:bg-accent astw:data-highlighted:text-accent-foreground astw:data-disabled:pointer-events-none astw:data-disabled:opacity-50"><span class="astw:absolute astw:right-2 astw:flex astw:size-3.5 astw:items-center astw:justify-center"></span>Date</div><div role="option" id="base-ui-_r_i_-4" aria-selected="false" data-slot="combobox-item" class="astw:relative astw:flex astw:w-full astw:cursor-default astw:items-center astw:gap-2 astw:rounded-sm astw:py-1.5 astw:pr-8 astw:pl-2 astw:text-sm astw:outline-hidden astw:select-none astw:data-highlighted:bg-accent astw:data-highlighted:text-accent-foreground astw:data-disabled:pointer-events-none astw:data-disabled:opacity-50"><span class="astw:absolute astw:right-2 astw:flex astw:size-3.5 astw:items-center astw:justify-center"></span>Elderberry</div><div role="status" aria-live="polite" aria-atomic="true" data-slot="combobox-empty" class="astw:px-4 astw:pt-2 astw:pb-4 astw:text-center astw:text-sm astw:text-muted-foreground astw:empty:hidden">No results found</div></div></div><span role="button" aria-label="Dismiss" style="clip-path: inset(50%); overflow: hidden; white-space: nowrap; border: 0px; padding: 0px; width: 1px; height: 1px; margin: -1px; position: absolute;"></span></div></div>"`;
4+
35
exports[`Combobox.Parts > snapshots > closed combobox with placeholder 1`] = `"<input data-list-empty="" autocomplete="off" spellcheck="false" autocorrect="off" autocapitalize="none" role="combobox" aria-expanded="false" aria-haspopup="listbox" aria-autocomplete="list" id="base-ui-_r_0_" data-slot="combobox-input" data-testid="input" placeholder="Search fruits..." class="astw:border-input astw:bg-background astw:text-foreground astw:placeholder:text-muted-foreground astw:flex astw:h-9 astw:w-full astw:rounded-md astw:border astw:px-3 astw:py-1 astw:text-sm astw:shadow-xs astw:outline-none astw:transition-colors astw:focus-visible:border-ring astw:focus-visible:ring-ring/50 astw:focus-visible:ring-[3px] astw:disabled:cursor-not-allowed astw:disabled:opacity-50" type="text" value=""><input id="base-ui-_r_0_-hidden-input" style="clip-path: inset(50%); overflow: hidden; white-space: nowrap; border: 0px; padding: 0px; width: 1px; height: 1px; margin: -1px; position: fixed; top: 0px; left: 0px;" tabindex="-1" aria-hidden="true" value="">"`;
46

57
exports[`Combobox.Parts > snapshots > open combobox 1`] = `"<div data-base-ui-inert=""><span role="button" aria-label="Dismiss" style="clip-path: inset(50%); overflow: hidden; white-space: nowrap; border: 0px; padding: 0px; width: 1px; height: 1px; margin: -1px; position: absolute;"></span><input data-list-empty="" autocomplete="off" spellcheck="false" autocorrect="off" autocapitalize="none" role="combobox" aria-expanded="true" aria-haspopup="listbox" aria-autocomplete="list" id="base-ui-_r_3_" data-slot="combobox-input" data-testid="input" placeholder="Search fruits..." class="astw:border-input astw:bg-background astw:text-foreground astw:placeholder:text-muted-foreground astw:flex astw:h-9 astw:w-full astw:rounded-md astw:border astw:px-3 astw:py-1 astw:text-sm astw:shadow-xs astw:outline-none astw:transition-colors astw:focus-visible:border-ring astw:focus-visible:ring-ring/50 astw:focus-visible:ring-[3px] astw:disabled:cursor-not-allowed astw:disabled:opacity-50" type="text" value="a" data-popup-open="" data-pressed="" data-popup-side="bottom" aria-controls="_r_4_"><input id="base-ui-_r_3_-hidden-input" style="clip-path: inset(50%); overflow: hidden; white-space: nowrap; border: 0px; padding: 0px; width: 1px; height: 1px; margin: -1px; position: fixed; top: 0px; left: 0px;" tabindex="-1" aria-hidden="true" value=""></div><div id="_r_6_" data-base-ui-portal="" style="position: relative; z-index: var(--z-popup);"><div data-open="" data-side="bottom" data-align="center" data-empty="" role="presentation" style="position: absolute; left: 0px; top: 0px; transform: translate(0px, 0px); --available-width: -10px; --available-height: -11px; --anchor-width: 0px; --anchor-height: 0px; --transform-origin: 0px 0px;" data-anchor-hidden=""><div data-open="" data-side="bottom" data-align="center" data-empty="" role="presentation" tabindex="-1" data-slot="combobox-content" class="astw:bg-popover astw:text-popover-foreground astw:data-open:animate-in astw:data-ending-style:animate-out astw:data-ending-style:fade-out-0 astw:data-open:fade-in-0 astw:data-ending-style:zoom-out-95 astw:data-open:zoom-in-95 astw:z-(--z-popup) astw:w-[var(--anchor-width)] astw:min-w-32 astw:origin-(--transform-origin) astw:overflow-hidden astw:rounded-md astw:border astw:shadow-md" data-anchor-hidden=""><div data-empty="" tabindex="-1" data-base-ui-focusable="" aria-orientation="vertical" role="listbox" id="_r_4_" data-slot="combobox-list" class="astw:max-h-60 astw:overflow-y-auto astw:p-1"><div role="option" id="base-ui-_r_3_-0" aria-selected="false" data-slot="combobox-item" class="astw:relative astw:flex astw:w-full astw:cursor-default astw:items-center astw:gap-2 astw:rounded-sm astw:py-1.5 astw:pr-8 astw:pl-2 astw:text-sm astw:outline-hidden astw:select-none astw:data-highlighted:bg-accent astw:data-highlighted:text-accent-foreground astw:data-disabled:pointer-events-none astw:data-disabled:opacity-50"><span class="astw:absolute astw:right-2 astw:flex astw:size-3.5 astw:items-center astw:justify-center"></span>Apple</div><div role="option" id="base-ui-_r_3_-1" aria-selected="false" data-slot="combobox-item" class="astw:relative astw:flex astw:w-full astw:cursor-default astw:items-center astw:gap-2 astw:rounded-sm astw:py-1.5 astw:pr-8 astw:pl-2 astw:text-sm astw:outline-hidden astw:select-none astw:data-highlighted:bg-accent astw:data-highlighted:text-accent-foreground astw:data-disabled:pointer-events-none astw:data-disabled:opacity-50"><span class="astw:absolute astw:right-2 astw:flex astw:size-3.5 astw:items-center astw:justify-center"></span>Banana</div><div role="option" id="base-ui-_r_3_-2" aria-selected="false" data-slot="combobox-item" class="astw:relative astw:flex astw:w-full astw:cursor-default astw:items-center astw:gap-2 astw:rounded-sm astw:py-1.5 astw:pr-8 astw:pl-2 astw:text-sm astw:outline-hidden astw:select-none astw:data-highlighted:bg-accent astw:data-highlighted:text-accent-foreground astw:data-disabled:pointer-events-none astw:data-disabled:opacity-50"><span class="astw:absolute astw:right-2 astw:flex astw:size-3.5 astw:items-center astw:justify-center"></span>Cherry</div><div role="option" id="base-ui-_r_3_-3" aria-selected="false" data-slot="combobox-item" class="astw:relative astw:flex astw:w-full astw:cursor-default astw:items-center astw:gap-2 astw:rounded-sm astw:py-1.5 astw:pr-8 astw:pl-2 astw:text-sm astw:outline-hidden astw:select-none astw:data-highlighted:bg-accent astw:data-highlighted:text-accent-foreground astw:data-disabled:pointer-events-none astw:data-disabled:opacity-50"><span class="astw:absolute astw:right-2 astw:flex astw:size-3.5 astw:items-center astw:justify-center"></span>Date</div><div role="option" id="base-ui-_r_3_-4" aria-selected="false" data-slot="combobox-item" class="astw:relative astw:flex astw:w-full astw:cursor-default astw:items-center astw:gap-2 astw:rounded-sm astw:py-1.5 astw:pr-8 astw:pl-2 astw:text-sm astw:outline-hidden astw:select-none astw:data-highlighted:bg-accent astw:data-highlighted:text-accent-foreground astw:data-disabled:pointer-events-none astw:data-disabled:opacity-50"><span class="astw:absolute astw:right-2 astw:flex astw:size-3.5 astw:items-center astw:justify-center"></span>Elderberry</div><div role="status" aria-live="polite" aria-atomic="true" data-slot="combobox-empty" class="astw:px-4 astw:pt-2 astw:pb-4 astw:text-center astw:text-sm astw:text-muted-foreground astw:empty:hidden">No results found⁠</div></div></div><span role="button" aria-label="Dismiss" style="clip-path: inset(50%); overflow: hidden; white-space: nowrap; border: 0px; padding: 0px; width: 1px; height: 1px; margin: -1px; position: absolute;"></span></div></div>"`;

0 commit comments

Comments
 (0)