Component toolkit

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.

Browse components
Introduction

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.

Own your code
  • 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.
Consistent patterns
  • Predictable structure: learn one component, understand the system.
  • Faster onboarding: teams move by intuition, not memorisation.
  • Composable by default: extend without breaking the model.
Copy & customise
  • Zero bundle bloat: take only what you need.
  • Portable patterns: the ideas travel across frameworks.
  • Incremental adoption: add components as your product grows.
Production ready
  • Accessibility-minded: sensible focus and semantics.
  • Polished defaults: calm styling out of the box.
  • Easy overrides: keep what works, customise what matters.
Developer experience

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.

1
Install
Add the package to your project.
2
Import CSS
Use the library stylesheet (tokens + components).
3
Optional: Web components
Call 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()
Notes
  • CSS-first: you can copy/paste snippets without adopting a framework.
  • Focus: components use :focus-visible to 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.

Core
Base colours and surfaces used across the system.
--brand
Primary accent
--ink
Text / on-dark
--muted
Secondary text
--bg
App background
--card
Panel base
--border
Hairline borders
:root{
  --brand:#47b8af;
  --ink:#eaf2f2;
  --muted:#a3b0b2;
  --bg:#060b0c;
  --card:#0c1415;
  --border:#1a2728;
  --shadow:0 18px 50px rgba(0,0,0,.55);
  --radius:18px;
}
Primary
Predictable accent shades (50–800) for borders, focus rings, tints, and emphasis.
50
--rk-primary-50
100
--rk-primary-100
200
--rk-primary-200
300
--rk-primary-300
400
--rk-primary-400
500
--rk-primary-500
600
--rk-primary-600
700
--rk-primary-700
800
--rk-primary-800
Secondary*
Support accent shades (50–800) for secondary actions and subtle highlights.
50
--rk-secondary-50
100
--rk-secondary-100
200
--rk-secondary-200
300
--rk-secondary-300
400
--rk-secondary-400
500
--rk-secondary-500
600
--rk-secondary-600
700
--rk-secondary-700
800
--rk-secondary-800
Semantic
Status + messaging colours. Use tint + border — avoid loud fills.
Success
--rk-success
Info
--rk-info
Warning
--rk-warning
Danger
--rk-danger
Shape & shadow
A single radius and a soft shadow token to keep surfaces consistent.
Radius
--radius = 18px
Shadow
--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.

Primary
50
--rk-primary-50
100
--rk-primary-100
200
--rk-primary-200
300
--rk-primary-300
400
--rk-primary-400
500
--rk-primary-500
600
--rk-primary-600
700
--rk-primary-700
800
--rk-primary-800
Secondary*
Support accent for secondary actions and subtle highlights. Shades run 50–800.
50
--rk-secondary-50
100
--rk-secondary-100
200
--rk-secondary-200
300
--rk-secondary-300
400
--rk-secondary-400
500
--rk-secondary-500
600
--rk-secondary-600
700
--rk-secondary-700
800
--rk-secondary-800
Semantic
Success
--rk-success
Info
--rk-info
Warning
--rk-warning
Danger
--rk-danger

Typography

Type styles and usage guidance. Optimised for dark UI, readability, and workflow density.

Font families
A simple split: serif for editorial headings, sans for UI and body, monospace for code.
UI / Body
ui-sans-serif, system-ui, -apple-system, Segoe UI, Inter, Roboto, Helvetica, Arial
Headings
ui-serif, Georgia, Times New Roman, Times, serif
Code
ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace
Type styles
Each row shows the token info on the left and a real preview on the right.
Display
44px · 1.02 · 520 · serif
Designing calm SaaS
Heading
22px · 1.15 · 520 · serif
Other topics
Subheading
16px · 1.45 · 650 · sans
Clear states, safe actions, fewer dead ends
Body
15px · 1.70 · 400 · sans
Body copy aims for clarity: explain the why, show the system, and keep the language practical.
Muted
13px · 1.55 · 400 · sans
Used for metadata, helper copy, and supporting information.
Label
12px · 1.2 · 600 · sans
Email
Code
12px · 1.5 · 400 · mono
.rk-btn.primary { background: var(--ink); }
Guidelines
  • 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.

Core token
RadKit uses a single base radius and applies it consistently across surfaces.
Base
--radius · 18px
Scale

Use these as a practical scale for small UI parts through to large panels.

Small
6px
Medium
12px
Large
14px
Panel
18px
Hero
22px
Pill
999px
Tip: clicking a tile copies the token example.
Applied examples

How radius shows up across common components.

Input (14px)
Email
name@company.com
Button (pill)

Breakpoints

Responsive breakpoints for Desktop, Tablet and Mobile. Use these to keep layouts predictable across devices.

Breakpoint tokens
A simple 3-breakpoint model that matches most product UI needs.
Mobile
0–767px
Tablet
768–1023px
Desktop
1024px+
/* Example media queries */
@media (max-width: 767px) { /* mobile */ }
@media (min-width: 768px) and (max-width: 1023px) { /* tablet */ }
@media (min-width: 1024px) { /* desktop */ }
Guidance
  • 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.

Opacity values
Click a tile to copy the token name and value.
Opacity-0
0%
Opacity-5
5%
Opacity-10
10%
Opacity-20
20%
Opacity-25
25%
Opacity-30
30%
Opacity-40
40%
Opacity-50
50%
Opacity-60
60%
Opacity-70
70%
Opacity-75
75%
Opacity-80
80%
Opacity-90
90%
Opacity-95
95%
Opacity-100
100%
Usage
  • 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.

Line (Default)
<div class="rk-divider" role="separator" aria-hidden="true"></div>
Line with Spacing
Section A
Section B
<div class="rk-divider" style="margin:16px 0" role="separator" aria-hidden="true"></div>
Line Text
<div class="rk-divider-text" role="separator" aria-label="or">
  <span>or</span>
</div>
Content
<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>
Button (line with button)
<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>
Text (Text inside rectangle divider)
<div class="rk-divider-pill" role="separator">
  <span class="rk-divider-pill-text">Archived</span>
</div>
Back to Browse all

Buttons

Primary button. Preview + code are shown as tabs.

Primary (glass)
<button class="rk-btn primary">Primary</button>
Primary filled
<button class="rk-btn primary filled">Primary</button>
Primary outlined
<button class="rk-btn primary outlined">Primary</button>

Browse all components

A quick index of component categories and their building blocks.

Actions
Buttons and action patterns
Forms
Inputs and form controls
Pickers
Colour, date, and time inputs
Indicators
Badges and status signals
Feedback
Messaging patterns
Data
Tables and dense views
Surfaces
Cards and containers
Widgets
Small, reusable UI blocks
Back to Browse all

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>
Back to Browse all

Inputs

Preview + code tabs for the default text input. Extended examples can be added as additional demos.

Helper text sits at 12–13px and uses muted colour.
<label class="rk-label">Email</label>
<input class="rk-input" placeholder="name@company.com" />
Back to Browse all

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>
Back to Browse all

Switch

A calm toggle pattern. Stacked, 1-column examples with Preview/Code per variant.

Default
<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>
Disabled
<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>
With 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>
With advanced labelling
<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>
Back to Browse all

Text Area

A flexible textarea for multi-line input: labels, hint text, validation, and character counting — without drama.

Simple
<textarea class="rk-textarea rk-textarea--lg rk-textarea--non-resizable"
  rows="4"
  placeholder="Jot down your thoughts..."></textarea>
Simple: Resizable
Resizable: drag to resize.
<textarea class="rk-textarea rk-textarea--lg rk-textarea--resizable"
  rows="4"
  placeholder="Jot down your thoughts..."></textarea>
With Label and Hint
Keep it brief. Bullets are fine.
<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>
Interactive Char Counter
Up to 140 characters.
0/140
<textarea class="rk-textarea" maxlength="140" data-rk-counter></textarea>
<div class="rk-counter"><span data-rk-counter-value>0</span>/140</div>
Disabled
<textarea class="rk-textarea" disabled>This textarea is disabled and cannot be edited.</textarea>
Has Error
Please add at least 10 characters.
<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>
Back to Browse all

Tabs

Preview + code tabs for the filter pill tabs pattern.

<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>
Back to Browse all

Color Picker

A calm colour input pattern using native pickers, wrapped in RadKit glass UI.

Default
Use native colour picking, but keep the surrounding UI consistent.
<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>
Disabled
<input class="rk-color-input" type="color" disabled />
Back to Browse all

Date Picker

Native date input, styled to sit inside RadKit glass surfaces.

Default
Works well for settings + forms without heavy JS.
<div class="rk-picker-field">
  <span class="rk-picker-icon" aria-hidden="true">...</span>
  <input class="rk-input rk-picker-input" type="date" />
</div>
Disabled
<input class="rk-input" type="date" disabled />
Back to Browse all

Time Picker

Native time input, styled with the same calm spacing and glass surfaces as the rest of RadKit.

Default
Use a 24h or 12h picker depending on platform locale.
<input class="rk-input" type="time" />
Disabled
<input class="rk-input" type="time" disabled />
Back to Browse all

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>
Back to Browse all

Feed

Row hover only. Rect thumbnails. Metadata is compact and readable.

<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>
Back to Browse all

Badges

Each badge variant is documented with a Preview/Code container for copy/paste.

Default
Default
<span class="rk-badge">Default</span>
Primary
Primary
<span class="rk-badge brand">Primary</span>
Info
Info
<span class="rk-badge info">Info</span>
Warning
Warning
<span class="rk-badge warning">Warning</span>
Danger
Danger
<span class="rk-badge danger">Danger</span>
Back to Browse all

Tooltip

Calm, glassy tooltips for short, contextual guidance. Show on hover or focus — disappear without fuss.

Button with Tooltip
Copy to clipboard
<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>
Position
Top Right Bottom Left
<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>
Size
XSmall Small Medium Large tooltip text
<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>
Light
Tooltip content
<span class="rk-tip rk-tip--top rk-tip--light">Tooltip content</span>
Icon
More information
<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>
Back to Browse all

Count

A small count widget for dashboards: calm hierarchy, tabular numerals, and a subtle accent.

Open tasks
12
+3 · this week
<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>
Back to Browse all

Calendar

Calendar widgets for dashboards: quiet structure, readable spacing, and clear states.

Default
February 2026
Mon
Tue
Wed
Thu
Fri
Sat
Sun
<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>
With selection
February 2026
10–14
Mon
Tue
Wed
Thu
Fri
Sat
Sun
<button class="rk-cal-day is-selected" type="button">14</button>
<button class="rk-cal-day is-range" type="button">13</button>
Drag to select
February 2026
Drag to select
Mon
Tue
Wed
Thu
Fri
Sat
Sun
Click and drag across days to create a range.
<div class="rk-cal-grid" data-rk-cal-range>
  <button class="rk-cal-day" data-rk-day="10">10</button>
  ...
</div>
With events
February 2026
3 events
Mon
Tue
Wed
Thu
Fri
Sat
Sun
Event Busy
<button class="rk-cal-day has-dot" type="button">
  <span class="rk-cal-num">12</span>
  <span class="rk-cal-dot"></span>
</button>
Back to Browse all

Tables

Keep tables calm: strong spacing, subtle separators, readable numeric columns.

Basic
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>
With actions
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>
Resizable columns
Drag the divider in the header to change the column width (demo).
Name Email 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>
Reorder columns
Drag a header to move the column left/right (demo).
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>
Back to Browse all

Graphs

Lightweight graph patterns for dashboards: calm grids, clear focus, and subtle emphasis.

Line
<svg class="rk-graph" viewBox="0 0 320 120">...</svg>
Bars
<div class="rk-bars">
  <span style="--v:.72"></span>
</div>
Sparkline
Active users
1,204
+6%
<svg class="rk-spark-svg" viewBox="0 0 120 28">
  <path d="..." />
</svg>
Back to Browse all

Alerts

Alerts are calm messaging blocks. Each variant is documented with Preview/Code for copy/paste.

Success
Success
Changes saved.
<div class="rk-alert success">
  <div class="rk-alert-title">Success</div>
  <div class="rk-alert-body">Changes saved.</div>
</div>
Info
Info
This pattern is useful for guidance in workflow-heavy screens.
<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>
Warning
Warning
Something needs attention, but it’s still safe to proceed.
<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>
Danger
Danger
Destructive actions should be explicit and reversible where possible.
<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>
Back to Browse all

Toast

Transient notifications: short, calm, and never blocking. Use for confirmations, warnings, and background status.

Default
Saved
Changes are live.
<div class="rk-toast-ui" role="status">
  <div class="rk-toast-title">Saved</div>
  <div class="rk-toast-body">Changes are live.</div>
</div>
With action
Invite sent
We’ll email them a link.
<div class="rk-toast-ui">
  ...
  <button class="rk-btn sm">Undo</button>
</div>
Status variants
Success
Saved without errors.
Info
Sync running in background.
Warning
Some fields need review.
Error
Couldn’t save changes.
<div class="rk-toast-ui success">...</div>
<div class="rk-toast-ui danger">...</div>