Dual-Layer Package Architecture: components and extra-components

Hikari splits its component system into two complementary packages, each responsible for a different level of concern:

mermaid

Responsibility Comparison

Dimensionhikari-componentshikari-extra-components
Renderingrsx! macro, reactive hooksNone (framework-agnostic)
State Managementuse_signal(), use_effect()Plain mutable struct fields
Event HandlingEventHandler<T> closuresdata-action attributes + external binding
CSS EmbeddingStyledComponent traitExports pub const *_STYLES
SerializationNot requiredAll state types derive serde
DOM DependencyRequires Tairitsu frameworkNone
Use CasesReal-time UI rendering within Tairitsu appsSSR, testing, state persistence, non-Tairitsu frameworks

Overlapping Component Domains

The following components exist in both packages. This is intentional design, not redundancy:

The components version provides ready-to-use render components (with animations, keyboard handling, icon integration, and StyledComponent CSS); the extra-components version provides pure data models (with builder pattern, serde serialization, mutation methods, and unit testing).

When to Use Which Package

Type Disambiguation

Some types share the same name across both packages (e.g., TimelinePosition, GuideStep). Use explicit module paths when importing:

rust,ignore
1
2
3
4
5
use hikari_extra_components::extra::TimelineState;     // Pure data model
use hikari_components::display::Timeline;              // Render component

use hikari_extra_components::extra::ZoomControlsState; // Pure state
use hikari_components::display::ZoomControls;          // Render component

CSS Class Names

Both packages use different CSS class names for the same conceptual element. This is intentional — components uses typed class enums from hikari-palette (e.g., ZoomControlsClass::Button), while extra-components uses hardcoded strings or computed methods. When both packages are used together, each renders with its own class set.