Skip to content

refactor: migrate all examples to progressive complexity (Tier 1)#36

Closed
adnaan wants to merge 3 commits intomainfrom
progressive-complexity-migration
Closed

refactor: migrate all examples to progressive complexity (Tier 1)#36
adnaan wants to merge 3 commits intomainfrom
progressive-complexity-migration

Conversation

@adnaan
Copy link
Copy Markdown
Contributor

@adnaan adnaan commented Mar 26, 2026

Summary

  • Migrated all examples to prefer Tier 1 (standard HTML) patterns from the progressive complexity framework (v0.8.6)
  • Replaced lvt-click, lvt-submit, lvt-data-* attributes with <form method="POST"> + named <button> elements + <input type="hidden"> across 11 examples
  • Retained justified Tier 2 attributes where no HTML equivalent exists: lvt-scroll (chat), lvt-upload (avatar), lvt-input/lvt-debounce (search), lvt-change (sort/toggle), lvt-disable-with (button states)
  • Added CLAUDE.md documenting progressive complexity conventions for future examples
  • Added tier tracking table to README.md classifying all 14 examples

Test plan

  • All 14 examples build successfully (go build)
  • counter, chat, live-preview, todos-progressive, profile-progressive E2E tests pass
  • ws-disabled E2E + HTTP unit tests pass
  • todos WebSocket unit tests pass
  • todos E2E tests have pre-existing Docker Chrome flakiness (same on main)
  • progressive-enhancement HTTP unit tests pass; WebSocketCRUD/DeleteThenToggle have pre-existing flakiness (same on main)

🤖 Generated with Claude Code

…r 1)

Replace lvt-* attributes with standard HTML patterns across all examples:
- lvt-click → <form method="POST"> + <button name="action">
- lvt-submit → <form method="POST"> + named submit buttons
- lvt-data-* → <input type="hidden">
- lvt-action hidden inputs → button name routing

Tier 2 attributes retained where no HTML equivalent exists:
- lvt-scroll (chat), lvt-upload (avatar), lvt-disable-with (todos)
- lvt-change on select/checkbox, lvt-input for search

Add CLAUDE.md with progressive complexity conventions.
Add tier tracking table to README.md.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings March 26, 2026 18:52
- Add SetupUpdateEventListener() before "NonExistent" search dispatch
  to fix race where empty state text was checked before search completed
- Use JS-based outerHTML read in Add_First_Todo to avoid stale node IDs
  after DOM patch

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR migrates the examples repo toward the “progressive complexity” Tier 1 pattern by replacing LiveTemplate-specific action attributes with standard HTML forms and named submit buttons, while retaining Tier 2 lvt-* attributes where HTML has no equivalent. It also adds documentation to keep future examples consistent.

Changes:

  • Refactors templates to use <form method="POST"> + named <button> actions + hidden inputs instead of lvt-click/lvt-submit/lvt-data-* in many examples.
  • Updates E2E + HTTP tests to target the new DOM structure and action triggers.
  • Adds/updates repository docs (CLAUDE.md, README.md) to describe and track tier usage across examples.

Reviewed changes

Copilot reviewed 18 out of 18 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
ws-disabled/ws_disabled_test.go Updates browser + HTTP tests to reflect form/button-based actions.
ws-disabled/ws-disabled.tmpl Replaces lvt-submit + lvt-action hidden fields with named submit buttons.
todos/todos_test.go Updates E2E selectors and timing to click named buttons and re-read DOM after patches.
todos/todos.tmpl Refactors row actions (toggle/delete), pagination, and clear-completed to use standard forms/buttons.
todos-components/todos_test.go Updates selectors for confirm/clear actions after moving to form/button-based routing.
todos-components/todos-components.tmpl Refactors add/delete/clear actions to use POST forms with named buttons (keeps Tier 2 checkbox toggle).
progressive-enhancement/progressive_enhancement_test.go Updates assertions/selectors and HTTP payloads for new button-name routing.
progressive-enhancement/progressive-enhancement.tmpl Replaces lvt-submit/lvt-action with POST forms and named action buttons.
production/single-host/app.tmpl Switches counter controls from lvt-click buttons to a POST form with named submit buttons.
observability/counter.tmpl Switches counter controls from lvt-click to a POST form with named submit buttons.
graceful-shutdown/counter.tmpl Switches counter controls from lvt-click to a POST form with named submit buttons.
flash-messages/flash.tmpl Migrates add/clear/simulate/remove item actions to standard POST forms/buttons.
counter/counter.tmpl Switches counter controls from lvt-click to a POST form with named submit buttons.
chat/chat_e2e_test.go Updates E2E selectors from lvt-submit forms to named join/send buttons.
chat/chat.tmpl Replaces lvt-submit join/send with POST forms and named submit buttons (keeps lvt-scroll).
avatar-upload/avatar-upload.tmpl Migrates profile save action from lvt-submit to POST form with named submit button.
README.md Adds a tier-tracking table classifying examples by Tier 1 vs Tier 1+2 usage.
CLAUDE.md Adds documented conventions for progressive complexity tiers and example patterns.
Comments suppressed due to low confidence (2)

ws-disabled/ws_disabled_test.go:248

  • These HTTP "no browser" tests post "action=add" etc, but the updated template submits via named buttons (e.g. ) without an "action" field. A real non-JS form submission will include the clicked button’s name/value (e.g. add=...) rather than action=add, so these tests may no longer reflect actual browser behavior. Either update the request bodies to include the submit button field(s) matching the template, or update the template to submit an explicit action field consistently.
	form := strings.NewReader("action=add&label=&url=")
	req, err := http.NewRequest("POST", server.URL, form)
	if err != nil {
		t.Fatalf("Failed to create request: %v", err)
	}

progressive-enhancement/progressive_enhancement_test.go:279

  • This test claims to simulate a no-JS browser, but it posts "action=add" while the updated HTML uses a named submit button () and no "action" field. To accurately simulate non-JS form submission, the request body should include the clicked submit button’s field (e.g. add=...) consistent with the template, or the template should be changed to submit an explicit action parameter.
	// POST a new todo (simulating form submission without JS)
	form := strings.NewReader("action=add&title=HTTP+test+todo")
	req, err := http.NewRequest("POST", server.URL, form)
	if err != nil {
		t.Fatalf("Failed to create request: %v", err)
	}
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	req.Header.Set("Accept", "text/html") // Indicate we want HTML, not JSON

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

todos/todos.tmpl Outdated
Comment on lines +75 to +90
<form method="POST" style="display:contents;">
<input type="hidden" name="id" value="{{ .ID }}">
<td>
<button type="submit" name="toggle" class="toggle-btn" aria-label="Toggle completion">
{{ if .Completed }}&#10003;{{ else }}&#9675;{{ end }}
</button>
</td>
<td style="{{ if .Completed }}text-decoration: line-through; opacity: 0.6;{{ end }}">
{{ .Text }}
</td>
<td>
<button type="submit" name="delete" class="secondary" aria-label="Delete this todo">
Delete
</button>
</td>
</form>
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In a table row, a element must only contain / (and related table content). Wrapping the row cells in a

(even with display:contents) produces invalid HTML and can lead to inconsistent DOM structure across browsers, which is especially risky for LiveTemplate’s DOM diff/patching. Consider moving the inside a , using separate per-action forms inside each cell, or using the HTML "form" attribute on controls so the can live outside the .

Suggested change
<form method="POST" style="display:contents;">
<input type="hidden" name="id" value="{{ .ID }}">
<td>
<button type="submit" name="toggle" class="toggle-btn" aria-label="Toggle completion">
{{ if .Completed }}&#10003;{{ else }}&#9675;{{ end }}
</button>
</td>
<td style="{{ if .Completed }}text-decoration: line-through; opacity: 0.6;{{ end }}">
{{ .Text }}
</td>
<td>
<button type="submit" name="delete" class="secondary" aria-label="Delete this todo">
Delete
</button>
</td>
</form>
<td>
<form method="POST">
<input type="hidden" name="id" value="{{ .ID }}">
<button type="submit" name="toggle" class="toggle-btn" aria-label="Toggle completion">
{{ if .Completed }}&#10003;{{ else }}&#9675;{{ end }}
</button>
</form>
</td>
<td style="{{ if .Completed }}text-decoration: line-through; opacity: 0.6;{{ end }}">
{{ .Text }}
</td>
<td>
<form method="POST">
<input type="hidden" name="id" value="{{ .ID }}">
<button type="submit" name="delete" class="secondary" aria-label="Delete this todo">
Delete
</button>
</form>
</td>

Copilot uses AI. Check for mistakes.
CLAUDE.md Outdated
Comment on lines +8 to +9
- **Form submission:** `<form method="POST">` with `<button type="submit" name="action">`
- **Multiple actions:** Use button `name` attribute for routing (e.g., `name="toggle"` routes to `Toggle()` method)
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tier 1 guidance is internally inconsistent: it first suggests using a generic submit button name="action", but later states that routing is based on the button name itself (name="X" routes to X()). Since the examples in this PR use name="add"/"delete"/etc, please clarify which pattern is the intended convention (and update this doc accordingly) to avoid future examples/tests diverging.

Suggested change
- **Form submission:** `<form method="POST">` with `<button type="submit" name="action">`
- **Multiple actions:** Use button `name` attribute for routing (e.g., `name="toggle"` routes to `Toggle()` method)
- **Form submission:** `<form method="POST">` with at least one `<button type="submit" name="ActionName">` (e.g., `name="toggle"`)
- **Multiple actions:** Use distinct semantic button `name` attributes for routing (e.g., `name="toggle"` routes to `Toggle()` method, `name="delete"` routes to `Delete()` method)

Copilot uses AI. Check for mistakes.
- Move forms back inside <td> elements in todo-item partial to fix
  invalid HTML (<form> is not allowed as child of <tr>)
- Clarify CLAUDE.md Tier 1 guidance: use semantic button names like
  name="add", name="delete" (not generic name="action")

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@adnaan adnaan closed this Mar 26, 2026
@adnaan adnaan deleted the progressive-complexity-migration branch March 27, 2026 05:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants