@sethlivingston/cathode 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +137 -0
- package/LICENSE +21 -0
- package/README.md +91 -0
- package/dist/cathode.css +1388 -0
- package/fonts/LICENSE.txt +4 -0
- package/fonts/ibm-plex-mono-latin-400-normal.woff2 +0 -0
- package/fonts/ibm-plex-mono-latin-500-normal.woff2 +0 -0
- package/fonts/ibm-plex-mono-latin-600-normal.woff2 +0 -0
- package/fonts/ibm-plex-sans-latin-400-italic.woff2 +0 -0
- package/fonts/ibm-plex-sans-latin-400-normal.woff2 +0 -0
- package/fonts/ibm-plex-sans-latin-500-normal.woff2 +0 -0
- package/fonts/ibm-plex-sans-latin-600-normal.woff2 +0 -0
- package/fonts/ibm-plex-sans-latin-700-normal.woff2 +0 -0
- package/package.json +38 -0
- package/src/base.css +166 -0
- package/src/components/badge.css +59 -0
- package/src/components/button.css +107 -0
- package/src/components/card.css +68 -0
- package/src/components/feedback.css +115 -0
- package/src/components/forms.css +206 -0
- package/src/components/layout.css +76 -0
- package/src/components/nav.css +151 -0
- package/src/components/overlay.css +126 -0
- package/src/components/table.css +57 -0
- package/src/fonts.css +65 -0
- package/src/reset.css +88 -0
- package/src/tokens.css +90 -0
package/AGENTS.md
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# Cathode — Agent Guidelines
|
|
2
|
+
|
|
3
|
+
You are styling an app with **Cathode**, a dark-only design system. This document
|
|
4
|
+
is your constitution: the defaults here are very strong. Follow them unless you
|
|
5
|
+
have a specific, articulable reason not to — and when you deviate, say so
|
|
6
|
+
explicitly in your summary/PR description so a human can review the call.
|
|
7
|
+
|
|
8
|
+
## Identity in one paragraph
|
|
9
|
+
|
|
10
|
+
A dark room lit by a monitor. Inky near-black surfaces, precise 1px-ruled boxes,
|
|
11
|
+
squared corners, comfortable density. Sans-serif prose, **monospace for all
|
|
12
|
+
data**. One magenta accent for interactivity, plus a palette of saturated arcade
|
|
13
|
+
hues that always carry meaning. A stranger sees a sharp modern app; a nerd
|
|
14
|
+
notices the wink. The wink stays a whisper: no pixel fonts, no scanlines, no
|
|
15
|
+
8-bit borders in app chrome.
|
|
16
|
+
|
|
17
|
+
## The three laws
|
|
18
|
+
|
|
19
|
+
1. **Tokens only.** Never write a raw color, font-family, font-size, spacing
|
|
20
|
+
value, radius, shadow, or z-index. Every visual property comes from a
|
|
21
|
+
`--ct-*` token. If no token fits, the answer is almost always the nearest
|
|
22
|
+
token — not a new value.
|
|
23
|
+
2. **Mono for data.** IDs, counts, timestamps, durations, file paths, versions,
|
|
24
|
+
money, table numerics, badges, keyboard keys: `--ct-font-mono` (use `.ct-data`,
|
|
25
|
+
`.ct-num`, `.ct-label-mono`, or components that bake it in). Prose, labels,
|
|
26
|
+
headings, buttons: sans. Never the reverse.
|
|
27
|
+
3. **Color means something.** Green = success, red = danger/destructive,
|
|
28
|
+
amber = warning, cyan = info, magenta accent = interactive/brand. Never use a
|
|
29
|
+
status hue decoratively, and never encode status with a categorical hue
|
|
30
|
+
(orange/lime/pink/indigo — those are free for tags, charts, and series).
|
|
31
|
+
|
|
32
|
+
## Hard rules (never violate)
|
|
33
|
+
|
|
34
|
+
- Dark only. No light theme, no `prefers-color-scheme` branching.
|
|
35
|
+
- Elevation is border brightness (`--ct-border` → `--ct-border-bright`), not
|
|
36
|
+
box-shadows. The only permitted shadows are the built-in focus glow and
|
|
37
|
+
`.ct-dot`'s glow.
|
|
38
|
+
- Corners are `--ct-radius` (2px). Exceptions that are already baked in:
|
|
39
|
+
radio dots and status dots are round. Nothing else is.
|
|
40
|
+
- Spacing sits on the 4px grid via `--ct-space-*`. No odd-pixel nudging.
|
|
41
|
+
- One `.ct-button--primary` per view, maximum. It is the single magenta action.
|
|
42
|
+
- `.ct-button--danger` only for destructive actions, and destructive actions
|
|
43
|
+
always confirm via `.ct-modal`.
|
|
44
|
+
- Focus stays visible. Never `outline: none` without the system's replacement
|
|
45
|
+
(inputs already do this correctly).
|
|
46
|
+
- Respect the components' ARIA hooks: active nav uses `aria-current="page"`,
|
|
47
|
+
active tab `aria-selected="true"`, invalid inputs `aria-invalid="true"`,
|
|
48
|
+
selected rows `aria-selected="true"`. Styling is attached to those attributes
|
|
49
|
+
on purpose — set the attribute, get the style.
|
|
50
|
+
|
|
51
|
+
## Strong defaults (deviate only with stated reason)
|
|
52
|
+
|
|
53
|
+
- Compose pages from existing components before inventing anything. The kit:
|
|
54
|
+
buttons, fields/inputs/select/textarea/check/radio/switch, badges/dots, cards/
|
|
55
|
+
stats, tables, navbar/sidebar/tabs/breadcrumb, modal/toast/tooltip, progress/
|
|
56
|
+
meter/spinner, alert, empty state, and layout helpers (`.ct-shell`,
|
|
57
|
+
`.ct-container`, `.ct-stack`, `.ct-cluster`, `.ct-grid`).
|
|
58
|
+
- New component needed? Build it from tokens, follow the naming scheme
|
|
59
|
+
(`.ct-thing`, `.ct-thing--variant`, `.ct-thing__part`), keep it in one CSS
|
|
60
|
+
file, and flag it as a candidate for the system.
|
|
61
|
+
- Empty lists/zero states use `.ct-empty` — never a blank region.
|
|
62
|
+
- Page titles use `h1`–`h3` defaults; section micro-headers use `.ct-label-mono`.
|
|
63
|
+
- Buttons: default for secondary actions, `--ghost` for toolbars and inline
|
|
64
|
+
affordances, `--sm` inside tables and cards.
|
|
65
|
+
- Use native `<dialog>` for modals and the `.ct-toasts` container for toasts.
|
|
66
|
+
|
|
67
|
+
## Canonical snippets
|
|
68
|
+
|
|
69
|
+
Status badge + data:
|
|
70
|
+
|
|
71
|
+
```html
|
|
72
|
+
<td><span class="ct-badge ct-badge--success">pass</span></td>
|
|
73
|
+
<td class="ct-num">1,204</td>
|
|
74
|
+
<td><span class="ct-data">2026-06-10 14:32</span></td>
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Form field with validation:
|
|
78
|
+
|
|
79
|
+
```html
|
|
80
|
+
<div class="ct-field">
|
|
81
|
+
<label class="ct-label ct-label--required" for="name">Project name</label>
|
|
82
|
+
<input class="ct-input" id="name" aria-invalid="true" />
|
|
83
|
+
<span class="ct-error">Name is already taken.</span>
|
|
84
|
+
</div>
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
App shell:
|
|
88
|
+
|
|
89
|
+
```html
|
|
90
|
+
<body class="ct-shell">
|
|
91
|
+
<nav class="ct-navbar">
|
|
92
|
+
<span class="ct-navbar__brand">Acme</span>
|
|
93
|
+
<span class="ct-navbar__spacer"></span>
|
|
94
|
+
<button class="ct-button ct-button--sm ct-button--primary">Deploy</button>
|
|
95
|
+
</nav>
|
|
96
|
+
<aside class="ct-sidebar">
|
|
97
|
+
<div class="ct-sidebar__section">Workspace</div>
|
|
98
|
+
<a class="ct-nav-item" aria-current="page" href="/">Overview</a>
|
|
99
|
+
<a class="ct-nav-item" href="/runs">Runs</a>
|
|
100
|
+
</aside>
|
|
101
|
+
<main class="ct-main ct-stack">…</main>
|
|
102
|
+
</body>
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Custom-hued tag (categorical, no fixed meaning):
|
|
106
|
+
|
|
107
|
+
```html
|
|
108
|
+
<span class="ct-badge" style="--badge-hue: var(--ct-pink)">design</span>
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Don't / Do
|
|
112
|
+
|
|
113
|
+
| Don't | Do |
|
|
114
|
+
|---|---|
|
|
115
|
+
| `color: #22c55e` | `color: var(--ct-green)` |
|
|
116
|
+
| `padding: 10px` | `padding: var(--ct-space-2) var(--ct-space-3)` |
|
|
117
|
+
| `border-radius: 8px` | `border-radius: var(--ct-radius)` |
|
|
118
|
+
| `box-shadow: 0 4px 12px …` on hover | brighten the border: `border-color: var(--ct-border-bright)` |
|
|
119
|
+
| Timestamp in sans | `<span class="ct-data">…</span>` |
|
|
120
|
+
| Red "Delete" link that fires immediately | `.ct-button--danger` opening a `.ct-modal` confirm |
|
|
121
|
+
| Two primary buttons side by side | one `--primary`, one default |
|
|
122
|
+
| Inventing a quieter gray | `--ct-text-dim` or `--ct-text-faint` |
|
|
123
|
+
|
|
124
|
+
## Token quick reference
|
|
125
|
+
|
|
126
|
+
| Group | Tokens |
|
|
127
|
+
|---|---|
|
|
128
|
+
| Surfaces | `--ct-bg-0..3` (page → hover), `--ct-border`, `--ct-border-bright` |
|
|
129
|
+
| Text | `--ct-text`, `--ct-text-dim`, `--ct-text-faint` |
|
|
130
|
+
| Accent | `--ct-accent`, `--ct-accent-bright`, `--ct-accent-glow`, `--ct-on-accent` |
|
|
131
|
+
| Status | `--ct-green`, `--ct-red`, `--ct-amber`, `--ct-cyan` |
|
|
132
|
+
| Categorical | `--ct-orange`, `--ct-lime`, `--ct-pink`, `--ct-indigo` |
|
|
133
|
+
| Fonts | `--ct-font-sans`, `--ct-font-mono` |
|
|
134
|
+
| Sizes | `--ct-text-xs/sm/md/lg/xl/2xl/3xl` |
|
|
135
|
+
| Space | `--ct-space-1..8` = 4/8/12/16/24/32/48/64px |
|
|
136
|
+
| Shape/motion | `--ct-radius`, `--ct-ease`, `--ct-quick`, `--ct-slow` |
|
|
137
|
+
| Layers | `--ct-z-nav/modal/toast/tooltip` |
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Seth Livingston
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# cathode
|
|
2
|
+
|
|
3
|
+
My personal design system for my pet projects.
|
|
4
|
+
|
|
5
|
+
Dark-only CSS design system: inky surfaces, hairline borders, monospace for
|
|
6
|
+
data, arcade semantic color. Built to be driven by AI agents.
|
|
7
|
+
|
|
8
|
+
A dark room lit by a monitor — modern skeleton, retro soul, and the retro stays
|
|
9
|
+
a whisper.
|
|
10
|
+
|
|
11
|
+

|
|
12
|
+
|
|
13
|
+
## Install
|
|
14
|
+
|
|
15
|
+
As a dependency:
|
|
16
|
+
|
|
17
|
+
```sh
|
|
18
|
+
npm install @sethlivingston/cathode
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
```css
|
|
22
|
+
@import "@sethlivingston/cathode";
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Or straight from a CDN (fonts resolve automatically — they ship in the package):
|
|
26
|
+
|
|
27
|
+
```html
|
|
28
|
+
<link
|
|
29
|
+
rel="stylesheet"
|
|
30
|
+
href="https://cdn.jsdelivr.net/npm/@sethlivingston/cathode/dist/cathode.css"
|
|
31
|
+
/>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Tokens only (bring your own components):
|
|
35
|
+
|
|
36
|
+
```css
|
|
37
|
+
@import "@sethlivingston/cathode/tokens";
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## For AI agents
|
|
41
|
+
|
|
42
|
+
[`AGENTS.md`](./AGENTS.md) is the system's constitution — identity, the three
|
|
43
|
+
laws (tokens only · mono for data · color means something), hard rules, strong
|
|
44
|
+
defaults, and canonical snippets. Point your agent at it from a project's
|
|
45
|
+
CLAUDE.md / system prompt:
|
|
46
|
+
|
|
47
|
+
```md
|
|
48
|
+
This project uses the Cathode design system.
|
|
49
|
+
Follow node_modules/@sethlivingston/cathode/AGENTS.md when writing any UI.
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## What's inside
|
|
53
|
+
|
|
54
|
+
- **Tokens** (`src/tokens.css`) — surfaces, text, accent, arcade palette,
|
|
55
|
+
type scale, 4px spacing grid, shape, motion, layers. All `--ct-*`.
|
|
56
|
+
- **Base** — element defaults: typography, links, code/kbd, scrollbars,
|
|
57
|
+
selection, focus ring.
|
|
58
|
+
- **Components** (`.ct-` prefix) — buttons, forms (input/select/textarea/
|
|
59
|
+
checkbox/radio/switch/validation), badges & status dots, cards & stats,
|
|
60
|
+
tables, navbar/sidebar/tabs/breadcrumb, modal (`<dialog>`)/toast/tooltip,
|
|
61
|
+
progress/meter/spinner, alerts, empty states, layout helpers
|
|
62
|
+
(`.ct-shell`, `.ct-container`, `.ct-stack`, `.ct-cluster`, `.ct-grid`).
|
|
63
|
+
- **Fonts** — IBM Plex Sans + IBM Plex Mono (latin, woff2), self-hosted,
|
|
64
|
+
OFL-1.1.
|
|
65
|
+
|
|
66
|
+
No build step required to use it; `npm run build` regenerates
|
|
67
|
+
`dist/cathode.css` from the `src/` layers after edits.
|
|
68
|
+
|
|
69
|
+
## Demo
|
|
70
|
+
|
|
71
|
+
Open [`demo/index.html`](./demo/index.html) for the full component gallery.
|
|
72
|
+
|
|
73
|
+
## Releasing
|
|
74
|
+
|
|
75
|
+
The published package is `@sethlivingston/cathode`, versioned by the root
|
|
76
|
+
`package.json`. To cut a release:
|
|
77
|
+
|
|
78
|
+
1. Bump `version` in `package.json`, run `npm run build`, and commit (dist is
|
|
79
|
+
committed; CI fails if it drifts from src).
|
|
80
|
+
2. Tag the commit `v<version>` (e.g. `v0.2.0`) and push the tag.
|
|
81
|
+
3. The Release workflow validates the build, publishes to npm via OIDC trusted
|
|
82
|
+
publishing with provenance, and creates the GitHub release.
|
|
83
|
+
|
|
84
|
+
Prerequisites: the `npm-publish` GitHub environment (tag policy `v*`) and an
|
|
85
|
+
npm trusted-publisher binding to `.github/workflows/release.yml`.
|
|
86
|
+
|
|
87
|
+
## License
|
|
88
|
+
|
|
89
|
+
MIT. Bundled IBM Plex fonts are licensed under the
|
|
90
|
+
[SIL Open Font License 1.1](https://github.com/IBM/plex/blob/master/LICENSE.txt),
|
|
91
|
+
© IBM Corp.
|