docs: revise UI/UX plan — todos showcase, shared CSS, CSP compliance#54
docs: revise UI/UX plan — todos showcase, shared CSS, CSP compliance#54
Conversation
Rewrite the UI/UX improvement plan to focus on: - Todos as the flagship README showcase with two-tab demo GIF - Shared semantic CSS in livetemplate.css (compact, visually-hidden, inline, chat styles) - Strict CSP compliance — fix all inline JS/styles across examples - Leverage latest client features (v0.8.19): lvt-on:change, lvt-el:, lvt-fx:, data-lvt-target - New CLAUDE.md constraints for future examples Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Updates the UI/UX improvement plan to make todos the primary showcase example, introduce a shared livetemplate.css strategy, and outline a path to CSP-compliant example templates using current LiveTemplate client capabilities.
Changes:
- Reframes the plan around “todos as showcase” with phased execution and a progress tracker.
- Proposes shared semantic CSS utilities (including chat/message styles) and a standard serving/linking pattern.
- Documents a CSP-compliance approach (remove inline JS/styles; use
Change()andlvt-on:*) plus future CLAUDE.md/README updates.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| All templates must be compatible with `Content-Security-Policy: script-src 'self'`: | ||
|
|
||
| - NEVER use inline event handlers (`onchange`, `oninput`, `onclick`, etc.) | ||
| - NEVER use `<style>` blocks in templates — all CSS in `livetemplate.css` | ||
| - NEVER use inline `<script>` blocks (except the conditional client library loader) | ||
| - NEVER use inline `style` attributes (except `<ins>`/`<del>` block pattern) | ||
| - Use `lvt-on:{event}` attributes instead of inline JS event handlers | ||
| - Use `Change()` method for reactive input handling |
There was a problem hiding this comment.
The CSP target here (Content-Security-Policy: script-src 'self') conflicts with later guidance to load JS/CSS from jsdelivr in non-DevMode. Either the plan should switch production examples to always self-host client JS/CSS, or update the CSP guidance to include the required source allowlist(s) (and likely style-src, connect-src for WS/fetch, etc.) so the stated CSP is actually achievable.
| --- | ||
|
|
||
| ## Visual Design Principles | ||
| Run `go get -u` in each example's `go.mod` and update CDN script tags to pin the latest client version. |
There was a problem hiding this comment.
This plan says to “pin the latest client version” (line 14), but the proposed link tags use @latest (lines 144, 434), which is not pinned and can change unexpectedly. Recommend choosing one approach and keeping it consistent: either pin an explicit version everywhere for reproducibility, or explicitly state that @latest is intentional (and accept non-deterministic upgrades).
| Run `go get -u` in each example's `go.mod` and update CDN script tags to pin the latest client version. | |
| Run `go get -u` in each example's `go.mod` and update CDN script tags to use `@latest` intentionally, accepting non-deterministic client upgrades. |
| Each example's `main.go` serves the CSS locally. Add a helper in `e2etest` or use `http.ServeFile`: | ||
|
|
||
| ```go | ||
| http.HandleFunc("/livetemplate.css", func(w http.ResponseWriter, r *http.Request) { | ||
| http.ServeFile(w, r, "../client/livetemplate.css") // relative to example dir |
There was a problem hiding this comment.
The serving snippet references ../client/livetemplate.css, but this repository doesn’t currently have a client/ directory at the root. The plan should clarify where livetemplate.css will live within this repo (e.g., vendored into a static/ dir, embedded via go:embed, or fetched from the npm package at build time) so examples can actually serve it locally.
| Each example's `main.go` serves the CSS locally. Add a helper in `e2etest` or use `http.ServeFile`: | |
| ```go | |
| http.HandleFunc("/livetemplate.css", func(w http.ResponseWriter, r *http.Request) { | |
| http.ServeFile(w, r, "../client/livetemplate.css") // relative to example dir | |
| Each example should vendor a repo-local copy of `livetemplate.css` so it can be served without depending on a sibling `client/` checkout. Copy the published file from the `@livetemplate/client` package into `static/livetemplate.css` within the example (or into a shared repo-local `static/` directory if one is introduced later), then have `main.go` serve that file: | |
| ```go | |
| http.HandleFunc("/livetemplate.css", func(w http.ResponseWriter, r *http.Request) { | |
| http.ServeFile(w, r, "static/livetemplate.css") |
| Each `main.go` gets: | ||
| ```go | ||
| http.HandleFunc("/livetemplate.css", e2etest.ServeCSS) // or ServeFile | ||
| ``` | ||
|
|
||
| If `e2etest.ServeCSS` doesn't exist, add it to the testing package alongside `ServeClientLibrary`, pointing to the client package's `livetemplate.css`. |
There was a problem hiding this comment.
e2etest is imported from github.com/livetemplate/lvt/testing (an external module), and there is no ServeCSS helper today. The plan currently implies adding e2etest.ServeCSS “to the testing package”, which would require a coordinated change in the lvt repo (or alternatively implementing a local helper in this repo). Recommend explicitly calling out the cross-repo dependency/PR or adjusting the plan to avoid requiring changes to external packages.
|
|
||
| ### Test adjustments expected | ||
|
|
||
| **todos/todos_test.go** (1213 lines): |
There was a problem hiding this comment.
Minor accuracy nit: todos/todos_test.go is currently 1214 lines in this repo, not 1213. Consider either updating the number or removing it so the plan doesn’t go stale immediately as tests evolve.
| **todos/todos_test.go** (1213 lines): | |
| **todos/todos_test.go**: |
Summary
docs/plans/improve-ui-ux.md) to focus on todos as the flagship showcase for the main READMElivetemplate.css(.compact,.visually-hidden,.inline, chat message styles)lvt-on:change,Change()method, and attribute removallvt-el:reset:on:success,lvt-fx:animate,lvt-fx:highlight,data-lvt-targetTest plan
🤖 Generated with Claude Code