Composition
Stisla is built to be composed. Most of what feels like “I need a new component” is really existing components placed together, then a knob or a utility to adjust the fit. Writing new CSS is the last step.
Compose first
Components are designed to nest. A media row inside a card. A table inside a card. A menu inside a popover. An avatar inside a media row, with a button as its action. Putting the pieces together is the primary way you build UI, and it’s usually all you need. Everything keeps reading from the same tokens, so a composed surface stays coherent with the rest of the system for free.
That card is four components (card, media, avatar, button) and no custom CSS. Before reaching for anything new, ask whether the thing you want is just a few of these put together.
Tune what you composed
Composition gets you the structure; the next thing you’ll want is to adjust a detail. The rows feel cramped, the avatars are a touch small. Reach for a knob or a utility before any new CSS. Here the same card sets --avatar-size (a component knob) and swaps one spacing utility, no stylesheet involved.
That’s the everyday case, and it covers more than it looks. The Styling page is the full story: tuning a knob that exists, overriding a property when there’s no knob, escaping to hand-tuned states, and the per-component variable surface. Exhaust that before writing a component.
Modifier or new component?
Compose, then tune. That’s most of it. Past that you’re writing new CSS, and the fork is which kind. Say you’re showing a product in a card: do you build a product-card component, or a card--product modifier on the card you already have?
Start specific and don’t abstract early. The first time, the tuning above is fine. Duplicate the second time. By the third use the real shape is visible, and the decision makes itself:
- Same component, extra bits. If it’s still honestly “a card, with a price and a buy button,” it’s a modifier.
.card--productadds the product-specific parts on top of.card, and you inherit every card token, surface tier, and state without re-authoring them. Prefer this. - A genuinely different pattern. If “a card with extras” has stopped being an honest description (different anatomy, different behavior, not a card at all), it’s a new component.
The modifier keeps you inside the system. It composes, it inherits, it tracks theme and density changes automatically. Author it in the same layer as the component it extends.
Reach for a new component only when none of the above is true. The next section is what that looks like.
Building a new component
When you do need one, author it the way Stisla authors its components. Lean on the shared tokens, derive any tinted part through color-mix, and keep everything inside @layer components so it sits in the same layer as the framework’s own rules. Say you want a metric tile for a dashboard: a label, a value, and a trend delta that goes green up or red down. Nothing in the set is that, so it earns its own component. Here’s .stat, around thirty lines. Layers are native CSS, so this is the same file whether or not you run a build.
It composes back into everything else. Drop a stat into a card or a grid and it stays on the surface tokens around it. Override --color-success on a parent and every upward delta repaints. Set --stat-delta-tone inline for a one-off and you get the same machinery without a new modifier.
Wiring it in
Because the file declares its own @layer components, a new component or a modifier drops in the same way in both setups from Theming. It reads the same tokens the framework already defined, so var(--radius-lg) and the intent colors resolve with nothing extra.
Without a build step. Save the file and link it after stisla.css.
With Vite and Tailwind. Import it from your app.css after Tailwind and the source theme. The layer is already in the file, so there’s no wrapper to add.
Document a new component the same way every Stisla component is documented. A Customization table at the end of its demo page listing the --stat-* variables (Variable, Use). The Button page is the reference shape, and Contributing covers the table conventions if you’re adding it to Stisla itself.