Components and Interaction
Ownership
@kartuli/ui supplies shared source exports and utilities. Its layout package owns AppShell, AppBar, ContentContainer, ShellRail, Dock and DockItem. Game Client's src/ui/components continues to own its app-bar and dock composition, navigation definitions, view-transition title, mascot/back behavior, alphabet rail decoration, panels, surfaces, actions, feedback and overlays; src/ui/experiences owns feature composition. A component can be reused inside an app without becoming a cross-app package contract.
Before moving a component into shared UI, identify its consumers, props and dependencies. Remove app-specific routing/content assumptions from the shared boundary or keep it app-local. Source aliases used by Storybook are an inspection mechanism, not proof that a component belongs in the package.
Use a component token when stable reusable geometry belongs to the component contract. Keep local composition values local, and do not add component color aliases when an existing semantic role already owns the meaning. A potentially reusable Game Client component does not move into @kartuli/ui without cross-app evidence.
States and interactions
Document meaningful default, hover, focus, selected, disabled, loading and error states where they exist. Use semantic tokens for these roles, accessible control names for icon-only actions and keyboard alternatives for gestures. Base UI provides primitive behavior for overlays/feedback; app wrappers still own semantics and styling.
Motion currently supports study-carousel interactions. React Icons supplies app icon families. Neither dependency establishes a complete motion/icon governance system. Library integration owns their technical setup.
Component change workflow
Update the component, relevant stories and behavior tests together. Check interaction and accessibility in a real browser, then inspect the component in its route composition. A story can look correct with simplified content while failing with actual translations or application context.
Review shared-token impact before adding another raw value. Use cn for conditional classes and inspect the final merged output for variants. Broader reduced-motion conventions and a curated icon catalog remain gaps to resolve explicitly, rather than claiming they are already standardized.
For a new reusable component, decide ownership before implementation:
- Put cross-app, product-neutral source in
packages/uiand expose it through the existing wildcard subpath contract; add colocated tests and a Storybook story. - Keep Game Client composition/panel/feature components under
apps/game-client/src/uiwhen they depend on app navigation, translations, learning data, view transitions or product semantics. Inject these concerns through shared slots or adapter props instead of teaching@kartuli/uiabout the app. - Keep feature composition under
src/ui/experiences; do not move it into a shared package merely to make Storybook discover it.
Verify a shared change with UI typecheck/tests, Storybook browser tests and at least one real consumer build. Verify an app-local component with its focused tests/story and the containing route. Use the full repository gate last; cached success is not a substitute for checking the changed interaction state.
For cross-theme shell review, open Design System/Workshop/Shared Shell. It composes the real shared shell primitives with neutral Storybook-owned content, so product routing, localization and application identity remain outside the shared package. Review each toolbar theme at 390x844, 900x900 and 1600x1000, checking bottom/compact/expanded navigation geometry, app-bar and content offsets, optional end-rail placement, hover, focus, selected state and readable contrast. The workshop is a review fixture—not a new shared component or evidence of runtime app theming.
Reusable UI review should cover Game / Default, Backoffice, Stress: Emerald and Stress: Rose when the component consumes affected roles. Exercise implemented default, hover, focus, selected, disabled, loading and error states as relevant, and inspect meaningful semantic foreground/background pairings rather than palette shades alone. Storybook is the shared-component review surface; it does not replace route-level review of app-owned composition, real translations or product data.