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
+14 -4
View File
@@ -224,20 +224,30 @@ export function useDevicesFeature({
export type DevicesFeature = ReturnType<typeof useDevicesFeature>;
export function DevicesToggle({ feature, onToggle }: { feature: DevicesFeature; onToggle: () => void }) {
export function DevicesToggle({
feature,
open,
onToggle,
}: {
feature: DevicesFeature;
open: boolean;
onToggle: () => void;
}) {
return <RailAction
buttonRef={feature.toggleRef}
className="client-instructions-toggle client-devices-toggle"
open={feature.isOpen}
open={open}
controls="client-devices"
ariaLabel={feature.isOpen ? 'Закрыть устройства' : 'Устройства Gateway'}
ariaLabel={open ? 'Закрыть устройства' : 'Устройства Gateway'}
label="Устройства"
onClick={onToggle}
>
<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-secondary" x="13.5" y="8" width="7" height="7" rx="1.5" />
<path className="client-rail-device-link" d="M6 19h12M7 15v4M17 15v4" />
<path className="client-rail-device-link" d="M7 15v4h3.5M17 15v4h-3.5" />
<path className="client-rail-device-bridge" d="M10.5 19h3" />
<path className="client-rail-device-pulse" pathLength="1" d="M7 19h10" />
</svg>
</RailAction>;
}
@@ -43,17 +43,19 @@ export type DiagnosticsFeature = ReturnType<typeof useDiagnosticsFeature>;
export function DiagnosticsToggle({
feature,
open,
onToggle,
}: {
feature: DiagnosticsFeature;
open: boolean;
onToggle: () => void;
}) {
return <RailAction
buttonRef={feature.toggleRef}
className="client-instructions-toggle client-diagnostics-toggle"
open={feature.isOpen}
open={open}
controls="client-diagnostics"
ariaLabel={feature.isOpen ? 'Закрыть диагностику' : 'Проверить маршруты'}
ariaLabel={open ? 'Закрыть диагностику' : 'Проверить маршруты'}
label="Диагностика"
onClick={onToggle}
>
@@ -232,23 +232,26 @@ export type InstructionsFeature = ReturnType<typeof useInstructionsFeature>;
export function InstructionsToggle({
feature,
open,
onToggle,
}: {
feature: InstructionsFeature;
open: boolean;
onToggle: () => void;
}) {
return <RailAction
buttonRef={feature.toggleRef}
className="client-instructions-toggle"
open={feature.isOpen}
open={open}
controls="client-instructions"
ariaLabel={feature.isOpen ? 'Закрыть инструкции' : 'Как использовать'}
ariaLabel={open ? 'Закрыть инструкции' : 'Как использовать'}
label="Как использовать"
onClick={onToggle}
>
<svg viewBox="0 0 24 24" aria-hidden="true">
<circle className="client-rail-info-ring" cx="12" cy="12" r="8.5" pathLength="1" />
<path d="M12 11v5M12 8h.01" />
<path className="client-rail-book-page is-left" d="M12 7.5C10.2 6.1 7.7 5.7 5 6v11c2.8-.3 5.2.3 7 1.7z" />
<path className="client-rail-book-page is-right" d="M12 7.5c1.8-1.4 4.3-1.8 7-1.5v11c-2.8-.3-5.2.3-7 1.7z" />
<path className="client-rail-book-spine" d="M12 7.5v11.2" />
</svg>
</RailAction>;
}
+8 -6
View File
@@ -381,12 +381,14 @@ function RuleTypePicker({ value, ruleKey, index, disabled, onChange }: RuleTypeP
export function RoutingToggle({
feature,
open,
gatewayDirect,
isGateway,
hasSubscription,
onOpen,
}: {
feature: RoutingFeature;
open: boolean;
gatewayDirect: boolean;
isGateway: boolean;
hasSubscription: boolean;
@@ -397,25 +399,25 @@ export function RoutingToggle({
<RailAction
buttonRef={feature.toggleRef}
className={`client-local-rules-toggle${feature.pendingRestart ? ' has-pending' : ''}`}
open={feature.isOpen}
open={open}
controls="client-local-rules"
disabled={disabled}
ariaLabel={disabled
? hasSubscription
? 'Локальные правила недоступны: сейчас работают правила Harbor Gateway'
: 'Локальные правила недоступны: сначала добавьте подписку'
: feature.isOpen ? 'Закрыть локальные правила' : 'Настроить локальные правила'}
: open ? 'Закрыть локальные правила' : 'Настроить локальные правила'}
label={disabled
? hasSubscription
? 'Локальные правила недоступны: сейчас работают правила Gateway'
: 'Сначала добавьте подписку'
: feature.pendingRestart ? 'Правила ждут перезапуска' : 'Локальные правила'}
onClick={() => feature.isOpen ? feature.requestClose() : onOpen()}
onClick={() => open ? feature.requestClose() : onOpen()}
>
<svg viewBox="0 0 24 24" aria-hidden="true">
<path d="M4 7h9M17 7h3M4 17h3M11 17h9" />
<circle className="client-rail-rule-knob is-top" cx="15" cy="7" r="2" />
<circle className="client-rail-rule-knob is-bottom" cx="9" cy="17" r="2" />
<path className="client-rail-rule-track" d="M4 7h16M4 17h16" />
<circle className="client-rail-rule-knob is-top" cx="12" cy="7" r="2" />
<circle className="client-rail-rule-knob is-bottom" cx="12" cy="17" r="2" />
</svg>
</RailAction>
);
@@ -301,22 +301,28 @@ type SubscriptionFeatureController = ReturnType<typeof useSubscriptionFeature>;
export function SubscriptionToggle({
feature,
open,
onToggle,
}: {
feature: SubscriptionFeatureController;
open: boolean;
onToggle: () => void;
}) {
return <RailAction
buttonRef={feature.toggleRef}
className="client-instructions-toggle client-subscription-toggle"
open={feature.open}
open={open}
controls="client-subscription-drawer"
ariaLabel={feature.open ? 'Закрыть подписки' : 'Управление подписками'}
ariaLabel={open ? 'Закрыть подписки' : 'Управление подписками'}
label="Подписки"
onClick={onToggle}
>
<svg viewBox="0 0 24 24" aria-hidden="true">
<path d="M5 5h14v14H5zM8 9h8M8 13h5" />
<rect className="client-rail-subscription-back" x="6" y="4.5" width="13" height="15" rx="1.5" />
<g className="client-rail-subscription-front">
<rect className="client-rail-subscription-card" x="4" y="6.5" width="13" height="13" rx="1.5" />
<path className="client-rail-subscription-lines" d="M7.5 10.5h6M7.5 14h4" />
</g>
</svg>
</RailAction>;
}