Refine rail drawer switching and toggle animations
Build and Deploy Gateway / build-and-push (push) Successful in 21s
Build and Deploy Gateway / deploy (push) Successful in 7s

This commit is contained in:
2026-08-14 15:52:56 +03:00
parent a9eca0e9d4
commit 5a21a09b82
11 changed files with 215 additions and 90 deletions
+24 -9
View File
@@ -146,17 +146,26 @@ test('secondary menus share one right rail and switch equal drawers as a vertica
assert.match(disabledRulesLabel, /opacity:\s*0/);
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(instructions, /client-rail-info-ring/);
assert.match(subscription, /client-rail-subscription-back[\s\S]*client-rail-subscription-front[\s\S]*client-rail-subscription-lines/);
assert.match(instructions, /client-rail-book-page is-left[\s\S]*client-rail-book-page is-right[\s\S]*client-rail-book-spine/);
assert.match(component, /<InstructionsToggle[\s\S]*<DevicesToggle[\s\S]*<DiagnosticsToggle[\s\S]*<RoutingToggle/);
assert.match(diagnosticsFeature, /client-rail-diagnostics-base[\s\S]*client-rail-diagnostics-pulse/);
assert.match(devices, /client-rail-device-primary[\s\S]*client-rail-device-secondary[\s\S]*client-rail-device-link/);
assert.match(routing, /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-diagnostics-pulse[\s\S]*client-rail-rule-top[\s\S]*client-rail-rule-bottom/);
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(devices, /client-rail-device-primary[\s\S]*client-rail-device-secondary[\s\S]*client-rail-device-link[\s\S]*client-rail-device-bridge[\s\S]*client-rail-device-pulse/);
assert.match(routing, /client-rail-rule-track[\s\S]*client-rail-rule-knob is-top[\s\S]*client-rail-rule-knob is-bottom/);
assert.match(styles, /\.client-rail-subscription-back \{[\s\S]*translate\(-1\.4px, 1\.4px\)/);
assert.match(styles, /\.client-subscription-toggle\.is-open \.client-rail-subscription-front \{[\s\S]*translate\(-1px, 0\.6px\)/);
assert.match(styles, /\.client-rail-book-page\.is-left \{[\s\S]*scaleX\(0\.58\)/);
assert.match(styles, /\.client-instructions-toggle\.is-open \.client-rail-book-page,[\s\S]*scale\(1\)/);
assert.match(styles, /\.client-rail-device-primary \{[\s\S]*translate\(-0\.9px, -1\.8px\)/);
assert.match(styles, /\.client-devices-toggle\.is-open \.client-rail-device-bridge \{[\s\S]*scaleX\(1\)/);
assert.match(styles, /\.client-rail-diagnostics-base,[\s\S]*scaleY\(0\.22\)/);
assert.match(styles, /\.client-diagnostics-toggle\.is-open \.client-rail-diagnostics-base,[\s\S]*scaleY\(1\)/);
assert.match(styles, /\.client-local-rules-toggle\.is-open \.client-rail-rule-knob\.is-top \{[\s\S]*translateX\(3px\)/);
assert.match(styles, /\.client-local-rules-toggle\.is-open \.client-rail-rule-knob\.is-bottom \{[\s\S]*translateX\(-3px\)/);
assert.match(styles, /@keyframes client-rail-device-signal[\s\S]*stroke-dashoffset: 1[\s\S]*stroke-dashoffset: 0/);
assert.match(styles, /@keyframes client-rail-diagnostics-scan[\s\S]*stroke-dashoffset: 1[\s\S]*stroke-dashoffset: 0/);
assert.match(styles, /transition: transform 620ms cubic-bezier\(0\.16, 1, 0\.3, 1\)/);
assert.doesNotMatch(styles, /client-rail-info-refill|client-rail-device-left|client-rail-rule-top/);
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'), /width:\s*min\(580px, 100vw\)/);
@@ -174,6 +183,11 @@ test('secondary menus share one right rail and switch equal drawers as a vertica
assert.match(subscription, /<Drawer[\s\S]*className="client-subscription-drawer"/);
assert.match(component, /const DRAWER_ORDER = \['subscription', 'instructions', 'devices', 'diagnostics', 'routing'\]/);
assert.match(component, /function switchDrawer\(target: DrawerKey\)[\s\S]*from\.inert = true[\s\S]*translateY\(\$\{direction \* 100\}%\)[\s\S]*translateY\(\$\{-direction \* 100\}%\)/);
assert.match(component, /const \[drawerSwitchTarget, setDrawerSwitchTarget\] = useState<DrawerKey \| null>\(null\)/);
assert.match(component, /const activeRailDrawer = drawerSwitchTarget && drawerControls\[drawerSwitchTarget\]\.isOpen[\s\S]*drawerControls\[drawer\]\.isOpen/);
assert.match(component, /setDrawerSwitchTarget\(target\);[\s\S]*flushSync\(\(\) => toControl\.show\(\)\)/);
assert.match(component, /fromControl\.close\(\);[\s\S]*setDrawerSwitchTarget\(null\)/);
assert.match(component, /<SubscriptionToggle[\s\S]*open=\{activeRailDrawer === 'subscription'\}[\s\S]*<RoutingToggle[\s\S]*open=\{activeRailDrawer === 'routing'\}/);
assert.match(component, /const cancel = \(\) => \{[\s\S]*from\.inert = false;[\s\S]*from\.removeAttribute\('aria-hidden'\)/);
assert.match(component, /DRAWER_SWITCH_MS = 620[\s\S]*prefers-reduced-motion: reduce[\s\S]*flushSync/);
assert.match(component, /current === 'routing' && routingFeature\.dirty[\s\S]*routingFeature\.requestClose\(\)/);
@@ -230,6 +244,7 @@ test('responsive motion has a reduced-motion fallback', () => {
assert.match(reducedMotion, /\.client-form/);
assert.match(reducedMotion, /\.harbor-brand/);
assert.match(reducedMotion, /\.client-rail-action circle/);
assert.match(reducedMotion, /\.client-rail-action g/);
assert.match(reducedMotion, /\.client-rail-action rect/);
assert.match(reducedMotion, /\.client-drawer/);
assert.match(reducedMotion, /transition:\s*none/);