@skirbi/pinta
v0.0.28
Published
Skirbi's theme song
Readme
@skirbi/pinta
Skirbi's theme song
Pinta is the theme + token engine for Skirbi.
- Semtic provides semantic structure and components
- Pinta provides tokens, derivations, and component recipes
- Dibuho provides higher-level composition/layout patterns
Pinta is intentionally small.
It is not:
- a utility framework
- a Tailwind replacement
- a Bootstrap clone
- a layout engine
Pinta follows the 80% rule:
- sensible defaults
- clean tokens
- predictable recipes
- easy overrides with normal CSS
Everything is CSS. No runtime. No JS required.
Philosophy
Pinta is built around:
color families
-> derivations
-> component recipesInstead of:
utility attributes
-> inline compositionYou are encouraged to use:
- semantic HTML
- Semtic components
- normal CSS classes
Example:
<semtic-panel login-card>semtic-panel[login-card] {
max-width: 28rem;
}Or if you prefer classes:
<semtic-panel class="login-card">.login-card {
max-width: 28rem;
}Pinta intentionally embraces native CSS instead of competing with it.
Opt-in
Pinta is explicit opt-in.
Nothing happens unless [skirbi-theme] exists.
Whole page:
<html skirbi-theme>Subtree:
<section skirbi-theme>Named theme:
<html skirbi-theme="voodoo">Why Skirbi and not Pinta?
The namespace skirbi- is chosen over pinta- because @skibri/dibuho also
paints the canvas and is part of the skirbi-universe. Having one namespace
makes things easier.
Cascade layers
Pinta defines stable layer order:
@layer skirbi-base, skirbi-theme, skirbi-transform, skirbi-components, skirbi-app;Meaning:
skirbi-base- derivation engine
- environment logic
- typography
- accessibility defaults
skirbi-theme- palette
- tokens
- theme overrides
skirbi-transform- color derivations and background transforms
skirbi-components- light component recipes for Semtic elements
skirbi-app- app-specific overrides, always wins over components
Theme authors should override in:
@layer skirbi-theme {
[skirbi-theme="foo"] {
}
}Theme modes
Pinta supports:
<html skirbi-theme skirbi-theme-mode="light">
<html skirbi-theme skirbi-theme-mode="dark">Dark mode changes:
- environment base
- surface derivation
- page wash
- default foregrounds
Mode can be applied to any subtree.
Color families
Pinta uses color families instead of loose palette slots.
Primary
--skirbi-primary-main
--skirbi-primary-light
--skirbi-primary-dark
--skirbi-primary-contrastSecondary
--skirbi-secondary-main
--skirbi-secondary-light
--skirbi-secondary-dark
--skirbi-secondary-contrastUsually only *-main needs to be set.
Pinta derives:
- light
- dark
- contrast
unless explicitly overridden.
Helper colors
Helper colors exist for supporting accents.
--skirbi-tertiary-main
--skirbi-quaternary-mainThese intentionally do not expose full family contracts. They are currently included, but unused. Component authors may be able to use them if needed.
Button tokens
--skirbi-button-radius
--skirbi-button-lead-bg
--skirbi-button-lead-color
--skirbi-button-lead-hover-bg
--skirbi-button-support-bg
--skirbi-button-support-color
--skirbi-button-support-border
--skirbi-button-extra-bg
--skirbi-button-extra-color
--skirbi-button-extra-border
--skirbi-button-antagonist-bg
--skirbi-button-antagonist-color
--skirbi-button-antagonist-borderVisual tokens
--skirbi-divider-image /* background-image for semtic-divider */Background transforms
Pinta derives atmospheric backgrounds from brand colors.
Transform modes
--skirbi-bg-transform: none;
--skirbi-bg-transform: wash;
--skirbi-bg-transform: reverse-wash;Wash controls
--skirbi-wash-perc: 8%;
--skirbi-reverse-wash-perc: 85%;Default page backgrounds use a wash transform.
This keeps themes calm and readable by default.
Status colors
Status colors are semantic, not branding.
--skirbi-info-base
--skirbi-success-base
--skirbi-warn-base
--skirbi-error-baseThey are intentionally opinionated for:
- readability
- contrast
- colorblind resilience
It is strongly advised not to override them without proper testing and validating assumptions.
Typography
Typography is opt-in and token-driven.
Core knobs
--skirbi-font-scale
--skirbi-line-height
--skirbi-h1-scale
--skirbi-h2-scale
--skirbi-h3-scale
--skirbi-h4-scale
--skirbi-prose-gapFont families
--skirbi-font-sans
--skirbi-font-monoComponent recipes
Pinta ships light recipes for Semtic elements.
Examples:
semtic-panelsemtic-tilesemtic-terminalsemtic-navsemtic-sidenavsemtic-tablesemtic-aside
These recipes are intentionally conservative and easy to override.
Layout primitives
Semtic ships minimal layout primitives:
<semtic-grid>
<semtic-flex>
<semtic-stack>These are structural primitives, not utility APIs.
Use normal CSS for:
- spacing
- layout tuning
- responsiveness
- composition
Pinta provides light defaults only.
Example:
<semtic-grid player-details>Use normal CSS for semtic-grid[player-details] to define columns.
Accessibility defaults
Pinta ships default focus handling:
--skirbi-focus-ring-size
--skirbi-focus-ring-colorFocus styling is theme-level because it affects accessibility.
Native CSS is the escape hatch
Pinta intentionally prefers normal CSS over utility APIs.
Example:
<semtic-panel class="featured">.featured {
border-color: var(--skirbi-primary-main);
}This is the preferred extension model. Whether you pick class based vs attribute based is up to you as the author.
Optional utilities
Pinta v0.0.12 removed built-in utility attributes from the core package.
An optional utility package may exist later for:
- prototypes
- demos
- quick experiments
Core Pinta intentionally stays focused on:
- tokens
- derivations
- recipes
- theming
