From 1f03631d2df2c3fa9264f9509e6d468e8fd6b6eb Mon Sep 17 00:00:00 2001 From: ZDDC Date: Sun, 10 May 2026 20:10:45 -0500 Subject: [PATCH] feat(motion): staggered page-load reveal on header chrome MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The header is the first thing a user sees. A short staggered fade-in (logo → title → action button → right-side icons over ~360ms) turns the instant-pop-in feel into a subtle "the tool is composing itself" beat. Pure CSS @keyframes (no JS), cubic-bezier(0.2, 0.7, 0.2, 1) for the "settle in" easing curve. Respects prefers-reduced-motion. Total budget ~260ms before everything is visible — well under the threshold where it becomes a perceptible delay. Co-Authored-By: Claude Opus 4.7 (1M context) --- shared/base.css | 34 +++++++++++++++++++++++++++++ zddc/internal/handler/tables.html | 36 ++++++++++++++++++++++++++++++- 2 files changed, 69 insertions(+), 1 deletion(-) diff --git a/shared/base.css b/shared/base.css index 9a8bb2a..1e39065 100644 --- a/shared/base.css +++ b/shared/base.css @@ -332,6 +332,40 @@ a:hover { display: block; } +/* Page-load reveal. The header is the first thing a user sees — a + short staggered fade-in over ~360ms turns "instant pop-in" into a + subtle "the tool is composing itself for you" beat. Pure CSS, no + JS; respects prefers-reduced-motion. The stagger order (logo → + title → action buttons → right-side icons) mirrors the reading + order of the chrome itself. */ +@keyframes zddc-header-rise { + from { opacity: 0; transform: translateY(-4px); } + to { opacity: 1; transform: translateY(0); } +} + +.app-header__logo, +.header-title-group, +.header-left > .btn, +.header-right > * { + animation: zddc-header-rise 360ms cubic-bezier(0.2, 0.7, 0.2, 1) both; +} + +.app-header__logo { animation-delay: 0ms; } +.header-title-group { animation-delay: 60ms; } +.header-left > .btn { animation-delay: 120ms; } +.header-right > *:nth-child(1) { animation-delay: 180ms; } +.header-right > *:nth-child(2) { animation-delay: 220ms; } +.header-right > *:nth-child(3) { animation-delay: 260ms; } + +@media (prefers-reduced-motion: reduce) { + .app-header__logo, + .header-title-group, + .header-left > .btn, + .header-right > * { + animation: none; + } +} + /* ── Build timestamp ──────────────────────────────────────────────────────── */ .build-timestamp { font-size: 0.55rem; diff --git a/zddc/internal/handler/tables.html b/zddc/internal/handler/tables.html index 91f3d7a..3758357 100644 --- a/zddc/internal/handler/tables.html +++ b/zddc/internal/handler/tables.html @@ -371,6 +371,40 @@ a:hover { display: block; } +/* Page-load reveal. The header is the first thing a user sees — a + short staggered fade-in over ~360ms turns "instant pop-in" into a + subtle "the tool is composing itself for you" beat. Pure CSS, no + JS; respects prefers-reduced-motion. The stagger order (logo → + title → action buttons → right-side icons) mirrors the reading + order of the chrome itself. */ +@keyframes zddc-header-rise { + from { opacity: 0; transform: translateY(-4px); } + to { opacity: 1; transform: translateY(0); } +} + +.app-header__logo, +.header-title-group, +.header-left > .btn, +.header-right > * { + animation: zddc-header-rise 360ms cubic-bezier(0.2, 0.7, 0.2, 1) both; +} + +.app-header__logo { animation-delay: 0ms; } +.header-title-group { animation-delay: 60ms; } +.header-left > .btn { animation-delay: 120ms; } +.header-right > *:nth-child(1) { animation-delay: 180ms; } +.header-right > *:nth-child(2) { animation-delay: 220ms; } +.header-right > *:nth-child(3) { animation-delay: 260ms; } + +@media (prefers-reduced-motion: reduce) { + .app-header__logo, + .header-title-group, + .header-left > .btn, + .header-right > * { + animation: none; + } +} + /* ── Build timestamp ──────────────────────────────────────────────────────── */ .build-timestamp { font-size: 0.55rem; @@ -1207,7 +1241,7 @@ body.help-open .app-header {
ZDDC Table - v0.0.17-alpha · 2026-05-11 01:08:41 · 8be6c4d-dirty + v0.0.17-alpha · 2026-05-11 01:10:25 · 6260aa4-dirty