summaryrefslogtreecommitdiff
path: root/docs/effects.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/effects.md')
-rw-r--r--docs/effects.md80
1 files changed, 80 insertions, 0 deletions
diff --git a/docs/effects.md b/docs/effects.md
new file mode 100644
index 00000000..3f375b7d
--- /dev/null
+++ b/docs/effects.md
@@ -0,0 +1,80 @@
+# Effects: feel reviews
+
+**The rule above all the others:** no effect may alter or cover a focus
+indicator (the focused pane's tag colour, its grip, the cursor, the
+selection) or reduce its contrast. The effects are sugar; the indicators are
+how a person knows where they are. Every G stage is reviewed against this.
+Lift, for one, falls only on pane bodies and rails, never on a tag, a grip or
+a header, and its strength is capped so text and the selection keep min(their
+contrast, 4.5) (tests in src/gui/gui.zig). The rule binds effects, not a
+theme's structure: the rules between panes (2px, `rule_px`) are the theme's
+borders, and the one over a tag band stays in the band's slack, never over
+its text. A dim touches only the unfocused
+panes, with the same floor, and the focused pane's text is never at less
+contrast than theirs (tests in src/draw.zig).
+
+Each effect of docs/render-pipeline.md §9 lands behind its own switch, off,
+and is kept only after a feel review (§8.4): a frame series on the virtual
+clock, a recording, and a verdict — keep, polish or drop — with one line of
+why. The verdict is the user's.
+
+| effect | switch | state | review material | verdict |
+|---|---|---|---|---|
+| Crt (bundled post pass) | `Crt 0..3` | kept, rewritten (no barrel) | fx-compare stills, live window | kept at the user's live look |
+| Ripple, Glitch | — | removed | live window | dropped by the user after a live look |
+| G1 lift | `Lift shadow\|rim\|auto` (off), `InactiveDim <percent>` | opt-in until the focus-lift default is decided | lift-shots-2 (off, shadow, rim, auto on acme, dusk, forge); frame series + mp4 per Motion flavour | shadow on acme: keep as is. Round 1 dropped glow and surface (surface lowered the focused text's contrast) and made rim a hairline just above the focused tag (light on a dark page, shade on a light one). auto on a dark page recedes the others (InactiveDim 30) |
+
+## Motion flavours
+
+`Motion off|crisp|smooth|bouncy|playful` (default smooth, tuned so arrivals
+land inside §8.1's 220 ms; bouncy and playful run longer, opt-in) is one parameter set
+(animation.Motion) every fx animation reads, so a flavour is data, not a
+branch in each effect. Input is never blocked, and a new target always
+retargets from the current position and velocity.
+
+| flavour | timing (ω, length) | follow-through (ζ) | anticipation | squash/stretch | exaggeration (gain) | secondary lag | arcs |
+|---|---|---|---|---|---|---|---|
+| off | instant | — | — | — | — | — | — |
+| crisp | 60, 0.6× (leaves at full speed) | 1 (none) | — | — | 1 | in step | — |
+| smooth | 34, 1.1× (slow in, slow out; ≤220 ms) | 1 (none) | — | — | 1 | 0.85 | 0.04 |
+| bouncy | 24, 1.4× | 0.35 (overshoots ~30%, settles twice) | — | 0.15 | 1.25 | 0.8 | 0.08 |
+| playful | 18, 1.7× | 0.28 (overshoots ~40%) | 0.15 of the move | 0.35 | 1.4 | 0.55 | 0.15 |
+
+The flavours are distinct by design, not tuning: crisp leaves at full speed
+and never passes its mark; smooth takes twice as long and eases in and out; bouncy clearly passes its mark and settles back once or twice;
+playful winds up the other way first, flies well past, and stretches along
+its path and squashes as it lands, its text with it (the user's choice); a
+pointer inverts the same stretched box, and landed, a pane is exactly its
+target. A motion only a few pixels big (Lift) is
+exaggerated by the flavour's gain so its character shows. The flavours drive
+the Lift spring (time-based), the notice drop and the pane moves (PanelSlide,
+PanelZoom, PanelVertical opening or moving, whose length scales with the
+flavour); a closing pane keeps its effect's own exit. Chart and side-by-side
+video: .scratch/render/motion/compare/.
+
+Which principles each motion uses:
+
+- **Lift** (G1): timing, slow in / slow out (the spring), follow-through
+ (bouncy and playful lift past full and settle back), anticipation (playful
+ dips before it rises; below zero nothing is drawn, so it reads as a beat
+ before the lift), staging (only the focused pane lifts; nothing else moves
+ with a focus change), exaggeration (the flavour's gain). Squash, stretch,
+ arcs and secondary lag have nothing to act on in a lift.
+- **Notice drop and pane moves**: timing and follow-through from the flavour's
+ spring over the move's length; anticipation (playful). A pane past its mark
+ never takes a neighbour's click, a rising one stays in its box, and a notice
+ past its row stays in its pane's body.
+- **Cursor** (G3, next): designed around the same set: glide on the spring,
+ stretch along the path, an arc on long jumps, the trailing corners as the
+ secondary action.
+
+
+Notes on G1: the lift and the dim run on one focus spring per pane, at the
+Motion flavour's pace, sampled at each frame's own time; while it moves the
+GUI draws at the display's rate, and a grid snaps. A notice floats on a lift
+of 1 while a shadow or rim is on. InactiveDim under `Lift auto` defaults to
+30. The fade is in linear light, so on a dark page it is gentle: at 30
+forge's text goes from 15.5:1 to 11.2:1 and dusk's from 6.4:1 to 4.8:1,
+plainly quieter and still easy reading; at 10 forge barely moves (14.1:1).
+On a light page the same percent bites far harder (acme: 7.0:1 at 10, the
+4.5 floor at 30), which is why `auto` shades there instead of dimming.