This commit is contained in:
182
docs/api/fx.md
Normal file
182
docs/api/fx.md
Normal file
@@ -0,0 +1,182 @@
|
||||
# Animation Helper: `fx( )`
|
||||
|
||||
The `fx` function applies simple **enter animations** to DOM elements. You can either use a predefined CSS keyframes animation or declare inline transition effects (scale, slide, rotate, blur). It is designed to be used when dynamically creating elements – especially inside `when` or `each` branches.
|
||||
|
||||
## Function Signature
|
||||
|
||||
```typescript
|
||||
fx(
|
||||
options: {
|
||||
name?: string; // CSS keyframes animation name (will append '-in')
|
||||
duration?: number; // Animation duration in ms (default: 200)
|
||||
scale?: boolean; // Start with scale(0.95) → none
|
||||
slide?: boolean; // Start with translateY(-10px) → none
|
||||
rotate?: boolean; // Start with rotate(-2deg) → none
|
||||
blur?: boolean; // Start with blur(4px) → none
|
||||
},
|
||||
child: Node | (() => Node)
|
||||
): Node
|
||||
```
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| **`options`** | `object` | Yes | Animation configuration. |
|
||||
| **`options.name`** | `string` | No | Name of a CSS `@keyframes` animation. The actual animation name becomes `${name}-in`. |
|
||||
| **`options.duration`** | `number` | No | Duration in milliseconds (default `200`). |
|
||||
| **`options.scale`** | `boolean` | No | Add a scale transform from `0.95` to `none`. |
|
||||
| **`options.slide`** | `boolean` | No | Add a vertical slide from `translateY(-10px)` to `none`. |
|
||||
| **`options.rotate`** | `boolean` | No | Add a small rotation from `rotate(-2deg)` to `none`. |
|
||||
| **`options.blur`** | `boolean` | No | Add a blur filter from `blur(4px)` to `none`. |
|
||||
| **`child`** | `Node` or `() => Node` | Yes | The element to animate. If a function is passed, it is called to obtain the node. |
|
||||
|
||||
**Returns:** The same DOM node (or the child if it is not a `Node`), after applying the animation setup.
|
||||
|
||||
---
|
||||
|
||||
## Usage Patterns
|
||||
|
||||
### 1. Named CSS Keyframes Animation
|
||||
|
||||
Define a `@keyframes` rule in your CSS, for example:
|
||||
|
||||
```css
|
||||
@keyframes fade-in {
|
||||
from { opacity: 0; }
|
||||
to { opacity: 1; }
|
||||
}
|
||||
```
|
||||
|
||||
Then apply it with `fx`:
|
||||
|
||||
```javascript
|
||||
const MyComponent = () =>
|
||||
fx({ name: "fade", duration: 300 },
|
||||
div("I will fade in")
|
||||
);
|
||||
```
|
||||
|
||||
> The animation name used is `${name}-in`. In this example: `fade-in`.
|
||||
|
||||
### 2. Inline Transition (Scale + Opacity)
|
||||
|
||||
No CSS keyframes needed. The element starts with `opacity: 0` and `transform: scale(0.95)`, then transitions to `opacity: 1` and `transform: none`.
|
||||
|
||||
```javascript
|
||||
fx({ scale: true, duration: 200 },
|
||||
button({ onClick: () => alert("Hi") }, "Click me")
|
||||
);
|
||||
```
|
||||
|
||||
### 3. Combining Multiple Effects
|
||||
|
||||
You can combine `scale`, `slide`, `rotate`, and `blur` at the same time.
|
||||
|
||||
```javascript
|
||||
fx({ scale: true, slide: true, blur: true, duration: 250 },
|
||||
div({ class: "card" }, "Smooth enter")
|
||||
);
|
||||
```
|
||||
|
||||
### 4. Using with `when` (Conditional Rendering)
|
||||
|
||||
Wrap the branch content with `fx` to animate entering elements.
|
||||
|
||||
```javascript
|
||||
when(show,
|
||||
() => fx({ slide: true },
|
||||
div("This slides in when visible")
|
||||
)
|
||||
);
|
||||
```
|
||||
|
||||
### 5. Using a Function as Child
|
||||
|
||||
If the element is created inside a function (e.g. to avoid recreation until needed), pass a function that returns the node.
|
||||
|
||||
```javascript
|
||||
fx({ scale: true },
|
||||
() => div("Lazy created and then animated")
|
||||
);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## What Happens Under the Hood
|
||||
|
||||
### With `name` (CSS animation)
|
||||
|
||||
- Sets `el.style.animation = `${name}-in ${duration}ms``.
|
||||
- The element animates according to your keyframes.
|
||||
- No further inline style changes are applied.
|
||||
|
||||
### Without `name` (transition effects)
|
||||
|
||||
- Sets `el.style.transition = `all ${duration}ms ease``.
|
||||
- Sets initial `opacity: 0`.
|
||||
- Applies initial transforms (`scale`, `slide`, `rotate`) if selected.
|
||||
- Applies initial `filter: blur(4px)` if `blur: true`.
|
||||
- In the next animation frame (via `requestAnimationFrame`), sets:
|
||||
- `opacity: 1`
|
||||
- `transform: none`
|
||||
- `filter: none`
|
||||
- The element transitions smoothly from the start state to the final state.
|
||||
|
||||
> **Important:** The element must be **in the DOM** when the animation starts. `fx` does **not** automatically mount the node – you must already have appended it or be about to mount it. In practice, when you call `fx` inside a component that is being mounted, the element will be added to the DOM shortly after, and the animation runs correctly.
|
||||
|
||||
---
|
||||
|
||||
## Complete Example
|
||||
|
||||
```javascript
|
||||
const App = () =>
|
||||
div([
|
||||
fx({ name: "fade", duration: 400 },
|
||||
h1("Welcome to SigPro")
|
||||
),
|
||||
fx({ scale: true, slide: true, duration: 250 },
|
||||
button({ onClick: () => alert("Animated!") }, "Animated button")
|
||||
)
|
||||
]);
|
||||
|
||||
mount(App, "#app");
|
||||
```
|
||||
|
||||
With accompanying CSS:
|
||||
|
||||
```css
|
||||
@keyframes fade-in {
|
||||
from { opacity: 0; transform: translateY(10px); }
|
||||
to { opacity: 1; transform: translateY(0); }
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Notes
|
||||
|
||||
- `fx` is **not** required for basic reactivity – it is purely a visual helper for enter animations.
|
||||
- For exit animations (when an element is removed), use CSS transitions on the element itself combined with `when` – or consider adding a wrapper that delays removal. SigPro does not include built‑in exit animations.
|
||||
- The function returns the same node you passed, so you can inline it inside `h` or tag helpers:
|
||||
|
||||
```javascript
|
||||
div([
|
||||
fx({ scale: true }, span("Hello"))
|
||||
])
|
||||
```
|
||||
|
||||
- If `child` is not a DOM node (e.g., a string or number), `fx` returns it unchanged – no animation is applied.
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
| Option | Effect |
|
||||
| :--- | :--- |
|
||||
| `name` | Uses `@keyframes ${name}-in` CSS animation. |
|
||||
| `duration` | Controls animation/transition length (ms). |
|
||||
| `scale` | Start scale `0.95` → `none`. |
|
||||
| `slide` | Start `translateY(-10px)` → `none`. |
|
||||
| `rotate` | Start `rotate(-2deg)` → `none`. |
|
||||
| `blur` | Start `blur(4px)` → `none`. |
|
||||
|
||||
Combine options to create smooth, modern entrance effects without writing extra CSS.
|
||||
Reference in New Issue
Block a user