Component Library

The KAINYNE design system — native Custom Elements themed via the shared --kn-* token sheet. Every component is template-customizable through HTML attributes, CSS custom properties, and slotted content. Foundation pieces below; forms, menus, and page templates ship in follow-up RFEs (SUP-024).

<kainyne-button>

Foundation button. Wraps a native <button> inside a shadow root so its press-feedback styling is independent of game-specific CSS. Attributes: variant (solid / outline / ghost), size (sm / md / lg), tone (neutral / accent / danger / muted), disabled, type.

Live stage

Play

Tone × variant matrix

Solid neutral Solid accent Solid danger Outline neutral Outline accent Outline danger Ghost neutral Ghost accent Ghost muted

Size scale

Small Medium Large

Disabled state

Disabled accent Disabled outline

<kainyne-frame>

Foundational container / card. Slots: header, default (body), footer. Each slot wrapper auto-hides when its slot is empty so a body-only frame doesn't render two empty bars. Attributes: tone, padding (none / sm / md / lg), radius (none / sm / md / lg), border (boolean).

Live stage

Frame header

Frame body — slot content composes freely. Try the controls below to flip every attribute.

Footer status line

Body-only frame (header / footer slots hide automatically)

Body-only frame — neither header nor footer is provided, and the shadow-DOM wrappers stay hidden.

Light-DOM Custom Element that wraps the existing src/carousel-core.js factory. Inherits the PTR-047 single-interval contract + PTR-093 self-heal on DOM detach. Attributes: auto-advance-ms (default 6000), resume-grace-ms (default 8000), aria-label (forwarded to the inner region). Children of the element are treated as slides.

Three-slide demo

One
Two
Three

Forms

Four form primitives: <kainyne-input> (text / email / password / number / tel / url / search), <kainyne-select> (clones light-DOM <option> children into a shadow-DOM <select>), <kainyne-checkbox> (with indeterminate support), and <kainyne-form> (Light-DOM wrapper for theme-consistent spacing). Every field carries label-text, required, disabled, invalid attributes plus help-text / error-text slots. Note: native form-data aggregation across shadow-rooted fields is deferred to a follow-up RFE — for now hook the submit event and pull values from the shadow-DOM fields directly.

kainyne-input — all variants

We'll never spam you. That doesn't look like an email address. Used to pre-populate the multiplayer lobby. You must accept to continue.
Cancel Save

Live stage — flip invalid on the input

Theming

Every component reads its surface from CSS custom properties prefixed --kn-*, declared at :root in /src/ui/tokens.css. The tokens default to the existing --bg / --accent / --font-body brand vars via var(fallback), so per-game :root overrides flow through to components without the games needing to know about --kn-* names.

Per-instance override (inline style)

Custom violet Custom teal

<kainyne-theme> — palette wrapper (REQ-570)

Wrap any subtree with <kainyne-theme palette="..."> to apply a token-override palette to its descendants. CSS variables inherit through Shadow DOM, so every nested <kainyne-*> component picks up the override.

default palette — brand yellow accent on dark surface. vivid palette — saturated orange accent. muted palette — desaturated greys. contrast palette — high-contrast B/W + yellow accent for accessibility.

<kainyne-window> (REQ-565)

Modal overlay built on the native <dialog> element. Focus trap + Esc-to-close come free from dialog.showModal(); scrim-click-to-dismiss is layered on top. Attributes: open, label, dismissable, size (sm / md / lg / full).

Open modal Open non-dismissable
Confirm action

This is a modal built on the native <dialog> element. Try pressing Esc, clicking the scrim, or using the buttons below.

Cancel Confirm
Non-dismissable

Esc and scrim-click are disabled. Use the button below to close.

Got it

<kainyne-menu> (REQ-566)

Accessible dropdown / popover. Arrow keys cycle focus through items; Esc closes; click-outside dismisses. Attributes: open, placement (top / bottom / left / right). Slots: trigger, default (items).

Pick a game ▾ War President The Crew Star Realms Actions ▸

Page templates (REQ-567..554)

Layout-level primitives so a new page is a few <kainyne-page-*> tags rather than copy-pasted scaffolding.

<kainyne-page-hero>

Tabletop OS A modular rule architecture for tabletop games — every game is a configuration of five pillars.
Browse games Read the spec

<kainyne-page-section> + <kainyne-page-grid>

Foundation components Button

variant × size × tone

Frame

header / body / footer

Carousel

swipe + autoplay

Input

required / invalid / disabled

Select

clones option children

Checkbox

checked + indeterminate

Drop your own <kainyne-frame> cards in to extend.

Round-3 components

Form-gap fillers (<kainyne-radio> / <kainyne-radio-group> / <kainyne-textarea> / <kainyne-switch>), disclosure pack (<kainyne-tabs> / <kainyne-accordion> / <kainyne-tooltip>), transient notifications (<kainyne-toast>), and inline labels (<kainyne-badge> / <kainyne-chip> / <kainyne-tag> / <kainyne-avatar>).

Form gap — radio / textarea / switch

Disclosure — tabs + accordion + tooltip

Overview content — tabs auto-show the matching panel.

Mechanics content — ArrowLeft / ArrowRight cycles tabs.

Lore content — Home / End jump to the bounds.

What is Tabletop OS?

A modular rule architecture (see /design/).

How are components customized?

Via --kn-* tokens, attributes, and slots.

Do components need a build step?

No — every file is loaded directly by the browser.

Hover for infoTooltip on top. Hover for infoTooltip on bottom. Hover for infoTooltip on right.

Transient notification — toast

Show toast (4s) Show sticky toast Dismiss sticky
Save succeeded — your lobby is live. This toast stays until you dismiss it.

Inline labels — badge / chip / tag / avatar

Beta 9 unread Archived
trick-take area-control compare-rank
solo multiplayer 2-4 players

<kainyne-font> (REQ-571)

Declarative font registration helper. Set family, href, optional preconnect + token; on connect the element injects the matching <link> tags into <head> (idempotent) and declares a --kn-font-<token> CSS custom property on itself so descendant components can opt in via font-family: var(--kn-font-<token>);. CSP note: every font origin MUST be allow-listed in the page's style-src / font-src directives.

Default body font.

Default mono token (--kn-font-mono).

Game primitives (REQ-596..600)

First round of card-game-surface components: playing card with rank/suit/face-down/interactive, fan/row/stack hand layout, labeled score with delta-flash, multi-player turn indicator, countdown timer with one-shot expire event.

<kainyne-card>

<kainyne-hand> — fan layout (default)

<kainyne-hand> — row layout (overlap 0.4)

<kainyne-hand> — stack layout (overlap 0.9, all face-down)

<kainyne-score-display>

<kainyne-turn-indicator>

Alice, Bob, Carla, Dave
Player 1Player 2Player 3

<kainyne-timer>