The AI DIAL UI Kit is an production-ready React component library designed to streamline your development process. It features a collection of base components, such as Buttons, Inputs, Dropdowns, and more — allowing you to effortlessly reuse elements, quick and easy.
- ✨ Highlights
- 📖 Documentation
- 🚀 Quick Start
- Development
- 🎨 Theming & Customization
- ♿ Accessibility
- 📖 Storybook
- 🚀 Usage in Projects
- 🤖 AI Agent MCP Server
- 🤝 Contributing
- 🔒 Security
- 📄 License
- 🌟 Related Projects
- 🎨 Unified User Experience: Ui Kit usage helps with design consistency across AI DIAL applications
- ⚡ Modern Stack: Built with latest React, TypeScript, Vite, and Tailwind CSS
- 🎨 Highly Customizable: Deep theming capabilities with CSS custom properties
- 🧪 Well-Tested: Comprehensive test coverage (70%+) with Vitest and React Testing Library
- 📚 Storybook Ready: Includes interactive component documentation and development playground
- 🛠️ Developer Experience: Leverage ESLint, Prettier, Husky for maintainable code quality
- 📦 Distribution Ready: Deployed as NPM package ready for easy integration
Explore our components and their usage in our interactive Storybook documentation.
- Node.js >= 22.2.0
- npm >= 10.7.0
npm install @epam/ai-dial-ui-kitimport { DialPrimaryButton } from '@epam/ai-dial-ui-kit';
import '@epam/ai-dial-ui-kit/styles.css';
function App() {
return (
<div>
<DialPrimaryButton onClick={() => alert('Hello AI DIAL!')} />
</div>
);
}If you're using markdown-related components (DialMarkdownEditor or DialMarkdownEditorContainer), you need to import the required CSS files globally in your application (e.g., in your root layout or main entry point):
import '@uiw/react-markdown-preview/markdown.css';
import '@uiw/react-md-editor/markdown-editor.css';This ensures the CSS is loaded once per application rather than being bundled with each component instance, reducing bundle size.
- Node.js >= 22.2.0
- npm >= 10.7.0
- Git
-
Clone the repo
git clone https://github.com/epam/ai-dial-ui-kit.git cd ai-dial-ui-kit -
Install Dependencies
npm install
-
Start Development Environment
# Start Storybook for component development npm run storybook # Run tests in watch mode npm run test -- --watch # Start Vite dev server npm run dev
# Run all tests with coverage
npm run testsrc/
├── components/ # React components
│ ├── Button/ # Example component
│ │ ├── Button.tsx
│ │ ├── Button.spec.tsx
│ │ └── Button.stories.tsx
│ └── ...
├── styles/ # Global styles and Tailwind configuration
│ ├── buttons.scss
│ ├── typography.scss
│ └── tailwind-entry.scss
├── types/ # TypeScript type definitions
└── index.ts # Main entry point
The library uses CSS custom properties for comprehensive theming. Override these variables to match your brand:
:root {
/* Background layers */
--bg-layer-0: #000000;
--bg-layer-1: #0C101D;
--bg-layer-2: #171B21;
/* Text colors */
--text-primary: ##EEF1F7;
--text-secondary: #9CA3AF;
--text-tertiary: #6B7280;
...
}Full list of variables is available here
Corner radii of the 2.0 controls are themable the same way. Each defaults to the fully rounded pill the buttons ship with, so setting nothing keeps the stock look:
:root {
--radius-control: 12px; /* Button at standard and large size */
--radius-control-small: 8px; /* Button at ElementSize.Small */
--radius-control-icon: 9999px; /* IconButton, ToggleIconButton — any size */
}Labelled and icon-only buttons read separate variables on purpose: a design that wants squarer action buttons usually still wants its icon buttons round.
These are defaults, not overrides: a rounded-* utility passed to a single
control through className still wins, because a consumer's utilities are
emitted after this package's stylesheet.
DialFabButton, DialIconButton, and IconButton render no text, so they need an
explicit accessible name. Pass aria-label; if you pass only a string
tooltipProps.tooltip, it is used as the label instead. Do not rely on the tooltip
alone to convey the name — a tooltip's aria-describedby lands on a wrapper element
rather than on the control, and tooltips are suppressed entirely on mobile.
InfoButton names itself from caption for the same reason. Pass a short
aria-label when the caption is a full sentence, so the name stays scannable.
Standard-size buttons render at 40×40 but expose a 44×44 pointer target via the
dial-kit-enhanced-target utility, which grows the target with a transparent
pseudo-element. The visible control is unchanged, so layouts keep their existing
metrics. WCAG 2.5.5 measures the region that accepts a pointer action, not the
visible decoration.
A control too small for a 44px target to clear its neighbours uses
dial-kit-minimum-target instead, which applies the same pseudo-element at the
Level AA minimum of 24×24 (WCAG 2.5.8).
These controls are documented exceptions and meet Level AA (2.5.8, 24×24) but not AAA:
| Control | Size | Why it is excluded |
|---|---|---|
ElementSize.Small variants |
24×24 | A 44px target overhangs 10px per side and would overlap adjacent controls in dense toolbars |
ButtonAppearance.Link |
content | Exempt under the 2.5.5 Inline exception; expanding it would overlap surrounding copy |
DialCloseButton |
icon-sized | Renders h-auto w-auto, so its target follows the caller's icon size |
DialInfoButton, InfoButton |
24×24 | Fixed small affordance, same overlap constraint as small variants |
Standard 2.0 fields (Input, Select, RadioGroupPopupField) |
40px tall | The pointer target spans the full field width but stays 4px short of 44 vertically; the height is a shared form design token, not a per-control choice. .dial-kit-input clips its overflow, so the pseudo-element cannot grow the target either |
Tag remove button |
16×16 rendered | Reaches 24×24 through dial-kit-minimum-target; a 44px target would overhang 14px per side and swallow the neighbouring tags of a TagInput row |
Clickable Tag |
32px tall | A 44px target would overhang 6px per side and swallow the neighbouring chips of a filter row; the tag is already wider than 24px on both axes |
Radio circle |
20×20 rendered | Reaches 24×24 through dial-kit-minimum-target; a 44px target would overhang 12px per side and swallow the adjacent label. Clicking the label selects the radio, so the practical target is wider |
Checkbox box |
20×20 rendered | Reaches 24×24 through dial-kit-minimum-target; a 44px target would overhang 12px per side and swallow the adjacent label. Clicking the label toggles the checkbox, so the practical target is wider |
Slider track row |
24px tall | The pointer target spans the full track width but is only 24px tall; a 44px row would add 20px of dead space to every form the slider sits in, and the thumb is dragged rather than tapped |
SegmentedControl segment |
32px tall | Sits 4px from its neighbours inside a 40px track, so a 44px target would overhang 6px per side and swallow the adjacent segments; the segment is already wider than 24px on both axes |
ResizableContainer resize handle |
10px wide pointer strip | The handle has to sit exactly on the panel boundary, so a 44px-wide strip would swallow content on both sides of it — essential to the control. It is a focusable separator, so the resize is also available from the keyboard with the arrow keys |
Give small-variant controls at least 20px of surrounding space if you need to reach AAA in a specific layout, or use the standard size instead.
Storybook is a handy library for documenting and developing of UI components.
To run fully interactive storybook:
npm run storybook
# Open http://localhost:6006npm run build-storybooknpx http-server ./storybook-static
# Open http://127.0.0.1:8080/To run documents only:
npm run storybook-docs
# Open http://localhost:54800/npm run build-storybook-docsnpx http-server ./storybook-static
# Open http://127.0.0.1:8080/Storybook provides:
- 📖 Interactive component documentation
- 🎨 Visual testing playground
- ♿ Accessibility testing tools
- 📱 Responsive design testing
- 🎯 Component isolation
Next.js Integration
- Install the package. React is the only peer you have to supply — everything the kit renders with, it installs itself.
npm install @epam/ai-dial-ui-kit
npm install react react-domAdd the editor packages only if you use the @epam/ai-dial-ui-kit/editors
subpath. They are optional peers, so npm install stays quiet without them, and
the kit only reaches for them when a Lazy* editor actually mounts:
npm install monaco-editor @monaco-editor/react @uiw/react-md-editor- Import style in the root layout of the project:
// app/layout.tsx
import "@epam/ai-dial-ui-kit/styles.css";- Usage example
// app/page.tsx
"use client";
import { DialPrimaryButton } from "@epam/ai-dial-ui-kit";
export default function Home() {
return (
<div className="w-full h-full flex flex-col gap-3 items-center justify-center">
<h1>Test library</h1>
<DialPrimaryButton onClick={() => alert('Hello AI DIAL!')} />
</div>
);
}Import only the components you need:
// ✅ Good - Tree shakable imports
import { DialPrimaryButton, DialInput } from '@epam/ai-dial-ui-kit';
import '@epam/ai-dial-ui-kit/styles.css'; // Import styles separately
// ❌ Avoid - Imports entire library
import * as UIKit from '@epam/ai-dial-ui-kit';The AI DIAL UI Kit includes a built-in MCP (Model Context Protocol) server that enables AI agents to discover components, types, hooks, and utilities programmatically. This allows AI assistants to generate accurate, type-safe component code without hallucination.
Component results are ranked generation 2.0 first — the current design system, exported without the Dial prefix — and each legacy Dial* component points at its 2.0 replacement, so agents land on the right component by default.
For setup, configuration, and detailed resources, see the MCP Server Guide.
We welcome contributions! Please see our Contributing Guide for details on:
- Code style guidelines
- Testing requirements
- Pull request process
If you discover a security vulnerability, please refer to our Security Policy.
Apache 2.0 - see the LICENSE file for details.
- AI-DIAL - Entrypoint for all AI Dial projects
Made with ❤️ by EPAM Systems