The Problem

Developers building AI‑driven chat UIs spend time wiring together low‑level UI primitives, handling theming, and keeping type safety across message schemas. Without a reusable, well‑typed component set, each project re‑implements the same atoms, molecules and layout logic, leading to duplicated code and inconsistent accessibility.

What This Does

@gravity-ui/aikit supplies a React component library organized by Atomic Design. The core UI lives under src/components/ with the hierarchy atoms → molecules → organisms → templates → pages.

  • Example entry: src/components/pages/ChatContainer/ChatContainer.tsx renders a full chat surface and delegates to hooks (useChatContainer.ts) and shared utilities (src/utils/cn.ts).
  • The theming system resides in src/themes/ and uses CSS variables, while type definitions are centralized in src/types/ (e.g., src/types/messages.ts).
  • Storybook (.storybook/) and Playwright component tests (playwright/) provide interactive documentation and visual regression coverage.

How It Is Wired

  1. Runtime start – A consumer imports a top‑level component, e.g. import {ChatContainer} from '@gravity-ui/aikit'. The compiled entry point is src/components/pages/ChatContainer/ChatContainer.tsx.
  2. Component composition – ChatContainer renders a layout of atoms and molecules, pulling styles via src/utils/cn.ts (the most‑connected module, imported by 59 other files).
  3. State & logic – ChatContainer calls the hook src/components/pages/ChatContainer/useChatContainer.ts, which manages message lists, active chat selection, and callbacks passed from the parent.
  4. Message typing – All message shapes flow through src/types/messages.ts, imported by both UI components and the hook, ensuring a single source of truth for TChatMessage.
  5. Theming – UI components read CSS variables defined in src/themes/ via the cn utility; no runtime theme‑switching code lives elsewhere, keeping the visual layer isolated.
  6. Export surface – src/components/atoms/index.ts, src/components/molecules/index.ts, etc., re‑export their sub‑modules, giving consumers a flat import path while the internal graph remains acyclic (0 circular dependencies).

The import graph shows no cycles and a clear hub (src/utils/cn) whose stability is critical because any change propagates to 59 dependents. Deeply nested components (e.g., src/components/molecules/BaseMessage/index.tsx) have up to nine indentation levels, indicating high cognitive load.

How To Use It

# Clone the repo
git clone https://github.com/moses-y/aikit
cd aikit

# Install dependencies
npm ci

# Run the library's test suite
npm test

# Launch Storybook for interactive exploration
npm run storybook   # script defined in package.json

No additional configuration files are required; the library reads no environment variables at runtime. For component‑level testing, Playwright can be invoked:

npx playwright test

(see playwright/README.md).

Real‑World Use

A SaaS product that embeds a multi‑chat UI can import the library and plug its own backend:

import {ChatContainer} from '@gravity-ui/aikit';
import type {ChatType, TChatMessage} from '@gravity-ui/aikit';

function App() {
  const [messages, setMessages] = useState<TChatMessage[]>([]);
  const [chats, setChats] = useState<ChatType[]>([]);
  const [active, setActive] = useState<ChatType | null>(null);

  return (
    <ChatContainer
      chats={chats}
      activeChat={active}
      messages={messages}
      onSendMessage={msg => api.send(msg)}
      onSelectChat={setActive}
      onCreateChat={() => api.create()}
      onDeleteChat={chat => api.delete(chat.id)}
    />
  );
}

The component handles UI rendering, theming, and accessibility out of the box; the application only needs to supply data and callbacks.

Code Health & Issues

Critical – Secrets in .github/workflows/pr-preview-deploy.yml (GRAVITY_UI_BOT_GITHUB_TOKEN, etc.). Move secret‑using steps to a workflow_run job or restrict to approved reviewers. High – GitHub Action versions are pinned to tags (@v1). Replace each with a full 40‑character commit SHA. Medium – No least‑privilege permissions declared for GITHUB_TOKEN in CI workflow. Add explicit read/write scopes. Medium – Dependabot not configured; add .github/dependabot.yml. Medium – No dependency‑vulnerability scan in CI; integrate dependency-review-action or osv-scanner. Medium – Large binary (docs/assets/aikit_cover.png, 5 MB) in repo; migrate to Git LFS or external storage. Medium – Checkout step retains token; set persist-credentials: false and pass token only where needed. Low – CI jobs lack timeout-minutes; define reasonable limits to avoid runaway runs.

Additional findings from static analysis:

  • Hub module src/utils/cn.ts (59 dependents) should stay minimal.
  • Deep nesting (max depth 9) in several components; refactor with early returns or extract sub‑logic.
  • Repeated 6‑line story blocks across many __stories__ files; consolidate into shared helpers.
  • Oversized story file ChatContainer.stories.tsx (1 072 lines); split by responsibility.
  • High branching density in ChatContainer.tsx and its hook; consider strategy tables.

The Bottom Line

aikit delivers a well‑typed, themable React UI kit for AI chat interfaces, with solid test coverage and Storybook documentation. The codebase is healthy overall but contains a few high‑impact maintenance hotspots (the cn utility and deeply nested components) and several CI/security hygiene gaps that should be addressed before production deployment. It is suited for teams needing a reusable chat UI foundation and are comfortable managing the identified CI improvements.