Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
54abe1c
feat: item actions
tenphi Oct 22, 2025
b21639e
Merge remote-tracking branch 'origin' into feat-item-button-with-actions
tenphi Oct 22, 2025
cb011d8
feat(ItemButton): show actions on hover flag
tenphi Oct 22, 2025
6790457
fix(ItemButton): minor
tenphi Oct 23, 2025
51a83d1
fix(ItemBase): description logic
tenphi Oct 23, 2025
c202b09
fix(Tooltip): disabled logic
tenphi Oct 23, 2025
5283d57
fix(Tooltip): disabled logic * 2
tenphi Oct 23, 2025
645b65e
fix(Tooltip): dynamic label case
tenphi Oct 23, 2025
f9ee5db
fix(ItemBase): default size
tenphi Oct 23, 2025
bfe8eaf
fix(ItemBase): default size * 2
tenphi Oct 23, 2025
4cb5120
fix(ItemAction): type from context
tenphi Oct 23, 2025
bed8032
fix(ItemBase): return inline size
tenphi Oct 23, 2025
f1907e3
fix: popover height limit
tenphi Oct 23, 2025
e5eed62
fix(ItemButton): styles desctruct
tenphi Oct 23, 2025
5f625b5
feat(ItemAction): brand new component
tenphi Oct 24, 2025
c239d29
fix(ItemAction): theme support
tenphi Oct 24, 2025
726bb87
fix(ItemAction): theme support * 2
tenphi Oct 24, 2025
f402373
fix(DateInputBase): suffix
tenphi Oct 24, 2025
b78ff54
fix(ComboBox): overlay props
tenphi Oct 24, 2025
e8b7e14
feat(ItemBadge): add component
tenphi Oct 24, 2025
232ee9c
fix(ItemBase): description padding
tenphi Oct 24, 2025
82865ba
fix(ItemBase): add isCard prop
tenphi Oct 24, 2025
91a5088
chore: add changeset
tenphi Oct 24, 2025
9377bd6
fix(ItemBase): side padding
tenphi Oct 24, 2025
a06d452
fix(ItemBase): actions sizing
tenphi Oct 24, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/big-pugs-deny.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@cube-dev/ui-kit": minor
---

Allow to add actions to Item, ItemButton, and ItemBase.
5 changes: 5 additions & 0 deletions .changeset/dry-carrots-double.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@cube-dev/ui-kit": minor
---

Add ItemBadge component.
5 changes: 5 additions & 0 deletions .changeset/large-spies-decide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@cube-dev/ui-kit": patch
---

Add isCard flag to ItemBase component.
5 changes: 5 additions & 0 deletions .changeset/sour-toys-accept.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@cube-dev/ui-kit": patch
---

Fix popover height limit for Select and ComboBox.
10 changes: 9 additions & 1 deletion src/components/Item.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { ReactElement } from 'react';
import { Item, ItemProps } from 'react-stately';

import { ItemAction } from './actions/ItemAction';
import { ItemBadge } from './content/ItemBadge';
import { CubeItemBaseProps } from './content/ItemBase/ItemBase';

export interface CubeItemProps<T>
Expand All @@ -11,6 +13,12 @@ export interface CubeItemProps<T>
[key: string]: any;
}

const _Item = Item as <T>(props: CubeItemProps<T>) => ReactElement;
const _Item = Object.assign(
Item as <T>(props: CubeItemProps<T>) => ReactElement,
{
Action: ItemAction,
Badge: ItemBadge,
},
);

export { _Item as Item };
107 changes: 107 additions & 0 deletions src/components/actions/CommandMenu/CommandMenu.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
import {
IconArrowBack,
IconArrowForward,
IconBook,
IconBulb,
IconClipboard,
IconCopy,
IconCut,
IconPlus,
IconReload,
IconSelect,
} from '@tabler/icons-react';
import React, { useState } from 'react';
import { expect, findByRole, userEvent, waitFor, within } from 'storybook/test';

import { ClearIcon, EditIcon } from '../../../icons';
import { tasty } from '../../../tasty';
import { Card } from '../../content/Card/Card';
import { HotKeys } from '../../content/HotKeys';
Expand All @@ -23,6 +28,7 @@ import {
useDialogContainer,
} from '../../overlays/Dialog';
import { Button } from '../Button';
import { ItemAction } from '../ItemAction';
import { Menu } from '../Menu/Menu';
import { useAnchoredMenu } from '../use-anchored-menu';
import { useContextMenu } from '../use-context-menu';
Expand Down Expand Up @@ -376,6 +382,107 @@ WithSections.args = {
width: '20x 50x',
};

export const ItemsWithActions = (props) => {
const handleAction = (key) => {
console.log('CommandMenu action:', key);
};

const handleItemAction = (itemKey, actionKey) => {
console.log(`Action "${actionKey}" triggered on item "${itemKey}"`);
};

return (
<CommandMenu
id="command-menu-with-actions"
{...props}
searchPlaceholder="Search files..."
autoFocus={true}
width="20x 50x"
onAction={handleAction}
>
<CommandMenu.Item
key="file1"
icon={<IconBook />}
description="PDF document"
actions={
<>
<ItemAction
icon={<EditIcon />}
aria-label="Edit"
onPress={() => handleItemAction('file1', 'edit')}
/>
<ItemAction
icon={<ClearIcon />}
aria-label="Delete"
onPress={() => handleItemAction('file1', 'delete')}
/>
</>
}
>
Document.pdf
</CommandMenu.Item>
<CommandMenu.Item
key="file2"
icon={<IconReload />}
description="Backup file"
actions={
<>
<ItemAction
icon={<EditIcon />}
aria-label="Edit"
onPress={() => handleItemAction('file2', 'edit')}
/>
<ItemAction
icon={<ClearIcon />}
aria-label="Delete"
onPress={() => handleItemAction('file2', 'delete')}
/>
</>
}
>
Backup.zip
</CommandMenu.Item>
<CommandMenu.Item
key="file3"
icon={<IconPlus />}
description="New file"
actions={
<>
<ItemAction
icon={<EditIcon />}
aria-label="Edit"
onPress={() => handleItemAction('file3', 'edit')}
/>
<ItemAction
icon={<ClearIcon />}
aria-label="Delete"
onPress={() => handleItemAction('file3', 'delete')}
/>
</>
}
>
Project.doc
</CommandMenu.Item>
<CommandMenu.Item
key="file4"
icon={<IconBulb />}
description="No actions"
>
Item without actions
</CommandMenu.Item>
</CommandMenu>
);
};

ItemsWithActions.parameters = {
docs: {
description: {
story:
'Demonstrates CommandMenu.Item with inline actions. Actions are displayed on the right side of each item and inherit the item type through ItemActionProvider context. Search to filter items and hover to see the actions.',
},
},
};

export const WithMenuTrigger: StoryFn<CubeCommandMenuProps<any>> = (args) => (
<CommandMenu.Trigger>
<Button>Open Command Palette</Button>
Expand Down
Loading
Loading