Skip to content

Commit 50def29

Browse files
authored
Merge pull request #263 from knockout/fix-tsx-examples
Fix TSX docs examples and playground payloads
2 parents 90827fa + c669027 commit 50def29

19 files changed

+798
-154
lines changed

AGENTS.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,17 @@ changes — update **both** the Starlight docs (for humans) and the agent guide
157157
(for agents). The agent guide should be token-efficient: dense, code-first,
158158
minimal prose.
159159

160+
## Docs Verification
161+
162+
When validating `tko.io` documentation changes with the local docs site:
163+
164+
- Use `playwright-cli` in headless mode by default. Do not use headed/browser-stealing runs unless the user explicitly asks for them.
165+
- Prefer a live Astro dev server on `127.0.0.1` so markdown/plugin edits reload while you work.
166+
- For docs pages with runnable examples, verify the live page and each `Open in Playground` button after edits.
167+
- Standard headless flow: `playwright-cli close-all`, `playwright-cli open http://127.0.0.1:4321/...`, inspect the snapshot for playground refs, click each button, switch to the playground tab, and confirm `#esbuild-status`, `#compile-time`, and `#error-bar`.
168+
- Treat docs example work as incomplete until the emitted playground payload compiles cleanly on the live site.
169+
- If a page has multiple TSX examples, check every TSX playground button, not just the first one.
170+
160171
## Important Guidelines
161172

162173
- Do not modify `tools/build.mk` or `tools/karma.conf.js` without understanding

plans/tsx-doc-examples-rollout.md

Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
# Plan: TSX Docs Example Rollout
2+
3+
## Goal
4+
5+
Make the TSX side of the docs easier to read than the legacy HTML + viewmodel
6+
examples while keeping every example runnable in the playground.
7+
8+
The reader-facing convention is:
9+
10+
- Declare observables and other referenced variables at the top of the example
11+
- Show the binding-focused TSX snippet only
12+
- Hide mount/setup boilerplate from the visible example
13+
- Keep the legacy HTML + JS example intact inside the HTML tab
14+
- Ensure both tabs continue to open working playground sessions
15+
16+
---
17+
18+
## Current Problem
19+
20+
The first TSX migration pass made several examples longer and noisier than the
21+
legacy HTML version:
22+
23+
- Some TSX examples include repeated `root / render / applyBindings` ceremony
24+
- Some examples introduce intermediate objects that are not needed to explain
25+
the binding
26+
- Legacy HTML `viewModel` blocks can appear visually detached from the HTML tab
27+
- The docs are teaching setup details at the same level as binding syntax
28+
29+
This is backwards for readers. TSX should feel more direct, not more verbose.
30+
31+
---
32+
33+
## Reader-First Convention
34+
35+
### Visible TSX example
36+
37+
Each TSX example should show only:
38+
39+
1. Top-level variables and observables referenced by `ko-*={...}`
40+
2. The JSX that demonstrates the binding itself
41+
42+
Example shape:
43+
44+
```tsx
45+
const url = ko.observable('year-end.html')
46+
const details = ko.observable('Report including final year-end statistics')
47+
48+
<a ko-attr={{ href: url, title: details }}>Report</a>
49+
```
50+
51+
### Hidden playground wrapper
52+
53+
The playground button should wrap the visible snippet with the standard mount
54+
code automatically:
55+
56+
- locate or create `#root`
57+
- render the JSX into the root
58+
- call `tko.applyBindings({}, root)`
59+
60+
This keeps the docs short without breaking playground execution.
61+
62+
### HTML tab behavior
63+
64+
- Keep the legacy HTML snippet visible
65+
- Keep the matching JS viewmodel visible, but only inside the HTML tab panel
66+
- Preserve a working HTML playground button using the paired HTML + JS payload
67+
68+
---
69+
70+
## Scope
71+
72+
Apply this convention to TSX-capable docs examples across:
73+
74+
- `tko.io/src/content/docs/bindings/`
75+
- selected examples in `observables/`, `computed/`, and `components/` where a
76+
TSX companion is helpful and already being introduced
77+
- supporting docs for agents/readers:
78+
- `tko.io/public/agent-guide.md`
79+
- `tko.io/public/agent-testing.md`
80+
81+
Initial priority is bindings pages that already have active TSX work:
82+
83+
- `attr`
84+
- `click`
85+
- `enable`
86+
- `foreach`
87+
- `hasfocus`
88+
- `if`
89+
- `text`
90+
- `textInput`
91+
- `value`
92+
- component pages already touched in the current branch
93+
94+
---
95+
96+
## Implementation Plan
97+
98+
### Phase 1: Lock the convention in tooling
99+
100+
Update the docs rendering/playground pipeline so it supports the reader-first
101+
shape:
102+
103+
- `plugins/tsx-tabs.js`
104+
- continue pairing handwritten `tsx` + `html` examples
105+
- keep legacy JS blocks inside the HTML tab panel
106+
- `plugins/playground-button.js`
107+
- support TSX snippets that omit mount/setup boilerplate
108+
- auto-wrap TSX snippets before encoding the playground payload
109+
- keep HTML payload pairing exact and deterministic
110+
111+
Success criteria:
112+
113+
- visible TSX snippet can stop at the JSX example
114+
- playground still receives runnable `{ html, js }`
115+
- HTML tab still renders its JS block inside the tab
116+
117+
### Phase 2: Migrate simple binding examples
118+
119+
For simple bindings, prefer:
120+
121+
- observables first
122+
- inline JSX binding expression
123+
- no extra `view` variable unless it improves readability
124+
- no visible mount/setup footer
125+
126+
Examples include:
127+
128+
- `attr`
129+
- `enable`
130+
- `text`
131+
- `textInput`
132+
- `value`
133+
- `click`
134+
135+
### Phase 3: Migrate context-sensitive examples
136+
137+
Bindings like `foreach` and `if` need extra care because they mix:
138+
139+
- compile-time variables in `ko-*={...}`
140+
- runtime binding-context strings like `$data`, `$parent`, `name`
141+
142+
For these pages:
143+
144+
- keep top-level collections/computeds explicit
145+
- keep runtime binding-context references as strings in child nodes
146+
- add short notes only where the compile-time/runtime boundary is easy to miss
147+
148+
### Phase 4: Align docs and agent docs
149+
150+
After the pattern stabilizes in the binding pages, update:
151+
152+
- `public/agent-guide.md`
153+
- `public/agent-testing.md`
154+
155+
to document the new visible-snippet convention and the hidden playground
156+
wrapper behavior.
157+
158+
---
159+
160+
## Content Rules
161+
162+
Use these rules consistently during migration:
163+
164+
- If a `ko-*` attribute references a value, define that value first
165+
- Prefer observables when the original example is demonstrating reactive data
166+
- Prefer literals only when reactivity is not the point of the example
167+
- Do not show `document.getElementById`, `appendChild`, or `applyBindings`
168+
unless the page is explicitly teaching render/setup mechanics
169+
- Avoid helper objects like `const attrs = { ... }` unless the object itself is
170+
part of what the reader should learn
171+
- Keep the TSX tab shorter than the HTML + JS alternative whenever possible
172+
173+
---
174+
175+
## Verification
176+
177+
For each migrated page:
178+
179+
1. Run `bun run build`
180+
2. Run the docs site locally with `bun x astro dev --host 127.0.0.1 --port 4321 --force`
181+
3. Verify the page with headless `playwright-cli`
182+
4. Confirm:
183+
- TSX tab renders the shortened reader-facing snippet
184+
- HTML tab renders both legacy HTML and its JS block inside the tab
185+
- TSX playground button opens a runnable payload
186+
- HTML playground button opens a runnable payload
187+
- no visible error bar or console errors in the playground
188+
189+
For the full rollout, spot-check every migrated page and fully verify the more
190+
complex ones (`foreach`, `if`, components).
191+
192+
---
193+
194+
## Risks
195+
196+
- Hidden wrapper logic can drift from the documented render pattern if it is not
197+
kept in sync with the playground
198+
- Over-shortening TSX examples can hide important compile-time scope rules
199+
- Complex bindings may need a visible `view` variable for readability even if
200+
simple bindings do not
201+
- Astro/Expressive Code caching can obscure plugin changes; force rebuilds may
202+
be needed during iteration
203+
204+
---
205+
206+
## Outcome
207+
208+
After this rollout:
209+
210+
- TSX examples read as the modern, concise path
211+
- observables remain explicit and teach the compile-time scope rule
212+
- setup ceremony stops dominating simple binding pages
213+
- HTML examples remain fully available for legacy readers
214+
- both tabs remain runnable through the playground

0 commit comments

Comments
 (0)