@trinityui/design-system
v2.13.2
Published
Trinity Design System — enterprise MUI v9 React component library with design tokens, AI components, and WCAG 2.2 AA accessibility.
Maintainers
Keywords
Readme
Trinity Design System
Enterprise component platform built on MUI 9 and React 19 for Trinity LifeSciences. Provides 146 accessible React components (46 of them AI and human-in-the-loop components, 17 chart components and 13 page templates), 32 hooks, a 3-tier design token system, and a CSS-only package for non-React consumers, with the tokens, the React theme and the CSS package kept in parity.
Table of Contents
- Key Capabilities
- Architecture
- Packages & Entry Points
- Installation
- Quick Start
- What's New in 2.13.0
- Component Catalog
- Hooks
- Accessibility
- Design Tokens
- Theme Presets
- CSS-Only Usage
- Storybook
- MCP (Model Context Protocol)
- Development
- Documentation
- License
Key Capabilities
| Capability | Details |
|---|---|
| 146 Components | Navigation, layout, AI, data display, inputs, feedback, charts |
| 46 AI Components | InsightEngine, ChatThread, AIMessage, AIChainOfThought, the human-in-the-loop blocks, voice input, explainability, sources, personas |
| 17 Chart Components | Line, bar, area, pie, donut, scatter, bubble, radial, gauge, composed, sparkline, plus the chart wrapper, tooltips and legends |
| 13 Page Templates | Dashboard, list-detail, settings, auth, catalog, wizard, report, the AI review queue and more, plus one pattern (AICopilotPattern) |
| 3-Tier Design Tokens | Base → Semantic → Component tokens; the React theme and the CSS variables are generated from the same source and kept in parity |
| Dark Mode | Automatic light/dark themes with WCAG 2.2 AA color contrast |
| 3 Theme Presets | CRM (compact), Portal (accessible), Analytics (data-viz) |
| 32 Hooks | Debounce, clipboard, breakpoints, disclosure, roving tabindex, live announcements, and more |
| TypeScript-First | 861 root exports with full type definitions |
| CSS-Only Package | Angular, Vue, and static HTML support through 1186 --trinity-* CSS variables |
| 80+ Brand Assets | Gradient icons, background images, logos |
| Bundle Governance | A size-limit ratchet on every public entry; each raise is measured and recorded |
| Accessibility | WCAG 2.2 AA: axe on every story, a strict behavior contract, live announcements, skip links, forced colors and reduced motion |
Architecture
┌─────────────────────────────────────────────────────────────┐
│ Design Tokens (tokens.ts) │
│ Base → Semantic → Component (2,700 lines) │
└──────────────┬──────────────────────────┬────────────────────┘
│ │
▼ ▼
┌──────────────────────────┐ ┌─────────────────────────────────┐
│ MUI Theme Layer │ │ CSS Variables Build │
│ lightTheme / darkTheme │ │ generate-css-from-tokens.ts │
│ + 3 preset themes │ │ trinity-generated.css │
└──────────┬───────────────┘ └──────────┬──────────────────────┘
│ │
▼ ▼
┌──────────────────────────┐ ┌─────────────────────────────────┐
│ @trinityui/design-system │ │ @trinityui/design-system-css │
│ React + MUI Components │ │ Angular / Vue / Static HTML │
└──────────────────────────┘ └─────────────────────────────────┘Packages & Entry Points
| Package / Import | Exports | Use Case |
|---|---:|---|
| @trinityui/design-system | 861 | Full API: components, templates, patterns, hooks, tokens, themes and utilities |
| @trinityui/design-system/essentials | 45 | Quick start: the themes and the core components |
| @trinityui/design-system/theme | 52 | Theme utilities only (tree-shakeable) |
| @trinityui/design-system/tokens | 131 | Design tokens only (tree-shakeable) |
| @trinityui/design-system/data-table | 6 | DataTable and the AG Grid Enterprise license setup |
| @trinityui/design-system/css | CSS file | The CSS variables, from the React package |
| @trinityui/design-system-css | 1186 CSS variables | Standalone CSS-only package for non-React apps |
Installation
React package
pnpm add @trinityui/design-system react react-dom @mui/material @mui/icons-material @emotion/react @emotion/styledRequirements: React and React DOM 19.2.4 or later, MUI 9 (@mui/material, @mui/icons-material), Emotion 11.14 or later, and Node 20, 22 or 24 (support matrix).
There are no optional dependencies to add: the chart (Highcharts), DataTable (AG Grid) and flow-layout libraries install with the package. DataTable's Enterprise features need your AG Grid license key; set it once at startup with setAgGridEnterpriseLicenseKey from @trinityui/design-system/data-table (see Data Display).
CSS-only package
pnpm add @trinityui/design-system-cssCommercial licensing: For MUI, AG Grid, or Syncfusion license procurement/renewal, contact Arun Manoharan, Rahul Desai, or Sangeetha before production use.
Quick Start
1. Wrap your app with the theme
import { ThemeProvider, CssBaseline } from '@mui/material';
import { lightTheme } from '@trinityui/design-system';
export function AppProviders({ children }: { children: React.ReactNode }) {
return (
<ThemeProvider theme={lightTheme}>
<CssBaseline />
{children}
</ThemeProvider>
);
}Pick a theme preset instead of lightTheme when your product is a dense CRM (crmLightTheme), a customer portal (portalLightTheme) or an analytics app (analyticsLightTheme); each has a dark twin. Build your own with createTrinityTheme(mode, overrides) or createTrinityThemePreset(options).
2. Import strategy
Use MUI for standard UI primitives. Use Trinity for domain-specific components, tokens, and hooks.
// MUI primitives
import { Button, Card, TextField } from '@mui/material';
// Trinity components
import { StatusIndicator, Toast, useToast } from '@trinityui/design-system';3. Dark mode
import { lightTheme, darkTheme } from '@trinityui/design-system';
<ThemeProvider theme={isDarkMode ? darkTheme : lightTheme}>
<CssBaseline />
<App />
</ThemeProvider>4. Add the AI assistant
AppLayout is the app shell; with aiTrigger="fab" it opens an AI panel, docked and resizable (320 to 800px) or fullscreen, and a full-width drawer on phones. Wire your backend through panelProps:
import { AppLayout, type ChatMessage } from '@trinityui/design-system';
<AppLayout
navStyle="topnav"
aiTrigger="fab"
panelProps={{
messages,
onMessagesChange: setMessages,
onSendMessage: (text, options) => ask(text, options),
streaming: waitingForAnswer,
userInitials: user.initials,
messageActions: { onFeedback: rate, onRegenerate: regenerate },
}}
>
<Page />
</AppLayout>| Option | Default | What it does |
|---|---|---|
| aiPanelSide | 'end' | 'start' docks the panel before the page content (the FAB, the resize handle and the phone drawer follow) |
| aiPanelWidth | 420 | The panel's first width; people resize it from 320 to 800px by dragging or with the arrow keys |
| keepAiPanelMounted | false | Keeps the draft, the conversation and the scroll position while the panel is closed |
| renderAiPanel | none | Renders your own surface (for example AICopilotPattern or InsightEngine presentation="embedded") inside the same panel, with onClose, isFullscreen and onFullscreenToggle |
| showFabWhenPanelOpen | false | Keeps the AI FAB beside the docked panel; by default it hides while the panel is open and focus returns to it on close |
| mobilePanelPresentation | 'drawer' | 'docked' keeps the desktop panel below the md breakpoint |
Answers with plans to confirm, clarifying questions, queries, confidence, verification and reasoning use the same panel (onBlockEvent, getReasoning); the AI panel guide explains the three routes and the 2.13.0 panel changes, and the AI table says which component does what.
5. AI strings and white-labelling
The AI components read their built-in strings from one catalog, which AIConfigProvider replaces for translation and white-labelling, with the confidence thresholds, locale and time zone (Overriding strings). The provider is not a package export yet: it waits for its component proposal vote, and the Storybook page AI/AIConfigProvider shows the proposed API. Until it ships, use the components' own props (for example the panel's title and placeholder).
6. Without React
Load the CSS package and use the --trinity-* variables; data-theme="dark" switches the mode. See CSS-Only Usage and the AI agent guide in Storybook (Getting Started/AI Agent Guide, "CSS only" track).
For the full getting-started guide, see docs/QUICK_START.md and the Getting Started page in Storybook.
What's New in 2.13.0
2.13.0 ships the remediation program's work in one minor release; nothing is removed (removals wait for v3.0).
- AI and human in the loop:
AIPlanReview,AIClarificationPrompt,AIQueryDisclosure,AIConfidenceBadge,AIVerificationBadge,AIFeedbackControlandAIFeedbackForm,AISourceChipwith inline citations,AIRelatedQuestions,AIReviewItemand the newAIReviewQueueTemplate, the golden-dataset action onAIMessage, theAIChatWelcomestart screen, the redesignedAIChainOfThought, and theAICopilotPatternpattern. - AppLayout's AI panel: messages render through
ChatThreadwith the interactive blocks;aiPanelSide,keepAiPanelMounted,renderAiPanel,showFabWhenPanelOpenand the phone drawer are new. - Theme: new colour roles (the AI avatar and launcher gradient, AI progress, the start-screen canvas, favorite), each in the tokens, the React theme and the CSS package.
- Accessibility: WCAG 2.2 AA, a strict behavior contract on every component, and screen-reader announcements across the AI set.
- Behavior corrections: defaults that were objectively broken change in this minor (ADR-23). MIGRATION.md, Behavior corrections lists each one with its before, after, opt-out and consumer action (the release adds the rows from its changesets), and the release notes land in CHANGELOG.md when 2.13.0 is published.
Component Catalog
Navigation
| Component | Import | Description |
|---|---|---|
| TopNavHeader | @trinityui/design-system | Primary navigation header with search, client switcher, and user menu |
| TopNavWithSidebar | @trinityui/design-system | Full layout with collapsible sidebar navigation |
| Footer | @trinityui/design-system | Page footer — light and dark variants, compact 40px height |
| SearchBar | @trinityui/design-system | Header search bar primitive with suggestion support |
| ClientMenu | @trinityui/design-system | Client/tenant switcher dropdown |
| AppsMenu | @trinityui/design-system | Application launcher grid menu |
Also exports: TrinityLogo, UserMenu, HeaderActions, and 14 navigation type definitions.
Layout
| Component | Import | Description |
|---|---|---|
| AppLayout | @trinityui/design-system | Primary app shell — nav + content + optional AI panel |
| PageHeader | @trinityui/design-system | Page header with breadcrumbs, title, and actions |
| SplitPane | @trinityui/design-system | Resizable split view (horizontal/vertical) |
| DockLayout | @trinityui/design-system | Dockable panel layout with configurable zones |
| ResizablePanel | @trinityui/design-system | Standalone resizable side panel |
| InsightEnginePanel | @trinityui/design-system | AI insight panel designed for AppLayout integration |
| LandingPage | @trinityui/design-system | Pre-built landing page template |
Also exports the page templates (DashboardTemplate, ListDetailTemplate, SettingsTemplate and the others under Templates/ in Storybook). Templates and patterns are public components, imported from the root like everything else.
AI
The largest component category — a full suite for building AI-powered experiences.
AI Containers & Orchestration
| Component | Description | Storybook |
|---|---|---|
| InsightEngine | A whole AI surface: header, history, ChatThread and composer; a right-anchored drawer (presentation="drawer", the default) or presentation="embedded" to fill its parent | AI/InsightEngine |
| InsightEnginePanel | The AI panel of AppLayout (aiTrigger; configure it with panelProps or replace it with renderAiPanel): docked and resizable or fullscreen, a modal drawer below md. Renders its messages through ChatThread, with messageActions / onRegenerate, getReasoning (an AIChainOfThought in the message), onBlockEvent and blockRenderers (the interactive blocks, hitlBlockRenderers by default) | Templates/InsightEnginePanel |
| AIChatWelcome | The AI start screen before the first message, in the showcase (greeting, centred composer, category cards) or context variant (scope chips, Continue, New since yesterday, Try asking); laid out by its container width; the default start screen of InsightEnginePanel and InsightEngine (welcome) | AI/AIChatWelcome |
| ChatThread | The conversation log: each turn as AIMessage or UserMessage, with the message actions (messageActions), the interactive blocks (onBlockEvent, blockRenderers, renderBlock), per-message slots (getMessageSlots) and the follow-up questions | AI/ChatThread |
| ChatHeader | Chat view header with mode switching | AI/ChatHeader |
| ChatHistoryList | Navigable list of past conversations | AI/ChatHistoryList |
AI Input
| Component | Description | Storybook |
|---|---|---|
| InsightEngineInput | The AI composer: send, stop while generating, mentions, models and sources, voice input, and an unavailable state with its reason | AI/InsightEngineInput |
| AIVoiceOverlay | Voice input overlay with transcription | AI/AIVoiceMode |
| AIVoiceMode | Full-screen voice conversation mode: an orb that follows the conversation, a live transcript, mute and end | AI/AIVoiceMode |
| AIListeningIndicator | Animated listening state indicator | AI/AIVoiceMode |
| PredictiveTextInput | AI-powered autocomplete text input (OpenAI-compatible) | Form Inputs/PredictiveTextInput |
AI Human in the Loop
| Component | Description | Storybook |
|---|---|---|
| AIPlanReview | The plan the AI proposes before it runs a query, for the user to review, correct and confirm (inline or in a dialog; readOnly for the record) | AI/AIPlanReview |
| AIReviewItem | One answer in a golden-dataset review: the question, what produced the answer, and the reviewer's approve, edit or reject decision with its history | AI/AIReviewItem |
| AIClarificationPrompt | A clarifying question the AI asks before it answers: options, a free-text answer and a typed result the backend can act on | AI/AIClarificationPrompt |
| AIClarificationFlow | Two to five related clarifying questions in one card, answered one at a time, with progress, Back and Next | AI/AIClarificationFlow |
| AIChangeSummary | What the AI changed in a document, on its version card: changed rows first, unchanged muted, Open | AI/AIChangeSummary |
| AIReplyBar | The next step at the end of an AI answer: one primary reply and a few suggestions, locked after use | AI/AIReplyBar |
| AIQueryDisclosure | The query behind an answer, shown on demand, with Copy | AI/AIQueryDisclosure |
| AIFeedbackControl | Thumbs up and down on an answer, and the "Tell us what went wrong" flow | AI/AIFeedbackControl |
| AIFeedbackForm | What went wrong with an answer: problem types, a comment and an optional rerun | AI/AIFeedbackForm |
| AIConfidenceBadge | How confident the AI is in an answer, as a level and a percent, with the rationale on demand | AI/AIConfidenceBadge |
| AIVerificationBadge | Who checked an answer or a plan, as a glyph and a label, with the details on demand | AI/AIVerificationBadge |
AI Rendering & Explainability
| Component | Description | Storybook |
|---|---|---|
| AIResponseRenderer | Renders an AI response's blocks: text blocks natively (through AITextBlock); the interactive blocks through hitlBlockRenderers; tables, charts and other block types through your blockRenderers (one component per block type) or renderBlock | AI/AIResponseRenderer |
| AITextBlock | Text of an AI response: plain text, or lightweight markdown (bold, italic, code, links, headings, lists, quotes, fenced code) with opt-in [^id] source citations and headingOffset | AI/AITextBlock |
| AIChainOfThought | The reasoning behind an answer: thinking, a plan awaiting confirmation, execution with failed tasks and Retry, and the output | AI/AIChainOfThought |
| AIExplainability | Confidence scores and explainability panel | AI/AIExplainability |
| AISource | One source citation | AI/AISourcesSection |
| AISourcesSection | A simple list of source citations | AI/AISourcesSection |
| AISourcesPanel | Source citations grouped by category | AI/AISourcesPanel |
| AISourceChip | One source at the number, sentence, table cell or chart point it supports: a number or label chip that opens the source's details | AI/AISourceChip |
| AIRelatedQuestions | Suggested follow-up questions | AI/AIRelatedQuestions |
AI Messages & Avatars
| Component | Description | Storybook |
|---|---|---|
| AIMessage | An assistant turn: the response blocks, sources, follow-ups, the reasoning slot and the actions (Copy always; Feedback, Share, Download and Regenerate when their handler is passed) | AI/AIMessage |
| UserMessage | A user turn | AI/UserMessage |
| AIAvatar | AI bot avatar (animated) | AI/AIAvatar |
| UserAvatar | User avatar for chat contexts | AI/AIAvatar |
| AILabel | "AI-generated" badge/label (multiple sizes and variants) | AI/AILabel |
AI Actions & Layout
| Component | Description | Storybook |
|---|---|---|
| AISuggestedAction | A suggested action as a pill button | AI/AISuggestedAction |
| AICircularAction | A suggested action as a circular icon button | AI/AICircularAction |
| AIActionsGroup | A group of suggested actions | AI/AIActionsGroup |
| AIContainer | Themed container for AI content | AI/AIContainer |
| AIExpandableSection | Collapsible section for AI detail panels | AI/AIExpandableSection |
| AIPersonaCard | AI persona/agent identity card | AI/AIContainer |
| AIDigestCard | An AI-generated daily or weekly briefing card | AI/AIDigestCard |
| GradientText | Gradient text for AI headings | AI/AIVisuals |
| GradientIconBadge | Gradient icon badge for AI UI | AI/AIVisuals |
| StatCard | KPI stat card for AI dashboards | AI/AIVisuals |
| AIShimmer | Shimmer loading state for AI content | AI/AIShimmer |
AI Contracts & Helpers
| Export | What it is |
|---|---|
| hitlBlockRenderers | The built-in renderers of the interactive blocks (query, clarification, plan-review): pass as blockRenderers or spread into your own map |
| ChatThreadMessage | One message of ChatThread (role, content, response, sources, relatedQuestions, feedback, streaming) |
| ChatThreadMessageSlots | The slots of an assistant message (badges, feedbackControl, attachments) that getMessageSlots can replace |
| InsightEnginePanelMessageActions | The panel's message actions: onCopy, onFeedback, onFeedbackSubmit, onShare, onDownload, onRegenerate, getActions |
| AIMessageAction | An app action on an assistant message (getActions) |
| AIRelatedQuestion | A follow-up question: its text, an optional stable id and the verified mark |
| aiTokens | The AI design tokens |
Deprecated (v3.0)
These still work in 2.x and warn once in development; do not start new work with them (MIGRATION.md).
| Deprecated | Use instead | Storybook |
|---|---|---|
| AIChatMessage | AIMessage (and UserMessage for the user's turn) | AI/AIMessage |
| AIChatInput | InsightEngineInput, or ChatThread for a whole conversation | Deprecated/AIChat |
| AITypingIndicator | AIMessage's streaming state with AIShimmer | Deprecated/AIChat |
| AIQuickReply | AISuggestedAction or AIActionsGroup | Deprecated/AIChat |
| QueryInput | InsightEngineInput | AI/InsightEngineInput |
| AIFabLayout | AppLayout with navStyle="topnav" and aiTrigger="fab" | Templates/AppLayout |
All AI components import from @trinityui/design-system. AI-specific design tokens available via aiTokens.
Data Display
| Component | Import | Description |
|---|---|---|
| DataTable | @trinityui/design-system/data-table | AG Grid Enterprise powered — sorting, filtering, grouping, pivot, server-side row models |
| SimpleTable | @trinityui/design-system/essentials | Lightweight table for simple data (no AG Grid dependency) |
| DataCard | @trinityui/design-system | KPI/metric card with trend indicator and sparkline |
| DiffViewer | @trinityui/design-system | Side-by-side or unified diff viewer |
| Timeline | @trinityui/design-system | Vertical timeline with status indicators |
| TreeView | @trinityui/design-system | Hierarchical tree view with expansion and selection |
| TransferList | @trinityui/design-system | Dual-list transfer component with search and bulk actions |
| StatusIndicator / StatusLegend | @trinityui/design-system | Unified status display (success/warning/error/info) + legend |
DataTable setup:
import { DataTable, setAgGridEnterpriseLicenseKey } from '@trinityui/design-system/data-table';
// Set license key once at app bootstrap
setAgGridEnterpriseLicenseKey('<YOUR_KEY>');App Layout
AppLayout is the recommended shell for React applications that need Trinity branding, sidebar navigation, user context, and optional AI panel integration.
import * as React from 'react';
import HomeOutlinedIcon from '@mui/icons-material/HomeOutlined';
import BarChartIcon from '@mui/icons-material/BarChart';
import SettingsOutlinedIcon from '@mui/icons-material/SettingsOutlined';
import { AppLayout, type NavItem } from '@trinityui/design-system';
const navItems: NavItem[] = [
{ id: 'home', label: 'Home', icon: <HomeOutlinedIcon /> },
{ id: 'analytics', label: 'Analytics', icon: <BarChartIcon /> },
{ id: 'settings', label: 'Settings', icon: <SettingsOutlinedIcon /> },
];
export default function AppShell() {
const [selectedNavItem, setSelectedNavItem] = React.useState('home');
return (
<AppLayout
navStyle="sidebar"
aiTrigger="none"
companyName="Portfolio Console"
navItems={navItems}
selectedNavItem={selectedNavItem}
onSelectedNavItemChange={setSelectedNavItem}
user={{ name: 'Jane Doe', email: '[email protected]', initials: 'JD' }}
>
<main>Page content</main>
</AppLayout>
);
}Optional header regions can be disabled when the consuming app owns those controls elsewhere:
<AppLayout
navStyle="sidebar"
showSearch={false}
showClientSelector={false}
showSidebarToggle={false}
>
<main>Page content</main>
</AppLayout>| Prop | Default | Description |
|---|---:|---|
| showSearch | true | Shows the desktop search field and mobile search action. |
| showClientSelector | true | Shows the client selector dropdown in the header. |
| showSidebarToggle | true | Shows the sidebar hamburger/collapse button in sidebar mode. |
Input & Forms
| Component | Import | Description |
|---|---|---|
| Autocomplete | @trinityui/design-system | Full-featured autocomplete — async loading, pagination, sortable chips, virtualization |
| VirtualizedAutocomplete | @trinityui/design-system | Deprecated (removed in v3.0): use Autocomplete, which is already virtualized |
| Combobox | @trinityui/design-system | Accessible combobox with keyboard navigation |
| SearchInput | @trinityui/design-system | Standalone search input with suggestion dropdown |
| ClearableTextField | @trinityui/design-system | Text field with integrated clear button |
| ChipsInput | @trinityui/design-system | Tag/chip entry input with validation |
| MentionsInput | @trinityui/design-system | @mention-enabled text input |
| FileUpload / UploadDropZone | @trinityui/design-system | Drag-and-drop file upload with progress |
| CommandPalette | @trinityui/design-system | Cmd+K style command palette with fuzzy search |
| FilterBar | @trinityui/design-system | Multi-filter toolbar with presets and saved filters |
| NestedMenu | @trinityui/design-system | Multi-level nested menu |
| Cron | @trinityui/design-system | Visual cron expression builder |
| Carousel | @trinityui/design-system | Content carousel with transition effects |
| Popper | @trinityui/design-system | Positioning utility component |
Form Utilities
import { FormProvider, useForm, useFormField } from '@trinityui/design-system';
// Built-in validators
import { required, email, minLength, maxLength, pattern, min, max, custom } from '@trinityui/design-system';FormProvider gives you form state management with composable validation — no additional form library required.
Async Autocomplete Example
import { Autocomplete, type AutocompleteAsyncRequest } from '@trinityui/design-system';
const loadUsers = async ({ search, page, pageSize, signal }: AutocompleteAsyncRequest) => {
const res = await fetch(`/api/users?q=${encodeURIComponent(search)}&page=${page}&pageSize=${pageSize}`, { signal });
const data = await res.json();
return { options: data.items, hasMore: data.hasMore, nextPage: page + 1 };
};
<Autocomplete
name="users"
label="Users"
options={[]}
multiple
value={[]}
onHandleChange={(next) => setUsers(next)}
labelProperty="name"
valueProperty="id"
async={{ dataSource: loadUsers, paginate: true, pageSize: 25, debounceMs: 250 }}
/>Predictive Text Input (OpenAI via Azure Function)
import { PredictiveTextInput, createOpenAIPredictor } from '@trinityui/design-system';
const predictor = createOpenAIPredictor({ endpoint: '/api/predictive-text', maxSuggestions: 5 });
<PredictiveTextInput label="Prompt" value={value} onChange={setValue} onPredict={predictor} />See the Azure Function template for the backend.
Feedback
| Component | Import | Description |
|---|---|---|
| Modal | @trinityui/design-system | Modal dialog with size variants and accessible focus management |
| ConfirmDialog | @trinityui/design-system | Confirm/cancel dialog (also available via useConfirmDialog hook) |
| ToastProvider / Toast | @trinityui/design-system | Toast notification system (wrap app in ToastProvider, trigger via useToast) |
| IllustratedMessage | @trinityui/design-system | Empty state / error illustrated message |
| Tour | @trinityui/design-system | Guided product tour with step-by-step highlights |
| GoToTop | @trinityui/design-system | Scroll-to-top floating button |
Charts
All charts are Highcharts-based, with Trinity theming applied automatically.
| Component | Description |
|---|---|
| LineChart | Line/time-series chart |
| BarChart | Vertical/horizontal bar chart |
| AreaChart | Filled area chart |
| PieChart | Pie chart |
| DonutChart | Donut variant |
| ScatterChart | Scatter plot |
| BubbleChart | Bubble chart |
| RadialBarChart | Radial/polar bar chart |
| GaugeChart | Gauge/meter chart |
| ComposedChart | Mixed line + bar + area chart |
| Sparkline | Inline mini chart for data cards |
| ChartWrapper | Chart container with consistent sizing |
| CustomTooltip / SimpleTooltip | Chart tooltip components |
| CustomLegend / InteractiveLegend / PieLegend | Chart legend components |
All import from @trinityui/design-system. Full type definitions for DataPoint, SeriesConfig, AxisConfig, and chart-specific props.
Icon System
import { Icon, IconProvider } from '@trinityui/design-system';
// Wrap with IconProvider to set the active icon library
<IconProvider library="feather">
<Icon name="check" size="md" />
</IconProvider>Supports multiple icon libraries via IconProvider. Six intent-based sizes: inline (14px), xs (16px), sm (18px), md (20px), lg (24px), display (36px).
Patterns
Reference compositions of public organisms in src/patterns/ (Patterns, ADR-12): a pattern owns layout and wiring only, with no state, live region, landmark or focus code of its own. Exported from the root entry only.
| Pattern | Status | Story |
|---|---|---|
| AICopilotPattern | Built (2.13.0): the HITL copilot (InsightEngine, the plan-review and clarification blocks, reasoning and sources), as a drawer or embedded in AppLayout's AI panel through renderAiPanel | Patterns/AICopilot |
| DashboardPattern, DataTablePattern, FilterPattern, EmptyStatePattern | Not started (owner unassigned) | - |
Hooks (33)
All hooks import from @trinityui/design-system.
| Hook | Description |
|---|---|
| useDebounce | Debounce a value by delay |
| useDebouncedCallback | Returns a debounced callback function |
| useInterval | Declarative setInterval with cleanup |
| useToggle | Boolean toggle: [value, toggle, setValue] |
| usePrevious | Access the previous render's value |
| useLocalStorage | Persist state to localStorage; server and hydration renders use initialValue |
| useClipboard | Copy text, with an optional screen reader announcement of the outcome |
| useOnClickOutside | Detect clicks outside a ref element |
| useKeyPress | Detect a specific key press |
| useAnnounce | Announce a message to screen readers through the nearest live region |
| useAriaLive | Live-region announcements; announces through useAnnounce, or through your own region when you spread its ariaProps |
| useDisclosure | Expand/collapse and popup triggers: aria-expanded, aria-controls and ids from useId |
| useAsyncAction | Run an async action once at a time: errors reported, pending, success and error announced |
| useRovingTabIndex | Arrow-key navigation for composite widgets (registry form) |
| useReducedMotion | Detect the prefers-reduced-motion preference (SSR-stable) |
| useFocusTrap | Deprecated (removed in v3.0): use MUI's built-in trap (Dialog, Popover, Menu, temporary Drawer) |
| useTrinityBreakpoints | Responsive flags: isMobile, isTablet, isDesktop, isLargeDesktop |
| useTrinityTokens | Typed access to the semantic tokens of the current theme |
| useTrinityPalette | Access Trinity semantic palette from the current theme |
| useForm | Form state manager paired with <FormProvider> |
| useFormField | Field registration and validation inside <FormProvider> |
| useConfirmDialog | Imperatively open confirmation dialogs |
| useToast | Show toast notifications (requires ToastProvider) |
| useFlowAutoLayout | Auto-layout for React Flow / XYFlow diagrams |
| useBrowserVoiceMode | Browser speech recognition and synthesis for AIVoiceMode |
| useSourceCategories | A response's sources as AISourcesPanel categories, numbered like inline source chips, with the AI strings, locale and time zone |
| useFormatAsOf | Formats ISO 8601 as-of dates and date-times the same way on the server and in the browser |
| useBlockSources | The sources behind one table or chart block of an AI response: per cell, per point, and each source's number |
| useAIStrings | The AI strings: the nearest AIConfigProvider's strings merged over its ancestors' and the English defaults |
| useAIThresholds | The confidence thresholds from the nearest AIConfigProvider, or the defaults (medium from 60%, high from 85%) |
| useAILocale | The locale for numbers and counts from AIConfigProvider, or undefined (formatters then use en-US) |
| useAITimeZone | The IANA time zone for dates from AIConfigProvider, else the runtime's; UTC during server rendering |
| useAIInteraction | Reports a content-free AIInteractionEvent to the nearest AIConfigProvider's onInteraction; a no-op without one |
The behavior toolkit (useAnnounce, liveRegionProps, REDUCED_MOTION_QUERY, visuallyHiddenSx, useDisclosure, useAsyncAction and the hooks above) is the one sanctioned way to build each behavior; docs/BEHAVIOR_CONTRACT.md maps every behavior to its export.
Accessibility
Trinity targets WCAG 2.2 AA. Every story runs axe in Storybook, the behavior contract's rules are all strict with no open finding, and the AI components announce their state changes to screen readers. Right-to-left layouts are best effort: logical properties, the theme's direction and bidi isolation are kept, but RTL is not release-tested (docs/RTL.md). The system provides:
| Feature | Details |
|---|---|
| Automated testing | vitest-axe (axe-core) a11y tests, dedicated test:a11y script |
| Linting | eslint-plugin-jsx-a11y enforced across all components |
| Storybook addon | @storybook/addon-a11y for interactive accessibility auditing |
| Behavior toolkit | useAnnounce, liveRegionProps, useAriaLive, useDisclosure, useAsyncAction, useClipboard, useRovingTabIndex, useReducedMotion, REDUCED_MOTION_QUERY (BEHAVIOR_CONTRACT); useFocusTrap is deprecated in favor of MUI's built-in trap |
| Skip links | SkipLink component for keyboard-first navigation |
| Accessible colors | accessibleCombinations — pre-validated WCAG AA text/background pairs |
| Contrast utilities | getContrastRatio(), validateAccessibility(), meetsWCAG() |
| Visual hiding | VisuallyHidden component for screen-reader-only content, and visuallyHiddenSx for an element that cannot be one |
import { accessibleCombinations } from '@trinityui/design-system';
// Pre-validated WCAG AA pairs
<Box sx={{
backgroundColor: accessibleCombinations.whiteOnNavy.bg,
color: accessibleCombinations.whiteOnNavy.text,
}}>
Guaranteed 4.5:1+ contrast ratio
</Box>For the full accessibility guide and component checklist, see docs/ACCESSIBILITY.md and docs/COMPONENT_A11Y_CHECKLIST.md.
Design Tokens
Trinity uses a 3-tier token architecture (2,700+ lines) spanning colors, spacing, typography, shadows, motion, z-index, border radius, opacity, breakpoints, and effects.
Token Tiers
| Tier | Purpose | Example |
|---|---|---|
| Base | Raw primitive values | baseTokens.colors.navy[900] → #050742 |
| Semantic | Contextual meaning | semanticTokens.colors.interactive.primary |
| Component | Component-level defaults | componentTokens.card.borderRadius → 12px |
Token Coverage
| Category | What's included | |---|---| | Colors | 6 brand palettes (navy, purple, indigo, coral, azure, gray) with full shade ranges | | Semantic colors | Brand, text (11 variants), background (8), surface (7), border (6), interactive (5), status (4 × 3) | | Spacing | 20-step scale (0–32), component spacing, layout spacing with dimensions, density scale | | Typography | 10 sizes, 6 weights, 6 line heights, 6 letter spacings, semantic scales (display/heading/body/label) | | Border radius | 9-step scale (none → 9999px), semantic radius (button, input, card, modal, badge, avatar, chip, tooltip) | | Shadows | 8 levels + semantic (card, dropdown, modal, button, input), effect-based (surface, dialog, inset) | | Motion | 7 durations (fastest → slowest) + 7 easings (linear, bounce, elastic, etc.) | | Z-index | 7 numeric levels + 7 semantic (dropdown, sticky, modal, tooltip) | | Effects | Overlay, onDark states, focus rings, status indicators |
Usage
import { baseTokens, semanticTokens, componentTokens } from '@trinityui/design-system/tokens';All tokens are also available as CSS variables, in two name families. The static stylesheet (trinity.css in @trinityui/design-system/css and @trinityui/design-system-css) uses short names. The runtime variables that injectTrinityCssVariables() adds use color-, spacing-, semantic- and component- names. Use the names of the layer you load.
/* Static stylesheet (trinity.css) */
var(--trinity-navy-900) /* base */
var(--trinity-text-primary) /* semantic */
var(--trinity-switch-track-on) /* component */
/* Runtime variables (injectTrinityCssVariables) */
var(--trinity-color-navy-900) /* base */
var(--trinity-semantic-text-primary) /* semantic */
var(--trinity-component-switch-track-on) /* component */For token usage rules, see docs/TOKEN_USAGE_RULES.md.
Theme Presets
Three pre-configured theme presets for different product contexts:
| Preset | Light / Dark | Use Case |
|---|---|---|
| CRM | crmLightTheme / crmDarkTheme | Compact tables, dense forms, high information density |
| Portal | portalLightTheme / portalDarkTheme | Large touch targets, accessible sizing, customer-facing |
| Analytics | analyticsLightTheme / analyticsDarkTheme | Data visualization optimized, chart-friendly palette |
import { crmLightTheme, crmDarkTheme } from '@trinityui/design-system';
<ThemeProvider theme={isDarkMode ? crmDarkTheme : crmLightTheme}>
<App />
</ThemeProvider>You can also create custom presets with createTrinityThemePreset().
CSS-Only Usage
For Angular, Vue, or static HTML projects:
/* Option 1: package import */
@import '@trinityui/design-system-css';
/* Option 2: direct file path */
@import 'node_modules/@trinityui/design-system-css/dist/trinity.css';<!-- Dark mode: add data-theme attribute -->
<html data-theme="dark">All design tokens are exposed as --trinity-* CSS variables with the static stylesheet names (--trinity-navy-900, --trinity-space-4). See the CSS package README for the full variable reference.
Storybook
Interactive component documentation with live controls, dark mode toggle, and accessibility audits:
pnpm run start # Opens at http://localhost:6006Stories for every public component, with:
- Live prop controls and variant previews
- Dark mode toggle for all components
- Accessibility audit panel (axe-core integration)
- Code examples with copy-to-clipboard
- Autodocs — auto-generated API documentation from TypeScript types
MCP (Model Context Protocol)
Trinity exposes component and docs knowledge to AI coding agents (Claude Code, Cursor, etc.) over MCP, so agents can look up real props, variants, and usage examples instead of guessing them.
| Server | URL | When to use |
|---|---|---|
| trinity-design-system-mcp | https://design.trinitylifesciences.com/api/mcp | Production, backed by the Storybook of the latest stable release (see below). Use this for day-to-day agent work. |
| trinity-storybook | http://localhost:6006/mcp | Local dev only. Backed by @storybook/addon-mcp, requires pnpm run start to be running. |
Both are pre-configured in .mcp.json — an MCP-aware client picks them up automatically from the repo root.
Available tools: list-all-documentation, get-documentation, get-documentation-for-story.
How the production server is deployed
The production endpoint is not a separate service — it's an Azure Functions app in api/ (@storybook/mcp), deployed alongside the static Storybook build by the Azure Static Web Apps workflow (api_location: "api").
- What it serves. The workflow copies the build's own component manifest (
manifests/components.json), itsindex.jsonand the package version intoapi/manifests/, and installs the API withnpm cifromapi/package-lock.json. The endpoint therefore lists exactly the components of the deployed build, named by their export (for exampleInsightEngine), without internal components. A component's status leads its summary and description:[Deprecated — use X],[Prerelease — @next only]or[Documentation incomplete](api/src/manifest.js). Without a bundled manifest it falls back to one derived from the deployedindex.json. - Which version. Production shows the latest stable release only: it is deployed after a successful npm publish, from the published commit. Pushes to
maingo to a separatenextenvironment (CHANGESETS.md). Both deploys are paused while the remediation program pauses npm publishing.
staticwebapp.config.json allows anonymous access to /api/mcp, /index.json, and /project.json specifically so the MCP handler and its manifest source stay reachable without authentication, while the rest of the site stays behind Azure AD.
Verifying it's up
MCP is a JSON-RPC protocol over POST, not a browsable page — hitting the URL directly in a browser opens a GET request that the transport treats as an idle SSE stream, which will hang and can surface as Azure's generic "Backend call failure" page. That's expected, not a sign of an outage. To check health, send a real initialize request:
curl -s -X POST https://design.trinitylifesciences.com/api/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"health-check","version":"0.0.1"}}}'A healthy response is HTTP/2 200 with an mcp-session-id header and a JSON-RPC result containing serverInfo.name: "@storybook/mcp".
For a full check, node scripts/mcp-smoke.mjs --url <host>/api/mcp --manifest storybook-static/manifests/components.json also lists the components and compares them with the manifest the deploy bundled. The catalog workflow runs it after every deploy, and the deploy fails when they differ. The next environment's URL, for checking unreleased work, is in the Azure portal (Static Web App → Environments). The production endpoint currently answers POST with HTTP 405; the triage and the open checks are in docs/DOCS_DEPLOYMENT.md.
Development
pnpm install # Install dependencies
pnpm run start # Storybook dev server (:6006); there is no separate app dev server
pnpm run build # Token CSS sync, Vite library build and declarations
pnpm run typecheck # Library type check and the app type-debt ratchet
pnpm run test # Run all tests
pnpm run test:a11y # Run accessibility tests only
pnpm run lint:changed # ESLint on the lines you changed
pnpm run lint:tokens # Token usage rule validation
pnpm run size # Check bundle size limits
pnpm run verify:release # Every release gate, in CI orderRelease and Publishing
- Versions and changelogs come from Changesets. Pull requests add changesets. A maintainer runs
pnpm changeset:versionon a release branch and merges the version andCHANGELOG.mdchanges tomainthrough a reviewed pull request.@trinityui/design-systemand@trinityui/design-system-cssare versioned together. - Only verified artifacts are published.
verify-release.ymlruns every gate ofpnpm run verify:release(the ordered list is in docs/process/CI.md) on pull requests tomainandrelease/**, and packs two checksum-bound tarballs, each with its LICENSE. The publish workflows run that verification again for the commit they publish. Thepublishjob checks the tarballs' checksums and publishes only those tarballs, with npm provenance and lifecycle scripts disabled, and only for versions not yet on npm. - Direct publication is blocked. In a source checkout, a
prepublishOnlyguard in both packages stopsnpm publishandpnpm publish,pnpm changeset:publishruns the same guard, andpnpm run check:release-pathsenforces the single publication path. - Publishing is paused during the remediation program. The
publishjob isif: false, so a push tomainruns verification and publishes nothing. See G-05 freeze record.
Documentation
| Document | Description | |---|---| | Quick Start | 5-minute getting-started guide | | Developer Guide | Comprehensive development reference | | Accessibility | WCAG 2.2 AA compliance guide | | Behavior Contract | The behavior rules every component meets, and the toolkit export for each | | Component A11y Checklist | Per-component accessibility requirements | | Token Usage Rules | When and how to use each token tier | | Storybook Standards | Story authoring conventions | | Testing Strategy | Unit, a11y, and visual regression testing | | Integrating into Existing Apps | Migration guide for existing projects | | New App Setup | Starting a new project with Trinity | | Component Picker | Which component to use, and what the theme changes on MUI components | | Patterns | The pattern layer: contract, index, export waiver | | AppLayout AI Panel | The AI panel's three routes, both modes, and what changed in 2.13.0 | | HITL Catalog | The human-in-the-loop components and their stories | | Microcopy | Voice, labels, errors and the AI strings | | Governance | Contribution process, RFC, and deprecation policy | | Migration | Behavior corrections in 2.x and the v3.0 removals | | Contributing | How to contribute | | Changelog | Release history |
License
MIT
