Docs
🪄 ⏐ Examples
Commands

Slash Commands

reachat 2.1 introduces slash command support with the same powerful suggestion system as mentions. Users can trigger commands by typing / followed by a command name.

Overview

The slash command feature provides:

  • Floating suggestion popup with keyboard navigation
  • Command filtering as you type
  • Support for both text insertion and custom actions
  • Customizable command items with shortcuts and descriptions
  • Full keyboard support (arrow keys, enter, escape)

Basic Usage

To enable slash commands, configure the RichTextInput component with a commands prop:

import { RichTextInput } from 'reachat';
 
const commands = [
  {
    id: 'summarize',
    label: 'Summarize',
    description: 'Summarize the conversation',
    shortcut: '⌘S'
  },
  {
    id: 'translate',
    label: 'Translate',
    description: 'Translate text to another language'
  },
  {
    id: 'help',
    label: 'Help',
    description: 'Show available commands'
  }
];
 
<RichTextInput
  commands={{
    trigger: '/',
    items: commands
  }}
  onSubmit={(value) => console.log(value)}
/>

Configuration Options

The commands prop accepts a SuggestionConfig object with the following options:

Command Types

Commands can either insert text or trigger custom actions:

<RichTextInput
  commands={{
    trigger: '/',
    items: [
      {
        id: 'insert-template',
        label: 'Bug Report',
        description: 'Insert bug report template',
        type: 'insert',
        value: '**Bug Description:**\n\n**Steps to Reproduce:**\n\n**Expected:**\n\n**Actual:**'
      },
      {
        id: 'clear-chat',
        label: 'Clear',
        description: 'Clear the current conversation',
        type: 'action'
      }
    ],
    onSelect: (item, insertText) => {
      if (item.type === 'action') {
        // Handle custom action
        if (item.id === 'clear-chat') {
          handleClearChat();
        }
      } else {
        // Insert text
        insertText(item.value || item.label);
      }
    }
  }}
/>

Dynamic Commands

Load commands dynamically based on context:

<RichTextInput
  commands={{
    trigger: '/',
    onSearch: async (query) => {
      // Fetch commands from API or compute based on context
      const allCommands = await fetchAvailableCommands();
 
      // Filter based on user query
      return allCommands
        .filter(cmd =>
          cmd.label.toLowerCase().includes(query.toLowerCase())
        )
        .slice(0, 10);
    }
  }}
/>

Custom Rendering

Customize the appearance of command suggestions:

<RichTextInput
  commands={{
    trigger: '/',
    items: commands,
    renderItem: (item, isHighlighted) => (
      <div style={{
        padding: '8px 12px',
        backgroundColor: isHighlighted ? '#e3f2fd' : 'transparent',
        display: 'flex',
        justifyContent: 'space-between',
        alignItems: 'center'
      }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
          {item.icon}
          <div>
            <div style={{ fontWeight: 'bold' }}>/{item.label}</div>
            <div style={{ fontSize: '12px', color: '#666' }}>
              {item.description}
            </div>
          </div>
        </div>
        {item.shortcut && (
          <kbd style={{
            padding: '2px 6px',
            borderRadius: '4px',
            backgroundColor: '#f5f5f5',
            fontSize: '11px'
          }}>
            {item.shortcut}
          </kbd>
        )}
      </div>
    )
  }}
/>

Using with ChatInput

The ChatInput component automatically supports commands when configured:

import { Chat, ChatInput } from 'reachat';
 
const slashCommands = [
  {
    id: 'summarize',
    label: 'Summarize',
    description: 'Summarize the conversation',
    type: 'action'
  },
  {
    id: 'export',
    label: 'Export',
    description: 'Export conversation to file',
    type: 'action'
  }
];
 
<Chat
  sessions={sessions}
  activeSessionId={activeId}
>
  <SessionMessagePanel>
    <SessionMessagesHeader />
    <SessionMessages />
    <ChatInput
      commands={{
        trigger: '/',
        items: slashCommands,
        onSelect: (item, insertText) => {
          handleCommand(item.id);
        }
      }}
    />
  </SessionMessagePanel>
</Chat>

Common Command Patterns

Text Templates

Insert predefined text templates:

const templateCommands = [
  {
    id: 'meeting-notes',
    label: 'Meeting Notes',
    description: 'Insert meeting notes template',
    type: 'insert',
    value: `# Meeting Notes - ${new Date().toLocaleDateString()}
 
**Attendees:**
 
**Agenda:**
 
**Discussion:**
 
**Action Items:**
 
**Next Steps:**`
  }
];

Quick Actions

Trigger actions without inserting text:

const actionCommands = [
  {
    id: 'new-session',
    label: 'New Chat',
    description: 'Start a new conversation',
    type: 'action',
    shortcut: '⌘N'
  },
  {
    id: 'search',
    label: 'Search',
    description: 'Search in conversations',
    type: 'action',
    shortcut: '⌘K'
  }
];
 
<RichTextInput
  commands={{
    trigger: '/',
    items: actionCommands,
    onSelect: (item) => {
      switch (item.id) {
        case 'new-session':
          createNewSession();
          break;
        case 'search':
          openSearchModal();
          break;
      }
    }
  }}
/>

Context-Aware Commands

Show different commands based on application state:

const getContextCommands = (hasSelection: boolean) => {
  const baseCommands = [
    { id: 'help', label: 'Help', description: 'Show help' }
  ];
 
  if (hasSelection) {
    return [
      ...baseCommands,
      {
        id: 'explain',
        label: 'Explain',
        description: 'Explain selected text'
      },
      {
        id: 'improve',
        label: 'Improve',
        description: 'Improve selected text'
      }
    ];
  }
 
  return baseCommands;
};
 
<RichTextInput
  commands={{
    trigger: '/',
    items: getContextCommands(hasTextSelection)
  }}
/>

Combining with Mentions

You can use both mentions and commands simultaneously:

<RichTextInput
  mentions={{
    trigger: '@',
    items: userMentions,
    onSearch: searchUsers
  }}
  commands={{
    trigger: '/',
    items: slashCommands,
    onSelect: handleCommand
  }}
  onSubmit={handleSubmit}
/>

Keyboard Navigation

Users can navigate the command list using:

  • Arrow Up/Down: Move selection
  • Enter: Execute selected command
  • Escape: Close command popup
  • Continue typing: Filter commands

API Reference

SlashCommandItem Interface

interface SlashCommandItem extends SuggestionItem {
  id: string;
  label: string;
  description?: string;
  icon?: ReactElement;
  shortcut?: string; // Display keyboard shortcut hint
  type?: 'insert' | 'action'; // Command behavior
  value?: string; // Text to insert (for 'insert' type)
  metadata?: Record<string, unknown>;
}

SuggestionConfig Interface

interface SuggestionConfig<T extends SuggestionItem = SuggestionItem> {
  trigger?: string; // Default: '/'
  items?: T[];
  onSearch?: (query: string) => Promise<T[]> | T[];
  onSelect?: (item: T, insertText: (text: string) => void) => void;
  maxResults?: number; // Default: 10
  renderItem?: (item: T, isHighlighted: boolean) => ReactNode;
  renderEmpty?: (query: string) => ReactNode;
}

For more examples and interactive demos, visit the storybook demos (opens in a new tab).