diff --git a/CHANGELOG.md b/CHANGELOG.md index c841f9130..5afd3a1de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ ### Fixes - Android: tapping the foreground service notification brings the app to the front. (#179) — thanks @Syhids - Cron tool passes `id` to the gateway for update/remove/run/runs (keeps `jobId` input). (#180) — thanks @adamgall +- Control UI: chat view uses page scroll with sticky header/sidebar and fixed composer (no inner scroll frame). - macOS: treat location permission as always-only to avoid iOS-only enums. (#165) — thanks @Nachx639 - macOS: make generated gateway protocol models `Sendable` for Swift 6 strict concurrency. (#195) — thanks @andranik-sahakyan - WhatsApp: suppress typing indicator during heartbeat background tasks. (#190) — thanks @mcinteerj diff --git a/ui/src/styles/components.css b/ui/src/styles/components.css index 7665f661f..716b58598 100644 --- a/ui/src/styles/components.css +++ b/ui/src/styles/components.css @@ -429,6 +429,16 @@ background: rgba(0, 0, 0, 0.2); } +.chat { + display: flex; + flex-direction: column; + min-height: 0; +} + +.shell--chat .chat { + flex: 1; +} + .chat-header { display: flex; justify-content: space-between; @@ -460,8 +470,9 @@ display: flex; flex-direction: column; gap: 12px; - max-height: 60vh; - overflow: auto; + flex: 1; + max-height: none; + overflow: visible; padding: 14px 12px; min-width: 0; border-radius: 16px; @@ -731,6 +742,16 @@ gap: 10px; } +.shell--chat .chat-compose { + position: sticky; + bottom: 0; + z-index: 5; + margin-top: 0; + padding-top: 12px; + background: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, var(--panel) 35%); + border-top: 1px solid var(--border); +} + .chat-compose__field { gap: 4px; } diff --git a/ui/src/styles/layout.css b/ui/src/styles/layout.css index 45e7073ec..b311c1447 100644 --- a/ui/src/styles/layout.css +++ b/ui/src/styles/layout.css @@ -1,4 +1,6 @@ .shell { + --shell-pad: 18px; + --shell-gap: 18px; min-height: 100vh; display: grid; grid-template-columns: minmax(220px, 280px) minmax(0, 1fr); @@ -6,13 +8,16 @@ grid-template-areas: "topbar topbar" "nav content"; - gap: 18px; - padding: 18px; + gap: var(--shell-gap); + padding: var(--shell-pad); animation: dashboard-enter 0.6s ease-out; } .topbar { grid-area: topbar; + position: sticky; + top: var(--shell-pad); + z-index: 20; display: flex; justify-content: space-between; align-items: center; @@ -51,6 +56,16 @@ .nav { grid-area: nav; + position: sticky; + top: calc( + var(--shell-pad) + var(--topbar-height, 0px) + var(--shell-gap) + ); + align-self: start; + max-height: calc( + 100vh - var(--topbar-height, 0px) - var(--shell-gap) - + var(--shell-pad) - var(--shell-pad) + ); + overflow: auto; padding: 16px; border: 1px solid var(--border); border-radius: 20px; @@ -132,6 +147,14 @@ display: flex; flex-direction: column; gap: 20px; + min-height: 0; +} + +.shell--chat .content { + min-height: calc( + 100vh - var(--topbar-height, 0px) - var(--shell-gap) - + var(--shell-pad) - var(--shell-pad) + ); } .content-header { @@ -204,16 +227,19 @@ @media (max-width: 1100px) { .shell { + --shell-pad: 12px; + --shell-gap: 12px; grid-template-columns: 1fr; grid-template-rows: auto auto 1fr; grid-template-areas: "topbar" "nav" "content"; - padding: 12px; } .nav { + position: static; + max-height: none; display: flex; gap: 16px; overflow-x: auto; @@ -234,6 +260,7 @@ } .topbar { + position: static; flex-direction: column; align-items: flex-start; gap: 12px; diff --git a/ui/src/ui/app-render.ts b/ui/src/ui/app-render.ts index 120fd5697..c38fc8544 100644 --- a/ui/src/ui/app-render.ts +++ b/ui/src/ui/app-render.ts @@ -184,9 +184,10 @@ export function renderApp(state: AppViewState) { const sessionsCount = state.sessionsResult?.count ?? null; const cronNext = state.cronStatus?.nextWakeAtMs ?? null; const chatDisabledReason = state.connected ? null : "Disconnected from gateway."; + const isChat = state.tab === "chat"; return html` -