GridCue
API reference

React

gridcue/react — the useGridCue hook, the GridCueBar command bar, and the CSS variables in gridcue/styles.css.

gridcue/react binds a GridCue Controller to React. useGridCue gives you the Controller's state and actions with no styling, for building your own UI. GridCueBar is a ready-made command bar styled by gridcue/styles.css that works in any React app, with or without Tailwind. React 19 or later is required.

import { APPLY_SHORTCUT, GridCueBar, STATUS_LABEL, useGridCue } from "gridcue/react";
import type { GridCueBarProps, GridCueBinding } from "gridcue/react";

useGridCue

function useGridCue(controller: GridCueController): GridCueBinding;

Subscribes a component to a GridCue Controller with useSyncExternalStore and returns its state plus its actions. It adds no styling and holds no credentials. Create the Controller once, outside render or in a useState initializer, and pass it in.

GridCueBinding

interface GridCueBinding extends ControllerState {
  propose: GridCueController["propose"];
  answer: GridCueController["answer"];
  apply: GridCueController["apply"];
  cancel: GridCueController["cancel"];
  undo: GridCueController["undo"];
  onInputKeyDown: (event: { key: string; metaKey: boolean; ctrlKey: boolean; preventDefault(): void }) => void;
}
NameTypeDescription
statusInteractionStatusWhere the current request is.
utterancestringThe text of the current request.
planViewPlan | nullThe compiled View Plan. Read plan.clarifications to render a Clarification.
previewPreview | nullWhat the plan will change: lines (one per operation) and text.
messagestring | nullA short, User-facing message for the current status.
issuesIssue[]Problems found, each with a stable code.
canUndobooleanWhether the last apply can be undone right now.
propose(text, options?) => Promise<ViewPlan | null>Sends an Utterance.
answer(clarificationId, optionId) => ViewPlan | nullAnswers a Clarification.
apply() => Promise<boolean>Applies the ready plan.
cancel() => voidDrops the current request and keeps the text.
undo() => Promise<boolean>Undoes the last apply.
onInputKeyDown(event) => voidKeyboard behavior for the request input, shared by every GridCue UI: Escape cancels, and Ctrl+Enter or Cmd+Enter applies a ready Preview without leaving the input.

The state fields and actions are the Controller's own; see createGridCue for what each does. dispose is not included: call controller.dispose() yourself when the grid unmounts.

import { APPLY_SHORTCUT, STATUS_LABEL, useGridCue } from "gridcue/react";

function MyBar({ controller }: { controller: GridCueController }) {
  const cue = useGridCue(controller);
  const [text, setText] = useState("");
  return (
    <form onSubmit={(e) => { e.preventDefault(); void cue.propose(text); }}>
      <input value={text} onChange={(e) => setText(e.target.value)} onKeyDown={cue.onInputKeyDown} />
      <p role="status">{STATUS_LABEL[cue.status]} {cue.message}</p>
      {cue.status === "ready" && cue.preview && (
        <>
          <ul>{cue.preview.lines.map((line) => <li key={line}>{line}</li>)}</ul>
          <button type="button" aria-keyshortcuts={APPLY_SHORTCUT.aria} onClick={() => void cue.apply()}>Apply</button>
        </>
      )}
    </form>
  );
}

STATUS_LABEL

const STATUS_LABEL: Record<InteractionStatus, string>;

Short, non-color status labels shared by every GridCue UI:

StatusLabel
idle(empty)
resolvingWorking out your request…
readyReady to apply
needs_clarificationNeeds your input
unsupportedCan't do that
applyingApplying…
appliedApplied
errorSomething went wrong

APPLY_SHORTCUT

const APPLY_SHORTCUT = { aria: "Control+Enter Meta+Enter", label: "Ctrl/⌘ Enter" };

The shortcut that applies a ready Preview. Use aria for aria-keyshortcuts and label for a visible hint. The key handling itself lives in onInputKeyDown.

GridCueBar

function GridCueBar(props: GridCueBarProps): JSX.Element;

interface GridCueBarProps {
  controller: GridCueController;
  label?: string;
  placeholder?: string;
  className?: string;
}

A ready-made command bar styled by gridcue/styles.css. It renders the request input with a Preview button, a live status line, the Preview with Apply and Cancel, option buttons for a Clarification, an Edit request button when the request needs changing, and an Undo button while canUndo is true.

NameTypeDefaultDescription
controllerGridCueControllerrequiredThe Controller from createGridCue.
labelstring"Describe the view you want"Visible label for the input.
placeholderstring"e.g. taxable accounts over $1M, largest first"Placeholder text for the input.
classNamestringnoneExtra class names, added after gridcue-bar on the outer section.
import { GridCueBar } from "gridcue/react";
import "gridcue/styles.css";

<GridCueBar controller={cue} label="Ask the accounts grid" className="my-bar" />

Accessibility built in: the status line is a polite live region the input points to with aria-describedby; the section sets aria-busy while resolving or applying; Apply carries aria-keyshortcuts; and the Preview button is disabled while busy or when the input is empty. Only the first Clarification's options are shown at a time.

For more on the bar and the other UI pieces, see GridCueBar in Components.

Styles and CSS variables

Import the stylesheet once:

import "gridcue/styles.css";

Every rule is scoped to gridcue- classes. The custom properties below are set on .gridcue-bar; override them to match your app. Pair .gridcue-bar with a class you pass through className, as in the example, so your values win over both the light and dark defaults whatever order the stylesheets load in.

VariableLight defaultDark defaultUsed for
--gridcue-bg#ffffff#111827Bar background
--gridcue-fg#111827#f9fafbText
--gridcue-muted#4b5563#d1d5dbStatus line, notes and hints
--gridcue-border#d1d5db#374151Input and button borders, panel divider
--gridcue-hoveroklch(0 0 0 / 0.04)oklch(1 0 0 / 0.06)Button hover background
--gridcue-accent#2563eb#60a5faApply button, focus ring
--gridcue-accent-hover#1d4ed8#93c5fdApply button hover
--gridcue-accent-fg#ffffff#111827Apply button text
--gridcue-radius6pxsameInput and button corner radius
--gridcue-pad12pxsameBar padding
--gridcue-gap8pxsameSpace between rows and buttons
--gridcue-fontinheritsameFont family
--gridcue-shadowa 1px ring plus two soft shadows0 0 0 1px oklch(1 0 0 / 0.08)Bar depth

The dark defaults apply under prefers-color-scheme: dark. The bar's outer radius is --gridcue-radius plus --gridcue-pad, so the corners stay concentric when you change either.

/* <GridCueBar controller={cue} className="my-bar" /> */
.gridcue-bar.my-bar {
  --gridcue-accent: #0f766e;
  --gridcue-accent-hover: #115e59;
  --gridcue-radius: 4px;
  --gridcue-font: "Inter", sans-serif;
}

The classes it uses, for finer overrides: gridcue-bar, gridcue-form, gridcue-label, gridcue-row, gridcue-input, gridcue-button, gridcue-primary, gridcue-status (with a data-status attribute set to the current status), gridcue-status-label, gridcue-message, gridcue-panel, gridcue-fieldset, gridcue-heading, gridcue-list, gridcue-note, gridcue-actions and gridcue-hint.

On this page