Assistant UI Package
@maya/assistant-ui is the production-grade React workspace UI package for Maya applications. It packages the workspace shell, route model, composer, transcript, settings, auth, sharing, theming, and operational contracts needed to ship an assistant surface with host-owned product data. It is not a grab bag of generic UI primitives; standalone entries let hosts adopt focused parts of the same assistant workspace experience.
This file is the single documentation source for consuming the package: install shape, peer dependencies, CSS assets, public subentries, tokens, controller wiring, accessibility expectations, and performance guidance all live here.
The package is UI-only. Host applications own protocol mapping, backend calls, persistence, command runtimes, and environment-specific adapters before passing data into the public controller types.
Workspace Composition Boundary
WCP-012 names @maya/claude-workspace as the owner for Claude product defaults: built-in route descriptors, sidebar descriptors, settings and customize surfaces, transcript/tool/activity renderer descriptors, fallback surfaces, and default policy. WCP-019 adds its private package root for descriptors and the deterministic runtime builder.
React page components still live in this package until migration is complete. Claude built-in render pack exports remain deferred to post-v0 @maya/claude-workspace work. New composition work should move product ownership toward @maya/claude-workspace while keeping generic rendering, scoped tokens, primitives, and AssistantWorkspace execution inside @maya/assistant-ui.
@maya/assistant-ui must not import @maya/claude-workspace, discover render packs automatically, resolve grants, or create hidden global render state.
Scoped Render Runtime
@maya/assistant-ui/render-runtime exposes the WCP-015 foundation for executing opaque composition render handles through explicit host-provided React render packs. It is a scoped runtime factory, not a package-level registry.
Use this subentry only when the host already has a WorkspaceComposition from @maya/assistant-composition and wants to execute handles without placing React components inside the headless composition output:
import { createReactRenderRuntime } from '@maya/assistant-ui/render-runtime';
import type { ReactRenderPack } from '@maya/assistant-ui/render-runtime';
const renderRuntime = createReactRenderRuntime({
packs: [claudeRenderPack, dataLabProdRenderPack] satisfies ReactRenderPack[],
mode: 'client',
});
Render runtimes accept explicit ReactRenderPack arrays only. They do not scan packages, auto-discover modules, install code, use remote ESM, mutate global state, or register providers at import time. A host can create multiple runtime instances for multiple workspaces, tenants, or test cases, and each runtime keeps its own diagnostics, events, providers, and subscribers.
The runtime diagnostics are structured WorkspaceDiagnostic objects with origin: 'render-runtime'. Grants remain UI activation contracts; backend authorization, secrets, persistence, and network execution stay outside this package.
Install
Published consumers install from the registry:
pnpm add @maya/assistant-composition @maya/assistant-ui react react-dom
For unpublished release candidates, validate with the tarballs produced by pnpm pack:dry-run or with workspace links inside this monorepo. Switch external consumers to the registry install only after the requested package version has been published.
import '@maya/assistant-ui/styles.css';
import { AssistantWorkspace } from '@maya/assistant-ui';
Import @maya/assistant-ui/global.css only when the host wants the optional document-level reset.
Peer Dependencies
| Peer | Range | Required | Notes |
|---|---|---|---|
@maya/assistant-composition | >=0.1.0 <0.2.0 | Yes | Shared headless composition contract. Hosts install it explicitly so UI and modules use one ABI. |
react | >=18.2.0 <20 | Yes | React 18 and React 19 are supported. |
react-dom | >=18.2.0 <20 | Yes | Match the host application's React major. |
mermaid | ^11.15.0 | No | Optional peer used only when transcript code blocks render Mermaid diagrams. |
lucide-react is a package dependency. Host apps do not need to install it separately. @maya/assistant-ui must not bundle or redeclare @maya/assistant-composition types; public declarations import the headless contract package as the ABI owner.
CSS And Global Opt-In
Use these CSS entries deliberately:
| CSS entry | Scope | Use |
|---|---|---|
@maya/assistant-ui/styles.css | Component-scoped under .aui-root | Required for visible components. Includes the generated token variables and package font-face declarations. It must not reset host body, host buttons, or non-package controls. |
Component CSS subentries such as @maya/assistant-ui/composer.css | Component-scoped under .aui-root | Import for lightweight standalone components when the host does not render the full workspace. These files are generated from the same CSS partials as styles.css; they are not a second style source. |
@maya/assistant-ui/tokens.css | Token-only custom properties | Import instead of styles.css only when the host wants generated --aui-* variables without component CSS or JavaScript token data. |
@maya/assistant-ui/global.css | Document-level opt-in | Optional reset layer. Import once at the application edge, not inside reusable widgets. |
Wrap rendered package surfaces in .aui-root unless a component already creates the root wrapper:
import '@maya/assistant-ui/styles.css';
export function AssistantPane() {
return (
<section className="aui-root" data-theme="system" data-resolved-theme="light">
<AssistantWorkspace {...workspaceControllers} />
</section>
);
}
Subentry Import Matrix
Prefer the lightest subentry that fits the use case. Public imports are exact; private source paths are not part of the package contract.
| Package path | Use when | Exported symbols |
|---|---|---|
@maya/assistant-ui | Application shell wants the main public surface. | AssistantSharedChatPage, AssistantSharedChatPageProps, AssistantUiAuthLabels, AssistantUiComposerLabels, AssistantUiLocalization, AssistantUiLocalizationLabels, AssistantUiMessageLabels, AssistantUiRouteListLabels, AssistantUiSettingsLabels, AssistantUiSharedChatLabels, AssistantUiTextDirection, AssistantUiTranscriptLabels, AssistantUiTranslateValue, AssistantUiTranslateValues, AssistantUiWorkspaceLabels, AssistantWorkspace, AssistantWorkspaceArtifactsController, AssistantWorkspaceChatController, AssistantWorkspaceCompositionInput, AssistantWorkspaceDirectoryController, AssistantWorkspaceGroupedInput, AssistantWorkspaceGroupedProps, AssistantWorkspaceInput, AssistantWorkspaceProjectsController, AssistantWorkspaceSettingsController, AssistantWorkspaceShellController, AuthEntry, AuthEntryProps, WorkspaceShellStatus, WorkspaceShellStatusLevel |
@maya/assistant-ui/auth | Render the auth entry screen. | AssistantUiAuthLabels, AssistantUiLocalization, AssistantUiLocalizationLabels, AssistantUiTextDirection, AssistantUiTranslateValue, AssistantUiTranslateValues, AuthEntry, AuthEntryProps |
@maya/assistant-ui/workspace | Render the workspace shell or type grouped workspace controllers and composition input. | AssistantUiAuthLabels, AssistantUiComposerLabels, AssistantUiLocalization, AssistantUiLocalizationLabels, AssistantUiMessageLabels, AssistantUiRouteListLabels, AssistantUiSettingsLabels, AssistantUiSharedChatLabels, AssistantUiTextDirection, AssistantUiTranscriptLabels, AssistantUiTranslateValue, AssistantUiTranslateValues, AssistantUiWorkspaceLabels, AssistantWorkspace, AssistantWorkspaceArtifactsController, AssistantWorkspaceChatController, AssistantWorkspaceCompositionInput, AssistantWorkspaceDirectoryController, AssistantWorkspaceGroupedInput, AssistantWorkspaceGroupedProps, AssistantWorkspaceInput, AssistantWorkspaceProjectsController, AssistantWorkspaceSettingsController, AssistantWorkspaceShellController, MaybePromise, Nullable, WorkspaceAccountSession, WorkspaceActivity, WorkspaceActivityAction, WorkspaceArtifactPreview, WorkspaceArtifactUpdateInput, WorkspaceArtifactVersion, WorkspaceAttachment, WorkspaceAttachmentEncoding, WorkspaceAttachmentUpload, WorkspaceCapabilities, WorkspaceChatPrivacySnapshot, WorkspaceCitation, WorkspaceCitationSource, WorkspaceCodeBranch, WorkspaceCodeRepository, WorkspaceCompletionReason, WorkspaceConnector, WorkspaceConnectorCreateInput, WorkspaceDataExportReceipt, WorkspaceInteraction, WorkspaceListItem, WorkspaceMessage, WorkspaceMessageErrorCode, WorkspaceMessageVersion, WorkspaceModel, WorkspacePlugin, WorkspacePluginCreateInput, WorkspaceProjectAccess, WorkspaceProjectAccessEntity, WorkspaceProjectAccessEntityKind, WorkspaceProjectCreateInput, WorkspaceProjectCustomConnectorCreateInput, WorkspaceProjectDirectoryCard, WorkspaceProjectDirectoryCardsBySection, WorkspaceProjectDirectoryConnectorCreateInput, WorkspaceProjectDirectorySection, WorkspaceProjectKnowledge, WorkspaceProjectKnowledgeCreateInput, WorkspaceProjectKnowledgeStats, WorkspaceProjectSortMode, WorkspaceProjectSyncSource, WorkspaceProjectSyncSourceType, WorkspaceProjectUpdateInput, WorkspaceSettingsActionId, WorkspaceSettingsActionReceipt, WorkspaceSettingsSection, WorkspaceSettingsSummary, WorkspaceSettingsUpdateInput, WorkspaceSharedChat, WorkspaceShellStatus, WorkspaceShellStatusLevel, WorkspaceSkill, WorkspaceSkillCreateInput, WorkspaceToolCall, WorkspaceToolResult, WorkspaceUsageNotice |
@maya/assistant-ui/routes | Build workspace links, labels, route guards, and sidebar behavior outside the full workspace. | WorkspaceCustomizeView, WorkspaceRoute, WorkspaceRouteCapabilities, WorkspaceRouteCapabilityKey, WorkspaceRouteMeta, WorkspaceSettingsRouteSection, WorkspaceSidebarPolicyContext, WorkspaceSidebarPreference, WorkspaceSidebarResolutionInput, WorkspaceSidebarSection, workspaceCustomizeViewFromPath, workspaceCustomizeViews, workspaceDesktopSidebarMinWidth, workspaceHasSettingsSectionLocation, workspaceHrefForCustomizeView, workspaceHrefForRoute, workspaceLabelForCustomizeView, workspaceLabelForRoute, workspaceMobileSidebarMaxWidth, workspaceMobileSidebarMediaQuery, workspacePrimaryRoutes, workspaceProductRoutes, workspaceResolveSidebarOpen, workspaceRouteEnabledByCapabilities, workspaceRouteFromPath, workspaceRouteMeta, workspaceRoutesForSidebarSection, workspaceSettingsPathForSection, workspaceSettingsRouteFromLocation, workspaceSettingsSectionFromLocation, workspaceSettingsSectionHashes, workspaceSettingsSectionRoutes, workspaceShouldCollapseSidebar, workspaceShouldForceClosedSidebar, workspaceSidebarCanPersistPreference, workspaceSidebarDefaultOpen, workspaceSidebarPreferenceFromBoolean, workspaceSidebarPreferenceStorageKey, workspaceSidebarPreferenceToBoolean |
@maya/assistant-ui/share | Render a shared-chat page or type shared-chat data. | AssistantSharedChatPage, AssistantSharedChatPageProps, AssistantUiLocalization, AssistantUiLocalizationLabels, AssistantUiMessageLabels, AssistantUiSharedChatLabels, AssistantUiTextDirection, AssistantUiTranslateValue, AssistantUiTranslateValues, WorkspaceMessage, WorkspaceSharedChat |
@maya/assistant-ui/tokens | Read JavaScript token data or a generated token manifest. | AssistantUiColorTheme, AssistantUiTokenCategory, AssistantUiTokenManifestEntry, AssistantUiTokenMetadata, AssistantUiTokenVisibility, AssistantUiTokens, assistantUiColorThemes, tokenManifest, tokenMetadata, tokens |
@maya/assistant-ui/composer | Use the standalone message composer. | AssistantUiComposerLabels, AssistantUiLocalization, AssistantUiLocalizationLabels, AssistantUiTextDirection, AssistantUiTranslateValue, AssistantUiTranslateValues, Composer, ComposerProps |
@maya/assistant-ui/transcript | Use the standalone transcript renderer. | AssistantUiLocalization, AssistantUiLocalizationLabels, AssistantUiMessageLabels, AssistantUiTextDirection, AssistantUiTranscriptLabels, AssistantUiTranslateValue, AssistantUiTranslateValues, Transcript, TranscriptProps |
@maya/assistant-ui/dialog | Use the standalone dialog primitive. | Dialog, DialogProps |
@maya/assistant-ui/menu | Use the standalone menu primitive. | Menu, MenuProps |
@maya/assistant-ui/route-list | Use route list rendering without the full workspace. | AssistantUiLocalization, AssistantUiLocalizationLabels, AssistantUiRouteListLabels, AssistantUiTextDirection, AssistantUiTranslateValue, AssistantUiTranslateValues, RouteList, RouteListItem, RouteListProps |
@maya/assistant-ui/render-runtime | Create scoped React render runtimes from explicit host-provided render packs. | CreateReactRenderRuntimeOptions, ReactPreloadMode, ReactRenderAdmissionDecision, ReactRenderAdmissionInput, ReactRenderAdmissionPolicy, ReactRenderBlockedHandle, ReactRenderComponent, ReactRenderComponentStackSummary, ReactRenderContext, ReactRenderCoverageEventSummary, ReactRenderCoverageResult, ReactRenderDuplicateProvider, ReactRenderErrorEvent, ReactRenderErrorSummary, ReactRenderEventHandleSummary, ReactRenderEventTargetSummary, ReactRenderFallbackProps, ReactRenderFallbackReason, ReactRenderModule, ReactRenderPack, ReactRenderPreloadOverride, ReactRenderPreloadPolicy, ReactRenderPreloadProps, ReactRenderPreloadRequest, ReactRenderPreloadResult, ReactRenderProps, ReactRenderProvider, ReactRenderProviderSummary, ReactRenderResolution, ReactRenderRuntime, ReactRenderRuntimeEvent, ReactRenderRuntimeListener, ReactRenderRuntimeMode, ReactRenderRuntimeSchemaVersion, ReactRenderTarget, ReactRenderTestOptions, ReactRenderTrustTier, ReactRenderUnsupportedProvider, ReactRenderableContribution, createReactRenderRuntime |
@maya/assistant-ui/settings-dialog | Render settings as a packaged dialog. | AssistantUiLocalization, AssistantUiLocalizationLabels, AssistantUiSettingsLabels, AssistantUiTextDirection, AssistantUiTranslateValue, AssistantUiTranslateValues, SettingsAccountSession, SettingsActionId, SettingsActionReceipt, SettingsConnector, SettingsCustomizeView, SettingsDataExportReceipt, SettingsDialog, SettingsDialogProps, SettingsModel, SettingsPlugin, SettingsSection, SettingsSkill, SettingsSummary |
@maya/assistant-ui/auth.css | Import AuthEntry CSS without the full workspace stylesheet. | CSS asset |
@maya/assistant-ui/composer.css | Import Composer CSS without the full workspace stylesheet. | CSS asset |
@maya/assistant-ui/dialog.css | Import Dialog CSS without the full workspace stylesheet. | CSS asset |
@maya/assistant-ui/menu.css | Import Menu CSS without the full workspace stylesheet. | CSS asset |
@maya/assistant-ui/route-list.css | Import RouteList CSS without the full workspace stylesheet. | CSS asset |
@maya/assistant-ui/settings-dialog.css | Import SettingsDialog CSS without the full workspace stylesheet. | CSS asset |
@maya/assistant-ui/share.css | Import shared-chat page CSS without the full workspace stylesheet. | CSS asset |
@maya/assistant-ui/transcript.css | Import Transcript CSS without the full workspace stylesheet. | CSS asset |
@maya/assistant-ui/styles.css | Import component CSS. | CSS asset |
@maya/assistant-ui/global.css | Opt into the document-level reset. | CSS asset |
@maya/assistant-ui/tokens.css | Import generated CSS variables without component CSS. | CSS asset |
@maya/assistant-ui/package.json | Let tooling inspect package metadata. | Metadata asset |
API Change Scope
The public package API includes export specifiers, exported symbols and types, CSS asset entries, public --aui-* variables, documented component states, grouped workspace controllers, public data attributes, and token manifest entries. Private source paths, Storybook fixtures, host adapters, generated reports, and .tmp artifacts are outside the package API.
The public API surface gate snapshots bundled .d.ts files and classifies declaration changes by the release levels defined in .docs/release-governance.md. Byte-only declaration changes with no modeled entry, symbol, member, or union change are patch. Adding optional view-model fields, exported symbols, subentries, or union literals is minor; adding required fields, removing exports, narrowing unions, or changing existing member signatures is major unless a deprecation path is already documented. When multiple API classifiers report changes, the package release level is the highest reported level.
Production Readiness / Adoption Playbook
Use the package as a React workspace component kit: start from the complete workspace when the host is shipping a Maya-style assistant surface, then reach for standalone subentries only when embedding a deliberate slice of that product experience.
| Adoption mode | Use | Production checks |
|---|---|---|
| Full assistant workspace | Render AssistantWorkspace with grouped controllers for a complete assistant shell. | Import styles.css, mount under .aui-root, wire route and sidebar state, preserve message and project ids, and run workspace Storybook coverage. |
| Focused assistant surface | Render Composer, Transcript, route lists, dialogs, or settings screens inside an existing host shell. | Pair each JS subentry with its CSS asset when styles.css is not already present, keep callbacks stable, and verify keyboard paths plus loading, empty, error, and long-content states. |
| Shared or signed-out surface | Render AssistantSharedChatPage or AuthEntry without the full workspace shell. | Pass sanitized view models, keep host auth and sharing rules outside the package, and verify mobile, zoom, theme, and high-contrast states. |
| Token or route integration | Consume @maya/assistant-ui/tokens or @maya/assistant-ui/routes for host-side tooling. | Use public --aui-* tokens and route helpers only; do not copy package internals into host docs or source trees. |
Before adopting in a product release, confirm these items:
- The host owns data loading, protocol mapping, persistence, command execution, auth, and environment adapters.
- The assistant UI is mounted inside one theme scope with
data-themeanddata-resolved-themeset by the host. - Optional Mermaid support is installed only for transcript diagram rendering.
- Storybook product states, package build, public API surface gate, docs/API parity gate, consumer smoke, and application typecheck pass for the release branch.
- Host-specific notes link back to this guide instead of copying the install matrix, export matrix, token policy, or release rules.
Storybook Product Documentation
Storybook is the package's product documentation and verification surface for visible states. It is not a second install guide or API matrix. The canonical package consumption guide remains this file, while Storybook shows how the public components behave across states, themes, keyboard paths, and host-owned data.
The Storybook coverage matrix is machine-readable in projects/claude-ui/stories/storyMetadata.ts and is checked by pnpm verify:ui-stories. Every public package entry maps to a story contract:
| Public surface | Storybook responsibility |
|---|---|
Components such as Composer, Transcript, Dialog, Menu, RouteList, SettingsDialog, AuthEntry, and AssistantSharedChatPage | Show default, empty, loading, error, long-content, disabled, mobile, theme, and interaction states where they apply. |
AssistantWorkspace | Show grouped-controller compositions for route, shell, project, settings, artifact, long-list, contrast, and reduced-motion states. |
@maya/assistant-ui/routes | Show route labels and href helpers without exposing private route tables. |
@maya/assistant-ui/tokens | Render the token catalog and theme axes from tokenManifest, with motion and forced-colors listed as style behavior contracts. |
| CSS entries | Explain scoped component CSS, generated token CSS, and global opt-in CSS behavior. |
Storybook stories can use controls, play checks, visual scenarios, axe checks, and render budgets. Long-form installation, peer dependency, controller ownership, and package governance text should stay here so there is not a second prose source to keep in sync.
Component Lifecycle
Every public Storybook surface has machine-readable lifecycle metadata in projects/claude-ui/stories/storyMetadata.ts: status, introducedIn, releaseImpact, replacement, deprecatedSince, and removalTarget.
| Status | Meaning |
|---|---|
preview | Available for feedback but not allowed in the stable public export map. |
stable | Part of the public component-library contract. |
deprecated | Still shipped, but has a documented replacement, deprecation version, and removal target. |
removed | No longer shipped; kept only in release history and migration notes. |
internal-contract | Used by package tooling or docs and not exported as public component API. |
Public component changes follow the release levels in .docs/release-governance.md. Value-only visual tuning that preserves semantics is patch; adding public props, states, subentries, or token hooks is minor; removing or repurposing public props, DOM landmarks, keyboard behavior, data attributes, CSS variables, or documented states is major. Deprecations require a reason, replacement, migration path, and target removal version before the old surface can be removed.
Grouped Controllers
AssistantWorkspace receives AssistantWorkspaceGroupedProps for grouped-controller rendering. The controller groups remain the host-owned data and callback contract:
import type { AssistantWorkspaceGroupedProps } from '@maya/assistant-ui/workspace';
import { AssistantWorkspace } from '@maya/assistant-ui/workspace';
export function WorkspaceHost(props: AssistantWorkspaceGroupedProps) {
return <AssistantWorkspace {...props} />;
}
Controller ownership is split by domain:
| Controller | Owns |
|---|---|
AssistantWorkspaceShellController | Current route, navigation, sidebar, viewport, account shell state. |
AssistantWorkspaceChatController | Messages, composer state, attachments, model choice, send and stream callbacks. |
AssistantWorkspaceProjectsController | Project lists, project detail state, knowledge, access, sync sources, project actions. |
AssistantWorkspaceSettingsController | Settings sections, account sessions, connectors, plugins, skills, data export, privacy controls. |
AssistantWorkspaceArtifactsController | Stream artifacts, artifact version state, artifact update callbacks. |
AssistantWorkspaceDirectoryController | Directory cards, directory connector creation, route-scoped directory data. |
Shell status semantics are explicit: workspaceStatus accepts WorkspaceShellStatus with WorkspaceShellStatusLevel values loading, refreshing, degraded, and unavailable; workspaceError maps to degraded when no status is supplied, and isWorkspaceLoading maps to loading only when neither status nor error is supplied. The rendered status uses role="alert" and assertive live-region behavior only for unavailable; the other levels use polite status announcements. onWorkspaceRetry receives the current WorkspaceShellStatus when the retry button is pressed.
The UI package receives view models and emits callbacks. It does not fetch, persist, read local storage for product data, or import host runtime adapters.
Composition Rendering Happy Path
AssistantWorkspace can also render a WorkspaceComposition through a scoped render runtime when the host opts into composition rendering. The host still owns controllers, module runtime resolution, permissions, persistence, and render pack construction.
- Host resolves modules and owns persistent controllers outside the UI package.
- Host calls
composeWorkspace(...)from@maya/assistant-composition. - Host builds explicit render packs with controller objects.
- Host creates
createReactRenderRuntime({ packs, fallback, admissionPolicy }). - Host may call
renderRuntime.validateCoverage(composition)before rendering. - Host renders the workspace:
import { AssistantWorkspace } from '@maya/assistant-ui/workspace';
import { createReactRenderRuntime } from '@maya/assistant-ui/render-runtime';
const renderRuntime = createReactRenderRuntime({ packs });
<AssistantWorkspace
{...groupedControllers}
activeRoutePath="/data-lab"
composition={composition}
renderRuntime={renderRuntime}
/>;
Composition rendering is explicit. The UI package does not call composeWorkspace(), create render runtimes, discover packages, install modules, resolve grants, read module runtime state, or accept a generic controllers or moduleState escape hatch. composition and renderRuntime must be provided together; invalid half-mode fallback means that if a JavaScript caller supplies only a composition object, the workspace keeps the grouped-controller route path and does not execute handles.
Assistant UI does not accept raw modules, does not use a global registry, does not create iframe plugin surfaces, does not provide a plugin marketplace, does not load remote ESM, and does not support local patching built-in pages. Hosts wire WorkspaceComposition and scoped render runtimes explicitly.
activeRouteKey and activeRoutePath are explicit selectors for composed routes. Once both composition and renderRuntime are present, the main route outlet is all-or-nothing: it renders the selected composed route through renderRuntime.render(...) or renders an explicit composition route-miss fallback. It must not silently fall back to the grouped-controller route switch. Built-in product parent routes may use their descriptor pathMatchers to keep host-owned detail state such as chat, project, or Customize subviews under the parent composed route; module routes are still selected by explicit key or static path only.
Localization And Direction
Public assistant surfaces accept an optional localization object through their props or through AssistantWorkspaceShellController.localization. The same AssistantUiLocalization and AssistantUiLocalizationLabels types are exported from the root entry and from component subentries that consume them: auth, workspace, share, composer, transcript, route-list, and settings-dialog. Leaf label types such as AssistantUiComposerLabels, AssistantUiMessageLabels, and AssistantUiSettingsLabels are exported where those labels are relevant.
localization.locale and localization.dir set the rendered lang and dir attributes for that surface and its package-owned descendants. Label overrides are shallow, domain-scoped override bags, so hosts can replace one group such as composer, message, or the stable workspace chrome/status labels without copying the default English catalog. Dynamic typed labels remain functions where stable public components need counts, filenames, artifact titles, or message roles. translate(key, fallback, values) provides the fallback hook for long-tail product-kit strings such as workspace routes, directory dialogs, project detail panels, model controls, attachment upload states, and settings rows without making every microcopy key part of the typed public ABI. values is typed as AssistantUiTranslateValues and carries named primitives such as title, count, name, noun, percent, or bytes when the package builds a dynamic fallback. formatDate and formatBytes let hosts align shared-chat metadata, project source metadata, and attachment sizes with their locale policy.
Route utility helpers such as workspaceLabelForRoute() return default English fallback labels for host-side routing and documentation tools. Localized rendered workspace navigation goes through the workspace text resolver and translate; host shells that render their own route chrome should call their own i18n layer around the route helper fallback.
Localization is a view concern only. Hosts still own translated product data, route names, project names, legal copy, auth rules, backend errors, and any content supplied through controller view models. Do not import private localization source files; use the subentry-exported types and the documented props.
Tokens And Theme
tokens/theme.ts is the package token source and publishes these JavaScript exports through @maya/assistant-ui/tokens: tokens, tokenManifest, tokenMetadata, assistantUiColorThemes, AssistantUiColorTheme, AssistantUiTokens, AssistantUiTokenManifestEntry, AssistantUiTokenMetadata, AssistantUiTokenCategory, and AssistantUiTokenVisibility.
Use public CSS variables as semantic --aui-* values. Component-private exact values may exist inside package CSS, but host themes should target public semantic variables only.
tokens contains the base light token object for ergonomic JavaScript access. Tooling that needs the full theme matrix, selector scope, changeLevel, or themeAxis should use tokenManifest.
The package also builds dist/token-manifest.json for tooling inside the published tarball. The public JavaScript entry is still @maya/assistant-ui/tokens; the JSON file mirrors the generated manifest so smoke tests and documentation gates can verify package contents.
Token Layers
Token metadata is part of the package contract. Every manifest entry includes name, cssVar, category, layer, role, usage, doNotUseFor, cssProperty, cssProperties, guidanceSource, themeAxis, changeLevel, status, introducedIn, fallback, owner, path, public, visibility, selector, theme, and value fields.
| Layer | Visibility | Use |
|---|---|---|
semantic | Public | App-wide semantic roles such as canvas, surface, text, border, focus, primary action, status, code, radius, font, and elevation. |
component | Public but scoped by role | Stable component-region tokens such as sidebar colors. These are public only for the named component region. |
theme | Internal source-only | Reserved for raw appearance/color/contrast objects inside tokens/theme.ts. The published tokenManifest contains public semantic and component entries only until the gates explicitly add internal manifest support. |
Public token names use --aui-* and are scoped to .aui-root or .aui-root[...] theme selectors. Host applications may override public semantic variables under their own .aui-root boundary, but should not override private selectors, private --_aui-* component variables, or alternate unscoped :root definitions.
Component CSS can keep exact private values for layout details that are not product theme API. Promote a value into tokens/theme.ts only when host applications are expected to theme it or when multiple public components need the same semantic role.
Theme attributes:
| Attribute | Meaning |
|---|---|
.aui-root | Scope root for package styles. |
data-theme | Host preference: light, dark, or system. |
data-resolved-theme | Runtime result after resolving system preference. |
data-color-theme | Optional named product color theme. |
data-high-contrast-dark | Enables high-contrast dark adjustments. |
data-motion | Motion preference such as system or reduced; this affects interaction styling, not token value generation. |
Token Change Policy
Token changes apply the release levels in .docs/release-governance.md to public token API:
| Change | Level |
|---|---|
| Value tuning for an existing public token without changing its semantic role | patch |
| Adding a new public semantic or component token | minor |
| Removing, renaming, or repurposing a public token role | major |
| Marking a token as deprecated while keeping its value and documenting a replacement | minor |
Initial public tokens are normally marked minor because they create stable theme API. A small source allowlist may mark foundational reset/default tokens as patch when the token exists only to expose an already-shipped CSS fallback such as the default font or accent text value. Later value tuning for an existing public token is patch; adding a new public semantic or component token is minor; removing, renaming, or repurposing a public token is major.
changeLevel describes the expected release impact for the current token entry. themeAxis identifies whether a value belongs to base variables, appearance, color theme, or contrast. doNotUseFor is required so consumers do not turn a narrow semantic token into a broad brand or layout escape hatch.
Required gates verify explicit public token approval, release-impact classification, color-theme domain parity, tokens.css, styles.css, token-manifest.json, Storybook token catalog stories, and this documentation against src/tokens/theme.ts.
SSR, Vite, And Next
Vite consumers can import CSS in the application entry and import components from the exact subentry they render.
Next.js App Router consumers should render interactive components from a client component boundary:
'use client';
import '@maya/assistant-ui/styles.css';
import { Composer } from '@maya/assistant-ui/composer';
Server-rendered shells can pass serialized view models into client components. Keep backend payload mapping outside the UI package boundary and pass camelCase view models into the controllers.
For optional Mermaid rendering, install mermaid only in applications that render diagram blocks. Lightweight imports such as @maya/assistant-ui/composer, @maya/assistant-ui/dialog, @maya/assistant-ui/menu, and @maya/assistant-ui/route-list must not eagerly load workspace surfaces or Mermaid.
A11y Contract
The package components are expected to provide accessible structure and keyboard behavior:
| Area | Package responsibility | Host responsibility |
|---|---|---|
Dialog | Label wiring, focus trap, initial focus, Escape close, focus restore, and background inert behavior. | Provide meaningful titles and close callbacks. |
Menu | Roving keyboard navigation, focus-visible behavior, Escape close, and stable item roles. | Supply item labels and disabled state truthfully. |
Composer | Proper upload progress/live regions and submit state. | Announce host-side failures through controller state. |
Transcript | Message semantics, copy/action labels, and code block controls. | Provide message authoring state and content that is safe to render. |
RouteList | Current route indication, list semantics, and keyboard reachable items. | Keep route ids and hrefs stable. |
SettingsDialog | Section navigation, dialog semantics, keyboard operation, and form labels. | Wire callbacks to durable settings state. |
Required verification covers keyboard navigation, axe checks, desktop/mobile layout, 200 percent zoom, forced colors or high contrast, and reduced motion.
Performance Guidance
Choose subentries by weight:
- Use
@maya/assistant-ui/composer,@maya/assistant-ui/dialog,@maya/assistant-ui/menu, or@maya/assistant-ui/route-listfor lightweight use cases. - Pair lightweight JS subentries with their matching CSS subentry, such as
@maya/assistant-ui/composer.css, when the host is not already importingstyles.css. - Use
@maya/assistant-ui/workspaceonly when the full assistant workspace is rendered. - Install
mermaidonly for transcript diagram rendering. - Keep long message lists and large route/project lists stable by preserving ids and callback references.
- Batch streaming message updates in the host runtime before passing message arrays into
TranscriptorAssistantWorkspace. - Keep tokens and CSS imported once at the application edge.
Bundle and render budgets are enforced outside the package docs. Performance reports are temporary build artifacts and are not committed documentation sources.
Migration
For source-path consumers migrating to the package boundary:
- Replace source-path imports with package subentries from the matrix above.
- Move protocol or backend payload conversion into the host application boundary.
- Create grouped controller objects and pass
AssistantWorkspaceGroupedPropsintoAssistantWorkspace. - Import
styles.cssfor the full component stylesheet, a matching component CSS subentry for lightweight standalone components,tokens.cssonly for token-only consumers, andglobal.cssonly at the application edge. - Update route, token, composer, transcript, dialog, menu, route-list, settings, and share imports to exact subentries.
- Run the package build, public API surface gate, docs/API parity gate,
tools/verify-agent-capability-map.mjs, consumer smoke, and application typecheck before release.
Documentation Source
Canonical package consumption docs stay in .docs/packages/assistant-ui.md. Package-root README copies, generated dist docs, and copied package docs are intentionally not published so consumers and maintainers have no duplicate docs and do not have two documentation truths.