Refactor layout for improved responsiveness and scroll control

Updated the app layout to separate fixed and scrollable sections, enabling only the notes panel to scroll. Introduced a new CSS file for a cleaner structure and responsive behavior, ensuring a more consistent user experience across different screen sizes.
This commit is contained in:
2026-02-07 11:31:55 +01:00
parent 3d7d4c01f7
commit e035a99179
3 changed files with 130 additions and 57 deletions

View File

@@ -13,6 +13,8 @@ import LoginPage from "./components/LoginPage";
import SheetSection from "./components/SheetSection"; import SheetSection from "./components/SheetSection";
import ChipModal from "./components/ChipModal"; import ChipModal from "./components/ChipModal";
import "./AppLayout.css";
export default function App() { export default function App() {
useHpGlobalStyles(); useHpGlobalStyles();
@@ -263,36 +265,26 @@ export default function App() {
<div style={styles.bgMap} /> <div style={styles.bgMap} />
</div> </div>
{/* Layout: Links Game/Board, Rechts Notizen */} {/* Layout: Links Game/Board (fix), Rechts Notizen (scroll) */}
<div <div className="appRoot">
style={{ {/* LEFT: Game Area */}
...styles.shell, <section className="leftPane">
display: "grid",
gridTemplateColumns: "1fr clamp(420px, 28vw, 560px)",
gap: 14,
alignItems: "start",
}}
>
{/* LEFT: Game Area (Placeholders) */}
<div style={{ display: "grid", gap: 14 }}>
{/* Top bar placeholders (User + Settings) */} {/* Top bar placeholders (User + Settings) */}
<div style={{ display: "flex", gap: 10, justifyContent: "space-between" }}> <div className="topBarRow">
<PlaceholderCard title="User Dropdown" hint="(placeholder)" /> <PlaceholderCard title="User Dropdown" hint="(placeholder)" />
<PlaceholderCard title="Einstellungen" hint="(placeholder)" /> <PlaceholderCard title="Einstellungen" hint="(placeholder)" />
</div> </div>
{/* Center Board */} {/* Center Board */}
<div <div
className="boardWrap"
style={{ style={{
borderRadius: 22,
border: `1px solid ${stylesTokens.panelBorder}`, border: `1px solid ${stylesTokens.panelBorder}`,
background: stylesTokens.panelBg, background: stylesTokens.panelBg,
boxShadow: "0 20px 70px rgba(0,0,0,0.45)", boxShadow: "0 20px 70px rgba(0,0,0,0.45)",
backdropFilter: "blur(10px)", backdropFilter: "blur(10px)",
padding: 12, padding: 12,
position: "relative", position: "relative",
overflow: "hidden",
minHeight: 420,
}} }}
> >
<div <div
@@ -304,7 +296,7 @@ export default function App() {
pointerEvents: "none", pointerEvents: "none",
}} }}
/> />
<div style={{ position: "relative" }}> <div style={{ position: "relative", height: "100%", display: "flex", flexDirection: "column" }}>
<div style={{ fontWeight: 900, color: stylesTokens.textMain, fontSize: 14 }}> <div style={{ fontWeight: 900, color: stylesTokens.textMain, fontSize: 14 }}>
3D Board / Game View 3D Board / Game View
</div> </div>
@@ -315,72 +307,67 @@ export default function App() {
<div <div
style={{ style={{
marginTop: 10, marginTop: 10,
height: 360, flex: 1,
borderRadius: 18, borderRadius: 18,
border: `1px dashed ${stylesTokens.panelBorder}`, border: `1px dashed ${stylesTokens.panelBorder}`,
opacity: 0.85, opacity: 0.85,
minHeight: 0,
}} }}
/> />
</div> </div>
</div> </div>
{/* Bottom row placeholders */} {/* Bottom HUD */}
<div <div className="bottomHud">
style={{
display: "grid",
gridTemplateColumns: "1.1fr 0.8fr 1.1fr",
gap: 14,
}}
>
<PlaceholderCard title="Meine Geheimkarten" hint="(placeholder)" /> <PlaceholderCard title="Meine Geheimkarten" hint="(placeholder)" />
<PlaceholderCard title="Würfel + Hogwarts Points" hint="(placeholder)" /> <PlaceholderCard title="Würfel + Hogwarts Points" hint="(placeholder)" />
<PlaceholderCard title="Spielerkarte / Turn" hint="(placeholder)" /> <PlaceholderCard title="Spielerkarte / Turn" hint="(placeholder)" />
</div> </div>
{/* Extra: Hilfskarten / Deck */} {/* Extra: Hilfskarten / Deck */}
<div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 14 }}> <div className="extraRow">
<PlaceholderCard title="Dunkles Deck" hint="(placeholder)" /> <PlaceholderCard title="Dunkles Deck" hint="(placeholder)" />
<PlaceholderCard title="Hilfskarten" hint="(placeholder)" /> <PlaceholderCard title="Hilfskarten" hint="(placeholder)" />
</div> </div>
</div> </section>
{/* RIGHT: Notes Panel */} {/* RIGHT: Notes Panel */}
<div <aside
className="notesPane"
style={{ style={{
position: "sticky",
top: 14,
alignSelf: "start",
borderRadius: 22, borderRadius: 22,
border: `1px solid ${stylesTokens.panelBorder}`, border: `1px solid ${stylesTokens.panelBorder}`,
background: stylesTokens.panelBg, background: stylesTokens.panelBg,
boxShadow: "0 22px 90px rgba(0,0,0,0.55)", boxShadow: "0 22px 90px rgba(0,0,0,0.55)",
backdropFilter: "blur(10px)", backdropFilter: "blur(10px)",
padding: 12, padding: 12,
maxHeight: "calc(100vh - 28px)",
overflow: "auto",
}} }}
> >
<div style={{ fontWeight: 900, color: stylesTokens.textMain, fontSize: 14 }}> <div>
Notizen <div style={{ fontWeight: 900, color: stylesTokens.textMain, fontSize: 14 }}>
</div> Notizen
<div style={{ marginTop: 6, color: stylesTokens.textDim, fontSize: 12 }}> </div>
Nur die 3 Tabellen (Verdächtige / Gegenstände / Orte). <div style={{ marginTop: 6, color: stylesTokens.textDim, fontSize: 12 }}>
Nur die 3 Tabellen (Verdächtige / Gegenstände / Orte).
</div>
</div> </div>
<div style={{ marginTop: 12, display: "grid", gap: 14 }}> <div className="notesScroll">
{sections.map((sec) => ( <div style={{ marginTop: 12, display: "grid", gap: 14 }}>
<SheetSection {sections.map((sec) => (
key={sec.key} <SheetSection
title={sec.title} key={sec.key}
entries={sec.entries} title={sec.title}
pulseId={pulseId} entries={sec.entries}
onCycleStatus={cycleStatus} pulseId={pulseId}
onToggleTag={toggleTag} onCycleStatus={cycleStatus}
displayTag={displayTag} onToggleTag={toggleTag}
/> displayTag={displayTag}
))} />
))}
</div>
</div> </div>
</div> </aside>
</div> </div>
<ChipModal <ChipModal

View File

@@ -0,0 +1,89 @@
/* Desktop-only layout: left fixed (no scroll), right notes scroll only */
html, body, #root {
height: 100%;
}
body {
overflow: hidden; /* no page scroll, only notes panel scrolls */
}
.appRoot {
height: 100vh;
display: grid;
grid-template-columns: minmax(720px, 1fr) clamp(380px, 32vw, 520px);
gap: 14px;
padding: 14px;
box-sizing: border-box;
overflow: hidden;
}
.leftPane {
overflow: hidden;
min-width: 0;
display: grid;
grid-template-rows: 72px minmax(340px, 1fr) 160px 110px; /* top / board / hud / extra */
gap: 14px;
}
.topBarRow {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 14px;
min-width: 0;
}
.boardWrap {
min-height: 0;
overflow: hidden;
border-radius: 22px;
}
.bottomHud {
min-height: 0;
overflow: hidden;
display: grid;
grid-template-columns: 1.15fr 0.9fr 1.15fr;
gap: 14px;
}
.extraRow {
min-height: 0;
overflow: hidden;
display: grid;
grid-template-columns: 1fr 1fr;
gap: 14px;
}
.notesPane {
overflow: hidden;
min-width: 0;
display: grid;
grid-template-rows: auto 1fr;
}
.notesScroll {
min-height: 0;
overflow-y: auto;
overflow-x: hidden;
padding-right: 4px;
}
/* Make it shrink gracefully on smaller viewports */
@media (max-height: 860px) {
.leftPane {
grid-template-rows: 64px minmax(280px, 1fr) 140px 96px;
}
}
@media (max-width: 1280px) {
.appRoot {
grid-template-columns: minmax(620px, 1fr) clamp(340px, 34vw, 480px);
}
}
@media (max-width: 1120px) {
.appRoot {
grid-template-columns: 1fr clamp(320px, 36vw, 440px);
}
}

View File

@@ -2,8 +2,6 @@ import { useEffect } from "react";
import { stylesTokens } from "../theme"; import { stylesTokens } from "../theme";
import { applyTheme } from "../themes"; import { applyTheme } from "../themes";
export function useHpGlobalStyles() { export function useHpGlobalStyles() {
// Google Fonts // Google Fonts
useEffect(() => { useEffect(() => {
@@ -76,8 +74,7 @@ export function useHpGlobalStyles() {
color: ${stylesTokens.textMain}; color: ${stylesTokens.textMain};
} }
body { body {
overflow-x: hidden; overflow: hidden;
-webkit-overflow-scrolling: touch;
} }
#root { background: transparent; } #root { background: transparent; }
* { -webkit-tap-highlight-color: transparent; } * { -webkit-tap-highlight-color: transparent; }