- Prop
groups- Type
CommandGroup[]- Default
- —
- Requirement
- required
- Description
- —
Docs Components Navigation
Command
React example follows below.
Vue example follows below.
Angular example follows below.
Svelte example follows below.
Solid example follows below.
- parts
- —
- nodes
- —
- size
- —
- part
- —
ts
import * as React from "react";/** * Command palette fixture. `groups` is the shared catalogue every adapter * renders; `query` and `activeIndex` pin the filtered state the * five-framework render proof compares (typing "de" drops the Navigate group * entirely and leaves two Actions rows, of which the second is active). * * Every item carries an explicit `value`: React's search-text extractor is * `value ?? (typeof label === "string" ? label : "")` while the other four * use ui-core's `defaultCommandSearchText` (`value ?? label`), so pinning * `value` makes the filter identical by construction rather than by * coincidence. */const commandFixture = { id: "command", trigger: "Open command palette", placeholder: "Search commands…", query: "de", activeIndex: 1, groups: [ { heading: "Navigate", items: [ { label: "Go to dashboard", value: "dashboard", shortcut: "G D" }, { label: "Go to settings", value: "settings", shortcut: "G S" }, ], }, { heading: "Actions", items: [ { label: "Deploy ledger-api", value: "deploy", shortcut: "⌘ ⏎" }, { label: "Redeploy last build", value: "redeploy" }, { label: "Roll back release", value: "rollback", shortcut: "⌘ R" }, ], }, ],} satisfies { id: string; trigger: string; placeholder: string; query: string; activeIndex: number; groups: readonly { heading: string; items: readonly { label: string; value: string; shortcut?: string }[]; }[];}; import { Button, Command, type CommandGroup } from "@grassroot/ui-react"; /** * Command is a full-viewport overlay, so — like DialogExample — the canonical * example is the closed palette behind its trigger: mounting it already open * would blanket the catalogue page. The open/filtered state is pinned by the * fixture (`query`, `activeIndex`) and proved in each adapter's own test. */export default function CommandDemo() { const [open, setOpen] = React.useState(false); const groups: CommandGroup[] = commandFixture.groups.map((group) => ({ heading: group.heading, items: group.items.map((item) => ({ label: item.label, value: item.value, shortcut: item.shortcut, })), })); return ( <div> <Button onClick={() => setOpen(true)}>{commandFixture.trigger}</Button> <Command groups={groups} open={open} onOpenChange={setOpen} placeholder={commandFixture.placeholder} /> </div> );}- parts
- —
- nodes
- —
- size
- —
- part
- —
ts
<script setup lang="ts">import { ref } from "vue";/** * Command palette fixture. `groups` is the shared catalogue every adapter * renders; `query` and `activeIndex` pin the filtered state the * five-framework render proof compares (typing "de" drops the Navigate group * entirely and leaves two Actions rows, of which the second is active). * * Every item carries an explicit `value`: React's search-text extractor is * `value ?? (typeof label === "string" ? label : "")` while the other four * use ui-core's `defaultCommandSearchText` (`value ?? label`), so pinning * `value` makes the filter identical by construction rather than by * coincidence. */const commandFixture = { id: "command", trigger: "Open command palette", placeholder: "Search commands…", query: "de", activeIndex: 1, groups: [ { heading: "Navigate", items: [ { label: "Go to dashboard", value: "dashboard", shortcut: "G D" }, { label: "Go to settings", value: "settings", shortcut: "G S" }, ], }, { heading: "Actions", items: [ { label: "Deploy ledger-api", value: "deploy", shortcut: "⌘ ⏎" }, { label: "Redeploy last build", value: "redeploy" }, { label: "Roll back release", value: "rollback", shortcut: "⌘ R" }, ], }, ],} satisfies { id: string; trigger: string; placeholder: string; query: string; activeIndex: number; groups: readonly { heading: string; items: readonly { label: string; value: string; shortcut?: string }[]; }[];}; import { Button, Command } from "@grassroot/ui-vue"; const open = ref(false);</script> <template> <div> <Button @click="open = true">{{ commandFixture.trigger }}</Button> <Command v-model:open="open" :groups="commandFixture.groups" :placeholder="commandFixture.placeholder" /> </div></template>- parts
- —
- nodes
- —
- size
- —
- part
- —
ts
import { Component, signal } from "@angular/core";/** * Command palette fixture. `groups` is the shared catalogue every adapter * renders; `query` and `activeIndex` pin the filtered state the * five-framework render proof compares (typing "de" drops the Navigate group * entirely and leaves two Actions rows, of which the second is active). * * Every item carries an explicit `value`: React's search-text extractor is * `value ?? (typeof label === "string" ? label : "")` while the other four * use ui-core's `defaultCommandSearchText` (`value ?? label`), so pinning * `value` makes the filter identical by construction rather than by * coincidence. */const commandFixture = { id: "command", trigger: "Open command palette", placeholder: "Search commands…", query: "de", activeIndex: 1, groups: [ { heading: "Navigate", items: [ { label: "Go to dashboard", value: "dashboard", shortcut: "G D" }, { label: "Go to settings", value: "settings", shortcut: "G S" }, ], }, { heading: "Actions", items: [ { label: "Deploy ledger-api", value: "deploy", shortcut: "⌘ ⏎" }, { label: "Redeploy last build", value: "redeploy" }, { label: "Roll back release", value: "rollback", shortcut: "⌘ R" }, ], }, ],} satisfies { id: string; trigger: string; placeholder: string; query: string; activeIndex: number; groups: readonly { heading: string; items: readonly { label: string; value: string; shortcut?: string }[]; }[];}; import { GrassrootButton, GrassrootCommand } from "@grassroot/ui-angular"; @Component({ selector: "app-command-demo", standalone: true, imports: [GrassrootButton, GrassrootCommand], template: ` <div> <grassroot-button (click)="open.set(true)">{{ fixture.trigger }}</grassroot-button> <grassroot-command [groups]="fixture.groups" [(open)]="open" [placeholder]="fixture.placeholder" /> </div> `,})export class CommandDemoComponent { protected readonly fixture = commandFixture; protected readonly open = signal(false);} export default CommandDemoComponent;- parts
- —
- nodes
- —
- size
- —
- part
- —
ts
<script lang="ts"> import { Button, Command } from "@grassroot/ui-svelte"; /** * Command palette fixture. `groups` is the shared catalogue every adapter * renders; `query` and `activeIndex` pin the filtered state the * five-framework render proof compares (typing "de" drops the Navigate group * entirely and leaves two Actions rows, of which the second is active). * * Every item carries an explicit `value`: React's search-text extractor is * `value ?? (typeof label === "string" ? label : "")` while the other four * use ui-core's `defaultCommandSearchText` (`value ?? label`), so pinning * `value` makes the filter identical by construction rather than by * coincidence. */ const commandFixture = { id: "command", trigger: "Open command palette", placeholder: "Search commands…", query: "de", activeIndex: 1, groups: [ { heading: "Navigate", items: [ { label: "Go to dashboard", value: "dashboard", shortcut: "G D" }, { label: "Go to settings", value: "settings", shortcut: "G S" }, ], }, { heading: "Actions", items: [ { label: "Deploy ledger-api", value: "deploy", shortcut: "⌘ ⏎" }, { label: "Redeploy last build", value: "redeploy" }, { label: "Roll back release", value: "rollback", shortcut: "⌘ R" }, ], }, ], } satisfies { id: string; trigger: string; placeholder: string; query: string; activeIndex: number; groups: readonly { heading: string; items: readonly { label: string; value: string; shortcut?: string }[]; }[]; }; let open = $state(false);</script> <div> <Button onClick={() => (open = true)}>{commandFixture.trigger}</Button> <Command groups={commandFixture.groups} {open} onOpenChange={(next) => (open = next)} placeholder={commandFixture.placeholder} /></div>- parts
- —
- nodes
- —
- size
- —
- part
- —
ts
/** @jsxImportSource solid-js */import { createSignal } from "solid-js";import { Button, Command } from "@grassroot/ui-solid";/** * Command palette fixture. `groups` is the shared catalogue every adapter * renders; `query` and `activeIndex` pin the filtered state the * five-framework render proof compares (typing "de" drops the Navigate group * entirely and leaves two Actions rows, of which the second is active). * * Every item carries an explicit `value`: React's search-text extractor is * `value ?? (typeof label === "string" ? label : "")` while the other four * use ui-core's `defaultCommandSearchText` (`value ?? label`), so pinning * `value` makes the filter identical by construction rather than by * coincidence. */const commandFixture = { id: "command", trigger: "Open command palette", placeholder: "Search commands…", query: "de", activeIndex: 1, groups: [ { heading: "Navigate", items: [ { label: "Go to dashboard", value: "dashboard", shortcut: "G D" }, { label: "Go to settings", value: "settings", shortcut: "G S" }, ], }, { heading: "Actions", items: [ { label: "Deploy ledger-api", value: "deploy", shortcut: "⌘ ⏎" }, { label: "Redeploy last build", value: "redeploy" }, { label: "Roll back release", value: "rollback", shortcut: "⌘ R" }, ], }, ],} satisfies { id: string; trigger: string; placeholder: string; query: string; activeIndex: number; groups: readonly { heading: string; items: readonly { label: string; value: string; shortcut?: string }[]; }[];}; export default function CommandDemo() { const [open, setOpen] = createSignal(false); return ( <div> <Button onClick={() => setOpen(true)}>{commandFixture.trigger}</Button> <Command groups={commandFixture.groups.map((group) => ({ heading: group.heading, items: [...group.items], }))} open={open()} onOpenChange={setOpen} placeholder={commandFixture.placeholder} /> </div> );}Installation
API Reference
Import
import * as React from "react";
import { Button, Command, type CommandGroup } from "@grassroot/ui-react";
Props
Prop
Type
Default
Requirement
Description
groupsCommandGroup[]—
required
—
valuestring | undefined—
optional
—
defaultValuestring | undefined—
optional
—
onValueChange((value: string) => void) | undefined—
optional
—
querystring | undefined—
optional
—
defaultQuerystring | undefined—
optional
—
onQueryChange((query: string) => void) | undefined—
optional
—
openboolean | undefined—
optional
—
defaultOpenboolean | undefined—
optional
—
onOpenChange((open: boolean) => void) | undefined—
optional
—
filter((item: CommandItem, normalizedQuery: string) => boolean) | undefined—
optional
—
dir"ltr" | "rtl" | undefined—
optional
—
placeholderstring | undefined—
optional
—
hotkeyboolean | undefinedtrueoptional
Bind ⌘K / Ctrl-K to toggle open.
- Prop
value- Type
string | undefined- Default
- —
- Requirement
- optional
- Description
- —
- Prop
defaultValue- Type
string | undefined- Default
- —
- Requirement
- optional
- Description
- —
- Prop
onValueChange- Type
((value: string) => void) | undefined- Default
- —
- Requirement
- optional
- Description
- —
- Prop
query- Type
string | undefined- Default
- —
- Requirement
- optional
- Description
- —
- Prop
defaultQuery- Type
string | undefined- Default
- —
- Requirement
- optional
- Description
- —
- Prop
onQueryChange- Type
((query: string) => void) | undefined- Default
- —
- Requirement
- optional
- Description
- —
- Prop
open- Type
boolean | undefined- Default
- —
- Requirement
- optional
- Description
- —
- Prop
defaultOpen- Type
boolean | undefined- Default
- —
- Requirement
- optional
- Description
- —
- Prop
onOpenChange- Type
((open: boolean) => void) | undefined- Default
- —
- Requirement
- optional
- Description
- —
- Prop
filter- Type
((item: CommandItem, normalizedQuery: string) => boolean) | undefined- Default
- —
- Requirement
- optional
- Description
- —
- Prop
dir- Type
"ltr" | "rtl" | undefined- Default
- —
- Requirement
- optional
- Description
- —
- Prop
placeholder- Type
string | undefined- Default
- —
- Requirement
- optional
- Description
- —
- Prop
hotkey- Type
boolean | undefined- Default
true- Requirement
- optional
- Description
- Bind ⌘K / Ctrl-K to toggle open.
Events
| Event | Payload |
|---|---|
onValueChange | ((value: string) => void) | undefined |
onQueryChange | ((query: string) => void) | undefined |
onOpenChange | ((open: boolean) => void) | undefined |
Import
import { ref } from "vue";
import { Button, Command } from "@grassroot/ui-vue";
Props
Prop
Type
Default
Requirement
groupsreadonly PublicCommandGroup[]—
required
valuestringundefinedoptional
defaultValuestringundefinedoptional
querystringundefinedoptional
defaultQuerystringundefinedoptional
openboolean | undefinedundefinedoptional
defaultOpenbooleanfalseoptional
filter(item: VueCommandItem["original"], query: string) => booleanundefinedoptional
dir"ltr" | "rtl"undefinedoptional
placeholderstring"Type a command…"optional
hotkeybooleantrueoptional
- Prop
groups- Type
readonly PublicCommandGroup[]- Default
- —
- Requirement
- required
- Prop
value- Type
string- Default
undefined- Requirement
- optional
- Prop
defaultValue- Type
string- Default
undefined- Requirement
- optional
- Prop
query- Type
string- Default
undefined- Requirement
- optional
- Prop
defaultQuery- Type
string- Default
undefined- Requirement
- optional
- Prop
open- Type
boolean | undefined- Default
undefined- Requirement
- optional
- Prop
defaultOpen- Type
boolean- Default
false- Requirement
- optional
- Prop
filter- Type
(item: VueCommandItem["original"], query: string) => boolean- Default
undefined- Requirement
- optional
- Prop
dir- Type
"ltr" | "rtl"- Default
undefined- Requirement
- optional
- Prop
placeholder- Type
string- Default
"Type a command…"- Requirement
- optional
- Prop
hotkey- Type
boolean- Default
true- Requirement
- optional
Events
| Event | Payload |
|---|---|
update:open | (_open: boolean) => true |
update:value | (_value: string) => true |
update:query | (_query: string) => true |
Import
import { Component, signal } from "@angular/core";
import { GrassrootButton, GrassrootCommand } from "@grassroot/ui-angular";
Props
Prop
Type
Default
Requirement
groupsreadonly CoreCommandGroup<AngularCommandItem>[]—
required
valuestring—
optional
defaultValuestring—
optional
openboolean—
optional
defaultOpenbooleanfalseoptional
querystring—
optional
defaultQuerystring—
optional
filterCommandFilter<AngularCommandItem>—
optional
dir"ltr" | "rtl"—
optional
placeholderstring"Type a command…"optional
hotkeybooleantrueoptional
- Prop
groups- Type
readonly CoreCommandGroup<AngularCommandItem>[]- Default
- —
- Requirement
- required
- Prop
value- Type
string- Default
- —
- Requirement
- optional
- Prop
defaultValue- Type
string- Default
- —
- Requirement
- optional
- Prop
open- Type
boolean- Default
- —
- Requirement
- optional
- Prop
defaultOpen- Type
boolean- Default
false- Requirement
- optional
- Prop
query- Type
string- Default
- —
- Requirement
- optional
- Prop
defaultQuery- Type
string- Default
- —
- Requirement
- optional
- Prop
filter- Type
CommandFilter<AngularCommandItem>- Default
- —
- Requirement
- optional
- Prop
dir- Type
"ltr" | "rtl"- Default
- —
- Requirement
- optional
- Prop
placeholder- Type
string- Default
"Type a command…"- Requirement
- optional
- Prop
hotkey- Type
boolean- Default
true- Requirement
- optional
Events
| Event | Payload |
|---|---|
valueChange | string |
openChange | boolean |
queryChange | string |
Import
import { Button, Command } from "@grassroot/ui-svelte";
Props
Prop
Type
Default
Requirement
groupsreadonly PublicCommandGroup[]—
required
openboolean—
optional
defaultOpenbooleanfalseoptional
valuestring—
optional
defaultValuestring—
optional
querystring—
optional
defaultQuerystring—
optional
filterCommandMachineInput["filter"]—
optional
dir"ltr" | "rtl"—
optional
placeholderstring"Type a command…"optional
hotkeybooleantrueoptional
onOpenChange(open: boolean) => void—
optional
onValueChange(value: string) => void—
optional
onQueryChange(query: string) => void—
optional
- Prop
groups- Type
readonly PublicCommandGroup[]- Default
- —
- Requirement
- required
- Prop
open- Type
boolean- Default
- —
- Requirement
- optional
- Prop
defaultOpen- Type
boolean- Default
false- Requirement
- optional
- Prop
value- Type
string- Default
- —
- Requirement
- optional
- Prop
defaultValue- Type
string- Default
- —
- Requirement
- optional
- Prop
query- Type
string- Default
- —
- Requirement
- optional
- Prop
defaultQuery- Type
string- Default
- —
- Requirement
- optional
- Prop
filter- Type
CommandMachineInput["filter"]- Default
- —
- Requirement
- optional
- Prop
dir- Type
"ltr" | "rtl"- Default
- —
- Requirement
- optional
- Prop
placeholder- Type
string- Default
"Type a command…"- Requirement
- optional
- Prop
hotkey- Type
boolean- Default
true- Requirement
- optional
- Prop
onOpenChange- Type
(open: boolean) => void- Default
- —
- Requirement
- optional
- Prop
onValueChange- Type
(value: string) => void- Default
- —
- Requirement
- optional
- Prop
onQueryChange- Type
(query: string) => void- Default
- —
- Requirement
- optional
Events
| Event | Payload |
|---|---|
onOpenChange | (open: boolean) => void |
onValueChange | (value: string) => void |
onQueryChange | (query: string) => void |
Import
import { createSignal } from "solid-js";
import { Button, Command } from "@grassroot/ui-solid";
Props
Prop
Type
Default
Requirement
groupsCommandGroup[]—
required
valuestring—
optional
defaultValuestring—
optional
onValueChange(value: string) => void—
optional
querystring—
optional
defaultQuerystring—
optional
onQueryChange(query: string) => void—
optional
openboolean—
optional
defaultOpenboolean—
optional
onOpenChange(open: boolean) => void—
optional
filter(item: CommandItem, normalizedQuery: string) => boolean—
optional
dir"ltr" | "rtl"—
optional
placeholderstring"Type a command…"optional
hotkeybooleantrueoptional
- Prop
groups- Type
CommandGroup[]- Default
- —
- Requirement
- required
- Prop
value- Type
string- Default
- —
- Requirement
- optional
- Prop
defaultValue- Type
string- Default
- —
- Requirement
- optional
- Prop
onValueChange- Type
(value: string) => void- Default
- —
- Requirement
- optional
- Prop
query- Type
string- Default
- —
- Requirement
- optional
- Prop
defaultQuery- Type
string- Default
- —
- Requirement
- optional
- Prop
onQueryChange- Type
(query: string) => void- Default
- —
- Requirement
- optional
- Prop
open- Type
boolean- Default
- —
- Requirement
- optional
- Prop
defaultOpen- Type
boolean- Default
- —
- Requirement
- optional
- Prop
onOpenChange- Type
(open: boolean) => void- Default
- —
- Requirement
- optional
- Prop
filter- Type
(item: CommandItem, normalizedQuery: string) => boolean- Default
- —
- Requirement
- optional
- Prop
dir- Type
"ltr" | "rtl"- Default
- —
- Requirement
- optional
- Prop
placeholder- Type
string- Default
"Type a command…"- Requirement
- optional
- Prop
hotkey- Type
boolean- Default
true- Requirement
- optional
Events
| Event | Payload |
|---|---|
onValueChange | (value: string) => void |
onQueryChange | (query: string) => void |
onOpenChange | (open: boolean) => void |