5.0 KiB
5.0 KiB
Reactive Branching: If( )
The If function is a reactive control flow operator. It manages the conditional rendering of components with optional smooth transitions, ensuring that only the active branch exists in the DOM and in memory.
Function Signature
If(
condition: Signal<boolean> | Function,
thenVal: Component | Node,
otherwiseVal?: Component | Node,
transition?: Transition
): HTMLElement
| Parameter | Type | Required | Description |
|---|---|---|---|
condition |
Signal |
Yes | A reactive source that determines which branch to render. |
thenVal |
any |
Yes | The content to show when the condition is truthy. |
otherwiseVal |
any |
No | The content to show when the condition is falsy (defaults to null). |
transition |
Transition |
No | Optional animation hooks for enter/exit transitions. |
Returns: A div element with display: contents that acts as a reactive portal for the branches.
Transition Interface
interface Transition {
/** Called when branch enters. Use for fade-in, slide-in, etc. */
in: (el: HTMLElement) => void;
/** Called when branch leaves. Call `done()` when animation completes. */
out: (el: HTMLElement, done: () => void) => void;
}
Example: Fade Transition
const fade = {
in: (el) => {
el.style.opacity = "0";
el.style.transition = "opacity 0.3s";
requestAnimationFrame(() => {
el.style.opacity = "1";
});
},
out: (el, done) => {
el.style.transition = "opacity 0.3s";
el.style.opacity = "0";
setTimeout(done, 300);
}
};
If(show, Modal, null, fade);
Usage Patterns
1. Simple Toggle
const isVisible = $(false);
Div([
Button({ onclick: () => isVisible(!isVisible()) }, "Toggle Message"),
If(isVisible,
P("Now you see me!"),
P("Now you don't...")
)
]);
2. With Smooth Animation
const showModal = $(false);
Div([
Button({ onclick: () => showModal(true) }, "Open Modal"),
If(showModal,
() => Modal({ onClose: () => showModal(false) }),
null,
fade // ← Smooth enter/exit animation
)
]);
3. Lazy Component Loading
Unlike CSS display: none, If is lazy. The inactive branch is never created, saving memory.
If(() => user.isLogged(),
() => Dashboard(), // Only executed if logged in
() => LoginGate() // Only executed if guest
)
4. Complex Conditions
If(() => count() > 10 && status() === 'ready',
Span("Threshold reached!")
)
5. If.not Helper
If.not(loading,
() => Content(), // Shows when loading is FALSE
() => Spinner() // Shows when loading is TRUE
)
Automatic Cleanup
One of the core strengths of If is its integrated Cleanup logic. SigPro ensures that when a branch is swapped out, it is completely purged.
- Stop Watchers: All
Watchcalls inside the inactive branch are permanently stopped. - Unbind Events: Event listeners attached via
Tagare removed. - Recursive Sweep: SigPro performs a deep "sweep" of the removed branch.
- Transition Respect: When using transitions, destruction only happens AFTER the
outanimation completes.
Best Practices
- Function Wrappers: For heavy components, use
() => MyComponent()to prevent initialization until needed. - Reusable Transitions: Define common transitions (fade, slide, scale) in a shared module.
- Cleanup: No manual cleanup needed. SigPro handles everything automatically.
Technical Comparison
| Feature | Standard CSS hidden |
SigPro If |
|---|---|---|
| DOM Presence | Always present | Only if active |
| Reactivity | Still processing | Paused/Destroyed |
| Memory usage | Higher | Optimized |
| Cleanup | Manual | Automatic |
| Smooth Transitions | Manual | Built-in hook |
| Animation Timing | You manage | Respected by core |
Complete Transition Examples
Fade
const fade = {
in: (el) => { el.style.opacity = "0"; requestAnimationFrame(() => { el.style.transition = "opacity 0.3s"; el.style.opacity = "1"; }); },
out: (el, done) => { el.style.transition = "opacity 0.3s"; el.style.opacity = "0"; setTimeout(done, 300); }
};
Slide
const slide = {
in: (el) => { el.style.transform = "translateX(-100%)"; requestAnimationFrame(() => { el.style.transition = "transform 0.3s"; el.style.transform = "translateX(0)"; }); },
out: (el, done) => { el.style.transition = "transform 0.3s"; el.style.transform = "translateX(-100%)"; setTimeout(done, 300); }
};
Scale
const scale = {
in: (el) => { el.style.transform = "scale(0)"; requestAnimationFrame(() => { el.style.transition = "transform 0.2s"; el.style.transform = "scale(1)"; }); },
out: (el, done) => { el.style.transition = "transform 0.2s"; el.style.transform = "scale(0)"; setTimeout(done, 200); }
};