Partials
RefaceComposer's Partials Plugin provides interactive components with HTMX integration.
Basic Usage
Simple Partial
1import { partial } from "@reface/plugins/partials";
2
3const Counter = partial(async () => {
4 ​const count = 0;
5 ​return (
6 ​ ​<div>
7 ​ ​ ​<span>{count}</span>
8 ​ ​ ​<button {...Counter.trigger()}>Increment</button>
9 ​ ​</div>
10 ​);
11}, "counter");
12
13// Usage
14<Counter />;
HTMX Integration
1// Default click trigger
2const Button = partial(async () => {
3 ​return <button {...Button.trigger()}>Click me</button>;
4}, "button");
5
6// Custom trigger with delay
7const SearchBox = partial(async () => {
8 ​return (
9 ​ ​<div>
10 ​ ​ ​<input type="text" />
11 ​ ​ ​<button {...SearchBox.trigger("keyup delay:500ms from:input")}>
12 ​ ​ ​ ​Search
13 ​ ​ ​</button>
14 ​ ​</div>
15 ​);
16}, "search");
17
18// Form submission
19const Form = partial(async () => {
20 ​return (
21 ​ ​<form {...Form.trigger("submit")}>
22 ​ ​ ​<input type="text" name="title" />
23 ​ ​ ​<button type="submit">Save</button>
24 ​ ​</form>
25 ​);
26}, "form");
State Management
Local State
1const TodoList = partial(async () => {
2 ​const todos = await fetch("/api/todos").then((r) => r.json());
3
4 ​return (
5 ​ ​<div>
6 ​ ​ ​<ul>
7 ​ ​ ​ ​{todos.map((todo) => (
8 ​ ​ ​ ​ ​<li>
9 ​ ​ ​ ​ ​ ​{todo.title}
10 ​ ​ ​ ​ ​ ​<button {...TodoList.trigger()}>Delete</button>
11 ​ ​ ​ ​ ​</li>
12 ​ ​ ​ ​))}
13 ​ ​ ​</ul>
14 ​ ​</div>
15 ​);
16}, "todo-list");
Shared State
1const CartCounter = partial(async () => {
2 ​const count = await getCartCount();
3 ​return <span>{count} items</span>;
4}, "cart-counter");
5
6const AddToCart = partial(async () => {
7 ​return (
8 ​ ​<button {...AddToCart.trigger()} data-rerender="cart-counter">
9 ​ ​ ​Add to Cart
10 ​ ​</button>
11 ​);
12}, "add-to-cart");
Implementation Details
Partial Registration
1// Partials are automatically registered during render
2const composer = new RefaceComposer();
3composer.use(new PartialsPlugin());
4
5// Each partial gets a unique identifier
6<div>
7 ​<Counter /> <!-- data-partial="counter" -->
8 ​<SearchBox /> <!-- data-partial="search" -->
9</div>
HTMX Attributes
1// Trigger generates HTMX attributes
2const trigger = Counter.trigger("click");
3// Results in:
4// hx-get="/reface-partial/counter"
5// hx-target="[data-partial='counter']"
6// hx-trigger="click"
7
8// Custom configuration
9const trigger = SearchBox.trigger({
10 ​event: "keyup",
11 ​modifiers: {
12 ​ ​delay: 500,
13 ​ ​from: "input",
14 ​},
15});
Server Integration
1// Partial handler is called on HTMX request
2const handler = composer.getPlugin(PartialsPlugin)?.getHandler("counter");
3const result = await handler();
4// Result is used to update the partial
Best Practices
Component Design
Keep partials focused
Clear state management
Proper error handling
Loading states
Performance
Minimal updates
Efficient triggers
Optimized responses
Cache when possible
User Experience
Loading indicators
Error feedback
Progressive enhancement
Fallback behavior
Security
Input validation
CSRF protection
Rate limiting
Error handling