jamkit doesn't ship every widget you'll ever need โ but every piece follows the same recipe. this guide shows you how to compose new UI from tokens + primitives, with a full walkthrough.
every jamkit surface shares these rules. break one and it'll look "off".
var(--jam-border-w) on every interactive surface4px 4px 0 var(--jam-shadow))border-radius: var(--jam-radius) (1rem)style="text-transform:none" for codes--jam-accent, never hardcode purplelet's build a "games played" stat card that isn't in the default pack.
the box class gives you border, background, radius, and shadow for free.
<div class="box" style="padding:1rem">...</div>
label on top, big number below. use display sizes for hierarchy.
games played
42
when you use it more than once, add to jamkit.css:
.stat-card {
padding: 1.25rem;
text-align: center;
}
.stat-card-value {
font-size: clamp(1.75rem, 4vw, 2.25rem);
color: var(--jam-accent);
margin: 0;
}
.stat-card-label {
color: var(--jam-muted);
font-size: 0.875rem;
margin: 0 0 0.5rem;
}
interactive cards get the press effect:
.stat-card-interactive {
cursor: pointer;
transition: transform 0.15s, box-shadow 0.15s;
}
.stat-card-interactive:hover {
transform: translate(2px, 2px);
box-shadow: none;
}
hover me
42
square buttons for toolbars โ compose from .btn with size overrides.
.icon-btn {
width: 2.75rem;
height: 2.75rem;
padding: 0;
font-size: 1.25rem;
line-height: 1;
}
<button class="btn btn-white icon-btn" aria-label="settings">โ</button>
track loading or quiz progress with a bordered track + accent fill.
.progress-track {
height: 1.25rem;
border: var(--jam-border-w) solid var(--jam-border);
border-radius: 999px;
background: var(--jam-raised);
box-shadow: 2px 2px 0 var(--jam-shadow);
overflow: hidden;
}
.progress-fill {
height: 100%;
background: var(--jam-accent);
border-right: var(--jam-border-w) solid var(--jam-accent-border);
transition: width 0.3s ease;
}
<div class="progress-track">
<div class="progress-fill" style="width:68%"></div>
</div>
never hardcode the brand purple. always reference tokens.
do
background: var(--jam-accent); border-color: var(--jam-accent-border); color: var(--jam-text); background: var(--jam-raised);
don't
background: #a855f7; /* breaks when user picks blue */ box-shadow: 0 4px 12px rgba(0,0,0,.15); /* soft shadow โ brutal */
import { applyAccent } from './js/theme.js'
applyAccent('#3b82f6') // updates all accent tokens site-wide
toggle html.dark class. surfaces auto-flip via css variables โ your custom classes inherit automatically if they use tokens.
document.documentElement.classList.toggle('dark', true)
mix primitives instead of reinventing:
| you need | start with | add |
|---|---|---|
| card with title | .box | .section-title inside |
| settings row | .box + flex | .pill-toggle group |
| user list item | .player-row | .avatar + .btn-white |
| confirm action | .modal-backdrop | .btn-primary + .btn-white |
| form section | .box | .input-field + .field-error |
| tag / chip | .pill-toggle | smaller padding, no shadow on active |
jammit itself uses tailwind + the same classes in src/index.css. to port jamkit:
jamkit.css into your global cssbg-jam-purple with background: var(--jam-accent) or a tailwind arbitrary value--jam-accent on :root