Mixins / foldkit-mixins

The mental model

There are five ideas to learn:

ConceptMeaning
SlotA named extension point in a view: root, input, label, trigger, ...
SlotsThe contract describing which extension points exist and what each permits.
StyleAppearance attached to a slot: classes, inline declarations and compiled CSS rules.
BehaviorElement-level interaction attached to a slot: attributes and an optional Foldkit Mount. Never application state.
SlotViewA pure Foldkit view that renders those slots and resolves attached Style/Behavior.

Style and Behavior both compile to a Mixin. The resolver combines their contributions and rejects ambiguous ownership instead of silently choosing a winner.

                Slots contract
                      │
          ┌───────────┴───────────┐
        Style                  Behavior
     appearance              interaction
          │                       │
          └───────────┬───────────┘
                      ▼
                    Mixin
                      │
                      ▼
                   resolver
                      │
                      ▼
          ordinary Foldkit attributes

Why not just className and props?

A class name says only "append this string." A slot is a typed public customization point. It can say:

  • this point is a text input rather than an arbitrary element;
  • it publishes input but not click;
  • callers may set aria-invalid but may not replace the structural role;
  • this point is internal and cannot be targeted publicly;
  • two independent behaviors may not both own the same event.

That matters once a design system, a feature, accessibility logic and product-specific behavior all need to customize the same view without knowing about each other.

Use it when

Use mixins when a view should be restyled or decorated where it is used, not only where it is defined, and you want those customizations checked.

Typical examples are a design system styling a feature component, a tooltip attached by a caller, analytics on an existing action, ARIA decoration, a focus trap, a ResizeObserver, keyboard behavior, or a reusable visual recipe.

Not for state. A widget's open/selected/value belongs in a Foldkit Model or Submodel. A transition is update; a network call is Message → Command; an element-scoped effect is a Mount. A Behavior that "needs state" is a signal to reach for a Submodel, not to hide an atom inside the mixin.

Install

bash
pnpm add foldkit-mixins

foldkit and effect are peer dependencies. foldkit-mixins-surface bridges a Surface projection, and foldkit-mixins-ui adapts @foldkit/ui components.

The design-system pieces are subpaths, so an application that only attaches classes pays for none of them: foldkit-mixins/layers, /theme, /layout, /defaults, /prose, /utilities and /app.