[editor] Slash command runs the wrong command when category groups are displayed out of array order
What versions are you using? (if relevant)
@react-email/[email protected] (also reproduced on the canary branch @724af1e)
Describe the Bug
The slash command menu can run different item's commands, when the menu is opened without a query.
The docs' own "Custom commands" example triggers it:
const customCommands = [
...defaultSlashCommands,
{ title: 'Image', /* … */ category: 'Media', command: /* setImage */ },
];
<SlashCommand items={customCommands} />The menu shows the groups Text → Media → Layout, but clicking Image inserts a Button, clicking Button inserts a Divider, and so on. The last Layout row, 4 columns, inserts the Image.
Cause
ui/slash-command/command-list.tsx: with an empty query,groupByCategorymoves categories in the hard-codedCATEGORY_ORDER = ['Text', 'Media', 'Layout', 'Utility']to the front. Other categories follow in order of first appearance. Each row callsonSelect(flatIndex), which is its position in the grouped display order.ui/slash-command/root.tsx:onSelect(click) and the Enter handler resolveitems[index]against the original, ungrouped array.
So whenever the grouped order differs from the array order, the highlighted or clicked row and the executed command don't match. With a query typed, the list is flat and works correctly.
Real-world impact: we translate categories for a Danish UI (Text → Tekst, while Layout stays Layout). Layout is in CATEGORY_ORDER but Tekst isn't, so the Layout group is displayed first and almost every row runs the wrong command. For example, clicking "Billede" (Image) inserts a heading. The official examples don't hit this only because imageSlashCommand uses Layout.
Tested on 1.7.7 (latest stable) and the canary branch (the canary npm dist-tag, 1.0.0-canary.51, is older than 1.7.7). Not a regression: the grouping and index lookup have been like this since the editor was introduced in #3130.
Possible fix
- Group by order of first appearance (drop
CATEGORY_ORDER), so display order always equals array order for the default list, or - keep the ordering, but have
CommandListpass the item (or its index initems) toonSelect, and keep the Enter/Arrow navigation on the same display-ordered list.
Happy to open a PR with a test next to search.spec.ts.
What is affected (leave empty if unsure)
No response
Link to the code that reproduces this issue
https://github.com/phillip-propstep/react-email-slash-command-category-repro
To Reproduce
- Clone https://github.com/phillip-propstep/react-email-slash-command-category-repro, then run
npm installandnpm run dev. - Keep "Docs example (Image in "Media")" selected (the docs' "Custom commands" example, as-is).
- Click into the editor and type
/(no query). Groups are shown as Text → Media → Layout. - Click Image. The "Blocks in the document" line shows
button, and a Button is inserted. - Also try: ArrowDown to Image and press Enter (same result); click 4 columns (inserts the image); type
/imageand click Image (works). - Select "Translated category" to see every row offset; select "Control (Image in "Layout")" to see every row work.
Expected Behavior
Clicking or pressing Enter on a row runs that row's command, regardless of how categories are grouped or named. Clicking "Image" inserts an image.
What's your node version? (if relevant)
v22.23.1
Source: resend/react-email