Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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/fix-collection-item-types.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@cube-dev/ui-kit': patch
---

Fix the types of `FilterListBox.Item` and `CommandMenu.Item`. Both were declared as React Stately's bare `Item`, so `Item` props such as `icon`, `rightIcon`, `description`, `hotkeys` and `actions` were rejected by TypeScript even though they worked at runtime. They now use `CollectionItem`, matching `ListBox.Item`, `Menu.Item` and the other collection components.
18 changes: 17 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,22 @@ Entry point for AI agents working on `@cube-dev/ui-kit`.

> **Maintenance note:** The design-system reference (tokens, presets, colors, modifiers, state syntax, form system, icons) lives in `src/stories/Usage.docs.mdx` (Storybook → **Getting Started / Usage**). The component creation guide lives in `src/stories/CreateComponent.docs.mdx` (**Getting Started / Create Component**). Update these whenever you add components, change the API surface, or modify tokens/presets.

## Before You Start

**Run this at the start of every task, before reading code, running tests, or trusting any type error:**

```bash
pnpm install && pnpm rebuild esbuild
```

A working copy can sit idle across dependency bumps, so `node_modules` may not match `pnpm-lock.yaml`. A stale tree does not fail loudly — it silently inverts results. Tests pass locally and fail on CI (or the reverse), and `tsc` reports errors that do not exist on the pinned version. Anything you conclude from a stale tree is unreliable, including the conclusion that a failure is "pre-existing".

When local results and CI disagree, suspect the dependency tree first. Compare the installed version against the lockfile before theorising about anything else:

```bash
pnpm list @tenphi/tasty @tenphi/glaze
```

## Rules

Project-specific working rules for AI agents. Not published with the package.
Expand Down Expand Up @@ -65,7 +81,7 @@ Each component lives in `src/components/{category}/{ComponentName}/` and ships `
## Environment

- Node `>=22.0.0`, pnpm `^10` (pinned to `pnpm@10.32.0`). The publish workflow (`publish.yml`) still runs on Node 24 because OIDC trusted publishing requires npm ≥ 11.5.1+, which Node 24 ships natively (Node 22 ships npm 10.x).
- After `pnpm install`, run `pnpm rebuild esbuild` (postinstall is blocked in `pnpm-workspace.yaml`).
- After `pnpm install`, run `pnpm rebuild esbuild` (postinstall is blocked in `pnpm-workspace.yaml`). Do this at the start of every task — see [Before You Start](#before-you-start).
- Husky hooks: `pre-commit` runs `pnpm lint-staged`; `pre-push` runs `pnpm test`. Skip only intentionally (`--no-verify` or `HUSKY=0`).
- No external services or databases required for local development.

Expand Down
6 changes: 4 additions & 2 deletions src/components/actions/CommandMenu/CommandMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@ import React, {
useState,
} from 'react';
import { useFilter, useMenu } from 'react-aria';
// Import Item and Section from Menu for CommandMenu compound component
import { Item, Section, useTreeState } from 'react-stately';
import { Section, useTreeState } from 'react-stately';

import { useI18n } from '../../../i18n';
import { LoadingIcon } from '../../../icons';
import { mergeProps } from '../../../utils/react';
import { extractStyles } from '../../../utils/styles';
// `CollectionItem` (not react-stately's bare `Item`) is what CommandMenu
// actually renders through `MenuItem`, so it carries the `Item` props.
import { CollectionItem as Item } from '../../CollectionItem';
import { TooltipProvider } from '../../overlays/Tooltip/TooltipProvider';
import { useMenuContext } from '../Menu';
import { CubeMenuProps } from '../Menu/Menu';
Expand Down
11 changes: 7 additions & 4 deletions src/components/fields/FilterListBox/FilterListBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,18 @@ import {
useState,
} from 'react';
import { useFilter, useKeyboard } from 'react-aria';
import { Section as BaseSection, Item, useListState } from 'react-stately';
import { CubeCollectionItemProps } from 'src/components/CollectionItem';
import { Section as BaseSection, useListState } from 'react-stately';

import { useI18n } from '../../../i18n';
import { LoadingIcon } from '../../../icons';
import { mergeProps, modAttrs, useCombinedRefs } from '../../../utils/react';
import { useFocus } from '../../../utils/react/interactions';
import { extractStyles } from '../../../utils/styles';
import { StyledHeader } from '../../actions/Menu/styled';
import {
CubeCollectionItemProps,
CollectionItem as Item,
} from '../../CollectionItem';
import { getValidationMods, useFieldProps, wrapWithField } from '../../form';
import { CubeListBoxProps, ListBox } from '../ListBox/ListBox';
import {
Expand Down Expand Up @@ -587,7 +590,7 @@ export const FilterListBox = forwardRef(function FilterListBox<
<Item
key={term}
textValue={term}
{...mergeProps(customValueProps, newCustomValueProps)}
{...mergeProps(customValueProps ?? {}, newCustomValueProps ?? {})}
>
{term}
</Item>
Expand Down Expand Up @@ -1166,7 +1169,7 @@ export const FilterListBox = forwardRef(function FilterListBox<
props: CubeFilterListBoxProps<T> & { ref?: ForwardedRef<HTMLDivElement> },
) => ReactElement) & { Item: typeof Item; Section: typeof BaseSection };

FilterListBox.Item = ListBox.Item;
FilterListBox.Item = Item;

FilterListBox.Section = BaseSection;

Expand Down
Loading