feat(ui): glide the underline tab indicator

Give the underline tab strips the same motion as the pill ones: the
indicator travels to the newly selected tab and leans toward a neighbour
on press, instead of jumping.

Opening, closing, and reordering tabs shift the indicator without a user
switch, so those repositions still snap.

Also drop the overshoot from the shared travel curve — both indicators now
decelerate into place rather than springing back.
This commit is contained in:
Bohdan Triapitsyn
2026-07-25 15:11:07 +03:00
parent aab9f3bca3
commit c9f673582a
2 changed files with 48 additions and 18 deletions
+13 -4
View File
@@ -939,14 +939,22 @@ html:not(.dark) .chat-scroll {
* instead of sliding in from the track origin.
*/
.pill-tabs__indicator--is-animated {
/* Slight overshoot on travel reads as a spring; size stays non-overshooting
so wide/narrow label swaps do not wobble. */
/* Decelerating ease with no overshoot: the indicator settles rather than
bouncing back at the end of its travel. */
transition:
transform 320ms cubic-bezier(0.34, 1.3, 0.64, 1),
transform 280ms cubic-bezier(0.22, 1, 0.36, 1),
width 260ms cubic-bezier(0.22, 1, 0.36, 1),
height 260ms cubic-bezier(0.22, 1, 0.36, 1);
}
/* Underline indicator shares the pill's travel curve so both tab styles feel
like the same control. */
.underline-tabs__indicator--is-animated {
transition:
transform 280ms cubic-bezier(0.22, 1, 0.36, 1),
width 260ms cubic-bezier(0.22, 1, 0.36, 1);
}
.pill-tabs__button {
transition-property: color, transform;
transition-duration: 150ms;
@@ -958,7 +966,8 @@ html:not(.dark) .chat-scroll {
}
@media (prefers-reduced-motion: reduce) {
.pill-tabs__indicator--is-animated {
.pill-tabs__indicator--is-animated,
.underline-tabs__indicator--is-animated {
transition: none;
}