691c6f009a
Require a complete dotted email before inline validation reports success, preserve the typed email after valid revalidation, and update progress via the actual progress element so visible progress is not stuck at 100%. req: htmx_equivalents/005 req: examples/001 req: test/006
131 lines
5.3 KiB
Plaintext
131 lines
5.3 KiB
Plaintext
<main data-hemx-root="gallery">
|
|
<header>
|
|
<p>Copy-pasteable hemx HTML patterns</p>
|
|
<h1>HTML UX pattern gallery</h1>
|
|
<p>Server-owned Rust state, boring .heml, generated resources, and tiny runtime behavior.</p>
|
|
</header>
|
|
|
|
<section id="click-to-edit" data-htmx-example="click-to-edit" aria-labelledby="click-to-edit-heading">
|
|
<h2 id="click-to-edit-heading">click-to-edit</h2>
|
|
<div data-hemx-slot="contact_card">
|
|
<template h-for="contact in &self.contacts" h-key="contact.id">
|
|
{+ contact +}
|
|
</template>
|
|
</div>
|
|
</section>
|
|
|
|
<section id="edit-row" data-htmx-example="edit-row" aria-labelledby="edit-row-heading">
|
|
<h2 id="edit-row-heading">edit-row</h2>
|
|
<p id="delete-row" data-htmx-example="delete-row">delete-row uses the same keyed row partial and a generated remove effect.</p>
|
|
<table>
|
|
<thead>
|
|
<tr><th>Task</th><th>Actions</th></tr>
|
|
</thead>
|
|
<tbody data-hemx-slot="editable_row">
|
|
<template h-for="row in &self.rows" h-key="row.id">
|
|
{+ row +}
|
|
</template>
|
|
</tbody>
|
|
</table>
|
|
</section>
|
|
|
|
<section id="inline-validation" data-htmx-example="inline-validation" aria-labelledby="validation-heading">
|
|
<h2 id="validation-heading">inline-validation</h2>
|
|
<form data-hemx-handle="validate_email" data-hemx-form="validate_email" data-hemx-on="input">
|
|
<label>Email <input name="email" +value="self.email" required="required"></label>
|
|
<button type="submit">Validate</button>
|
|
<p data-hemx-error-for="email"></p>
|
|
<p data-hemx-slot="email_status">{+ self.email_status +}</p>
|
|
</form>
|
|
</section>
|
|
|
|
<section id="lazy-load" data-htmx-example="lazy-load" aria-labelledby="lazy-heading">
|
|
<h2 id="lazy-heading">lazy-load</h2>
|
|
<form data-hemx-handle="lazy_load" data-hemx-form="lazy_load" data-hemx-revealed="true">
|
|
<input type="hidden" name="request" value="lazy">
|
|
<button type="submit">Load lazy content</button>
|
|
</form>
|
|
<div data-hemx-slot="lazy_panel">{+ self.lazy_panel +}</div>
|
|
</section>
|
|
|
|
<section id="click-to-load" data-htmx-example="click-to-load" aria-labelledby="load-heading">
|
|
<h2 id="load-heading">click-to-load</h2>
|
|
<ul data-hemx-slot="loaded_row">
|
|
<template h-for="row in &self.loaded_rows" h-key="row.id">
|
|
{+ row +}
|
|
</template>
|
|
</ul>
|
|
<form data-hemx-handle="load_more" data-hemx-form="load_more">
|
|
<input type="hidden" name="request" value="more">
|
|
<button type="submit">Load more</button>
|
|
</form>
|
|
<p data-hemx-slot="load_status">{+ self.load_status +}</p>
|
|
</section>
|
|
|
|
<section id="infinite-scroll" data-htmx-example="infinite-scroll" aria-labelledby="infinite-heading">
|
|
<h2 id="infinite-heading">infinite-scroll</h2>
|
|
<ul data-hemx-slot="infinite_row">
|
|
<template h-for="row in &self.infinite_rows" h-key="row.id">
|
|
{+ row +}
|
|
</template>
|
|
</ul>
|
|
<form data-hemx-handle="infinite_scroll" data-hemx-form="infinite_scroll" data-hemx-revealed="true">
|
|
<input type="hidden" name="request" value="more">
|
|
<button type="submit">Reveal more rows</button>
|
|
</form>
|
|
<p data-hemx-slot="infinite_status">{+ self.infinite_status +}</p>
|
|
</section>
|
|
|
|
<section id="progress-bar" data-htmx-example="progress-bar" aria-labelledby="progress-heading">
|
|
<h2 id="progress-heading">progress-bar</h2>
|
|
<form data-hemx-handle="tick_progress" data-hemx-form="tick_progress">
|
|
<input type="hidden" name="request" value="tick">
|
|
<button type="submit">Tick progress</button>
|
|
</form>
|
|
<p data-hemx-slot="progress_meter">
|
|
<progress max="100" +value="self.progress">{+ self.progress_label +}</progress>
|
|
</p>
|
|
</section>
|
|
|
|
<section id="value-select" data-htmx-example="value-select" aria-labelledby="value-heading">
|
|
<h2 id="value-heading">value-select</h2>
|
|
<form data-hemx-handle="choose_category" data-hemx-form="choose_category">
|
|
<label>Category
|
|
<select name="category">
|
|
<option value="letters">Letters</option>
|
|
<option value="numbers">Numbers</option>
|
|
</select>
|
|
</label>
|
|
<button type="submit">Choose</button>
|
|
</form>
|
|
<select data-hemx-slot="value_option" name="value">
|
|
<template h-for="option in &self.value_options" h-key="option.id">
|
|
{+ option +}
|
|
</template>
|
|
</select>
|
|
</section>
|
|
|
|
<section id="reset-user-input" data-htmx-example="reset-user-input" aria-labelledby="reset-heading">
|
|
<h2 id="reset-heading">reset-user-input</h2>
|
|
<form data-hemx-handle="reset_message" data-hemx-form="reset_message">
|
|
<label>Message <input name="message"></label>
|
|
<button type="submit">Send and reset</button>
|
|
</form>
|
|
<p data-hemx-slot="reset_status">{+ self.reset_status +}</p>
|
|
</section>
|
|
|
|
<section id="active-search" data-htmx-example="active-search" aria-labelledby="search-heading">
|
|
<h2 id="search-heading">active-search</h2>
|
|
<form data-hemx-handle="search" data-hemx-form="search">
|
|
<label>Search <input name="query" +value="self.query"></label>
|
|
<button type="submit">Search</button>
|
|
</form>
|
|
<p data-hemx-slot="search_status">{+ self.search_status +}</p>
|
|
<ul data-hemx-slot="search_result">
|
|
<template h-for="result in &self.search_results" h-key="result.id">
|
|
{+ result +}
|
|
</template>
|
|
</ul>
|
|
</section>
|
|
</main>
|