Design system

Mode Text Box

A chat input where the person picks what kind of request they are making before they type it.

import { ModeTextBox } from "@/ui";

Mode Text Box matches the Figma Mode Text Fields component. It is the workbook chat's input: a text field, a mode button that says what the request will do, and a send button. Each mode has its own placeholder, so the field explains what to type.

Default

Click the mode button to open the menu above it. The selected mode has a check. Type and press Enter or click send; Shift+Enter adds a new line.

import { Note, ChartScatter, Path, Play, Compass } from "@phosphor-icons/react";

const groups = [
  {
    label: "Create from Analysis",
    modes: [
      { id: "generate-memo", label: "Generate Memo", icon: Note,
        placeholder: "Generate a memo summarizing the key findings from this analysis" },
      { id: "create-chart", label: "Create Chart", icon: ChartScatter,
        placeholder: "Create a chart from the results of this analysis" },
      { id: "save-as-definition", label: "Save as Definition", icon: Path,
        placeholder: "Save the logic from this analysis as a reusable definition" },
    ],
  },
  {
    label: "Start New",
    modes: [
      { id: "quick-analysis", label: "Quick Analysis", icon: Play,
        placeholder: "Run a quick analysis to answer the following question" },
      { id: "build-analysis", label: "Build an Analysis", icon: Compass,
        placeholder: "Build a multi-step analysis to answer the following question" },
    ],
  },
];

<ModeTextBox
  groups={groups}
  defaultMode="quick-analysis"
  onSubmit={(text, mode) => run(mode, text)}
/>

onSubmit gets the trimmed text and the mode id, and the field clears. Send stays grey until there is text.

Modes that aren't available yet

Set disabled on a mode to show it greyed out in the menu. The workbook chat does this for the "Create from Analysis" modes until every analysis step has run.

{ id: "generate-memo", label: "Generate Memo", icon: Note, disabled: !analysisReady }

States

StateBoxMode buttonSend
DefaultWhite, Grey 200 borderWhite, Primary 500 border and textGrey 100, Grey 300 arrow
Mode (menu open)SamePrimary 50 fill, Primary 100 border, Primary 300 text, caret upSame
TypingPrimary 500 border while the field has focusSame as DefaultPrimary 500, white arrow once there is text
DisabledGrey 50 fillGrey 100 fill, Grey 300 textGrey 100

Pass disabled to lock the whole box, for example while a plan is still being built.

Anatomy

PartSizeStyle
BoxFills its container; 124px tall when empty8px top and bottom padding, 12px sides, 10px gap, 1px border, 8px radius, 0 8px 4px shadow at 8%
Field14px / 22px, at least 64px tallGrows with the text up to six lines, then scrolls. Placeholder in --color-text-disabled
Mode button32px tall, 20px radius, 12px sides12px text and icons, 6px gap
Send32 × 32px, 8px radius12px arrow
Menu200px wide, opens above the mode button4px padding, Grey 200 border, 8px radius, 0 8px 24px shadow at 10%
Group label12px / 19px medium--color-text-disabled, 2px × 6px padding. Groups after the first have a Grey 100 line above
Menu item14px / 22px, 6px × 12px padding16px icon, 8px gap, 4px radius, check on the right when selected

Props

PropTypeDefaultNotes
groups{ label?, modes: Mode[] }[][]Menu sections, in order.
modestringSelected mode id, if you control it.
defaultModestringFirst modeStarting mode when uncontrolled.
onModeChange(id) => void
valuestringText, if you control it.
defaultValuestring""
onChange(text) => void
onSubmit(text, modeId) => voidCalled on send or Enter.
disabledbooleanfalseLocks the field, the mode button and send.
placeholderstringThe mode'sOverrides every mode's placeholder.
classNamestringOther props are passed to the root too.

Each Mode has id, label, and optionally icon (a Phosphor component), placeholder and disabled.

Differences from Figma

  • In Figma, the Default memo example's button says "Generate Memo" and the other states say "Create Memo". Here the button always shows the mode's label, so it matches the menu item.
  • Figma has no hover states. Here the mode button and menu items turn light on hover, and send turns Primary 800.
  • Figma shows "Typing" with text and a blue border together. Here the border is blue while the field has focus, and send turns blue once there is text, so the two can happen apart.

Accessibility

  • The field's accessible name is the current placeholder. Pass aria-label to set your own.
  • The mode button has aria-haspopup="menu" and aria-expanded. Up and Down arrows on it open the menu.
  • Menu items are menuitemradio with aria-checked. Up, Down, Home and End move between them, skipping disabled ones; Escape closes the menu and returns focus to the button.
  • Send is labelled "Send" and is disabled until there is text.

Do and don't

  • Do write each placeholder as the start of the request, so the field reads like a sentence.
  • Do keep mode labels to two or three words.
  • Don't hide a mode that isn't available yet. Show it disabled, so people know it will be there.
  • Don't use it for a plain message box with one kind of request. Use Text Area with a send button.

On this page