Skip to content

Latest commit

 

History

History
291 lines (198 loc) · 7.18 KB

File metadata and controls

291 lines (198 loc) · 7.18 KB

AIKit Library Architecture

Atomic Design Principles

The library is built on Atomic Design principles, which ensure:

  • Clear component hierarchy
  • Element reusability
  • Easy maintenance
  • Flexible customization

Component Levels

1. Atoms

Minimal indivisible UI elements without business logic.

Characteristics:

  • Do not contain business logic
  • Stateless
  • Unaware of usage context
  • Accept data only through props

Examples: ActionButton, Alert, Loader, Shimmer, MarkdownRenderer

2. Molecules

Simple groups of atoms forming basic UI blocks.

Characteristics:

  • Combine multiple atoms
  • Minimal internal logic
  • Reusable blocks

Examples: ButtonGroup, Tabs, Suggestions, BaseMessage, PromptInputBody

3. Organisms

Complex self-sufficient components with internal logic.

Characteristics:

  • Contain business logic
  • Have internal state
  • Can be used independently

Examples: Header, MessageList, PromptInput, UserMessage, AssistantMessage, ToolMessage, ThinkingMessage, FileUploadDialog

4. Templates

Complete layouts combining organisms.

Characteristics:

  • Define page structure
  • Coordinate organism interactions
  • Work with abstract data

Examples: History, EmptyContainer, ChatContent

5. Pages

Full integrations with specific data.

Characteristics:

  • Highest level of abstraction
  • Manage data and state
  • Connect all components together

Examples: ChatContainer, AIStudioChat

6. Server

Code that runs exclusively on the server side and is responsible for interacting with external APIs, primarily neural network services.

Characteristics:

  • Runs only on the server
  • Contains no UI and is not involved in component rendering
  • Serves as a middleware layer between the application and external services (such as neural network APIs)

Examples: OpenAIService (@gravity-ui/aikit/server/openai)

Two-Level Approach

The library offers two ways to integrate a chat:

1. Ready Page Component

ChatContainer (or AIStudioChat) — a fully assembled chat with header, history, message list, and prompt input:

import {ChatContainer} from '@gravity-ui/aikit';

<ChatContainer
  chats={chats}
  activeChat={activeChat}
  messages={messages}
  onSendMessage={handleSend}
  onSelectChat={setActiveChat}
  onCreateChat={createChat}
  onDeleteChat={deleteChat}
/>;

2. Compose from Organisms

Drop down to individual organisms when you need a custom layout:

import {Header, MessageList, PromptInput} from '@gravity-ui/aikit';

function CustomChat() {
  return (
    <div className="custom-chat">
      <Header title="AI Assistant" onNewChat={createChat} />
      <MessageList messages={messages} status="ready" />
      <PromptInput onSubmit={handleSend} placeholder="Enter message…" />
    </div>
  );
}

Composition-level hooks (useToolMessage, useSmartScroll, useFileUploadStore, etc.) are documented in HOOKS.md.

State Management

Data Handling Principle

  • The library is state-agnostic: it does not own messages, chats, or upload state
  • All data flows through props
  • The library invokes callbacks (onSendMessage, onSelectChat, onCreateChat, onDeleteChat, …) and lets the host application manage requests, persistence, and errors

Data Flow Example

const [messages, setMessages] = useState<TChatMessage[]>([]);
const [status, setStatus] = useState<ChatStatus>('ready');

<ChatContainer
  messages={messages}
  status={status}
  onSendMessage={async (data) => {
    setStatus('streaming');
    const reply = await fetchAssistantReply(data.content);
    setMessages((prev) => [...prev, reply]);
    setStatus('ready');
  }}
/>;

Type System

Message Types

export type TMessageRole = 'user' | 'assistant' | 'system';

export type TUserMessage = {
  role: 'user';
  content: string;
  timestamp?: string;
  format?: 'plain' | 'markdown';
  images?: string[];
  fileAttachments?: FileAttachment[];
};

export type TAssistantMessage<TCustomContent = never> = {
  role: 'assistant';
  content: string | TMessageContent | TMessageContent[];
  timestamp?: string;
  userRating?: 'like' | 'dislike';
};

export type TChatMessage<TCustomContent = never> = TUserMessage | TAssistantMessage<TCustomContent>;

Assistant content can be a plain string, a single typed part ('text' | 'thinking' | 'tool'), or an array of parts. Custom part types extend via the TCustomContent generic.

Chat Types

export type ChatType = {
  id: string;
  name: string;
  createTime: string | null;
  lastMessage?: string;
  metadata?: Record<string, unknown>;
};

export type ChatStatus = 'submitted' | 'streaming' | 'streaming_loading' | 'ready' | 'error';

Full type catalog: src/types/{messages,chat,tool,common}.ts.

Extensibility

Custom Message Content Renderers

Register custom content types via MessageRendererRegistry:

import {
  createMessageRendererRegistry,
  registerMessageRenderer,
  type MessageRendererRegistry,
} from '@gravity-ui/aikit';

type ChartMessageContent = {
  type: 'chart';
  data: {points: number[]};
};

const renderers: MessageRendererRegistry = createMessageRendererRegistry();
registerMessageRenderer<ChartMessageContent>(renderers, 'chart', {
  render: ({content}) => <Chart points={content.data.points} />,
});

<MessageList messages={messages} messageRendererRegistry={renderers} />;

See src/components/organisms/MessageList/README.md for the full registry API and validators.

Adapters

src/adapters/ houses pre-built integrations (e.g. openai). They are imported through the main package entry: import {…} from '@gravity-ui/aikit'.

Theming

CSS Variables

All styles are controlled through CSS variables in the --g-aikit-* namespace, with fallbacks to Gravity UI's --g-color-* system:

.g-root {
  --g-aikit-color-bg-primary: var(--g-aikit-bg-primary, var(--g-color-base-float));
}

[data-theme='dark'] {
  --g-aikit-bg-message-user: #0066cc;
}

Applying a Theme

Wrap the application in Gravity UI's <ThemeProvider> and import the matching theme CSS:

import {ThemeProvider} from '@gravity-ui/uikit';
import '@gravity-ui/aikit/themes/common';
import '@gravity-ui/aikit/themes/dark';

<ThemeProvider theme="dark">
    <ChatContainer />
</ThemeProvider>;

Full CSS variable reference: THEMING.md.

Performance

Optimizations

  • React.memo on heavy renderers
  • react-window virtualization for long message lists
  • Lazy hooks (useSmartScroll, useScrollPreservation) to avoid layout thrash
  • Markdown transform cache (useMarkdownTransform)

Accessibility

ARIA Attributes

All interactive elements expose:

  • aria-label for screen readers
  • role for semantics
  • aria-live for streaming/loading regions

Keyboard Navigation

  • Enter — send message
  • Shift+Enter — newline
  • Escape — cancel / close
  • Tab — navigation

Testing

Component tests run under Playwright Component Testing — see TESTING.md. For developer guidelines specific to writing components, stories, and tests inside this repo, see guidelines/.