platejs

Inline Combobox

Component 1

About

An inline combobox for editor suggestion menus like @mentions, slash commands, and emoji pickers, built for Plate/Slate rich-text editors.

Built with React and Tailwind. Copy the prompt and paste it into Claude Code, Cursor or Lovable: your agent adds Inline Combobox to your project and fits it to your theme.

Code

How Inline Combobox is used: the demo's code. The component's own source comes with a free account.

Usage.tsx

"use client";

import * as React from "react";

import {
  InlineCombobox,
  InlineComboboxContent,
  InlineComboboxEmpty,
  InlineComboboxGroup,
  InlineComboboxInput,
  InlineComboboxItem,
} from "@/components/ui/inline-combobox";

import { getMentionOnSelectItem } from "@platejs/mention";
import { MentionInputPlugin, MentionPlugin } from "@platejs/mention/react";
import {
  Plate,
  PlateContent,
  PlateElement,
  useFocused,
  usePlateEditor,
  useSelected,
} from "platejs/react";
import { cn } from "@/lib/utils";

const MENTIONABLES = [
  { key: "0", text: "Aayla Secura" },
  { key: "1", text: "Adi Gallia" },
  { key: "2", text: "Admiral Dodd Rancit" },
  { key: "3", text: "Admiral Firmus Piett" },
  { key: "4", text: "Admiral Gial Ackbar" },
  { key: "5", text: "Admiral Ozzel" },
  { key: "6", text: "Admiral Raddus" },
  { key: "7", text: "Aurra Sing" },
  { key: "8", text: "Boba Fett" },
];

function MentionElement(props: any) {
  const selected = useSelected();
  const focused = useFocused();
  const element = props.element as { value: string };

  return (
    <PlateElement
      {...props}
      className={cn(
        "inline-block rounded-md bg-muted px-1.5 py-0.5 align-baseline font-medium text-sm",
        selected && focused && "ring-2 ring-ring",
      )}
      attributes={{
        ...props.attributes,
        contentEditable: false,
        "data-slate-value": element.value,
        draggable: true,
      }}
    >
      {"@"}
      {element.value}
      {props.children}
    </PlateElement>
  );
}

const onSelectItem = getMentionOnSelectItem();

function MentionInputElement(props: any) {
  const { editor, element } = props;
  const [search, setSearch] = React.useState("");

  return (
    <PlateElement {...props} as="span">
      <InlineCombobox
        value={search}
        element={element}
        setValue={setSearch}
        showTrigger={false}
        trigger="@"
      >
        <span className="inline-block rounded-md bg-muted px-1.5 py-0.5 align-baseline text-sm ring-ring focus-within:ring-2">
          <InlineComboboxInput />
        </span>

        <InlineComboboxContent className="my-1.5">
          <InlineComboboxEmpty>No results</InlineComboboxEmpty>

          <InlineComboboxGroup>
            {MENTIONABLES.map((item) => (
              <InlineComboboxItem
                key={item.key}
                value={item.text}
                onClick={() => onSelectItem(editor, item, search)}
              >
                {item.text}
              </InlineComboboxItem>
            ))}
          </InlineComboboxGroup>
        </InlineComboboxContent>
      </InlineCombobox>

      {props.children}
    </PlateElement>
  );
}

export default function InlineComboboxDemo() {
  const editor = usePlateEditor({
    plugins: [
      MentionPlugin.configure({
        options: {
          triggerPreviousCharPattern: /^$|^[\s"']$/,
        },
      }).withComponent(MentionElement),
      MentionInputPlugin.withComponent(MentionInputElement),
    ],
    value: [
      {
        type: "p",
        children: [
          { text: "Type " },
          { text: "@", bold: true },
          { text: " to open the inline combobox and mention someone." },
        ],
      },
    ],
  });

  return (
    <div className="w-full max-w-xl rounded-lg border bg-background p-2">
      <Plate editor={editor}>
        <PlateContent
          className="min-h-[160px] rounded-md px-3 py-2 text-sm outline-none"
          placeholder="Type @ to mention..."
        />
      </Plate>
    </div>
  );
}

Dependencies

More by platejs

View all
  • Math Base Kit

    Math Base Kit

    15
  • Highlight Leaf

    Highlight Leaf

    6
  • Cursor Overlay

    Cursor Overlay

    5
  • Editor

    Editor

    4
  • Link Element

    Link Element

    3
  • Resize Handle

    Resize Handle

    3
  • List

    List

    1
  • Blockquote Element

    Blockquote Element

    1