RadKit
A calm, copy-first UI toolkit for developers who value ownership. Production-ready components that live in your codebase — not behind a package wall.
Traditional UI libraries ask you to install, import, and accept their decisions. When the abstraction cracks, you end up fighting wrappers and workarounds.
RadKit flips the model: components are readable source you can copy, keep, and shape. Grab the components. Adapt them. Ship faster.
- Full transparency: read every line, debug without a black box.
- Direct modification: change markup, behaviour, and styling in-place.
- Update control: pull improvements when you’re ready — no surprise breakage.
- Predictable structure: learn one component, understand the system.
- Faster onboarding: teams move by intuition, not memorisation.
- Composable by default: extend without breaking the model.
- Zero bundle bloat: take only what you need.
- Portable patterns: the ideas travel across frameworks.
- Incremental adoption: add components as your product grows.
- Accessibility-minded: sensible focus and semantics.
- Polished defaults: calm styling out of the box.
- Easy overrides: keep what works, customise what matters.
RadKit prioritises readable, well-organised source. Because components live in your project, AI tools can analyse them, learn your patterns, and help you extend the system without drifting.
Installation
Install RadKit as CSS-first UI styles. Optional web components are available for a few primitives.
defineRadKit() if you want <rk-button> etc.# Install
npm i @calrxd/radkit
# Import CSS
import '@calrxd/radkit/radkit.css'
# Optional web components
import { defineRadKit } from '@calrxd/radkit'
defineRadKit()
- CSS-first: you can copy/paste snippets without adopting a framework.
- Focus: components use
:focus-visibleto stay accessible. - Dark-first: tokens are optimised for dark glass surfaces by default.
Tokens
All core design tokens in one place. One-column layout, copy-friendly, and designed for dark glass surfaces.
:root{
--brand:#47b8af;
--ink:#eaf2f2;
--muted:#a3b0b2;
--bg:#060b0c;
--card:#0c1415;
--border:#1a2728;
--shadow:0 18px 50px rgba(0,0,0,.55);
--radius:18px;
}
--radius = 18px--shadow = 0 18px 50px rgba(0,0,0,.55)Colors
Semantic colours + a primary scale for predictable contrast and states. Primary shades run 50–800.
Typography
Type styles and usage guidance. Optimised for dark UI, readability, and workflow density.
- Line length: aim for 60–80 characters per line for scanning.
- Hierarchy: one dominant heading per surface; keep subheadings short and descriptive.
- Metadata: keep dates, counts, and helper text muted so primary content leads.
- Accessibility: ensure contrast remains readable on glass backgrounds and in hover states.
Radius
Corner radius tokens and usage guidance. Keep the system consistent by using a small set of radii.
Use these as a practical scale for small UI parts through to large panels.
How radius shows up across common components.
Breakpoints
Responsive breakpoints for Desktop, Tablet and Mobile. Use these to keep layouts predictable across devices.
/* Example media queries */
@media (max-width: 767px) { /* mobile */ }
@media (min-width: 768px) and (max-width: 1023px) { /* tablet */ }
@media (min-width: 1024px) { /* desktop */ }
- Design mobile-first where possible, then enhance for tablet/desktop.
- Use layout changes (grid → stacked) rather than shrinking text.
- Keep tap targets comfortable on mobile (buttons, nav items).
Opacity
Opacity tokens for subtle layering on glass surfaces. Use lower values for backgrounds and higher values for overlays.
- 5–10% for subtle panel tints and hover fills.
- 20–30% for overlays behind modals/drawers.
- 70%+ for strong scrims (use sparingly in this visual style).
Divider
Lightweight separators for grouping content on glass surfaces. Each variant includes Preview/Code for copy/paste.
<div class="rk-divider" role="separator" aria-hidden="true"></div>
<div class="rk-divider" style="margin:16px 0" role="separator" aria-hidden="true"></div>
<div class="rk-divider-text" role="separator" aria-label="or">
<span>or</span>
</div>
<div class="rk-divider-content" role="separator">
<div class="rk-divider-line" aria-hidden="true"></div>
<div class="rk-divider-slot">Showing 12 results</div>
<div class="rk-divider-line" aria-hidden="true"></div>
</div>
<div class="rk-divider-content" role="separator">
<div class="rk-divider-line" aria-hidden="true"></div>
<button class="rk-btn sm" type="button">Add filter</button>
<div class="rk-divider-line" aria-hidden="true"></div>
</div>
<div class="rk-divider-pill" role="separator">
<span class="rk-divider-pill-text">Archived</span>
</div>
<button class="rk-btn primary">Primary</button>
<button class="rk-btn primary filled">Primary</button>
<button class="rk-btn primary outlined">Primary</button>
Browse all components
A quick index of component categories and their building blocks.
Button Group
Grouped buttons share a single surface, useful for segmented actions and compact toolbars.
<div class="rk-btn-group" role="group">
<button class="rk-btn">Day</button>
<button class="rk-btn primary">Week</button>
<button class="rk-btn">Month</button>
</div>
Link Button
A button-styled link for navigation actions. Use when the element changes location rather than submitting.
<a class="rk-btn link" href="/path">Open details</a>
Inputs
Preview + code tabs for the default text input. Extended examples can be added as additional demos.
<label class="rk-label">Email</label>
<input class="rk-input" placeholder="name@company.com" />
Checkbox
Checkbox pattern with a calm hit area, clear checked state, and focus-visible ring.
<label class="rk-checkbox-row">
<input class="rk-checkbox" type="checkbox" checked />
<span class="rk-checkbox-box" aria-hidden="true"></span>
<span class="rk-checkbox-text">
<span class="rk-checkbox-title">Email updates</span>
<span class="rk-checkbox-desc">Occasional, useful.</span>
</span>
</label>
Switch
A calm toggle pattern. Stacked, 1-column examples with Preview/Code per variant.
<label class="rk-switch-row">
<input class="rk-switch-input" type="checkbox" role="switch" />
<span class="rk-switch" aria-hidden="true"></span>
<span class="rk-switch-text">Enable reminders</span>
</label>
<label class="rk-switch-row">
<input class="rk-switch-input" type="checkbox" role="switch" disabled />
<span class="rk-switch" aria-hidden="true"></span>
<span class="rk-switch-text">Sync over mobile data</span>
</label>
<label class="rk-switch-row is-split">
<span class="rk-switch-text">
<span class="rk-switch-title">Auto-archive</span>
<span class="rk-switch-desc">Move items to Archive after 30 days.</span>
</span>
<input class="rk-switch-input" type="checkbox" role="switch" />
<span class="rk-switch" aria-hidden="true"></span>
</label>
<label class="rk-switch-row is-split">
<span class="rk-switch-text">
<span class="rk-switch-title">Require approvals</span>
<span class="rk-switch-desc">Requests over £250 will need manager approval. This applies to all departments.</span>
</span>
<input class="rk-switch-input" type="checkbox" role="switch" />
<span class="rk-switch" aria-hidden="true"></span>
</label>
Text Area
A flexible textarea for multi-line input: labels, hint text, validation, and character counting — without drama.
<textarea class="rk-textarea rk-textarea--lg rk-textarea--non-resizable"
rows="4"
placeholder="Jot down your thoughts..."></textarea>
<textarea class="rk-textarea rk-textarea--lg rk-textarea--resizable"
rows="4"
placeholder="Jot down your thoughts..."></textarea>
<div class="rk-field">
<label class="rk-label" for="rk-ta-1">Description</label>
<div class="rk-help" id="rk-ta-1-hint">Keep it brief. Bullets are fine.</div>
<textarea id="rk-ta-1"
class="rk-textarea rk-textarea--lg rk-textarea--non-resizable"
rows="4"
placeholder="Jot down your thoughts..."
aria-describedby="rk-ta-1-hint"></textarea>
</div>
<textarea class="rk-textarea" maxlength="140" data-rk-counter></textarea>
<div class="rk-counter"><span data-rk-counter-value>0</span>/140</div>
<textarea class="rk-textarea" disabled>This textarea is disabled and cannot be edited.</textarea>
<textarea class="rk-textarea is-error" aria-invalid="true" aria-describedby="rk-ta-3-error">...</textarea>
<div class="rk-error" id="rk-ta-3-error">Please add at least 10 characters.</div>
<div class="rk-tabs" role="tablist">
<button class="rk-tab active" type="button">All <span class="rk-count">12</span></button>
<button class="rk-tab" type="button">UX <span class="rk-count">4</span></button>
</div>
Color Picker
A calm colour input pattern using native pickers, wrapped in RadKit glass UI.
<div class="rk-picker-row">
<input class="rk-color-input" type="color" value="#47b8af" />
<input class="rk-input rk-picker-text" value="#47b8af" readonly />
</div>
<input class="rk-color-input" type="color" disabled />
<div class="rk-picker-field">
<span class="rk-picker-icon" aria-hidden="true">...</span>
<input class="rk-input rk-picker-input" type="date" />
</div>
<input class="rk-input" type="date" disabled />
Time Picker
Native time input, styled with the same calm spacing and glass surfaces as the rest of RadKit.
<input class="rk-input" type="time" />
<input class="rk-input" type="time" disabled />
Cards
Hover lift, soft border shift toward brand. Thumbnails are rounded and slightly inset.
<div class="rk-grid">
<a class="rk-card" href="#">
<div class="rk-thumb"><span></span></div>
<div class="rk-card-title">Workflow audit</div>
<div class="rk-muted">Mapped the current journey, surfaced divergence, and defined a consistent model.</div>
</a>
<a class="rk-card" href="#">
<div class="rk-thumb"><span></span></div>
<div class="rk-card-title">Component patterns</div>
<div class="rk-muted">Reusable states and copy rules so the flow scales without drifting.</div>
</a>
</div>
<div class="rk-feed">
<a class="rk-feed-item" href="#">
<div class="rk-feed-thumb"><span></span></div>
<div class="rk-feed-main">
<div class="rk-meta">
<span class="rk-badge brand">UX</span>
<span class="rk-dotsep">·</span>
<span class="rk-muted">Jan 2025</span>
</div>
<div class="rk-feed-title">Adding attachments — a calmer, clearer upload experience</div>
</div>
</a>
</div>
Badges
Each badge variant is documented with a Preview/Code container for copy/paste.
<span class="rk-badge">Default</span>
<span class="rk-badge brand">Primary</span>
<span class="rk-badge info">Info</span>
<span class="rk-badge warning">Warning</span>
<span class="rk-badge danger">Danger</span>
Tooltip
Calm, glassy tooltips for short, contextual guidance. Show on hover or focus — disappear without fuss.
<span class="rk-tip-wrap">
<button class="rk-btn sm" type="button">Hover me</button>
<span class="rk-tip rk-tip--top" role="tooltip">Copy to clipboard</span>
</span>
<span class="rk-tip rk-tip--top">...</span>
<span class="rk-tip rk-tip--right">...</span>
<span class="rk-tip rk-tip--bottom">...</span>
<span class="rk-tip rk-tip--left">...</span>
<span class="rk-tip rk-tip--top rk-tip--xs">XSmall</span>
<span class="rk-tip rk-tip--top rk-tip--sm">Small</span>
<span class="rk-tip rk-tip--top rk-tip--md">Medium</span>
<span class="rk-tip rk-tip--top rk-tip--lg">Large</span>
<span class="rk-tip rk-tip--top rk-tip--light">Tooltip content</span>
<span class="rk-tip-wrap">
<button class="rk-tip-icon" type="button" aria-label="More info">?</button>
<span class="rk-tip rk-tip--top" role="tooltip">More information</span>
</span>
Count
A small count widget for dashboards: calm hierarchy, tabular numerals, and a subtle accent.
<div class="rk-count">
<div class="rk-count-label">Open tasks</div>
<div class="rk-count-value">12</div>
<div class="rk-count-meta">
<span class="rk-count-delta up">+3</span>
<span class="rk-dotsep">·</span>
<span class="rk-muted">this week</span>
</div>
</div>
Calendar
Calendar widgets for dashboards: quiet structure, readable spacing, and clear states.
<div class="rk-cal">
<div class="rk-cal-head">
<div class="rk-cal-title">February 2026</div>
<div class="rk-cal-actions">
<button class="rk-btn sm" type="button">Today</button>
</div>
</div>
<div class="rk-cal-week">...</div>
<div class="rk-cal-grid">...</div>
</div>
<button class="rk-cal-day is-selected" type="button">14</button>
<button class="rk-cal-day is-range" type="button">13</button>
<div class="rk-cal-grid" data-rk-cal-range>
<button class="rk-cal-day" data-rk-day="10">10</button>
...
</div>
<button class="rk-cal-day has-dot" type="button">
<span class="rk-cal-num">12</span>
<span class="rk-cal-dot"></span>
</button>
Tables
Keep tables calm: strong spacing, subtle separators, readable numeric columns.
| Component | Status | Usage |
|---|---|---|
| Buttons | Stable | High |
| Feed rows | Stable | Medium |
| Modals | Planned | Low |
<table class="rk-table">
<thead>
<tr>
<th>Component</th>
<th>Status</th>
<th class="num">Usage</th>
</tr>
</thead>
<tbody>...</tbody>
</table>
| Member | Role | Usage | Actions |
|---|---|---|---|
| Cal | Owner | High | |
| Sam | Member | Medium | |
| Alex | Guest | Low |
<td class="rk-actions">
<button class="rk-btn sm outline" type="button">Edit</button>
<button class="rk-btn sm" type="button">View</button>
</td>
| Name | Spend | |
|---|---|---|
| Cal | hey@radkit.design | £1,240 |
| Sam | sam@example.com | £320 |
| Alex | alex@example.com | £80 |
<table class="rk-table is-resizable" data-rk-col-resize>
<thead>
<tr>
<th style="width:40%">Name<span class="rk-col-resize"></span></th>
...
</tr>
</thead>
</table>
| Name | Status | Usage |
|---|---|---|
| Buttons | Stable | High |
| Feed rows | Stable | Medium |
| Modals | Planned | Low |
<table class="rk-table" data-rk-col-reorder>
<thead>
<tr>
<th>Name <span class="rk-col-drag">⋮⋮</span></th>
...
</tr>
</thead>
</table>
Graphs
Lightweight graph patterns for dashboards: calm grids, clear focus, and subtle emphasis.
<svg class="rk-graph" viewBox="0 0 320 120">...</svg>
<div class="rk-bars">
<span style="--v:.72"></span>
</div>
<svg class="rk-spark-svg" viewBox="0 0 120 28">
<path d="..." />
</svg>
Alerts
Alerts are calm messaging blocks. Each variant is documented with Preview/Code for copy/paste.
<div class="rk-alert success">
<div class="rk-alert-title">Success</div>
<div class="rk-alert-body">Changes saved.</div>
</div>
<div class="rk-alert info">
<div class="rk-alert-title">Info</div>
<div class="rk-alert-body">This pattern is useful for guidance in workflow-heavy screens.</div>
</div>
<div class="rk-alert warning">
<div class="rk-alert-title">Warning</div>
<div class="rk-alert-body">Something needs attention, but it’s still safe to proceed.</div>
</div>
<div class="rk-alert danger">
<div class="rk-alert-title">Danger</div>
<div class="rk-alert-body">Destructive actions should be explicit and reversible where possible.</div>
</div>
Toast
Transient notifications: short, calm, and never blocking. Use for confirmations, warnings, and background status.
<div class="rk-toast-ui" role="status">
<div class="rk-toast-title">Saved</div>
<div class="rk-toast-body">Changes are live.</div>
</div>
<div class="rk-toast-ui">
...
<button class="rk-btn sm">Undo</button>
</div>
<div class="rk-toast-ui success">...</div>
<div class="rk-toast-ui danger">...</div>