All projects

Charcoal: A Flexible, Open Source Design System

An open source, dark-first design system and agentic workflow primitives. Monochromatic backbone with a configurable accent color. Three presets. No bloat. Still evolving.

Year
2025 — Present
Type
Open Source
Status
Work in Progress
License
MIT
Charcoal Design System hero: dark monochromatic background with the Charcoal wordmark
Foundation Components
Status Badges
AI Agent Complete Pending Approval Failed Draft
Neutral Ramp
50
100
200
300
500
700
800
900
950
Foundation layer: 5 button variants, status badges, and the dark monochromatic neutral ramp

AI products deserve their own design system

Every design system I've used was built for CRUD apps: forms, tables, dashboards. When I started designing AI-native products, the gaps became obvious. There were no components for approval gates where a human decides whether an agent proceeds. No reasoning traces that show users why an AI made a decision. No confidence indicators, no token counters, no execution timelines.

Teams were either building these from scratch on every project or bolting AI features onto systems that weren't designed for them. The results were inconsistent, inaccessible, and hard to maintain.

Charcoal exists because AI products have fundamentally different interaction patterns than traditional software. Agents need approval gates. Users need transparency into what the AI is doing and why. Costs need to be visible. And all of it needs to work within a cohesive design language that scales.

The system is a work in progress, built to flex as the AI landscape shifts. What matters now is getting the primitives right.

4
Component layers
3
Accent presets
WIP
Active development
MIT
Open source

Four principles that drive every decision

01
Monochromatic backbone, single accent
Dark-first with a monochromatic gray ramp as the foundation. One configurable accent color handles every action and signal, keeping the interface focused. Three presets ship out of the box (Magenta, Purple, Blue), and any hex value generates a full 11-step ramp automatically. Semantic colors (green, amber, red) exist only for status. The accent is the only color with personality.
02
AI transparency over black boxes
Every tool call, reasoning step, cost, and decision is visible to the user. Components like ReasoningTrace, ToolCallCard, and TokenCounter exist specifically to expose what the AI is doing and why. Trust is built through visibility, not abstraction.
03
Human attention is scarce
Approval gates and handoffs are visually prominent, use distinct warning and error borders, and show clear impact statements: "If Approved" and "If Rejected." When an AI agent needs human input, that moment gets the full visual weight it deserves. Critical decisions demand focus.
04
Built to flex
The AI design landscape is shifting fast. Charcoal is built as a flexible foundation, not a rigid framework. Token-driven architecture means the system adapts as new interaction patterns emerge. Every component reads from tokens via a useTokens() hook. No prop drilling, no inline overrides. Change the TokenProvider and every component responds.
System at a Glance
4px
Base Unit
1.25
Type Scale
4.5:1
Min Contrast
3
Accent Presets
Status Colors (Semantic Only)
Success
#1AAF5D
Warning
#E9A50E
Error
#B91C1C
Info
#4575AA
Design rationale: 4px grid, 1.25 major third type scale, WCAG AA contrast, and muted semantic status colors

Tokens that flex with the system

The token system is the core of Charcoal. A single source file defines the dark monochromatic palette, accent color ramp generation, spacing scale, typography, and semantic colors. Everything is organized into categories that components consume through a React context provider.

Tokens are organized into semantic categories: colors (neutral darks, accent ramp, status), spacing (4px base unit, 13-step scale), typography (Inter for UI, JetBrains Mono for code), radius, shadows, and animation (durations, easing functions).

What makes the token system unique are the AI-specific namespaces. Agent state, confidence levels, tool status indicators, and cost tracking are all first-class tokens. These aren't ad-hoc CSS variables. They're part of the design language.

All tokens are emitted as --ch-* CSS custom properties via a TokenProvider. Components consume them through a useTokens() hook internally. Swap the provider and every component in the tree updates.

Token Categories
Spacing (4px base)
Radius
0 2 4 6 8 12 full
Typography
Inter — UI text
The quick brown fox
JetBrains Mono — Code
const tokens = buildTokens()
Token system: spacing scale, border radius ramp, and dual-font typography

Four layers, zero bloat

Components are organized into four layers. Each builds on the previous without redundancy. Layer 1 handles standard UI. Layers 2-4 are what make Charcoal different: primitives purpose-built for AI products that no other design system ships. The component inventory is actively evolving.

Layer 1
Foundations
Core UI primitives
Button, Input, Select, Checkbox, Radio, Switch, Badge, Avatar, Alert, Tooltip, Card, Modal, Tabs, Breadcrumb, Pagination
Layer 2
AI-Native
Conversational AI primitives
ChatMessage, PromptInput, ConversationThread, DateSeparator, CodeBlock, StreamingText, ResponseActions, CitationCard, ModelBadge, TokenCounter
Layer 3
Agentic Workflow
Agent coordination primitives
ApprovalGate, ToolCallCard, ReasoningTrace, AgentStatus, ExecutionTimeline, MultiAgentRoster, CostDashboard, ConfidenceIndicator
Layer 4
Generative UI
Dynamic interface primitives
AdaptiveCard, DynamicForm, GenerativeLayout, ProgressiveDisclosure, ConfirmationPreview, ContextSwitcher, SchemaDataDisplay, SlotContainer
Layer 2 — AI-Native Chat
You
You2:31 PM
Can you analyze this CSV data and show me the top 5 products by revenue?
AI
Assistant Claude 4 Opus 2:31 PM
I'll analyze the sales data using pandas. Here's the code to extract the top 5 products by revenue:
python
import pandas as pd
df = pd.read_csv("sales_data.csv")
top5 = df.groupby("product")["revenue"].sum()
    .nlargest(5)
# Product E  $2,854,200
# Product A  $2,421,800
# Product C  $1,987,600
SYS
System
Context: 4,096 tokens remaining. Temperature: 0.7
Layer 2 AI-Native: ChatMessage with role-aware rendering (user, assistant, system), model badges, code blocks, and response actions
Layer 3 — Agentic Workflow
search_database Success
0.3s$0.003
query: "Q4 revenue by region" · 1,247 rows
generate_report Running
1.2s
processing 3 data sources...
send_email Error
0.1s
Error: SMTP authentication failed
Approval Gate
Urgent Approval Required
Send follow-up email to 47 recipients
The agent wants to send a follow-up email to 47 recipients who haven't opened the recap email. This action will use the personalized email draft template.
If Approved
47 emails sent via campaign tool
If Rejected
No action taken, draft saved
Confidence & Cost Tracking
Confidence87%
Token Budget72% used
Layer 3 Agentic Workflow: ToolCallCard with status states, ApprovalGate with consequence preview, ConfidenceIndicator, and TokenBudgetMeter

The interaction patterns no one had solved

When an AI agent takes an action in the real world, sends an email, queries a database, writes code, there needs to be a moment where a human can see what's about to happen and decide whether to proceed. That's not a modal with an "OK" button. It's an approval gate that shows the action, the consequences of approving, the consequences of rejecting, and the confidence level of the agent making the request.

When multiple agents are working in parallel, each calling different tools, each at different stages of completion, users need a way to see the full picture without getting overwhelmed. That's Agent Status Cards and Parallel Thread Views, not a list of log entries.

When an agent hands off work to another agent, users need to see what was passed, what context was included, and what was left out. That's the Agent Handoff Chain, not an invisible backend event.

These aren't edge cases. They're the core interaction patterns of agentic products. Every team building with LLMs hits these problems. Charcoal gives them production-ready components instead of starting from scratch.

Multi-Agent Roster
Planner
Parsing user request...
thinking
Researcher
12 documents retrieved
complete
Analyst
Awaiting human approval
waiting
Writer
Standing by
idle
Multi-agent coordination: status cards showing four agent states
Reasoning Trace
Parse request 0.1s
Extracted intent: data retrieval, entity: users, filter: active
Search knowledge base 0.4s
Queried 3 indexes, found 12 relevant documents
Generate SQL 0.2s
Built parameterized query with active filter
sql_builder Success
0.2s
Execute query 0.8s
Returned 47 rows in 84ms
ReasoningTrace: step-by-step agent reasoning with nested tool calls
Execution Timeline
8 events
Duration: 4.4s Cost: $0.026
TimeActionAgentStatusCost
00:00.0 Initialize Planner $0.001
00:00.3 Search docs Researcher $0.004
00:01.5 Generate SQL Analyst $0.002
00:01.8 Execute query Analyst $0.003
00:03.8 Draft response Writer $0.005
ExecutionTimeline: multi-agent event log with cost tracking

Not a retrofit, a rethink

01
AI-first, not AI-added
Charcoal isn't a general-purpose system with AI components bolted on. It's designed from the ground up for agentic interfaces. ApprovalGate, ToolCallCard, ReasoningTrace, ExecutionTimeline, and ConfidenceIndicator are primitives that no other design system ships. They exist because agentic products need them.
02
Web-first development
The React components are the source of truth, not Figma. The demo app is the documentation. Every component has real event handlers, proper HTML semantics, and accessibility attributes. This inverts the typical design system workflow: build in the browser, validate with users, then create Figma assets from working code.
03
Flexible by design
Charcoal is built to evolve. The token architecture means new component patterns can be added without breaking existing ones. As new AI interaction patterns emerge, the system grows with them rather than requiring a rewrite.
04
Constraint as clarity
Dark monochromatic backbone. One accent color. No color overload. This is a deliberate constraint, not a limitation. In AI products where users are monitoring agents, reviewing decisions, and approving actions, visual noise is the enemy. A single accent on a dark canvas means your eye always knows what demands attention.

Components working together

Individual components are building blocks. Patterns show how they compose into real interfaces. Each pattern uses components from multiple layers to demonstrate how the system works as a whole, not just as a parts catalog.

Composed Pattern — Agent Workflow
You
You
Send a follow-up email to everyone who hasn't opened the Q4 recap.
AI
AssistantClaude 4 Opus
I'll check the campaign analytics first to identify recipients.
campaign_analytics Success
0.4s$0.002
47 recipients haven't opened · 312 total sent
Found 47 recipients. I'll need your approval before sending.
Urgent Approval Required
Send follow-up to 47 recipients
Using the personalized email draft template for non-openers.
If Approved
47 emails sent
If Rejected
Draft saved, no action
Composed pattern: ChatMessage + ToolCallCard + ApprovalGate working together in a single conversation flow
Confidence — Bar
Confidence92%
Confidence54%
Confidence18%
Confidence — Ring
92%
54%
18%
Confidence — Labels
High Confidence Medium Confidence Low Confidence Very High Confidence
ConfidenceIndicator: three display modes (bar, ring, label) across four confidence levels

An evolving system

Charcoal is a work in progress. The foundation is set: token architecture, four component layers, and a dark monochromatic visual language with configurable accent that stays out of the way. What comes next is driven by real usage and the patterns that emerge as AI products mature.

Next project
RepoIntel