Fit browser workspace within viewport below dynamic header bars
This commit is contained in:
@@ -51,3 +51,15 @@ Validation: build/typecheck and all 8 tests pass; integration tests now assert
|
|||||||
reported image's existence/read permission was verified from inside LTX without
|
reported image's existence/read permission was verified from inside LTX without
|
||||||
opening its content. A fresh synthetic upload was also checked from LTX and then
|
opening its content. A fresh synthetic upload was also checked from LTX and then
|
||||||
removed. Only the GUI was recreated; real image generation remains a user retry.
|
removed. Only the GUI was recreated; real image generation remains a user retry.
|
||||||
|
|
||||||
|
## Browser viewport layout — 2026-09-29
|
||||||
|
|
||||||
|
Replaced desktop view-level `100vh` sizing with parent-relative heights. The web
|
||||||
|
shell owns `100dvh`; headers/status banners do not shrink, and the workspace takes
|
||||||
|
only the remaining height with `min-height: 0`. Information panels are internally
|
||||||
|
scrollable and height-limited. Home and Project no longer add a second viewport.
|
||||||
|
|
||||||
|
Typecheck, build and all 8 existing tests pass. In an isolated browser fixture at
|
||||||
|
720 px viewport height, document/shell height remains 720 px and the Generate
|
||||||
|
button's bottom stays at 693 px, both with the information panel open and closed.
|
||||||
|
No production prompts or media were used for this check.
|
||||||
|
|||||||
+10
-8
@@ -19,13 +19,15 @@ function Workspace() {
|
|||||||
const { isLoaded, runtimePolicyLoaded } = useAppSettings()
|
const { isLoaded, runtimePolicyLoaded } = useAppSettings()
|
||||||
useGenerationRecoveryWatcher()
|
useGenerationRecoveryWatcher()
|
||||||
const ready = connected && isLoaded && runtimePolicyLoaded
|
const ready = connected && isLoaded && runtimePolicyLoaded
|
||||||
return <>
|
return <div className="flex flex-1 min-h-0 min-w-0 flex-col overflow-hidden" data-testid="workspace">
|
||||||
<div className={`px-4 py-2 text-sm ${ready ? 'bg-emerald-950 text-emerald-200' : 'bg-amber-950 text-amber-200'}`} role="status">
|
<div className={`shrink-0 px-4 py-2 text-sm ${ready ? 'bg-emerald-950 text-emerald-200' : 'bg-amber-950 text-amber-200'}`} role="status">
|
||||||
{ready ? 'LTX backend connected · generation runs on the remote server' : isLoading ? 'Checking LTX connection…' : 'LTX is not ready. Activate Video mode in Athena Deck. The connection is checked automatically.'}
|
{ready ? 'LTX backend connected · generation runs on the remote server' : isLoading ? 'Checking LTX connection…' : 'LTX is not ready. Activate Video mode in Athena Deck. The connection is checked automatically.'}
|
||||||
</div>
|
</div>
|
||||||
|
<div className="flex-1 min-h-0 min-w-0 overflow-hidden" data-testid="workspace-content">
|
||||||
{currentView === 'home' ? <Home /> : ready ? <Project /> : <div className="p-12"><p>Projects are retained. Generation becomes available when the LTX backend and its settings are reachable.</p><button className="mt-4 underline" onClick={goHome}>Back to projects</button></div>}
|
{currentView === 'home' ? <Home /> : ready ? <Project /> : <div className="p-12"><p>Projects are retained. Generation becomes available when the LTX backend and its settings are reachable.</p><button className="mt-4 underline" onClick={goHome}>Back to projects</button></div>}
|
||||||
|
</div>
|
||||||
<KeyboardShortcutsModal /><DevPanel />
|
<KeyboardShortcutsModal /><DevPanel />
|
||||||
</>
|
</div>
|
||||||
}
|
}
|
||||||
export default function App() {
|
export default function App() {
|
||||||
const [session, setSession] = useState<{ backendUrl: string } | null>(null)
|
const [session, setSession] = useState<{ backendUrl: string } | null>(null)
|
||||||
@@ -48,18 +50,18 @@ export default function App() {
|
|||||||
<button className="bg-blue-600 rounded px-4 py-2" type="submit">Sign in</button><p role="alert" className="mt-4 text-red-300">{error}</p>
|
<button className="bg-blue-600 rounded px-4 py-2" type="submit">Sign in</button><p role="alert" className="mt-4 text-red-300">{error}</p>
|
||||||
</form>
|
</form>
|
||||||
</main>
|
</main>
|
||||||
return <>
|
return <div className="h-dvh w-full min-h-0 flex flex-col overflow-hidden" data-testid="web-shell">
|
||||||
<header className="flex justify-between items-center px-4 py-2 bg-zinc-900 border-b border-zinc-700 text-sm">
|
<header className="shrink-0 flex justify-between items-center px-4 py-2 bg-zinc-900 border-b border-zinc-700 text-sm">
|
||||||
<strong>LTX DeskWEB · Preview</strong><div className="flex gap-4"><button onClick={() => setHelp(!help)}>Connection & information</button><button onClick={async () => { await webRequest('/web/logout', {}); location.reload() }}>Sign out</button></div>
|
<strong>LTX DeskWEB · Preview</strong><div className="flex gap-4"><button onClick={() => setHelp(!help)}>Connection & information</button><button onClick={async () => { await webRequest('/web/logout', {}); location.reload() }}>Sign out</button></div>
|
||||||
</header>
|
</header>
|
||||||
{help && <aside className="p-5 bg-zinc-900 border-b border-zinc-700 space-y-2">
|
{help && <aside className="shrink-0 max-h-[35dvh] overflow-y-auto p-5 bg-zinc-900 border-b border-zinc-700 space-y-2">
|
||||||
<p>Native LTX API via: <code>{session.backendUrl}</code>. Change the address and token in the container configuration.</p>
|
<p>Native LTX API via: <code>{session.backendUrl}</code>. Change the address and token in the container configuration.</p>
|
||||||
<p>Video mode is managed in Athena Deck. This web app never starts or installs a model.</p>
|
<p>Video mode is managed in Athena Deck. This web app never starts or installs a model.</p>
|
||||||
<p>Preview: projects are saved in this browser. Use “Back up projects” before clearing browser data. Timeline rendering, desktop folder dialogs and Hugging Face desktop login are not yet ported.</p>
|
<p>Preview: projects are saved in this browser. Use “Back up projects” before clearing browser data. Timeline rendering, desktop folder dialogs and Hugging Face desktop login are not yet ported.</p>
|
||||||
<WebProjectBackup />
|
<WebProjectBackup />
|
||||||
<button className="ml-4 underline" onClick={() => setHelp(false)}>Close</button>
|
<button className="ml-4 underline" onClick={() => setHelp(false)}>Close</button>
|
||||||
</aside>}
|
</aside>}
|
||||||
{message && <div className="p-3 bg-blue-950 flex justify-between" role="status">{message}<button onClick={() => setMessage('')}>Dismiss</button></div>}
|
{message && <div className="shrink-0 max-h-[15dvh] overflow-y-auto p-3 bg-blue-950 flex justify-between gap-4" role="status">{message}<button onClick={() => setMessage('')}>Dismiss</button></div>}
|
||||||
<AppSettingsProvider><ProjectProvider><ViewProvider><KeyboardShortcutsProvider><DevFlagsProvider><Workspace /></DevFlagsProvider></KeyboardShortcutsProvider></ViewProvider></ProjectProvider></AppSettingsProvider>
|
<AppSettingsProvider><ProjectProvider><ViewProvider><KeyboardShortcutsProvider><DevFlagsProvider><Workspace /></DevFlagsProvider></KeyboardShortcutsProvider></ViewProvider></ProjectProvider></AppSettingsProvider>
|
||||||
</>
|
</div>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -172,7 +172,7 @@ export function Home() {
|
|||||||
: 0
|
: 0
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="h-screen bg-background flex items-center justify-center">
|
<div className="h-full min-h-0 bg-background flex items-center justify-center">
|
||||||
<div className="w-[360px]">
|
<div className="w-[360px]">
|
||||||
<p className="text-center text-sm text-zinc-300 mb-4">
|
<p className="text-center text-sm text-zinc-300 mb-4">
|
||||||
Migrating project references...
|
Migrating project references...
|
||||||
@@ -189,7 +189,7 @@ export function Home() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="h-screen bg-background flex">
|
<div className="h-full min-h-0 bg-background flex">
|
||||||
{/* Sidebar */}
|
{/* Sidebar */}
|
||||||
<aside className="w-64 border-r border-zinc-800 flex flex-col">
|
<aside className="w-64 border-r border-zinc-800 flex flex-col">
|
||||||
<div className="p-6">
|
<div className="p-6">
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ export function Project() {
|
|||||||
|
|
||||||
if (!activeProject) {
|
if (!activeProject) {
|
||||||
return (
|
return (
|
||||||
<div className="h-screen bg-background flex items-center justify-center">
|
<div className="h-full min-h-0 bg-background flex items-center justify-center">
|
||||||
<div className="text-center">
|
<div className="text-center">
|
||||||
<p className="text-zinc-400 mb-4">Project not found</p>
|
<p className="text-zinc-400 mb-4">Project not found</p>
|
||||||
<Button onClick={goHome}>Go Home</Button>
|
<Button onClick={goHome}>Go Home</Button>
|
||||||
@@ -104,7 +104,7 @@ export function Project() {
|
|||||||
: 0
|
: 0
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="h-screen bg-background flex items-center justify-center">
|
<div className="h-full min-h-0 bg-background flex items-center justify-center">
|
||||||
<div className="w-[360px]">
|
<div className="w-[360px]">
|
||||||
<p className="text-center text-sm text-zinc-300 mb-4">
|
<p className="text-center text-sm text-zinc-300 mb-4">
|
||||||
Preparing your project assets...
|
Preparing your project assets...
|
||||||
@@ -121,9 +121,9 @@ export function Project() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="h-screen bg-background flex flex-col">
|
<div className="h-full min-h-0 bg-background flex flex-col">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<header className="flex items-center px-4 py-3 border-b border-zinc-800">
|
<header className="shrink-0 flex items-center px-4 py-3 border-b border-zinc-800">
|
||||||
<div className="flex-1 flex items-center gap-4">
|
<div className="flex-1 flex items-center gap-4">
|
||||||
{/* Back button and logo */}
|
{/* Back button and logo */}
|
||||||
<button
|
<button
|
||||||
@@ -161,7 +161,7 @@ export function Project() {
|
|||||||
<div className="flex-1" />
|
<div className="flex-1" />
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<main className="flex-1 overflow-hidden relative">
|
<main className="flex-1 min-h-0 overflow-hidden relative">
|
||||||
{currentTab === 'gen-space' ? (
|
{currentTab === 'gen-space' ? (
|
||||||
<GenSpace />
|
<GenSpace />
|
||||||
) : (
|
) : (
|
||||||
|
|||||||
Reference in New Issue
Block a user