Refine secondary rail icon animations
Build and Deploy Gateway / build-and-push (push) Successful in 14s
Build and Deploy Gateway / deploy (push) Successful in 7s

This commit is contained in:
2026-08-07 22:51:51 +03:00
parent 9751f4b8c8
commit b084d7e42c
4 changed files with 32 additions and 37 deletions
+2 -2
View File
@@ -1,6 +1,6 @@
export const HARBOR_VERSIONS = Object.freeze({ export const HARBOR_VERSIONS = Object.freeze({
macClient: '0.17.14', macClient: '0.17.15',
gatewayClient: '0.18.14', gatewayClient: '0.18.15',
gatewayBackend: '0.18.1', gatewayBackend: '0.18.1',
}); });
+3 -2
View File
@@ -1164,7 +1164,7 @@ export function ClientOverviewPage({
<svg viewBox="0 0 24 24" aria-hidden="true"> <svg viewBox="0 0 24 24" aria-hidden="true">
<rect className="client-rail-device-primary" x="3.5" y="5" width="7" height="10" rx="1.5" /> <rect className="client-rail-device-primary" x="3.5" y="5" width="7" height="10" rx="1.5" />
<rect className="client-rail-device-secondary" x="13.5" y="8" width="7" height="7" rx="1.5" /> <rect className="client-rail-device-secondary" x="13.5" y="8" width="7" height="7" rx="1.5" />
<path className="client-rail-device-link" pathLength="1" d="M6 19h12M7 15v4M17 15v4" /> <path className="client-rail-device-link" d="M6 19h12M7 15v4M17 15v4" />
</svg> </svg>
<span>Устройства</span> <span>Устройства</span>
</button>} </button>}
@@ -1183,7 +1183,8 @@ export function ClientOverviewPage({
}} }}
> >
<svg viewBox="0 0 24 24" aria-hidden="true"> <svg viewBox="0 0 24 24" aria-hidden="true">
<path className="client-rail-diagnostics-wave" pathLength="1" d="M3 12h4l2.2-5 4.2 10 2.1-5H21" /> <path className="client-rail-diagnostics-base" d="M3 12h4l2.2-5 4.2 10 2.1-5H21" />
<path className="client-rail-diagnostics-pulse" pathLength="1" d="M3 12h4l2.2-5 4.2 10 2.1-5H21" />
</svg> </svg>
<span>Диагностика</span> <span>Диагностика</span>
</button> </button>
+21 -30
View File
@@ -1693,22 +1693,23 @@ p {
filter: drop-shadow(0 0 7px color-mix(in oklch, var(--client-accent) 52%, transparent)); filter: drop-shadow(0 0 7px color-mix(in oklch, var(--client-accent) 52%, transparent));
} }
.client-rail-info-ring,
.client-rail-device-primary, .client-rail-device-primary,
.client-rail-device-secondary, .client-rail-device-secondary,
.client-rail-device-link,
.client-rail-diagnostics-wave,
.client-rail-rule-knob { .client-rail-rule-knob {
transform-box: fill-box; transform-box: fill-box;
transform-origin: center; transform-origin: center;
} }
.client-rail-info-ring, .client-rail-info-ring {
.client-rail-device-link,
.client-rail-diagnostics-wave {
stroke-dasharray: 1; stroke-dasharray: 1;
} }
.client-rail-diagnostics-pulse {
stroke-width: 2.4;
opacity: 0;
stroke-dasharray: 0.16 0.84;
}
.client-instructions-toggle.is-open:not(.client-devices-toggle):not(.client-diagnostics-toggle) .client-rail-info-ring { .client-instructions-toggle.is-open:not(.client-devices-toggle):not(.client-diagnostics-toggle) .client-rail-info-ring {
animation: client-rail-info-refill 680ms cubic-bezier(0.16, 1, 0.3, 1); animation: client-rail-info-refill 680ms cubic-bezier(0.16, 1, 0.3, 1);
} }
@@ -1721,12 +1722,8 @@ p {
animation: client-rail-device-right 680ms cubic-bezier(0.16, 1, 0.3, 1); animation: client-rail-device-right 680ms cubic-bezier(0.16, 1, 0.3, 1);
} }
.client-devices-toggle.is-open .client-rail-device-link { .client-diagnostics-toggle.is-open .client-rail-diagnostics-pulse {
animation: client-rail-device-link 680ms cubic-bezier(0.16, 1, 0.3, 1); animation: client-rail-diagnostics-pulse 760ms cubic-bezier(0.16, 1, 0.3, 1);
}
.client-diagnostics-toggle.is-open .client-rail-diagnostics-wave {
animation: client-rail-diagnostics-wave 760ms cubic-bezier(0.16, 1, 0.3, 1);
} }
.client-local-rules-toggle.is-open .client-rail-rule-knob.is-top { .client-local-rules-toggle.is-open .client-rail-rule-knob.is-top {
@@ -1744,38 +1741,32 @@ p {
@keyframes client-rail-device-left { @keyframes client-rail-device-left {
0%, 100% { transform: translate(0, 0); } 0%, 100% { transform: translate(0, 0); }
45% { transform: translate(1.5px, -1px); } 38%, 58% { transform: translate(-0.6px, -2.25px); }
72% { transform: translate(0.5px, 0); } 82% { transform: translate(0.15px, 0.35px); }
} }
@keyframes client-rail-device-right { @keyframes client-rail-device-right {
0%, 100% { transform: translate(0, 0); } 0%, 100% { transform: translate(0, 0); }
45% { transform: translate(-1.5px, 1px); } 38%, 58% { transform: translate(0.6px, -2.25px); }
72% { transform: translate(-0.5px, 0); } 82% { transform: translate(-0.15px, 0.35px); }
} }
@keyframes client-rail-device-link { @keyframes client-rail-diagnostics-pulse {
from { opacity: 0.28; stroke-dashoffset: 1; } 0% { opacity: 0; stroke-dashoffset: 1; }
to { opacity: 1; stroke-dashoffset: 0; } 16%, 84% { opacity: 1; }
} 100% { opacity: 0; stroke-dashoffset: 0; }
@keyframes client-rail-diagnostics-wave {
0%, 100% { stroke-dashoffset: 0; transform: scaleY(1); }
32% { stroke-dashoffset: -0.24; transform: scaleY(0.68); }
68% { stroke-dashoffset: -0.58; transform: scaleY(1.32); }
84% { stroke-dashoffset: -0.82; transform: scaleY(0.9); }
} }
@keyframes client-rail-rule-top { @keyframes client-rail-rule-top {
0%, 100% { transform: translateX(0); } 0%, 100% { transform: translateX(0); }
42% { transform: translateX(3px); } 42% { transform: translateX(-3px); }
72% { transform: translateX(-1px); } 72% { transform: translateX(1px); }
} }
@keyframes client-rail-rule-bottom { @keyframes client-rail-rule-bottom {
0%, 100% { transform: translateX(0); } 0%, 100% { transform: translateX(0); }
42% { transform: translateX(-3px); } 42% { transform: translateX(3px); }
72% { transform: translateX(1px); } 72% { transform: translateX(-1px); }
} }
.client-local-rules-toggle:disabled { .client-local-rules-toggle:disabled {
+6 -3
View File
@@ -112,9 +112,12 @@ test('secondary menus share one right rail and both drawers open from the right'
assert.match(disabledRulesLabel, /opacity:\s*0/); assert.match(disabledRulesLabel, /opacity:\s*0/);
assert.match(disabledRulesLabel, /filter:\s*blur\(5px\)/); assert.match(disabledRulesLabel, /filter:\s*blur\(5px\)/);
assert.match(styles, /\.client-local-rules-toggle:disabled:hover span\s*\{[\s\S]*opacity:\s*1/); assert.match(styles, /\.client-local-rules-toggle:disabled:hover span\s*\{[\s\S]*opacity:\s*1/);
assert.match(component, /client-rail-info-ring[\s\S]*client-rail-device-primary[\s\S]*client-rail-device-secondary[\s\S]*client-rail-device-link[\s\S]*client-rail-diagnostics-wave[\s\S]*client-rail-rule-knob is-top[\s\S]*client-rail-rule-knob is-bottom/); assert.match(component, /client-rail-info-ring[\s\S]*client-rail-device-primary[\s\S]*client-rail-device-secondary[\s\S]*client-rail-device-link[\s\S]*client-rail-diagnostics-base[\s\S]*client-rail-diagnostics-pulse[\s\S]*client-rail-rule-knob is-top[\s\S]*client-rail-rule-knob is-bottom/);
assert.match(styles, /client-rail-info-refill[\s\S]*client-rail-device-left[\s\S]*client-rail-device-right[\s\S]*client-rail-device-link[\s\S]*client-rail-diagnostics-wave[\s\S]*client-rail-rule-top[\s\S]*client-rail-rule-bottom/); assert.match(styles, /client-rail-info-refill[\s\S]*client-rail-device-left[\s\S]*client-rail-device-right[\s\S]*client-rail-diagnostics-pulse[\s\S]*client-rail-rule-top[\s\S]*client-rail-rule-bottom/);
assert.match(styles, /@keyframes client-rail-diagnostics-wave[\s\S]*scaleY\(0\.68\)[\s\S]*scaleY\(1\.32\)/); assert.match(styles, /\.client-rail-diagnostics-pulse \{[\s\S]*stroke-dasharray: 0\.16 0\.84/);
assert.match(styles, /@keyframes client-rail-diagnostics-pulse[\s\S]*stroke-dashoffset: 1[\s\S]*stroke-dashoffset: 0/);
assert.match(styles, /@keyframes client-rail-device-left[\s\S]*translate\(-0\.6px, -2\.25px\)[\s\S]*@keyframes client-rail-device-right[\s\S]*translate\(0\.6px, -2\.25px\)/);
assert.match(styles, /@keyframes client-rail-rule-top[\s\S]*translateX\(-3px\)[\s\S]*@keyframes client-rail-rule-bottom[\s\S]*translateX\(3px\)/);
assert.match(styles, /@keyframes client-rail-info-refill[\s\S]*stroke-dashoffset: 1[\s\S]*stroke-dashoffset: 0/); assert.match(styles, /@keyframes client-rail-info-refill[\s\S]*stroke-dashoffset: 1[\s\S]*stroke-dashoffset: 0/);
assert.doesNotMatch(styles, /client-secondary-icon-motion|\.client-local-rules-toggle\.is-open svg\s*\{[^}]*rotate/); assert.doesNotMatch(styles, /client-secondary-icon-motion|\.client-local-rules-toggle\.is-open svg\s*\{[^}]*rotate/);
assert.match(rule('.client-drawer'), /inset:\s*0 0 0 auto/); assert.match(rule('.client-drawer'), /inset:\s*0 0 0 auto/);