From 5c21968158c60a5a0c4854196e37740893e9ef28 Mon Sep 17 00:00:00 2001 From: dobby-d-elf Date: Sun, 24 May 2026 19:09:31 -0600 Subject: [PATCH] adjust animation scaling --- static/sessions.js | 20 +++++++++++++---- static/style.css | 35 +++++++++++++++++++++++------ tests/test_session_touch_actions.py | 35 ++++++++++++++++++++++++----- 3 files changed, 74 insertions(+), 16 deletions(-) diff --git a/static/sessions.js b/static/sessions.js index 223dd981..d65259ff 100644 --- a/static/sessions.js +++ b/static/sessions.js @@ -1577,13 +1577,16 @@ function _makeSessionSwipeAffordance(side, icon, label){ const affordance=document.createElement('div'); affordance.className='session-swipe-affordance session-swipe-affordance-'+side; affordance.setAttribute('aria-hidden','true'); + const stack=document.createElement('span'); + stack.className='session-swipe-action-stack'; const badge=document.createElement('span'); badge.className='session-swipe-badge'; badge.innerHTML=li(icon,18); const text=document.createElement('span'); text.className='session-swipe-label'; text.textContent=label; - affordance.append(badge,text); + stack.append(badge,text); + affordance.append(stack); return affordance; } const SESSION_VIRTUAL_ROW_HEIGHT = 52; @@ -3864,10 +3867,17 @@ function renderSessionListFromCache(){ const progress=Math.min(1,Math.abs(revealedOffset)/72); const reveal=Math.abs(offset); const iconScale=Math.min(1,Math.max(.01,progress*1.12)); - const badgeStretch=Math.min(Math.max(0,reveal-34),overshoot*1.15); + const badgeSize=34*iconScale; + const iconSize=18*iconScale; + const labelScale=Math.min(1,Math.max(.01,progress*1.12)); + const actionInset=0; + const tileGap=6; + const badgeStretch=Math.min(Math.max(0,reveal-34),overshoot*1.15,Math.max(0,reveal-badgeSize-actionInset-tileGap)); el.style.setProperty('--session-swipe-offset',offset+'px'); el.style.setProperty('--session-swipe-reveal',reveal+'px'); - el.style.setProperty('--session-swipe-icon-scale',iconScale); + el.style.setProperty('--session-swipe-badge-size',badgeSize+'px'); + el.style.setProperty('--session-swipe-icon-size',iconSize+'px'); + el.style.setProperty('--session-swipe-label-scale',labelScale); el.style.setProperty('--session-swipe-badge-stretch',badgeStretch+'px'); el.style.setProperty('--session-swipe-progress',Math.pow(progress,1.5)); el.classList.toggle('swiping-right',offset>0); @@ -3876,7 +3886,9 @@ function renderSessionListFromCache(){ const _clearSessionSwipePaint=()=>{ el.style.removeProperty('--session-swipe-offset'); el.style.removeProperty('--session-swipe-reveal'); - el.style.removeProperty('--session-swipe-icon-scale'); + el.style.removeProperty('--session-swipe-badge-size'); + el.style.removeProperty('--session-swipe-icon-size'); + el.style.removeProperty('--session-swipe-label-scale'); el.style.removeProperty('--session-swipe-badge-stretch'); el.style.removeProperty('--session-swipe-progress'); el.style.removeProperty('height'); diff --git a/static/style.css b/static/style.css index 51a95324..6d7e6751 100644 --- a/static/style.css +++ b/static/style.css @@ -733,7 +733,7 @@ flex-direction:column; align-items:center; justify-content:center; - gap:3px; + gap:0; width:var(--session-swipe-reveal,0px); padding:0; box-sizing:border-box; @@ -748,6 +748,7 @@ color:#fff; background:transparent; border-radius:0; + align-items:flex-start; transform-origin:left center; --session-swipe-action-color:var(--warning); } @@ -756,6 +757,7 @@ color:#fff; background:transparent; border-radius:0; + align-items:flex-end; transform-origin:right center; --session-swipe-action-color:var(--error); } @@ -764,9 +766,18 @@ opacity:var(--session-swipe-progress,0); } .session-text,.session-state-indicator,.session-actions{z-index:1;} + .session-swipe-action-stack{ + width:calc(var(--session-swipe-badge-size,34px) + var(--session-swipe-badge-stretch,0px)); + max-width:100%; + display:flex; + flex-direction:column; + align-items:center; + gap:3px; + flex:0 0 auto; + } .session-swipe-badge{ - width:calc(34px + var(--session-swipe-badge-stretch,0px)); - height:34px; + width:calc(var(--session-swipe-badge-size,34px) + var(--session-swipe-badge-stretch,0px)); + height:var(--session-swipe-badge-size,34px); border-radius:999px; background:var(--session-swipe-action-color); display:flex; @@ -774,19 +785,29 @@ justify-content:center; color:#fff; flex:0 0 auto; - transform:scale(var(--session-swipe-icon-scale,1)); - transform-origin:center; + overflow:hidden; + } + .session-swipe-badge svg{ + display:block; + width:var(--session-swipe-icon-size,18px); + height:var(--session-swipe-icon-size,18px); + stroke-width:2.2; } - .session-swipe-badge svg{display:block;stroke-width:2.2;} .session-swipe-label{ - max-width:58px; + min-width:58px; + width:100%; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; + text-align:center; font-size:10px; font-weight:600; line-height:1; + transform:scale(var(--session-swipe-label-scale,1)); + transform-origin:top center; } + .session-swipe-affordance-right .session-swipe-action-stack{margin-left:0;} + .session-swipe-affordance-left .session-swipe-action-stack{margin-right:0;} .session-item.dragging{transition:background .15s,color .15s,box-shadow .15s ease;will-change:transform;} .session-item.session-reflowing{transition:background .15s,color .15s,transform .36s cubic-bezier(.2,.8,.2,1),box-shadow .15s ease;will-change:transform;} .session-item.swipe-committed, diff --git a/tests/test_session_touch_actions.py b/tests/test_session_touch_actions.py index 8d6fada3..d539047e 100644 --- a/tests/test_session_touch_actions.py +++ b/tests/test_session_touch_actions.py @@ -124,16 +124,27 @@ def test_session_swipe_paint_uses_transform_only_exit(): assert "--session-swipe-badge-stretch" in paint assert "const reveal=Math.abs(offset);" in paint assert "const iconScale=Math.min(1,Math.max(.01,progress*1.12));" in paint - assert "const badgeStretch=Math.min(Math.max(0,reveal-34),overshoot*1.15);" in paint + assert "const badgeSize=34*iconScale;" in paint + assert "const iconSize=18*iconScale;" in paint + assert "const labelScale=Math.min(1,Math.max(.01,progress*1.12));" in paint + assert "const actionInset=0;" in paint + assert "const tileGap=6;" in paint + assert "const badgeStretch=Math.min(Math.max(0,reveal-34),overshoot*1.15,Math.max(0,reveal-badgeSize-actionInset-tileGap));" in paint + assert "el.style.setProperty('--session-swipe-badge-size',badgeSize+'px');" in paint + assert "el.style.setProperty('--session-swipe-icon-size',iconSize+'px');" in paint + assert "el.style.setProperty('--session-swipe-label-scale',labelScale);" in paint assert "window.innerWidth+'px'" in complete assert "el.style.height=rect.height+'px'" in complete assert "requestAnimationFrame(()=>el.classList.add('swipe-removing'))" in complete assert "requestAnimationFrame(()=>requestAnimationFrame(_clearSessionSwipePaint))" in SESSIONS_JS assert "el.classList.remove('swiping-right','swiping-left','swipe-committed','swipe-removing')" in clear + assert "el.style.removeProperty('--session-swipe-badge-size');" in clear + assert "el.style.removeProperty('--session-swipe-icon-size');" in clear + assert "el.style.removeProperty('--session-swipe-label-scale');" in clear assert "el.style.removeProperty('--session-swipe-badge-stretch');" in clear assert ".session-item.swipe-committed,\n .session-item.swipe-removing{transition:" in STYLE_CSS assert "transform:translate3d(calc(-1 * var(--session-swipe-offset,0px)),0,0)" in STYLE_CSS - assert "transform:scale(var(--session-swipe-icon-scale,1))" in STYLE_CSS + assert "transform:scale(var(--session-swipe-icon-scale,1))" not in STYLE_CSS swipe_start = STYLE_CSS.find(".session-item.swipe-removing{") swipe_end = STYLE_CSS.find("}", swipe_start) assert swipe_start >= 0 and swipe_end > swipe_start @@ -153,18 +164,32 @@ def test_session_swipe_actions_use_circular_icon_badges(): badge = STYLE_CSS[badge_start:STYLE_CSS.find(".session-swipe-badge svg", badge_start)] assert "background:transparent" in right assert "background:transparent" in left + assert "align-items:flex-start" in right + assert "align-items:flex-end" in left assert "--session-swipe-action-color:var(--warning)" in right assert "--session-swipe-action-color:var(--error)" in left - assert "width:calc(34px + var(--session-swipe-badge-stretch,0px))" in badge - assert "height:34px" in badge + assert "width:calc(var(--session-swipe-badge-size,34px) + var(--session-swipe-badge-stretch,0px))" in badge + assert "height:var(--session-swipe-badge-size,34px)" in badge assert "border-radius:999px" in badge assert "background:var(--session-swipe-action-color)" in badge + assert "overflow:hidden" in badge assert ".session-item.archived .session-swipe-affordance-right{--session-swipe-action-color:var(--success);}" in STYLE_CSS assert "_makeSessionSwipeAffordance('right',s.archived?'undo':'archive',s.archived?'Restore':t('session_batch_archive'))" in SESSIONS_JS + assert "stack.className='session-swipe-action-stack'" in SESSIONS_JS + assert "stack.append(badge,text)" in SESSIONS_JS + stack = STYLE_CSS[STYLE_CSS.find(".session-swipe-action-stack{"):STYLE_CSS.find(".session-swipe-badge{")] label = STYLE_CSS[STYLE_CSS.find(".session-swipe-label{"):STYLE_CSS.find(".session-item.dragging")] assert "session-swipe-label" in SESSIONS_JS - assert "max-width:58px" in label + assert "width:calc(var(--session-swipe-badge-size,34px) + var(--session-swipe-badge-stretch,0px))" in stack + assert "align-items:center" in stack + assert "min-width:58px" in label + assert "width:100%" in label + assert "text-align:center" in label assert "font-size:10px" in label + assert "transform:scale(var(--session-swipe-label-scale,1))" in label + assert "transform-origin:top center" in label + assert ".session-swipe-affordance-right .session-swipe-action-stack{margin-left:0;}" in STYLE_CSS + assert ".session-swipe-affordance-left .session-swipe-action-stack{margin-right:0;}" in STYLE_CSS def test_session_removal_reflows_surviving_rows_smoothly():