Package Exports
- @dimkant/physics-engine
- @dimkant/physics-engine/exporter
- @dimkant/physics-engine/linter
- @dimkant/physics-engine/parser
Readme
⚡ Physics Engine
A generative design system based on physical laws, not static values.
Most design systems are dictionaries — you look up a value and apply it. Physics Engine adds two things on top: semantic naming (tokens describe intent, not just value) and enforcement rules (a linter that validates Fitts Law, WCAG contrast, and geometric consistency). The tokens are hand-curated. The value is in what they mean and what the linter catches.
npx @trubnikov/physics-engine lint DESIGN.md
npx @trubnikov/physics-engine export --format tailwind DESIGN.mdThe Idea
UI elements obey physical laws. A button press is not a CSS state change — it is an energy elevation and a physical compression. A card doesn't have a shadow — it has a low energy level that puts it above the void.
This metaphor makes design decisions self-explanatory to any AI agent. Instead of "use #3B82F6 for the primary button", you say: "primary actions are at Kinetic Peak (Level 3) and emit glow as a side effect of their energy state."
The agent never needs to guess. It derives the right value from the law.
DESIGN.md Format
Physics Engine uses the DESIGN.md format — YAML front matter for machine-readable tokens, markdown prose for the rationale.
---
name: Physics Engine
colors:
void: "#050505" # Level 0 — Background universe
surface: "#111113" # Level 1 — Cards, panels
kinetic: "#3B82F6" # Level 3 — Primary actions, emits glow
spacing:
compact: "8px" # 2× Base Unit
optimal: "16px" # 4× Base Unit — most common value
motion:
micro:
type: spring
mass: 0.5
stiffness: 500
damping: 25
components:
button-primary:
backgroundColor: "{colors.kinetic}"
textColor: "{colors.kinetic-text}"
height: "44px" # Fitts Law minimum
motion: "{motion.micro}"
---
## Overview
A generative system where every value is derived, not chosen.An AI agent that reads this file will produce a UI where primary buttons glow at #3B82F6, all spacing is divisible by 4, interactive elements never drop below the 44px touch minimum, and animations use calibrated spring physics — without you telling it any of that explicitly.
The Physics
Energy Levels (Color System)
| Level | Name | Material | Use |
|---|---|---|---|
| 0 | Void | #050505 |
Background universe |
| 1 | Surface | #111113 |
Cards, panels, containers |
| 2 | Interactive | #1F1F24 |
Idle inputs, secondary buttons |
| 2.5 | Hover | #2A2A30 |
Energy elevation on hover |
| 3 | Kinetic Peak | #3B82F6 |
Primary actions, emits glow |
| — | Destructive | #EF4444 |
Danger, follows Level 3 rules |
Spatial Mathematics
All dimensions derive from a single Base Unit: 4px.
Compact = 2× = 8px → icon-to-text gap
Optimal = 4× = 16px → standard component padding
Loose = 6× = 24px → section spacing
Macro = 12× = 48px → modal internal paddingTopology Collapse (Border Radius)
Dynamic Radius = min(12px, height / 2)This formula prevents two failure states: over-rounding a small element into an unintended pill, and under-rounding a tall element into a rectangle. Radius is a function of the element's geometry, not a designer's choice.
Kinematics (Spring Physics)
No ease-in-out. No linear. Physics Engine uses spring presets defined as machine-readable tokens:
motion:
micro: # Buttons, toggles, checkboxes
type: spring
mass: 0.5
stiffness: 500
damping: 25
macro: # Modals, sidebars, drawers
type: spring
mass: 1.0
stiffness: 250
damping: 30
tap-scale: 0.96State transitions follow energy laws:
- Hover → Elevate energy +0.5
- Press → Compress to
scale(0.96), elevate energy +1
Accessibility
- Fitts Law — Every interactive element must be at least
44×44px - Focus Ring — Never suppress without replacement. Always
2px Kinetic-colored ring - ARIA — All interactive elements carry semantic HTML and
aria-*states
CLI
Install
npm install -g @trubnikov/physics-engine
# or run without installing:
npx @trubnikov/physics-engine lint DESIGN.mdlint — Validate your DESIGN.md
npx @trubnikov/physics-engine lint DESIGN.md{
"findings": [
{
"rule": "contrast-ratio",
"severity": "info",
"path": "components.button-primary",
"message": "textColor (#FFFFFF) on backgroundColor (#3B82F6) has contrast ratio 4.51:1 — passes WCAG AA."
},
{
"rule": "fitts-law",
"severity": "info",
"path": "components.button-primary",
"message": "height 44px meets Fitts Law minimum."
}
],
"summary": { "errors": 0, "warnings": 0, "info": 3 }
}Exit code 1 if errors are found.
export — Convert to other formats
# Tailwind theme config
npx @trubnikov/physics-engine export --format tailwind DESIGN.md > tailwind.config.js
# W3C Design Token Format (DTCG)
npx @trubnikov/physics-engine export --format dtcg DESIGN.md > design_tokens.json
# SwiftUI Design System
npx @trubnikov/physics-engine export --format swiftui DESIGN.md > DesignSystem.swiftspec — Print the specification
npx @trubnikov/physics-engine spec
npx @trubnikov/physics-engine spec --format jsonProgrammatic API
import { lint } from '@trubnikov/physics-engine/linter';
import { exportTokens } from '@trubnikov/physics-engine/exporter';
const report = lint(designMdString);
console.log(report.findings); // Finding[]
console.log(report.summary); // { errors, warnings, info }
console.log(report.designSystem); // Parsed DesignSystem
const tailwind = exportTokens(designMdString, 'tailwind');
const dtcg = exportTokens(designMdString, 'dtcg');
const swiftui = exportTokens(designMdString, 'swiftui');Generating UI with AI
Drop DESIGN.md into your AI agent's context. The agent now has everything it needs to generate correct, physics-consistent UI.
Prompt:
Build a login form using DESIGN.md.What the agent derives — without being told:
- Input backgrounds at Level 2 (
#1F1F24) - Focus state elevates to Level 2.5 (
#2A2A30) - Submit button at Level 3 (
#3B82F6) with glow emission - All padding multiples of 4px
- Spring physics (
mass: 0.5, stiffness: 500, damping: 25) for all transitions - ARIA labels on all fields
- Minimum 44px tap targets on all interactive elements
Linting Rules
| Rule | Severity | What it checks |
|---|---|---|
broken-ref |
error | Token references {path.to.token} must resolve |
missing-primary |
warning | A kinetic or primary color must exist |
contrast-ratio |
warning | WCAG AA minimum 4.5:1 for text/background pairs |
orphaned-tokens |
warning | Defined colors should be referenced by components |
fitts-law |
error | Interactive elements must be ≥ 44×44px |
energy-conservation |
error | Kinetic color must contrast against Void background |
nested-radius-law |
error | Outer radius must be ≥ padding |
token-summary |
info | Count of tokens in each section |
missing-typography |
warning | Typography tokens should exist alongside colors |
Examples
Three reference implementations — each a complete product design system derived from Physics Engine laws:
| Example | Theme | Demonstrates |
|---|---|---|
dark-command |
AI chat / dev console | Energy levels, dual typography, motion layer |
kinetic-commerce |
E-commerce product page | Single kinetic focal point, success state physics |
calm-focus |
Productivity / notes | Physics of restraint, prose typography |
Each example includes DESIGN.md, design_tokens.json, tailwind.config.js, and README.md.
Project Structure
design-physics-engine/
├── DESIGN.md ← The design system spec (start here)
├── src/
│ ├── cli.ts ← CLI entry point
│ ├── lint.ts ← Linter (9 rules)
│ ├── export.ts ← Export to Tailwind / DTCG / SwiftUI
│ └── parse.ts ← DESIGN.md parser
├── examples/
│ ├── dark-command/ ← AI chat interface example
│ ├── kinetic-commerce/ ← E-commerce example
│ └── calm-focus/ ← Productivity app example
└── docs/
└── spec.md ← Full specificationCompatibility
Physics Engine's DESIGN.md format is compatible with and extends @google-labs-code/design.md. Any valid Physics Engine file is a valid @google-labs-code/design.md file.
Physics Engine adds:
motiontoken section (spring physics presets) — absent from Google's specenergy-conservationandnested-radius-lawlinting rulesfitts-lawlinting rule- Energy Level semantic naming convention
- SwiftUI export target
npx @google-labs-code/design.md lint DESIGN.md # Google's linter
npx @trubnikov/physics-engine lint DESIGN.md # Physics Engine linter (stricter + motion)Roadmap
- v1.1 — Motion token validation in linter + Framer Motion code generation
- v1.2 — OKLCH color space (
Laxis maps directly to Energy Levels) - v2.0 — VS Code extension (live linting) · Figma Variables sync
License
MIT ©2026 Dima Trubnikov