mockpit 0.0.0-stage → 1.0.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/LICENSE +22 -0
- package/README.md +232 -2
- package/bin/demoData.js +132 -0
- package/bin/initDesign.js +846 -0
- package/bin/mockpit.js +1830 -0
- package/bin/serveUrl.d.ts +1 -0
- package/bin/serveUrl.js +7 -0
- package/dist/mcp/server.d.ts +2 -0
- package/dist/mcp/server.js +230 -0
- package/dist/server/apiViews.d.ts +329 -0
- package/dist/server/apiViews.js +135 -0
- package/dist/server/app.d.ts +53 -0
- package/dist/server/app.js +3112 -0
- package/dist/server/base64.d.ts +1 -0
- package/dist/server/base64.js +16 -0
- package/dist/server/cdn.d.ts +6 -0
- package/dist/server/cdn.js +33 -0
- package/dist/server/codeRunner.d.ts +5 -0
- package/dist/server/codeRunner.js +89 -0
- package/dist/server/codeWorker.d.ts +1 -0
- package/dist/server/codeWorker.js +196 -0
- package/dist/server/designGuide.d.ts +16 -0
- package/dist/server/designGuide.js +311 -0
- package/dist/server/events.d.ts +53 -0
- package/dist/server/events.js +14 -0
- package/dist/server/feedbackBatch.d.ts +43 -0
- package/dist/server/feedbackBatch.js +98 -0
- package/dist/server/icons.d.ts +50 -0
- package/dist/server/icons.js +225 -0
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.js +64 -0
- package/dist/server/kits.d.ts +36 -0
- package/dist/server/kits.js +279 -0
- package/dist/server/knobs.d.ts +15 -0
- package/dist/server/knobs.js +333 -0
- package/dist/server/mcpHttp.d.ts +53 -0
- package/dist/server/mcpHttp.js +143 -0
- package/dist/server/mcpSpec.d.ts +191 -0
- package/dist/server/mcpSpec.js +402 -0
- package/dist/server/parts.d.ts +31 -0
- package/dist/server/parts.js +338 -0
- package/dist/server/postMarkdown.d.ts +10 -0
- package/dist/server/postMarkdown.js +271 -0
- package/dist/server/postSurfaces.d.ts +40 -0
- package/dist/server/postSurfaces.js +407 -0
- package/dist/server/public.d.ts +5 -0
- package/dist/server/public.js +5 -0
- package/dist/server/push.d.ts +45 -0
- package/dist/server/push.js +234 -0
- package/dist/server/richRender.d.ts +15 -0
- package/dist/server/richRender.js +392 -0
- package/dist/server/run.d.ts +82 -0
- package/dist/server/run.js +290 -0
- package/dist/server/runApi.d.ts +6 -0
- package/dist/server/runApi.js +82 -0
- package/dist/server/slots.d.ts +14 -0
- package/dist/server/slots.js +71 -0
- package/dist/server/sqlStore.d.ts +119 -0
- package/dist/server/sqlStore.js +954 -0
- package/dist/server/sqliteStorage.d.ts +2 -0
- package/dist/server/sqliteStorage.js +90 -0
- package/dist/server/surfacePage.d.ts +48 -0
- package/dist/server/surfacePage.js +1099 -0
- package/dist/server/themes.d.ts +48 -0
- package/dist/server/themes.js +305 -0
- package/dist/server/types.d.ts +599 -0
- package/dist/server/types.js +299 -0
- package/dist/workers/public.d.ts +1 -0
- package/dist/workers/public.js +3 -0
- package/extensions/mockpit.js +703 -0
- package/guide/AGENT_SETUP.md +23 -0
- package/guide/topics/asks.md +87 -0
- package/guide/topics/feedback.md +127 -0
- package/guide/topics/html.md +175 -0
- package/guide/topics/http.md +76 -0
- package/guide/topics/knobs.md +72 -0
- package/guide/topics/scripts.md +129 -0
- package/guide/topics/surfaces.md +100 -0
- package/package.json +165 -4
- package/skills/launch-video/SKILL.md +159 -0
- package/skills/mockpit/SKILL.md +40 -0
- package/viewer/dist/index.html +1922 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ben Vinegar (sideshow)
|
|
4
|
+
Copyright (c) 2026 Fábio Galiano (mockpit)
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
in the Software without restriction, including without limitation the rights
|
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
furnished to do so, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,233 @@
|
|
|
1
|
-
#
|
|
1
|
+
# mockpit
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**A design-decision loop for terminal coding agents.**
|
|
4
|
+
|
|
5
|
+
Your agent publishes a mock (a page or a component) in each of its UI states and
|
|
6
|
+
in a few parallel looks. It shows up live in your browser with the agent's
|
|
7
|
+
questions beside it: pick a look from pictures, tune the knobs it exposed, leave
|
|
8
|
+
comments on the parts it marked, then press **Send**, at your own pace. Nothing
|
|
9
|
+
the agent calls waits for you: it gets the whole batch once and revises.
|
|
10
|
+
|
|
11
|
+
<table>
|
|
12
|
+
<tr>
|
|
13
|
+
<td width="50%" valign="top">
|
|
14
|
+
<picture>
|
|
15
|
+
<source media="(prefers-color-scheme: dark)" srcset="docs/mockpit-dark.png">
|
|
16
|
+
<img width="100%" alt="The Writer mock on its first question, Look: the Writing state on the stage with a numbered question pin, the strip of four UI states below it, and the panel offering three looks (Quiet, Dark, Editorial) as picture options" src="docs/mockpit-light.png">
|
|
17
|
+
</picture>
|
|
18
|
+
</td>
|
|
19
|
+
<td width="50%" valign="top">
|
|
20
|
+
<img width="100%" alt="Animated demo: the agent publishes the Writer mock; the user previews the three looks on the stage, picks Quiet, answers where the trim goes, keeps a part from another look and presses Send; the top bar reads Sent, Not seen yet, then Delivered once the agent reads the feedback; the agent replies and publishes v2" src="docs/mockpit-demo.gif">
|
|
21
|
+
</td>
|
|
22
|
+
</tr>
|
|
23
|
+
</table>
|
|
24
|
+
|
|
25
|
+
## Fork of sideshow
|
|
26
|
+
|
|
27
|
+
mockpit is a fork of [sideshow](https://github.com/modem-dev/sideshow) by
|
|
28
|
+
[Ben Vinegar](https://github.com/benvinegar), sponsored by
|
|
29
|
+
[Modem](https://modem.dev). The renderer, sandboxing, MCP/CLI/HTTP tiers and
|
|
30
|
+
Cloudflare deploy all come from that work. Thank you.
|
|
31
|
+
|
|
32
|
+
Upstream is a live visual surface where agents post renders and you comment.
|
|
33
|
+
mockpit turns that into a design-decision loop:
|
|
34
|
+
|
|
35
|
+
| | sideshow | mockpit |
|
|
36
|
+
| ------------- | -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
|
|
37
|
+
| Structure | A stream of posts per session | **project › mock › state › variant › version**: a repo, a page or component by slug, its UI states, parallel looks, history |
|
|
38
|
+
| Questions | Free-text comments | The agent asks; you answer in place, picking from pictures of each option |
|
|
39
|
+
| Tuning | — | Knobs the agent declares (sliders, colours, springs…) on [tunekit](https://github.com/fabiogaliano/tunekit), live on the stage |
|
|
40
|
+
| Comments | Text on a post | Anchored on a **part** the agent marked with `data-part`, in a given state |
|
|
41
|
+
| Feedback | Each comment reaches the agent as it's written | Picks, tuned values, mix and comments stay drafts until you **Send**, then go out as one reply |
|
|
42
|
+
| Design system | Built-in viewer themes | `mockpit init` detects the repo's tokens, fonts and kit so the agent's markup matches your codebase |
|
|
43
|
+
| Agent verbs | Post-level: `publish`, `update`, `wait`, `comment` | Mock-level, never blocking: `publish`, `ask`, `read`, `feedback`, `say`, `export`, `upload`, `guide`, `run` |
|
|
44
|
+
|
|
45
|
+
## The loop
|
|
46
|
+
|
|
47
|
+
1. **Publish.** The agent publishes each state of the mock ("Writing", "Lab
|
|
48
|
+
open") in one or more variants ("quiet", "dark"). One stage shows the mock;
|
|
49
|
+
the strip under it switches states.
|
|
50
|
+
2. **Ask.** The agent asks what it can't decide alone: which look, where a
|
|
51
|
+
panel goes, which of two layouts. The question lives in the mock, not in
|
|
52
|
+
chat; the agent tells you where to look and ends its turn. Options bound to
|
|
53
|
+
a variant or to knob values render as pictures; hovering one previews it on
|
|
54
|
+
the stage, clicking picks it. After the look, **Mix** offers to borrow a part
|
|
55
|
+
from another look. Variants the agent forgot to ask about get a built-in
|
|
56
|
+
**Which one?**.
|
|
57
|
+
3. **Tune.** Parts the agent marked are selectable on the stage. Tune lists
|
|
58
|
+
them with the knobs it declared for each, plus a comment field. Presets
|
|
59
|
+
save a set of tuned values in your browser.
|
|
60
|
+
4. **Send.** Everything above is a draft (it survives a reload) until one
|
|
61
|
+
**Send**. A mock with a single variant and no questions gets **Accept /
|
|
62
|
+
Revise / Drop** instead. The Send lands in the Thread as **Not seen yet**,
|
|
63
|
+
then **Delivered** once the agent has it. If it isn't picked up, tell your
|
|
64
|
+
agent you've answered.
|
|
65
|
+
5. **Revise.** The agent gets one reply (answers, tuned values, mix, comments)
|
|
66
|
+
on its next write, its next `feedback` call, or from `mockpit watch` under a
|
|
67
|
+
background monitor. It publishes the next version; the frame header's `v3 ▾` lists the history,
|
|
68
|
+
and an older version opens under a banner with "restore as vN". Looks that
|
|
69
|
+
lost are archived, not deleted.
|
|
70
|
+
|
|
71
|
+
**Home** lists the project's mocks with a thumbnail, their states and how many
|
|
72
|
+
questions are open, with "Answer next ›" to jump to the first one. Dark and
|
|
73
|
+
light themes, toggled from the top bar. On a narrow screen the panel becomes a
|
|
74
|
+
bottom sheet.
|
|
75
|
+
|
|
76
|
+
## Quick start
|
|
77
|
+
|
|
78
|
+
Requires Node 22.18 or newer.
|
|
79
|
+
|
|
80
|
+
```sh
|
|
81
|
+
git clone https://github.com/fabiogaliano/mockpit && cd mockpit
|
|
82
|
+
npm install
|
|
83
|
+
npm start # viewer on http://localhost:8228
|
|
84
|
+
npm link # puts the `mockpit` CLI on your PATH
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Point your agent at it by pasting the setup block into its instructions:
|
|
88
|
+
|
|
89
|
+
```sh
|
|
90
|
+
curl -s http://localhost:8228/setup >> AGENTS.md
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Then run `mockpit init` once per repo and ask the agent to "mock this up on
|
|
94
|
+
mockpit". No agent handy? `mockpit demo` seeds the Writer: one mock in four
|
|
95
|
+
states and three looks, with questions, knobs and marked parts.
|
|
96
|
+
|
|
97
|
+
MCP, the Pi extension and the Claude Code plugin are covered in
|
|
98
|
+
**[docs/connecting-agents.md](docs/connecting-agents.md)**.
|
|
99
|
+
|
|
100
|
+
## What a mock can show
|
|
101
|
+
|
|
102
|
+
A version is an ordered list of **surfaces**, and one version can carry several.
|
|
103
|
+
Html is what design mocks use and the only kind with parts and knobs; the others
|
|
104
|
+
render the same way on the stage.
|
|
105
|
+
|
|
106
|
+
<table>
|
|
107
|
+
<tr>
|
|
108
|
+
<td width="50%" valign="top">
|
|
109
|
+
<img src="docs/surfaces/01-html.png" width="100%" alt="html surface">
|
|
110
|
+
<p><b><code>html</code></b>: markup the agent authors, rendered in a sandbox and themed by your design system.</p>
|
|
111
|
+
</td>
|
|
112
|
+
<td width="50%" valign="top">
|
|
113
|
+
<img src="docs/surfaces/02-markdown.png" width="100%" alt="markdown surface">
|
|
114
|
+
<p><b><code>markdown</code></b>: prose, tables and fenced code.</p>
|
|
115
|
+
</td>
|
|
116
|
+
</tr>
|
|
117
|
+
<tr>
|
|
118
|
+
<td width="50%" valign="top">
|
|
119
|
+
<img src="docs/surfaces/03-diff.png" width="100%" alt="diff surface">
|
|
120
|
+
<p><b><code>diff</code></b>: a patch as a syntax-highlighted code review (unified or split).</p>
|
|
121
|
+
</td>
|
|
122
|
+
<td width="50%" valign="top">
|
|
123
|
+
<img src="docs/surfaces/07-mermaid.png" width="100%" alt="mermaid surface">
|
|
124
|
+
<p><b><code>mermaid</code></b>: diagram source rendered to SVG in the viewer palette.</p>
|
|
125
|
+
</td>
|
|
126
|
+
</tr>
|
|
127
|
+
</table>
|
|
128
|
+
|
|
129
|
+
There are also `terminal` (ANSI output), `image` (uploaded assets), `json`
|
|
130
|
+
(collapsible tree) and `code` (shiki-highlighted source with line numbers).
|
|
131
|
+
|
|
132
|
+
## Agent verbs
|
|
133
|
+
|
|
134
|
+
Nine verbs, the same on every tier with the same fields: a zero-dependency CLI
|
|
135
|
+
for agents with only a shell, MCP over stdio or streamable HTTP at `/mcp`, and
|
|
136
|
+
plain HTTP. None of them waits for the user.
|
|
137
|
+
|
|
138
|
+
| CLI | MCP | HTTP |
|
|
139
|
+
| --------------------- | -------------------- | -------------------------------------- |
|
|
140
|
+
| `mockpit publish` | `publish` | `POST /api/mocks` |
|
|
141
|
+
| `mockpit ask` | `ask` | `POST /api/mocks/:id/asks` |
|
|
142
|
+
| `mockpit read [slug]` | `read` | `GET /api/mocks`, `GET /api/mocks/:id` |
|
|
143
|
+
| `mockpit feedback` | `feedback` | `GET /api/feedback?session=…` |
|
|
144
|
+
| `mockpit say` | `say` | `POST /api/mocks/:id/say` |
|
|
145
|
+
| `mockpit export` | `export` | `GET /api/mocks/:id/export` |
|
|
146
|
+
| `mockpit upload` | `upload` | `POST /api/assets` |
|
|
147
|
+
| `mockpit guide` | `guide` | `GET /agent-howto` |
|
|
148
|
+
| `mockpit run` | `run` (`?mode=code`) | `POST /api/run` |
|
|
149
|
+
|
|
150
|
+
The CLI adds `mockpit init` (detect the repo's design system, once per repo)
|
|
151
|
+
and `mockpit watch` (one line per Send, for a background monitor).
|
|
152
|
+
|
|
153
|
+
- **`publish` is the one write.** It creates the mock, state or variant, or the
|
|
154
|
+
next version of an existing one. Send `html`, the full ordered `surfaces`
|
|
155
|
+
list (an entry that is only `{id}` keeps that surface), or `parts` to replace
|
|
156
|
+
just the marked elements.
|
|
157
|
+
- **`feedback` returns at once** with what the user sent since the agent last
|
|
158
|
+
heard, plus `pending`: whether the viewer is open and how far the user's
|
|
159
|
+
draft has got (`2 of 3 answered`). Every write returns `feedback` too, and
|
|
160
|
+
each Send is delivered exactly once across all of them.
|
|
161
|
+
- **Asks are nudged.** A publish that leaves several variants with no ask
|
|
162
|
+
binding them returns a nudge and a ready `suggestedAsk`.
|
|
163
|
+
|
|
164
|
+
A typical turn:
|
|
165
|
+
|
|
166
|
+
```sh
|
|
167
|
+
mockpit publish --mock writer --state "Writing" --variant quiet --html quiet.html
|
|
168
|
+
mockpit publish --mock writer --state "Writing" --variant dark --html dark.html
|
|
169
|
+
mockpit ask --mock writer "Which look?" --option Quiet=quiet --option Dark=dark
|
|
170
|
+
# the agent says where to look and ends its turn; once you've answered:
|
|
171
|
+
mockpit feedback
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
The running server serves the brief at `/agent-howto`: one short, project-aware
|
|
175
|
+
document an agent reads before its first publish. Reference topics (`knobs`,
|
|
176
|
+
`asks`, `surfaces`, `html`, `reply`, `http`, `scripts`) are at
|
|
177
|
+
`/agent-howto?topic=<id>`; `/guide` is the `html` topic. `run` executes one
|
|
178
|
+
script against the same verbs on the server, so publishing variants and asking
|
|
179
|
+
take one call; `/mcp?mode=code` serves it as the only tool, for connectors
|
|
180
|
+
without a codemode of their own.
|
|
181
|
+
|
|
182
|
+
## Run it anywhere
|
|
183
|
+
|
|
184
|
+
It runs locally as a small Node server (SQLite at `~/.mockpit/mockpit.db`), or on
|
|
185
|
+
Cloudflare Workers when your agent and browser are on different machines. See
|
|
186
|
+
**[docs/deploying.md](docs/deploying.md)**.
|
|
187
|
+
|
|
188
|
+
The server app is importable from `mockpit/server` (`createApp`, `SqlStore`,
|
|
189
|
+
`createSqliteStorage`). The embeddable viewer engine (`mockpit/viewer-embed`,
|
|
190
|
+
`mountViewer`) is gone: the viewer is self-hosted only.
|
|
191
|
+
|
|
192
|
+
## Migrating from 0.x
|
|
193
|
+
|
|
194
|
+
- **SQLite workspaces migrate in place on first boot.** Each item becomes a
|
|
195
|
+
single-state mock with its variants and version history; comments keep their
|
|
196
|
+
ids and sequence numbers, so agents' feedback cursors carry over. Comments a
|
|
197
|
+
user was still drafting become the mock's draft. Deployed Durable Objects
|
|
198
|
+
migrate the same way.
|
|
199
|
+
- **The JSON store is gone.** If you run with `MOCKPIT_STORE=json`, start your
|
|
200
|
+
current version once without it **before upgrading**:
|
|
201
|
+
`env -u MOCKPIT_STORE mockpit serve` (keep `MOCKPIT_DATA`/`MOCKPIT_DB` if you
|
|
202
|
+
set them). That first SQLite boot copies `~/.mockpit/mockpit.json` into
|
|
203
|
+
`~/.mockpit/mockpit.db`, as long as the database is still empty; then upgrade.
|
|
204
|
+
The JSON file is left untouched either way.
|
|
205
|
+
- **`--item` is now `--mock`** (`mockpit publish --mock <slug> --state <s>
|
|
206
|
+
--variant <v>`), and the MCP tools are named by verb (`publish`, `ask`,
|
|
207
|
+
`read`, `feedback`, `say`, `export`, `upload`, `guide`).
|
|
208
|
+
- **Removed:** the item, post, snippet and session-page routes
|
|
209
|
+
(`/api/projects/:name/items`, `/api/posts`, `/api/surfaces`, `/api/snippets`,
|
|
210
|
+
`/session/:id`, `/p/:id`), `?part=`, the item/post MCP tools and their
|
|
211
|
+
deprecated aliases (`publish_item`, `publish_post`, `publish_surface`, …), the
|
|
212
|
+
CLI's `page`, `list`, `sessions`, `update`, per-kind shortcuts (`markdown`,
|
|
213
|
+
`diff`, …), `test-post` and `trace*` commands, the github/gruvbox/one themes
|
|
214
|
+
and the embed engine. Agents should re-fetch `/agent-howto`; refresh pasted
|
|
215
|
+
setup blocks from `/setup`.
|
|
216
|
+
|
|
217
|
+
## Development
|
|
218
|
+
|
|
219
|
+
```sh
|
|
220
|
+
npm run dev # server with watch + viewer watch build
|
|
221
|
+
npm test # Node unit/API/store tests + viewer unit tests
|
|
222
|
+
npm run test:worker # local workerd + Durable Object integration
|
|
223
|
+
npm run typecheck # node + workers + viewer
|
|
224
|
+
npm run lint # oxlint
|
|
225
|
+
npm run format # oxfmt
|
|
226
|
+
npm run test:e2e # Playwright, chromium + webkit (bridge, mock screen, decide flow)
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
The architecture and contributor rules are in [AGENTS.md](AGENTS.md).
|
|
230
|
+
|
|
231
|
+
## License
|
|
232
|
+
|
|
233
|
+
[MIT](LICENSE). The original sideshow copyright is retained.
|
package/bin/demoData.js
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
// Seed content for `mockpit demo`: the Writer mock — four states of one
|
|
2
|
+
// writing app, each drawn in three looks, with its parts marked so the viewer
|
|
3
|
+
// can show questions, tuning and part comments. Dependency-free like the CLI.
|
|
4
|
+
|
|
5
|
+
const LOOKS = {
|
|
6
|
+
quiet: {
|
|
7
|
+
paper: "#fbfaf7",
|
|
8
|
+
ink: "#1f1d1a",
|
|
9
|
+
muted: "#8a857c",
|
|
10
|
+
rule: "#e7e3dc",
|
|
11
|
+
panel: "#f3f0ea",
|
|
12
|
+
font: "Georgia, serif",
|
|
13
|
+
},
|
|
14
|
+
dark: {
|
|
15
|
+
paper: "#17181b",
|
|
16
|
+
ink: "#e9e7e2",
|
|
17
|
+
muted: "#8d8f96",
|
|
18
|
+
rule: "#2a2c31",
|
|
19
|
+
panel: "#202227",
|
|
20
|
+
font: "Georgia, serif",
|
|
21
|
+
},
|
|
22
|
+
editorial: {
|
|
23
|
+
paper: "#fffdf8",
|
|
24
|
+
ink: "#111",
|
|
25
|
+
muted: "#6f6a60",
|
|
26
|
+
rule: "#111",
|
|
27
|
+
panel: "#f4efe4",
|
|
28
|
+
font: "'Times New Roman', serif",
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const BODY = `<p>The fog came in before noon, the way it always did in late August, and by the time
|
|
33
|
+
Mara reached the pier the boats were only outlines.</p>
|
|
34
|
+
<p>She had promised herself she would finish the chapter before the light went. The light
|
|
35
|
+
was going. The chapter was not finished.</p>`;
|
|
36
|
+
|
|
37
|
+
const GHOST = " She sat on the bollard and wrote the last line anyway.";
|
|
38
|
+
|
|
39
|
+
// Knob values reach the render as --k-<path> custom properties (dots become
|
|
40
|
+
// dashes), so every knob below has a CSS fallback for the un-tuned render.
|
|
41
|
+
function render(state, variant) {
|
|
42
|
+
const look = LOOKS[variant.name];
|
|
43
|
+
const lab = state.label === "Lab open";
|
|
44
|
+
const versions = state.label === "Versions open";
|
|
45
|
+
const ghost = state.label === "Ghost text";
|
|
46
|
+
const editorial = variant.name === "editorial";
|
|
47
|
+
return `<div class="writer" style="--paper:${look.paper};--ink:${look.ink};--muted:${look.muted};--rule:${look.rule};--panel:${look.panel};font-family:${look.font};background:var(--paper);color:var(--ink);display:flex;min-height:420px;border-radius:10px;overflow:hidden">
|
|
48
|
+
<main style="flex:1;padding:36px 44px;position:relative">
|
|
49
|
+
<div data-part="trim" data-part-label="Trim" style="display:flex;justify-content:space-between;font:12px/1 system-ui;color:var(--muted);padding-bottom:14px;border-bottom:1px solid var(--rule)">
|
|
50
|
+
<span>Chapter 7 · draft</span><span>1,284 words</span>
|
|
51
|
+
</div>
|
|
52
|
+
<h1 data-part="title" data-part-label="Title" style="font-size:${editorial ? "40px" : "28px"};font-weight:${editorial ? 700 : 500};letter-spacing:${editorial ? "-0.02em" : "0"};margin:26px 0 18px">The Pier</h1>
|
|
53
|
+
<article data-part="body" data-part-label="Body" style="font-size:calc(var(--k-body-size, 17) * 1px);line-height:1.65;max-width:calc(var(--k-body-measure, 64) * 1ch)">
|
|
54
|
+
${BODY}${ghost ? `<p><span data-part="ghost" data-part-label="Ghost text" style="color:var(--muted);font-style:italic">${GHOST}</span></p>` : ""}
|
|
55
|
+
</article>
|
|
56
|
+
${
|
|
57
|
+
state.label === "Writing"
|
|
58
|
+
? `<div data-part="toast" data-part-label="Toast" style="position:absolute;right:20px;bottom:18px;font:12px system-ui;background:var(--panel);border:1px solid var(--rule);padding:8px 12px;border-radius:8px">Saved · 2s ago</div>`
|
|
59
|
+
: ""
|
|
60
|
+
}
|
|
61
|
+
</main>
|
|
62
|
+
${
|
|
63
|
+
lab
|
|
64
|
+
? `<aside data-part="lab" data-part-label="Lab" style="width:220px;background:var(--panel);border-left:1px solid var(--rule);padding:22px;font:13px/1.5 system-ui">
|
|
65
|
+
<b>Lab</b><p style="color:var(--muted)">Try the paragraph three ways.</p>
|
|
66
|
+
<div style="border:1px solid var(--rule);border-radius:6px;padding:8px;margin:6px 0">Shorter</div>
|
|
67
|
+
<div style="border:1px solid var(--rule);border-radius:6px;padding:8px;margin:6px 0">Warmer</div>
|
|
68
|
+
<div style="border:1px solid var(--rule);border-radius:6px;padding:8px;margin:6px 0">Plainer</div>
|
|
69
|
+
</aside>`
|
|
70
|
+
: ""
|
|
71
|
+
}
|
|
72
|
+
${
|
|
73
|
+
versions
|
|
74
|
+
? `<aside data-part="versions" data-part-label="Versions" style="width:200px;background:var(--panel);border-left:1px solid var(--rule);padding:22px;font:13px/1.6 system-ui">
|
|
75
|
+
<b>Versions</b>
|
|
76
|
+
<div style="margin-top:10px">v3 · now</div><div style="color:var(--muted)">v2 · 1h ago</div><div style="color:var(--muted)">v1 · yesterday</div>
|
|
77
|
+
</aside>`
|
|
78
|
+
: ""
|
|
79
|
+
}
|
|
80
|
+
</div>`;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export const DEMO = {
|
|
84
|
+
project: "demo/writer",
|
|
85
|
+
agent: "designer",
|
|
86
|
+
sessionTitle: "Writer redesign",
|
|
87
|
+
slug: "writer",
|
|
88
|
+
title: "Writer",
|
|
89
|
+
states: [
|
|
90
|
+
{ label: "Writing" },
|
|
91
|
+
{ label: "Lab open" },
|
|
92
|
+
{ label: "Versions open" },
|
|
93
|
+
{ label: "Ghost text" },
|
|
94
|
+
],
|
|
95
|
+
variants: [{ name: "quiet" }, { name: "dark" }, { name: "editorial" }],
|
|
96
|
+
knobs: {
|
|
97
|
+
"body.size": [17, 14, 22, 1],
|
|
98
|
+
"body.measure": [64, 48, 80, 1],
|
|
99
|
+
"trim.position": { type: "select", options: ["top", "bottom"], value: "top" },
|
|
100
|
+
"toast.show": true,
|
|
101
|
+
},
|
|
102
|
+
asks: [
|
|
103
|
+
{
|
|
104
|
+
id: "look",
|
|
105
|
+
text: "Which look?",
|
|
106
|
+
scope: "mock",
|
|
107
|
+
options: [
|
|
108
|
+
{ label: "Quiet", variant: "quiet" },
|
|
109
|
+
{ label: "Dark", variant: "dark" },
|
|
110
|
+
{ label: "Editorial", variant: "editorial" },
|
|
111
|
+
],
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
id: "versions-layout",
|
|
115
|
+
text: "Where should versions live?",
|
|
116
|
+
scope: "state",
|
|
117
|
+
state: "Versions open",
|
|
118
|
+
options: [{ label: "Side drawer" }, { label: "In the margin" }],
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
id: "trim",
|
|
122
|
+
text: "Trim above or below the page?",
|
|
123
|
+
scope: "part",
|
|
124
|
+
part: "trim",
|
|
125
|
+
options: [
|
|
126
|
+
{ label: "Above", set: { "trim.position": "top" } },
|
|
127
|
+
{ label: "Below", set: { "trim.position": "bottom" } },
|
|
128
|
+
],
|
|
129
|
+
},
|
|
130
|
+
],
|
|
131
|
+
render,
|
|
132
|
+
};
|