Materializr
Open-source parametric 3D CAD for makers — constraint sketches, solid modeling, threads, SVG & text engraving, STL/STEP export. Android, iPad, Linux, Mac, Windows. Vibe coded.
DOS design system: 61 React components, 6 themes, Tailwind preset. Phosphor aesthetics, WCAG 2.1 AA, tree-shakeable.
Translation pending
DesignTypeScript · CSSGitHub @CinimoDYOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
DOS-themed React component library with authentic CGA terminal aesthetics
Translation pending
Taken from the repository README
Loading the full README.
Read the full README ↗┌──────────────────────────────────────────────┐
│ C:\> EIDOTTER_ │
│ │
│ DOS terminal design system for React. │
│ Authentic CGA phosphor. WCAG AA. │
│ Tree-shakable. No CSS-in-JS runtime. │
└──────────────────────────────────────────────┘
eiDotter is a React component library that takes the DOS/CGA terminal aesthetic seriously: authentic 16-color palette, bitmap-accurate typography, phosphor glow physics, keyboard-first interactions. 63 components across forms, navigation, windowing, timelines, health displays, and terminal chrome — shipped as ES modules with a prebuilt stylesheet so consumers don't need Tailwind to use it.
→ Storybook · CHANGELOG · Accessibility · Issues · npm
npm install eidotter
import { Terminal, Alert, Button } from 'eidotter';
import 'eidotter/styles';
function App() {
return (
<Terminal title="MY-APP.EXE">
<Alert color="success" title="System Ready">
DOS interface loaded successfully.
</Alert>
<Button variant="primary">Execute</Button>
</Terminal>
);
}
A single CSS import pulls everything: font, tokens, component styles, and compiled Tailwind utilities. Tailwind is not required to use eiDotter — consume it as plain React + one stylesheet.
import 'eidotter/styles'; // Everything: font + tokens + components + utilities
import 'eidotter/themes/amber-mono.css'; // Optional: theme override
import 'eidotter/utilities'; // Optional: .dos-* typography classes for raw HTML
Granular imports are still available (eidotter/fonts.css, eidotter/tokens.css) if you want to override the font or tokens independently.
Fonts in your build output: your bundler emits the four JetBrains Mono Nerd Font woff2 files (body tier, about 4 MB) even if you never use the body tier. Browsers only download faces a page uses, so this is deploy size, not page weight. To leave them out, see "Fonts: what your build emits" in guidelines/README.md.
Favicon: the logomark favicon ships as eidotter/favicon.svg (SVG only). Copy it into your site's public dir or point a bundler at it, then <link rel="icon" href="/favicon.svg" type="image/svg+xml" />.
If you already use Tailwind, register eiDotter's preset and drop the eidotter/styles import (the preset compiles utilities in your build):
// tailwind.config.js
module.exports = {
presets: [require('eidotter/tailwind.preset')],
content: ['./src/**/*.{ts,tsx,jsx}'],
};
<div className="bg-dos-bg-primary text-dos-text-accent font-dos">
DOS terminal content
</div>
dist/eidotter.css ships the stock utilities its components use (.flex, .flex-col, .hidden, about 200) unlayered, and unlayered CSS beats Tailwind v4's @layer utilities whatever the order: your md:flex-row loses to eiDotter's .flex-col. Import eiDotter into a named layer before your utilities, in the CSS file that imports Tailwind:
@layer theme, base, components, eidotter, utilities;
@import "tailwindcss";
@import "eidotter/styles" layer(eidotter);
Drop the JS import 'eidotter/styles' (it would add an unlayered second copy) and do not point @source at node_modules/eidotter/dist. Trade-off: inside the layer, eiDotter loses to any unlayered global rule of yours (an unlayered * { margin: 0; padding: 0 } beats eiDotter's component utilities), and eiDotter's reset beats element defaults in your @layer base. Keep your resets layered, and put global element styles in a layer declared after eidotter. Details: migrations/0.41.0.md.
The preset auto-registers tailwindcss-react-aria-components and tailwindcss-animate if they resolve. Migrating from the pre-0.19.2 dual-preset split? See CHANGELOG → 0.19.2.
The . barrel (import { Button } from 'eidotter') inlines every component into one
module, so importing it into a server component pulls interactive components' hooks
into the RSC graph and fails. For server components, deep-import per component instead:
// In a Server Component:
import { SectionHeading } from 'eidotter/components/SectionHeading'; // presentational — renders on the server
import { Button } from 'eidotter/components/Button'; // interactive — resolves as a client reference
import 'eidotter/styles'; // CSS still ships once, app-wide (unchanged)
eidotter/components/<Name> (PascalCase, matching the component) carries 'use client'
on interactive components automatically, so they cross the client boundary correctly while
presentational primitives stay server-renderable. The . barrel remains the right default
for client apps and 'use client' files.
Every minor with breaking or visible changes ships an upgrade guide in the package, at node_modules/eidotter/migrations/<version>.md (source: migrations/). Read every guide between your installed version and the target, oldest first. Start with 0.41.0, then 0.43.0, 0.44.0 , 0.45.0 and 0.46.0.
0.x caret ranges stop at the next minor (^0.40.2 never resolves to 0.41.0), so bump the range explicitly: npm install eidotter@^0.46.0.
| Live docs | Storybook — every component with stories, controls, and source |
| Design tokens | src/tokens/*.json (DTCG format) → tokens.css via Style Dictionary |
| Themes | amber-mono (default), cga-amber, cga-mode4-p0/p1, cga-mode5 |
| Font | Perfect DOS VGA 437 by Zeh Fernando — pixel-perfect-vector TTF (every glyph outline axis-aligned). Free-to-redistribute per bundled license. Single-weight; all fontWeight tokens resolve to 400 |
| Icons | pixelarticons (MIT) — DOS pixel-art glyphs |
| Accessibility | WCAG AA, React Aria primitives under interactive components, prefers-reduced-motion + prefers-contrast honored throughout |
63 components across six families — complete catalog in Storybook. Also exported but not tabled below: Bench, CalendarHeatmap, Connector, CopyButton, ChecklistRow, DisplayMenu, EmptyState, HeaderButton, HoldToComplete, LabeledProgress, LedgerRow, PageShell (with PageSection), ProgressRing, SectionHeading, Select, TimelineFeed, TimelinePage and the Mark brand component.
| Component | Purpose |
|---|---|
Terminal | DOS window with title bar, minimize/maximize/close controls |
DosDialog | The one overlay shell (CmdPalette chrome, dark title strip, placement and size map); Modal, Lightbox and CmdPalette are built on it |
DosWindow | In-page window chrome (title strip on a brand border with drop shadow); Card and DosFigure are built on it |
IconButton | The one icon-only control for close, prev/next and window controls |
Modal | Dialog overlay built on DosDialog (React Aria ModalOverlay + Modal + Dialog) |
Lightbox | Fullscreen image viewer on Modal's primitives — prev/next, counter, keyboard nav, swipe |
CommandPrompt | Interactive command-line input with blinking cursor |
CmdPalette | ⌘K overlay with scored search, keyboard nav, configurable hotkey |
Header | Sticky site header (retro / modern variants), composes branding + Nav |
Footer | Site footer with default legal links (Impressum + Datenschutz) |
Nav | Responsive navigation with desktop + mobile variants |
Brand | Logo, Wordmark, BrandLockup — eiDotter branding marks |
| Component | Purpose |
|---|---|
Gauge | Quantised ring with a dominant percent, secondary value, tone, status, provenance tag and overflow marker |
Meter | Single fill bar (vertical / horizontal) with an optimal tick or range and pattern fills |
MeterGroup | Row or grid of Meters with an optional shared scale |
RangeBar | Stacked range bar of ordered segments with legend and target tick (time-in-range style) |
SeriesBars | Short bar series with a goal line and consumer-supplied threshold tones |
DecayStrip | On-board decay over time from consumer-supplied samples — now marker, dimmed future, provenance required |
VitalsStrip | Monitor-style vitals tiles with per-tile tone, status and paired values |
All six are presentational and server-safe; bands, targets and clinical copy are consumer props (no medical defaults), and tone is never the only signal.
| Component | Purpose |
|---|---|
Card | Content container (elevated, bordered, glow, interactive, minimal, callout) |
Accordion | Collapsible content sections (Section + AccordionFill) |
Alert | Inline alert banner with featured icon, actions, 6 color variants |
Badge | Status indicator chips |
Tag | Interactive labels for tags, categories, filter chips |
Notification | Toast popup with layered amber glow, auto-dismiss, progress variant |
Stat | Key-value display for metrics |
Progress | DOS-style progress bar with block characters |
Skeleton | DOS/CGA loading placeholder — ░▒▓ shade rows with a CRT hum-bar band rolling top→bottom |
Separator | Horizontal / vertical divider |
Breadcrumb | Navigation path display |
LegalPage | Impressum / Datenschutz layout primitive with reusable German DDG/DSGVO clauses |
| Component | Purpose |
|---|---|
Button | DOS-style buttons (primary, secondary, ghost, link) on React Aria Button |
Input | Text input with error variant, React Aria TextField |
Checkbox | [X]-bracket indicator, React Aria Checkbox |
Switch | Toggle on/off, React Aria Switch |
Tabs | Tabbed navigation on React Aria TabList/Tab/TabPanel |
FilterBar | Multi-select toggle group for faceted filtering |
| Component | Purpose |
|---|---|
ChatMessage | Chat message with role-based DOS styling and streaming cursor |
ChatHistory | Scrollable message list with auto-scroll + role="log" |
ChatInput | Multiline textarea with Enter-to-send |
ChatContainer | Composes ChatHistory + ChatInput — drop inside Terminal |
DosFigure | Demoscene painted-screen media placeholder with scanline sweep |
Icon | SVG icons backed by pixelarticons |
InlineLink | In-flow anchor with dotted underline + ▸ / ↗ glyph |
InlineExpand | Inline disclosure widget for prose |
AIText | Inline AI-content marker (data-provenance="ai-draft") with shimmer gradient |
| Component | Purpose |
|---|---|
TimelineContainer | Multi-zoom timeline (year / month / day / hour views); text / image / gallery / article entry kinds |
TimelineNode | Axis markers with shape variants and glow |
TextScramble | DOS text decode animation |
RetroEffects | CRT scanlines, noise, phosphor glow |
Authentic 16-color CGA palette plus amber/phosphor variants, exposed as CSS custom properties:
--color-cga-amber: #FFB000; /* Primary accent */
--color-cga-amber-bright: #FDCA9F;
--color-cga-amber-dim: #9A5700;
--color-cga-black: #020003; /* Background */
/* …16-color CGA palette + semantic tokens */
Semantic tokens (--color-semantic-*) and Tailwind classes (bg-dos-*, text-dos-*, border-dos-*) are the preferred surface — the raw CGA names are primitives. Full reference in src/styles/tokens.css or in Storybook's Tokens page.
Theming is attribute-driven:
<div data-theme="amber-mono">…</div>
npm install
npm run storybook # Launch Storybook on :6006
npm run build # Production build (tsup + tsc)
npm run test # Jest + React Testing Library
npm run lint # ESLint
npm run build-tokens # Rebuild tokens from src/tokens/*.json
eiDotter commits to the constraints that other "DOS-inspired" systems relax:
fontWeight tokens resolve to 400 and font-synthesis: none blocks browser faux-bold. Emphasis comes from color, uppercase on labels, or inverse video — never weight.prefers-reduced-motion and prefers-contrast are honored across the board.The aesthetic is a constraint the system holds itself to — not a theme that can be turned off.
CC-BY-NC-4.0 — Creative Commons Attribution-NonCommercial 4.0 International. Bundled third-party licenses (pixelarticons MIT, Perfect DOS VGA 437 free-redistribution by Zeh Fernando, Flexi IBM VGA True CC BY-SA 4.0 — kept for legacy consumers) attributed in LICENSE.md.