@ammduncan/easel 0.2.27 → 0.2.28
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/CHANGELOG.md +8 -0
- package/dist/client/viewer.js +31 -1
- package/dist/mcp.js +11 -6
- package/package.json +1 -1
- package/skills/using-easel/SKILL.md +17 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to easel. This project adheres to [Semantic Versioning](https://semver.org/).
|
|
4
4
|
|
|
5
|
+
## 0.2.28 — 2026-05-25
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
- **Built-in `.code` / `.terminal` code-block primitive — kills the invisible-code-block bug at the source.** The single most recurring failure was a hand-rolled dark code container: an agent sets `background:#0f172a` on a custom div but leaves base text inheriting `.wrap`'s `light-dark(#111,…)`, which resolves to near-black in light host mode and vanishes against the dark panel (only the explicitly-coloured syntax spans survive). The guidance to lock bg+ink as a pair was correct but purely advisory — it relied on the agent remembering it every push. Now the wrapper ships a baked-in primitive: `<div class="code">` (alias `.terminal`) locks both background and ink, re-scopes `color: inherit` to every child, and provides the verified github-dark token classes (`.kw .string .fn .prop .num .comment .muted .accent`) so syntax highlighting reads against `#0f172a` with no per-token tuning. Same lever as the existing `.window` chrome — a safe primitive agents reach for instead of hand-rolling. Prints on white paper with dark text like `pre`/`code`.
|
|
9
|
+
|
|
10
|
+
### Docs
|
|
11
|
+
- **Steered the `push` tool description and skill toward the new primitive.** The locked-mode section now leads with "use the built-in `.code`/`.terminal`, don't hand-roll", demoting the hand-rolled CSS to a fallback for other locked containers (brand heroes, custom callouts). Added a "Code & terminal blocks" entry to the skill's Built-in helpers. Plain `<pre>`/`<code>` remain safe (bg+ink token pair) as before.
|
|
12
|
+
|
|
5
13
|
## 0.2.27 — 2026-05-23
|
|
6
14
|
|
|
7
15
|
### Fixed
|
package/dist/client/viewer.js
CHANGED
|
@@ -837,6 +837,35 @@ pre {
|
|
|
837
837
|
margin: 16px 0 24px;
|
|
838
838
|
}
|
|
839
839
|
pre code { background: transparent; padding: 0; color: inherit; font-size: inherit; }
|
|
840
|
+
/* Locked-dark code / terminal primitive. Reach for this instead of hand-rolling
|
|
841
|
+
a dark code container — the recurring failure is a custom dark <div> that sets
|
|
842
|
+
its own background but lets base text inherit .wrap's light-dark() ink, which
|
|
843
|
+
resolves to near-black in light host mode and vanishes against the dark panel.
|
|
844
|
+
This class locks BOTH background and ink, and re-scopes color:inherit to every
|
|
845
|
+
child so the host theme can never leak in. Ships the verified github-dark token
|
|
846
|
+
palette so syntax highlighting reads against #0f172a without per-token tuning.
|
|
847
|
+
Usage: <div class="code"><span class="kw">gcloud</span> services enable …</div>
|
|
848
|
+
.terminal is an alias; add .terminal for a prompt feel (same colors). */
|
|
849
|
+
.code, .terminal {
|
|
850
|
+
background: #0f172a;
|
|
851
|
+
color: #e6edf3;
|
|
852
|
+
border-radius: 12px;
|
|
853
|
+
padding: 18px 22px;
|
|
854
|
+
font-family: ui-monospace, "SF Mono", Menlo, monospace;
|
|
855
|
+
font-size: 13.5px;
|
|
856
|
+
line-height: 1.7;
|
|
857
|
+
overflow: auto;
|
|
858
|
+
margin: 16px 0 24px;
|
|
859
|
+
}
|
|
860
|
+
.code *, .terminal * { color: inherit; }
|
|
861
|
+
.code .kw, .terminal .kw { color: #ff7b72; } /* keywords, control flow */
|
|
862
|
+
.code .string, .terminal .string { color: #a5d6ff; } /* strings, attr values */
|
|
863
|
+
.code .fn, .terminal .fn { color: #d2a8ff; } /* function names */
|
|
864
|
+
.code .prop, .terminal .prop { color: #79c0ff; } /* identifiers, properties */
|
|
865
|
+
.code .num, .terminal .num { color: #ffa657; } /* numbers, constants */
|
|
866
|
+
.code .comment, .terminal .comment { color: #8b949e; } /* comments */
|
|
867
|
+
.code .muted, .terminal .muted { color: #94a3b8; } /* dim / secondary */
|
|
868
|
+
.code .accent, .terminal .accent { color: #6ee7b7; } /* highlight / success */
|
|
840
869
|
blockquote {
|
|
841
870
|
border-left: 3px solid var(--ds-accent);
|
|
842
871
|
margin: 18px 0;
|
|
@@ -883,7 +912,8 @@ img { max-width: 100%; height: auto; border-radius: 10px; }
|
|
|
883
912
|
body { padding: 24px !important; max-width: none !important; }
|
|
884
913
|
body > p, body > .deck, body > .lede, body > ul, body > ol, body > blockquote,
|
|
885
914
|
body > h1, body > h2, body > h3, body > h4 { max-width: none !important; }
|
|
886
|
-
pre, code { background: #f4f3ed !important; color: #111 !important; border: 1px solid #ddd; }
|
|
915
|
+
pre, code, .code, .terminal { background: #f4f3ed !important; color: #111 !important; border: 1px solid #ddd; }
|
|
916
|
+
.code *, .terminal * { color: #111 !important; }
|
|
887
917
|
.card, .panel { background: #fff !important; border: 1px solid #ddd !important; box-shadow: none !important; }
|
|
888
918
|
a { color: #111 !important; text-decoration: underline; border-bottom: 0 !important; }
|
|
889
919
|
}
|
package/dist/mcp.js
CHANGED
|
@@ -112,12 +112,17 @@ export async function main() {
|
|
|
112
112
|
" .wrap { color: light-dark(#111, #e8e8e8); padding: 56px 48px; font-family: -apple-system, 'Inter', system-ui, sans-serif; max-width: 820px; }\n" +
|
|
113
113
|
" .wrap *, .wrap h1, .wrap h2, .wrap h3, .wrap p, .wrap li, .wrap span { color: inherit; }\n" +
|
|
114
114
|
" .card { background: light-dark(#fff, #161616); border: 1px solid light-dark(#e0d9c3, #2a2a2a); border-radius: 12px; padding: 24px; }\n\n" +
|
|
115
|
-
"═══
|
|
116
|
-
"
|
|
117
|
-
"
|
|
118
|
-
"
|
|
119
|
-
" .
|
|
120
|
-
" .
|
|
115
|
+
"═══ CODE / TERMINAL BLOCKS — USE THE BUILT-IN PRIMITIVE, DON'T HAND-ROLL ═══\n" +
|
|
116
|
+
"The #1 recurring bug is a hand-rolled dark code container: you set `background:#0f172a` on a custom div but leave base text inheriting `.wrap`'s `light-dark(#111,…)`, which resolves to near-black in light host mode and VANISHES against the dark panel (only the explicitly-coloured syntax spans survive). Don't hand-roll it. The wrapper ships a baked-in, always-safe primitive:\n" +
|
|
117
|
+
" <div class=\"code\"> … </div> (alias: class=\"terminal\")\n" +
|
|
118
|
+
"It locks BOTH background (#0f172a) and ink (#e6edf3), re-scopes `color:inherit` to every child, and provides verified github-dark syntax token classes you can drop onto spans — NO per-token tuning needed:\n" +
|
|
119
|
+
" .kw (keywords #ff7b72) · .string (#a5d6ff) · .fn (function #d2a8ff) · .prop (identifiers #79c0ff) · .num (#ffa657) · .comment (#8b949e) · .muted (#94a3b8) · .accent (#6ee7b7)\n" +
|
|
120
|
+
" e.g. <div class=\"code\"><span class=\"kw\">gcloud</span> services enable run.googleapis.com</div>\n" +
|
|
121
|
+
"Plain <pre>/<code> are also already safe (bg+ink token pair). Only reach for a fully custom container when .code/.terminal genuinely don't fit — and then obey the locked-mode rule below.\n\n" +
|
|
122
|
+
"═══ COPY-PASTE STARTER (any OTHER LOCKED-MODE container — brand hero, custom panel) ═══\n" +
|
|
123
|
+
"If a container has a FIXED background (not `light-dark()`), you MUST set its own text color AND re-scope `color: inherit` to its children. Otherwise the children inherit `light-dark(...)` from `.wrap` and the text flips to the wrong shade in one mode (e.g. dark text on a locked-dark panel in light host mode → invisible).\n" +
|
|
124
|
+
" .hero { background: #0f172a; color: #e6edf3; border-radius: 12px; padding: 20px 24px; }\n" +
|
|
125
|
+
" .hero * { color: inherit; }\n" +
|
|
121
126
|
"• Same pairing applies in the OPPOSITE direction — locked-LIGHT containers (e.g. a white card on the host canvas). A `.card { background: #fff }` with no `color:` inherits `.wrap`'s light-dark() text, which in dark host mode resolves to a light cream/gray → invisible titles on a white card. Commit text too AND re-scope inherit on children. This bites just as often as the dark case.\n" +
|
|
122
127
|
" .card { background: #ffffff; color: #111111; border: 1px solid #e5e5e5; border-radius: 12px; padding: 24px 32px; }\n" +
|
|
123
128
|
" .card * { color: inherit; }\n" +
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ammduncan/easel",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.28",
|
|
4
4
|
"description": "A live browser tab for every Claude Code (and MCP) session. The push MCP tool appends HTML cards to a scrolling feed you keep open in split-screen.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -205,8 +205,10 @@ So the rule is **faithful height, not minimal height** — but always expressed
|
|
|
205
205
|
|
|
206
206
|
The test: cropped the same way, would your mock look like a screenshot of the real thing? Empty bands the real screen doesn't have = over-padded. A desktop screen squashed to a short strip = under-sized.
|
|
207
207
|
|
|
208
|
+
**For code / terminal blocks, don't hand-roll — use the built-in `.code` / `.terminal` primitive** (see Built-in helpers below). It already locks bg + ink, re-scopes `color: inherit` to children, and ships the verified github-dark token palette. The hand-rolled patterns below are the fallback for *other* locked containers (brand heroes, custom dark callouts) where no primitive fits.
|
|
209
|
+
|
|
208
210
|
```css
|
|
209
|
-
/* Locked-dark container (
|
|
211
|
+
/* Locked-dark container (custom dark callout, brand hero). */
|
|
210
212
|
.terminal {
|
|
211
213
|
background: #0f172a; /* locked dark, ignores host mode */
|
|
212
214
|
color: #e6edf3; /* MUST set text too */
|
|
@@ -328,6 +330,20 @@ The width rule above has a vertical twin, and it's the more common footgun: **ne
|
|
|
328
330
|
- **Decorative frames** (browser chrome, phone bezel, device frame) must grow with their content — give the frame `min-height` and let it expand, or don't constrain height at all.
|
|
329
331
|
- **The mental test:** render the tallest card in your head. If any text or button could exceed the container, the container is wrong. When unsure, leave height unset. A mockup exists to show the design *fully* — uniform-looking rectangles are never worth clipped content; let frames be different heights.
|
|
330
332
|
|
|
333
|
+
### Code & terminal blocks
|
|
334
|
+
|
|
335
|
+
Reach for the built-in **`.code`** (alias **`.terminal`**) class instead of hand-rolling a dark code container — that hand-roll is the single most recurring failure (custom `background:#0f172a` div + base text inheriting `.wrap`'s `light-dark(#111,…)` → invisible in light host mode). The primitive locks bg + ink, re-scopes `color: inherit` to children, and ships the verified github-dark token palette so syntax highlighting reads against `#0f172a` with no per-token tuning:
|
|
336
|
+
|
|
337
|
+
```html
|
|
338
|
+
<div class="code">
|
|
339
|
+
<span class="kw">gcloud</span> services enable run.googleapis.com
|
|
340
|
+
<span class="comment"># dvla artifact registry</span>
|
|
341
|
+
<span class="prop">--location=</span><span class="string">europe-west1</span>
|
|
342
|
+
</div>
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
Token classes: `.kw` (keywords) · `.string` · `.fn` (functions) · `.prop` (identifiers/properties) · `.num` · `.comment` · `.muted` · `.accent`. Plain `<pre>`/`<code>` are already safe too (bg + ink token pair). Only hand-roll a custom dark container when neither fits — and then obey the locked-mode pairing rule above.
|
|
346
|
+
|
|
331
347
|
### Semantic chips
|
|
332
348
|
|
|
333
349
|
```html
|