v0.9.10 — world map fills entire tab area, no scrollbar (#36) #39

Merged
kamilkrzywda merged 1 commits from world-map-full-area into master 2026-09-29 16:09:16 +02:00
4 changed files with 31 additions and 16 deletions
Showing only changes of commit c012b0fe56 - Show all commits
+1
View File
@@ -2,6 +2,7 @@
## v0.9.10 — 2026-09-29 12:57
- The WORLD MAP now fills the entire available area of its tab (#36): in wide mode (pinned viewport, #21) the OPERATIONS Tabs are a full-height flex column and the world-map panel flexes to the bottom of the pane — the chart SVG sizes to the measured container instead of the old fixed 380px height, so there is no internal scrollbar on this tab at any window size. The scene keeps its viewBox and scales with the pane on resizes (pan/zoom stay accurate; re-fitting after a resize is intentionally not done). Narrow mode keeps the fixed fallback height since the page scrolls naturally there.
- Follow-up to that layout change (CI run 382): the OPERATIONS Tabs root uses `min-height: 100%` instead of `height: 100%`. With a capped height, a tall tab's content overflowed the flex column and shrank items down to their automatic minimum — the tablist's `overflow-x: auto` zeroes that minimum per CSS spec, so the bar collapsed to ~0px with its buttons clipped out of hit-testing (every subsequent tab click failed with "div intercepts pointer events"); a capped box also released the sticky pin on deep scrolls. With min-height the box grows to fit tall tabs — the bar keeps its natural height and stays pinned across the whole scroll range, while WORLD MAP still fills the pane exactly.
- e2e: the #31 spec no longer relies on WORLD MAP's overflow to force scrolling — it now switches to SHIP SYSTEMS, whose six always-present stacked system cards deterministically overflow the shrunk 1280×560 pane (waiting for the HULL card first), and asserts the same pinned tab bar.
## v0.9.9 — 2026-09-29 11:21
+6
View File
@@ -160,6 +160,12 @@ body {
-moz-osx-font-smoothing: grayscale;
}
/* Radix Tabs hides inactive content via the `hidden` attribute, but inline display styles (the
#36 pane-fill flex chain on the WORLD MAP tab) outrank the UA stylesheet — restore semantics. */
[hidden] {
display: none !important;
}
#root {
min-height: 100vh;
}
+22 -15
View File
@@ -383,26 +383,28 @@ export function MissionControl() {
</PanelHeader>
<PanelContent style={{ padding: 0, flex: 1, minHeight: 0, overflowY: 'auto' }}>
{/* Flex column at full height so a tab can fill the pane (#36); other tabs stay
content-sized and overflow into this same scroll area as before. */}
{/* Flex column at least pane-tall so a tab can fill it (#36). min-height, not height:
tall tabs grow the box to their content, which keeps the sticky tab bar's containing
block spanning the whole scroll range (a capped height releases the pin on deep
scrolls) and means items never overflow the box, so nothing gets shrink-squashed. */}
<Tabs
value={activeTab ?? 'world-map'}
onValueChange={(v) => {
setActiveTab(v)
window.localStorage.setItem(ACTIVE_TAB_KEY, v) // #27 — keep the tab across refreshes
}}
style={{ display: 'flex', flexDirection: 'column', height: '100%' }}
style={{ display: 'flex', flexDirection: 'column', minHeight: '100%' }}
>
<TabsList
style={{
padding: '0 1rem',
background: 'var(--surface-raised)', // opaque — content scrolls under it (#31)
overflowX: 'auto',
position: 'sticky', // #31 — pinned in both modes: to the top of the OPERATIONS
top: 0, // scroll area (wide) and to the viewport when the body scrolls (narrow)
zIndex: 1,
}}
>
<TabsList
style={{
padding: '0 1rem',
background: 'var(--surface-raised)', // opaque — content scrolls under it (#31)
overflowX: 'auto',
position: 'sticky', // #31 — pinned in both modes: to the top of the OPERATIONS
top: 0, // scroll area (wide) and to the viewport when the body scrolls (narrow)
zIndex: 1,
}}
>
<TabsTrigger value="world-map">WORLD MAP</TabsTrigger>
<TabsTrigger value="local-system">LOCAL SYSTEM</TabsTrigger>
<TabsTrigger value="crew">CREW</TabsTrigger>
@@ -412,8 +414,13 @@ export function MissionControl() {
<TabsTrigger value="event-log">EVENT LOG</TabsTrigger>
</TabsList>
{/* WORLD MAP TAB — live data from /api/world; fills the whole pane (#36) */}
<TabsContent value="world-map" style={{ margin: 0, padding: '1rem', flex: 1, minHeight: 0 }}>
{/* WORLD MAP TAB — live data from /api/world; fills the whole pane (#36). Wide mode:
flex column so the panel can fill it with pure flex sizing (a min-height-only
container breaks percentage resolution, so no height:'100%' anywhere in this chain). */}
<TabsContent
value="world-map"
style={{ margin: 0, padding: '1rem', ...(!narrow ? { display: 'flex', flexDirection: 'column', flex: 1, minHeight: 0 } : {}) }}
>
<WorldMapPanel height={380} narrow={narrow} onJumped={refreshSystem} />
</TabsContent>
+2 -1
View File
@@ -265,8 +265,9 @@ export function WorldMapPanel({ height = 380, narrow = false, onJumped }: WorldM
)
}
// flex (not height:'100%'): the pane chain is sized by min-height, where percentages don't resolve
return (
<div style={{ display: 'flex', flexDirection: 'column', gap: '0.75rem', ...(filling ? { height: '100%' } : {}) }}>
<div style={{ display: 'flex', flexDirection: 'column', gap: '0.75rem', ...(filling ? { flex: 1, minHeight: 0 } : {}) }}>
{/* Wrapper + title bar; in wide mode the box flexes to fill the whole pane (#36). d3 owns everything inside it. */}
<div
style={{