Add Harbor mode tooltip on hover and focus
All checks were successful
Build and Deploy Gateway / build-and-push (push) Successful in 13s
Build and Deploy Gateway / deploy (push) Successful in 1s

This commit is contained in:
2026-07-11 15:28:42 +03:00
parent e6bcdc9c62
commit d5a42d8b7b
2 changed files with 50 additions and 4 deletions

View File

@@ -105,12 +105,18 @@ function HarborBrand({ isGateway, gatewayAvailable, gatewayDirect, busy, onSetGa
className="harbor-brand-control"
type="button"
aria-label={label}
aria-describedby="harbor-mode-tooltip"
aria-pressed={gatewayDirect}
title={label}
disabled={busy}
onClick={() => onSetGatewayAuto(!gatewayDirect)}
>
{content}
<span id="harbor-mode-tooltip" className="harbor-mode-tooltip" role="tooltip">
<strong>{gatewayDirect ? 'Harbor Gateway активен' : 'Harbor Gateway доступен'}</strong>
<span>{gatewayDirect
? 'Трафик идёт через Gateway в этой сети. Нажмите, чтобы использовать локальный VPN.'
: 'Сейчас используется локальный VPN. Нажмите, чтобы направить трафик через Gateway.'}</span>
</span>
</button> : <div aria-label={`Harbor ${product}`}>{content}</div>}
</div>
);

View File

@@ -110,6 +110,7 @@ p {
}
.harbor-brand-control {
position: relative;
appearance: none;
border: 0;
border-radius: 7px;
@@ -198,7 +199,7 @@ p {
.harbor-mode-stack {
position: relative;
display: inline-block;
width: 7.2em;
width: 4.5em;
height: 1.25em;
}
@@ -238,7 +239,7 @@ p {
.harbor-brand .harbor-mode-swap {
position: absolute;
top: 50%;
left: calc(100% + 12px);
left: calc(100% + 4px);
width: 14px;
height: 14px;
color: var(--harbor-connect);
@@ -248,6 +249,44 @@ p {
transition: color 320ms ease, opacity 320ms ease, transform 420ms cubic-bezier(0.16, 1, 0.3, 1);
}
.harbor-mode-tooltip {
position: absolute;
top: calc(100% + 12px);
left: 50%;
width: 116px;
display: grid;
gap: 2px;
padding: 5px 6px;
border-radius: 5px;
background: color-mix(in oklch, var(--client-panel) 94%, var(--client-bg));
box-shadow: 0 6px 20px oklch(0.08 0.015 145 / 0.16);
color: var(--client-muted);
font-size: 4px;
line-height: 1.5;
letter-spacing: 0;
text-align: left;
opacity: 0;
visibility: hidden;
filter: blur(2px);
pointer-events: none;
transform: translate(-50%, -3px);
transition: opacity 240ms ease, filter 320ms ease, transform 400ms cubic-bezier(0.16, 1, 0.3, 1), visibility 0s 400ms;
}
.harbor-mode-tooltip strong {
color: var(--client-text);
font-size: 4.2px;
}
.harbor-brand-control:hover .harbor-mode-tooltip,
.harbor-brand-control:focus-visible .harbor-mode-tooltip {
opacity: 1;
visibility: visible;
filter: blur(0);
transform: translate(-50%, 0);
transition-delay: 120ms, 120ms, 120ms, 0s;
}
.harbor-brand.is-gateway-active .harbor-mode-swap {
color: var(--harbor-gateway);
}
@@ -1625,7 +1664,8 @@ p {
}
.harbor-mode-stack em,
.harbor-brand .harbor-mode-swap {
.harbor-brand .harbor-mode-swap,
.harbor-mode-tooltip {
transition: none;
}