From 61e06ef8833feafbe2d27eb2655dc4097bf0452c Mon Sep 17 00:00:00 2001 From: VooDisss Date: Wed, 1 Apr 2026 17:04:20 +0300 Subject: [PATCH] refactor(ui): group extra remote addresses behind disclosure Replace the standalone show/hide button with a full-width collapsible disclosure container in both remote access surfaces. This keeps the hidden address list visually grouped, makes the header easier to scan and click, and centers the label so it reads as structure rather than an unrelated action button. Keep the first recommended remote address visible by default while preserving access to the full list behind the compact disclosure header. --- .../src/components/remote-access-overlay.tsx | 132 ++++++++++-------- .../remote-access-settings-section.tsx | 124 ++++++++-------- .../src/styles/components/remote-access.css | 49 +++++++ 3 files changed, 187 insertions(+), 118 deletions(-) diff --git a/packages/ui/src/components/remote-access-overlay.tsx b/packages/ui/src/components/remote-access-overlay.tsx index 04fd26fb..ec0ea522 100644 --- a/packages/ui/src/components/remote-access-overlay.tsx +++ b/packages/ui/src/components/remote-access-overlay.tsx @@ -2,7 +2,7 @@ import { Dialog } from "@kobalte/core/dialog" import { Switch } from "@kobalte/core/switch" import { For, Show, createEffect, createMemo, createSignal } from "solid-js" import { toDataURL } from "qrcode" -import { ExternalLink, Link2, Loader2, RefreshCw, Shield, Wifi } from "lucide-solid" +import { ChevronDown, ExternalLink, Link2, Loader2, RefreshCw, Shield, Wifi } from "lucide-solid" import type { NetworkAddress, ServerMeta } from "../../../server/src/api-types" import { serverApi } from "../lib/api-client" import { restartCli } from "../lib/native/cli" @@ -431,69 +431,79 @@ export function RemoteAccessOverlay(props: RemoteAccessOverlayProps) { 0}> -
- -
-
- - - {(address) => { - const url = address.remoteUrl - const expandedState = () => expandedUrl() === url - const qr = () => qrCodes()[url] - const scopeLabel = () => - address.scope === "external" - ? t("remoteAccess.address.scope.network") - : address.scope === "loopback" - ? t("remoteAccess.address.scope.loopback") - : t("remoteAccess.address.scope.internal") - return ( -
-
-
-

{url}

-

- {address.family.toUpperCase()} • {scopeLabel()} • {address.ip} -

-
-
- - -
-
- -
- -
-
+ +
+ + {(address) => { + const url = address.remoteUrl + const expandedState = () => expandedUrl() === url + const qr = () => qrCodes()[url] + const scopeLabel = () => + address.scope === "external" + ? t("remoteAccess.address.scope.network") + : address.scope === "loopback" + ? t("remoteAccess.address.scope.loopback") + : t("remoteAccess.address.scope.internal") + return ( +
+
+
+

{url}

+

+ {address.family.toUpperCase()} • {scopeLabel()} • {address.ip} +

+
+
+ + +
+
+ +
+ +
+
+
+ ) + }} +
- ) - }} - +
+
diff --git a/packages/ui/src/components/settings/remote-access-settings-section.tsx b/packages/ui/src/components/settings/remote-access-settings-section.tsx index a4a61a0f..a91d8318 100644 --- a/packages/ui/src/components/settings/remote-access-settings-section.tsx +++ b/packages/ui/src/components/settings/remote-access-settings-section.tsx @@ -1,7 +1,7 @@ import { Switch } from "@kobalte/core/switch" import { For, Show, createMemo, createSignal, type Component, onMount } from "solid-js" import { toDataURL } from "qrcode" -import { ExternalLink, Link2, Loader2, RefreshCw, Shield, Wifi } from "lucide-solid" +import { ChevronDown, ExternalLink, Link2, Loader2, RefreshCw, Shield, Wifi } from "lucide-solid" import type { NetworkAddress, ServerMeta } from "../../../../server/src/api-types" import { serverApi } from "../../lib/api-client" import { restartCli } from "../../lib/native/cli" @@ -401,66 +401,76 @@ export const RemoteAccessSettingsSection: Component = () => { 0}> -
- -
-
- - - {(address) => { - const url = address.remoteUrl - const expandedState = () => expandedUrl() === url - const qr = () => qrCodes()[url] - const scopeLabel = () => - address.scope === "external" - ? t("remoteAccess.address.scope.network") - : address.scope === "loopback" - ? t("remoteAccess.address.scope.loopback") - : t("remoteAccess.address.scope.internal") + +
+ + {(address) => { + const url = address.remoteUrl + const expandedState = () => expandedUrl() === url + const qr = () => qrCodes()[url] + const scopeLabel = () => + address.scope === "external" + ? t("remoteAccess.address.scope.network") + : address.scope === "loopback" + ? t("remoteAccess.address.scope.loopback") + : t("remoteAccess.address.scope.internal") - return ( -
-
-
-

{url}

-

- {address.family.toUpperCase()} - {scopeLabel()} - {address.ip} -

-
-
- - -
-
- -
- -
-
+ return ( +
+
+
+

{url}

+

+ {address.family.toUpperCase()} - {scopeLabel()} - {address.ip} +

+
+
+ + +
+
+ +
+ +
+
+
+ ) + }} +
- ) - }} -
+ +
diff --git a/packages/ui/src/styles/components/remote-access.css b/packages/ui/src/styles/components/remote-access.css index feee3fbc..be7b8ad0 100644 --- a/packages/ui/src/styles/components/remote-access.css +++ b/packages/ui/src/styles/components/remote-access.css @@ -256,6 +256,55 @@ cursor: pointer; } +.remote-address-disclosure { + border: 1px solid var(--border-base); + border-radius: 12px; + background: var(--surface-primary); + overflow: hidden; +} + +.remote-address-disclosure-trigger { + width: 100%; + min-height: 40px; + display: grid; + grid-template-columns: 1fr auto 1fr; + align-items: center; + padding: 8px 12px; + border: 0; + background: transparent; + color: var(--text-primary); + cursor: pointer; +} + +.remote-address-disclosure-label { + grid-column: 2; + justify-self: center; + text-align: center; + font-size: 13px; + font-weight: 600; +} + +.remote-address-disclosure-chevron { + grid-column: 3; + justify-self: end; + width: 16px; + height: 16px; + color: var(--text-secondary); + transition: transform 0.2s ease; +} + +.remote-address-disclosure-chevron.is-expanded { + transform: rotate(180deg); +} + +.remote-address-disclosure-content { + display: flex; + flex-direction: column; + gap: 10px; + padding: 0 10px 10px; + border-top: 1px solid var(--border-base); +} + .remote-qr { margin-top: 12px; display: flex;