AIKit by Gravity UI

repository·main·Indexed 41 days ago

https://github.com/gravity-ui/aikit

A flexible, SDK-agnostic React component library for building complex AI chat interfaces using Atomic Design principles. Version 2.21.0 provides 49 components and hooks for handling assistant/user/tool messages, thinking states, and streaming responses, including a specialized useOpenAIStreamAdapter hook for OpenAI integration.

Tokens
145.9K
Snippets
290
Records
459
Agent score
48%

What's inside AIKit

  1. Overview of the MessageList component

    main

    The MessageList component is used to display a list of messages in a chat interface. It is designed to be highly extensible and performant, featuring:

    • Automatic Rendering: It automatically selects and renders the correct component based on the message type.
    • Extensibility: You can register custom message renderers using the MessageRendererRegistry.
    • Optimized Performance: Each message is memoized to ensure that during streaming, only the active message re-renders. For very large histories, you can enable Virtualization via the virtualized prop to keep the DOM size constant using react-window.
    • Smart Action Filtering: The component automatically excludes assistantActions when rendering 'thinking' messages.
    • User Rating Support: You can set the userRating on assistant messages to control the filled state of like/dislike icons.
  2. What is included in the AIKit Generative UI toolset

    main

    The AIKit Generative UI toolset provides several built-in mechanisms to manage the lifecycle of tool calls within a chat interface:

    • Registry: useToolset returns a MessageRendererRegistry where the tool dispatcher is automatically wired to your defined toolset.
    • Typed Results: submitResult is available on ToolComponentProps and is injected via createToolsetRenderer.
    • History Management: applyToolResult is automatically called on every successful tool submission to merge results into the chat history.
    • Continuation Support: The useToolResultContinuation hook allows you to observe tool status transitions and receive the updated transcript.
    • Error Handling/Validation: If tool arguments are invalid or an unknown toolName is encountered, the system automatically falls back to rendering <ToolMessage status="error" />.

    Note: You are responsible for providing the tool definitions (schemas, components, and execute functions), the LLM adapter, the sendTurn function, and the server-side route that manages provider credentials.

  3. Explore AIKit components and hooks

    main

    AIKit provides a comprehensive set of building blocks for AI interfaces:

    • Components: A catalog of 49 components available for building chat interfaces (COMPONENTS.md).
    • Hooks: A reference for all public hooks provided by the library (HOOKS.md).
  4. Use the RatingBlock component

    main

    The RatingBlock is a universal component designed to display a title alongside a 5-star rating system. It is useful for surveys, feedback forms, or displaying existing ratings.

    Key Features

    • Flexible Title: Supports React elements like text, links, or formatted content.
    • Integrated Rating: Includes a built-in 5-star rating component.
    • Configurable Sizes: You can adjust the star size using the size property.
    • Responsive Layout: Comes with built-in border and padding for a consistent look.
  5. Understand the ChatContainer architecture and layout

    main

    The ChatContainer component is organized using atomic design principles and follows a specific vertical layout structure. It manages the orchestration between navigation, message display, and user input.

    Layout Structure

    The component is composed of the following sections:

    1. Header (Organism): Provides navigation and action controls.
    2. ChatContent (Template): The scrollable central area. It dynamically switches between:
      • EmptyContainer: A welcome screen shown when there are no messages.
      • MessageList: The active display area for chat history.
    3. Footer: The interaction area at the bottom, containing:
      • PromptInput: The user input field with send and cancel capabilities.
      • Disclaimer: Optional informational or legal text.
    4. History (Template): A popup component used for managing chat history.

    Internal Logic

    The component utilizes the useChatContainer hook to handle:

    • Chat history popup state.
    • Switching views based on message count.
    • Integrating the History component with the Header via refs.
    • Merging i18n configurations with default text values.
    • Managing focus via an internal promptInputKey counter, which triggers a PromptInput remount with autoFocus when autoFocusOnNewChat or autoFocusOnChatSelect are enabled.
  6. How screenshot testing works

    main

    Screenshot tests create visual baselines that are compared during subsequent test runs.

    1. First run: Creates baseline screenshots in __snapshots__ directories.
    2. Subsequent runs: Compares the current component state against the baselines. The test fails if any visual differences are detected.
    3. Updating: If visual changes are intentional, you must run npm run test:ct:update to overwrite the old baselines.

    Best Practices:

    • Keep screenshots focused on single components.
    • Test various states (e.g., default, hover, disabled).
    • Test responsive behavior using different viewport sizes.
    • Use descriptive names for screenshots.
  7. Implement copy functionality in ThinkingMessage

    main

    The copy button appears when status='thought' and either onCopyClick or enabledCopy is provided. The priority is as follows:

    1. Custom Logic: If onCopyClick is provided, it is used exclusively.
    2. Default Logic: If onCopyClick is absent but enabledCopy={true}, the default logic is used.
    3. None: If neither is provided, no copy button is shown.

    Default Copy Behavior:

    • String content: Copied as-is.
    • Array content: Items are joined with double newlines (\n\n), matching the visual paragraph separation.
    // Example: Custom Copy Handler
    <ThinkingMessage
      content="Processing your request..."
      status="thought"
      onCopyClick={() => {
        navigator.clipboard.writeText('Custom text');
        showNotification('Copied!');
      }}
    />
    
    // Example: Default Copy Functionality
    <ThinkingMessage
      content={['First thinking block', 'Second thinking block']}
      status="thought"
      enabledCopy={true}
    />
  8. Understand History component sub-components

    main

    The History template is composed of several exported sub-components that can be used independently if required:

    • History: The main orchestrator that manages the popup and the list display.
    • ChatItem: Represents an individual chat entry, including hover states and action buttons (like delete).
    • DateHeaderItem: A component used to render the grouping headers (e.g., "Today", "Yesterday") when groupBy is active.
  9. Understand the PromptInput component structure

    main

    The PromptInput component is an orchestrator for AI chat interfaces, composed of several layers:

    Main Component

    • PromptInput: The primary component that manages the overall state and sub-components.

    Wrapper Components

    • PromptInputWithSuggestions: Adds support for displaying suggestion chips.
    • PromptInputWithPanels: Adds support for expandable top and bottom panels.
    • PromptInputFull / PromptInputSimple: Specific view implementations for different UI requirements.

    Molecule Components

    • PromptInputHeader: Displays context indicators or custom content (used in full view).
    • PromptInputBody: An auto-growing textarea for user input.
    • PromptInputFooter: Contains action icons (settings, attachment, microphone) and the submit button.
    • PromptInputPanel: A styled container used for expandable panel content.
    • Suggestions: Renders clickable suggestion chips.

    All internal state (textarea value, validation, keyboard shortcuts, attachments) is managed by the usePromptInput hook.

  10. Understand ThinkingMessage status values

    main

    The status prop determines the visual state of the component:

    • thinking: Represents an active thinking process. It shows a loader animation (if showStatusIndicator is true) and the button label is "Thinking".
    • thought: Represents a completed thought. It shows a copy button (if onCopyClick or enabledCopy is provided) and the button label is "Thought".
  11. How AIKit's atomic design architecture works

    main

    AIKit is built using Atomic Design principles, organizing components into a hierarchy of complexity. This allows you to use high-level ready-made components or build custom interfaces using smaller building blocks:

    • Atoms: Basic, indivisible UI elements without business logic (e.g., ActionButton, Loader, MarkdownRenderer, SubmitButton).
    • Molecules: Simple combinations of atoms (e.g., BaseMessage, PromptInputHeader, Suggestions).
    • Organisms: Complex components with internal logic (e.g., AssistantMessage, MessageList, PromptInput, UserMessage).
    • Templates: Ready-made layouts (e.g., ChatContent, History).
    • Pages: Full integrations with data (e.g., ChatContainer).

    Key architectural features include:

    • SDK Independence: Not tied to any specific AI SDK.
    • Two-level approach: Provides both ready-to-use components and hooks for deep customization.
    • CSS Variables: Easy theme customization without component overrides.
    • Extensibility: A system for registering custom message types.
  12. Understand FeedbackForm behavior and submission

    main

    Reason Selection

    • Users can select multiple reasons by clicking chips.
    • Selected chips are visually indicated using the selected prop on the underlying Button component.

    Submit Button Logic

    To prevent empty submissions, the submit button's state is managed automatically:

    • Disabled: When no reasons are selected AND no comment has been entered.
    • Enabled: When at least one reason is selected OR a comment is entered.

    Submission Data

    When the onSubmit callback is triggered, it provides:

    1. reasons: An array of the id strings from the selected FeedbackOption objects.
    2. comment: The string content of the comment field (an empty string if the field was left blank).