diff --git a/src/web/components/ClientOverviewPage.jsx b/src/web/components/ClientOverviewPage.jsx
index 1221b7a..cd03c83 100644
--- a/src/web/components/ClientOverviewPage.jsx
+++ b/src/web/components/ClientOverviewPage.jsx
@@ -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}
+
+ {gatewayDirect ? 'Harbor Gateway активен' : 'Harbor Gateway доступен'}
+ {gatewayDirect
+ ? 'Трафик идёт через Gateway в этой сети. Нажмите, чтобы использовать локальный VPN.'
+ : 'Сейчас используется локальный VPN. Нажмите, чтобы направить трафик через Gateway.'}
+
:
{content}
}
);
diff --git a/src/web/styles.css b/src/web/styles.css
index 6ceb39b..d70bb22 100644
--- a/src/web/styles.css
+++ b/src/web/styles.css
@@ -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;
}