Files
hemx/examples/html_examples/README.md
T
slhx agent 0922a46e21 docs(examples): classify full htmx pattern catalog
Extend the html_examples gallery README to cover every htmx UI example slug exactly, marking each as implemented, deferred, integration-owned, or refused. Add a test that guards the full slug matrix while keeping the implemented gallery focused on the first CRUD/form/search/load slice.

req: htmx_equivalents/001

req: htmx_equivalents/002

req: examples/001
2026-06-23 07:24:28 +02:00

6.8 KiB

hemx HTML examples

A copy-pasteable pattern gallery for the boring HTML UX patterns popularized by htmx. The point is not to clone htmx attributes; it is to show the hemx idiom: plain .heml, generated resources, server-owned Rust state, keyed partials, and tiny runtime behavior. req: htmx_equivalents/001 req: htmx_equivalents/002 req: examples/001

Run it:

cargo run -p hemx-html-examples

Open http://127.0.0.1:3029.

Pattern matrix

Names match the htmx example URL slug exactly, e.g. modal-custom from https://htmx.org/examples/modal-custom/. Rust resource names use normal identifier spelling only where the language requires it.

Status legend:

  • implemented: copyable .heml and server handlers exist in this example.
  • integration-owned: use hemx generated resources plus app/host/browser policy; do not grow hemx core for the policy.
  • refused: would clone htmx/client framework behavior or a third-party UI kit.
  • deferred: useful, but needs a later vertical slice and proof before becoming a copyable hemx pattern.
htmx example slug Status hemx idiom / boundary Proof anchor
click-to-edit implemented A read view and edit form are the same generated contact_card partial; the server toggles editing and returns gallery::contact_card.replace(...). templates/partials/contact_card.heml, contact_card_handlers::edit_contact, save_contact
bulk-update deferred Same generated-form path as inline validation, but needs a real multi-row selection/write slice so batch semantics are tested instead of claimed. Next slice should add keyed batch rows plus one server-owned bulk command.
click-to-load implemented The server owns the loaded count and returns generated keyed loaded_row replacements plus status text. gallery_handlers::load_more, LoadedRow
delete-row implemented Server state removes the row and returns gallery::editable_row.remove(id). editable_row_handlers::delete_row
edit-row implemented A table row is a keyed .heml partial with generated edit/save forms; no selector target strings. templates/partials/editable_row.heml, editable_row_handlers::edit_row, save_row
lazy-load deferred Should be the same loaded-row resource with a browser-owned visibility trigger; needs a tiny runtime convention or explicit app JS policy before copy/paste. Not implemented in core gallery yet.
inline-validation implemented A generated form reports field failure with validate_email_form.error(...), focuses the field, and updates status text. templates/gallery.heml, gallery_handlers::validate_email
infinite-scroll integration-owned This is load-more plus scroll/visibility policy; hemx should not own infinite-scroll state without an app proof. Use click-to-load until a product slice proves scroll policy.
active-search implemented The search form posts a query; the server derives result rows and replaces generated search_result keyed partials. gallery_handlers::search, SearchResult
progress-bar deferred Needs a real job/progress source and polling or push convention; a fake timer would be a trophy demo. Later slice should prove server-owned job state.
value-select deferred Dependent selects are ordinary generated form state, but need a copyable domain example and validation path. Later slice should add two select resources and server-derived options.
animations integration-owned CSS transitions are presentation policy around generated replacements; hemx should only preserve stable DOM boundaries. Use keyed partials and app CSS; no core animation framework.
file-upload integration-owned Upload transport, size limits, progress, storage, and security are app/integration policy. Needs product-owned upload route before becoming copyable.
file-upload-input integration-owned Preserving file inputs after errors is browser/security policy; hemx should not fake file state in core effects. Use app-owned upload form policy.
reset-user-input deferred Generated form .clear() already exists; needs a small copyable pattern showing reset after success and preserved values after failure. Later slice can add to inline-validation.
dialogs integration-owned Browser alert/confirm/prompt are app policy; hemx can expose event boundaries but should not own dialog UX. Use native controls or host/app code.
modal-uikit refused Third-party UI kit integration is not a hemx core pattern. Keep as app-owned integration.
modal-bootstrap refused Third-party UI kit integration is not a hemx core pattern. Keep as app-owned integration.
modal-custom deferred A custom modal can be a generated partial plus focus/escape policy, but needs accessibility proof before copy/paste. Later slice should include keyboard/focus tests.
tabs-hateoas deferred Good hemx fit: server-owned selected tab and generated tab panel replacement; needs a focused slice. Later slice should add one tab group.
tabs-javascript refused Client-owned tab state is exactly what generated server-owned state is meant to avoid unless a product needs it. Prefer tabs-hateoas.
keyboard-shortcuts integration-owned Keyboard policy belongs to the app/host; hemx should only receive explicit events. Use Effect::event/app JS when needed.
sortable integration-owned Drag/drop ordering needs a browser library or pointer policy plus server reorder command. Keep Sortable.js as app-owned integration until proven reusable.
update-other-content implemented Generated effects can update multiple slots from one handler; validation and search already update status plus rows/errors. validate_email, search handlers.
confirm integration-owned Confirmation wording and irreversible-action policy belong to the app; hemx should not own a global confirm system. Use native confirm/app dialog around generated delete forms.
async-auth integration-owned Token refresh/auth sessions belong to auth/session integration, not hemx core. See auth/session recipe boundary.
web-components integration-owned Shadow DOM/custom elements are host integration; hemx can emit events but should not pierce component internals. Use app-owned web component adapters.
move-before refused Experimental DOM preservation API is not a stable hemx contract. Avoid until browser support and a product need make it boring.

Boundary

Implemented rows must remain runnable hemx behavior. Deferred/integration-owned/refused rows are not failures; they prevent a trophy checklist from turning hemx into a client framework. Promote a deferred row only when the slice proves a reusable, boring contract with .heml, generated resources, server-owned state, and tests.