Command Palette
لوحة الأوامرrole="dialog" + role="combobox"
also calledcommand bar، command menu، quick open، Cmd+K menu، quick switcher، action launcher، كوماند باليت، شريط الأوامر، صندوق الأوامر السريع، قائمة الإجراءات السريعة، نافذة Cmd+K، التنقّل السريع
A command palette is a blocking dialog opened by a keyboard shortcut, holding one input whose typing narrows a list of commands that run on the spot. What comes out of it is an action, never a value: Enter makes something happen (a file opens, the theme changes, a task is created) and the field keeps nothing. A search field is different, because it returns content for the user to read and judge while the palette acts for you. A menu is different too, since it shows its items in full and you walk them with arrow keys without typing, while a palette starts from the assumption that the command list is far too long to display. A combobox is the closest of the three and still not the same: it deposits a chosen value into a field and hands the user back to the form, and the palette closes itself because the command already ran. One question settles it: what is left after Enter? A page of results means search, a value sitting in a field means combobox, and a changed application state means command palette.
If you called it…
Live specimen
Interact with the demo. Every part is real and numbered.
Anatomy: every part, named
Hover a row to locate it in the demo above.
Build prompt
How it behaves right-to-left
This section is ours alone.
Isolating the command label
never mirrorsThe rows run RTL while command names arrive mixed: "فتح Pull Request جديد", or a label ending in PDF. Neutral characters touching the Latin run (colons, brackets, an ellipsis, a slash) join the Arabic text around them and move to the far end of the line. Wrap every label in <bdi>, which carries dir="auto" and unicode-bidi: isolate together and turns that label into a direction unit of its own that nothing outside can reorder. Do not settle for dir="auto" on the list container: the algorithm takes the direction from the first strong character inside the element, so every row inherits the direction of the first one.
The shortcut hint inside a row
mirrorsThe hint sits at the logical end of the row, which puts it on the left in Arabic: use margin-inline-start: auto inside the flex row, never margin-left: auto and never a float. The order of the keys inside the hint mirrors nothing, and the glyphs command, shift and option are all bidi class ON (other neutral) in Unicode, so in an Arabic context they take the paragraph direction, detach from the Latin letter after them, and render with the symbol to the right of the letter instead of the left. Put dir="ltr" on the key container, or wrap it in <bdi dir="ltr">. If each key is its own <kbd> in a flex row, the inline axis itself flips and shows K before the command glyph: the fix is direction: ltr on the container, not flex-direction: row-reverse.
The direction of the command field
mirrorsDo not pin dir="rtl" on the command field. People in an Arabic palette type settings and PDF in Latin, and in a field locked to rtl the trailing dot, slash or bracket joins the Arabic paragraph and jumps to the opposite end of the field. Put dir="auto" on the input itself: HTML resolves an input direction from the first strong character of its value, and falls back to the parent element while the value is empty, so the Arabic placeholder stays on the right and the field turns ltr on the first Latin letter. A dir="auto" on the wrapper around the input does nothing at all, because that computation walks text content and never sees the value of an input.
The highlighted row indicator
mirrorsThe thin bar marking the active row stands at the logical start of that row: either a ::before pinned with inset-inline-start: 0, or border-inline-start-width: 2px on the row itself with a transparent colour on the others so the text does not shift as the highlight moves. Do not draw it with box-shadow: inset 2px 0, because shadow offsets are purely physical and CSS gives them no logical form, so the bar stays on the wrong side after the flip. The command icon follows the same logical start through flex order and never needs a margin-right.
The shortcut on an Arabic layout
never mirrorsMatching a press with event.key === "k" breaks for an Arabic user: event.key carries the character the layout produces, and the key printed K on a standard Arabic layout produces ن. event.code describes the physical position and stays "KeyK" whatever the layout, so bind to that, or accept both values. The other half is display: what you print in the hint has to match the letter printed on the key the user is pressing, so read the character from navigator.keyboard.getLayoutMap() where it exists and fall back to the Latin letter, instead of hard-coding it from the code. None of this is a direction problem: the same rule holds for Persian, Hebrew, and every non-QWERTY layout.
In code
Each row is one framework's word for the same thing. Take the row your project speaks.
See also
Updated · 2026-08-19