diff --git a/web/src/components/Kartenspalten.jsx b/web/src/components/Kartenspalten.jsx new file mode 100644 index 0000000..87e9a91 --- /dev/null +++ b/web/src/components/Kartenspalten.jsx @@ -0,0 +1,47 @@ +import { Children, useEffect, useRef, useState } from "react"; + +/** + * Karten in feste Spalten verteilen. + * + * Warum nicht CSS: Ein Raster richtet die Karten zeilenweise aus – die zweite + * Reihe beginnt erst unter der höchsten Karte der ersten, was bei sehr + * unterschiedlich hohen Karten grosse Löcher hinterlässt. Der CSS-Spaltenfluss + * (`column-width`) füllt zwar schön auf, verteilt aber ALLE Karten neu, sobald + * eine ihre Höhe ändert. Beim Bearbeiten oder nach einem Abruf sprang deshalb + * die halbe Seite. + * + * Hier bekommt jede Karte fest ihre Spalte (reihum). Wächst eine, verschiebt + * sich nur, was in derselben Spalte darunter steht – alles andere bleibt liegen. + */ +export default function Kartenspalten({ children, min = 380, gap = "var(--sp-4)" }) { + const container = useRef(null); + const [spalten, setSpalten] = useState(1); + + useEffect(() => { + const el = container.current; + if (!el) return undefined; + const messen = () => { + const breite = el.getBoundingClientRect().width; + setSpalten(Math.max(1, Math.floor((breite + 24) / (min + 24)))); + }; + messen(); + const beobachter = new ResizeObserver(messen); + beobachter.observe(el); + return () => beobachter.disconnect(); + }, [min]); + + const karten = Children.toArray(children).filter(Boolean); + const verteilt = Array.from({ length: spalten }, () => []); + karten.forEach((karte, i) => verteilt[i % spalten].push(karte)); + + return ( +
+ {verteilt.map((spalte, i) => ( +
+ {spalte} +
+ ))} +
+ ); +} diff --git a/web/src/finance.css b/web/src/finance.css index f66f352..042e86b 100644 --- a/web/src/finance.css +++ b/web/src/finance.css @@ -284,22 +284,6 @@ min-width: 0; } -/* Einstellungen & Mein Konto: Karten fliessen spaltenweise. - Ein Raster richtet die Karten zeilenweise aus – die zweite Reihe beginnt erst - unter der HOECHSTEN Karte der ersten, was bei sehr unterschiedlich hohen - Karten ein grosses Loch hinterlaesst. Der Spaltenfluss stapelt stattdessen - weiter, sobald oben Platz frei wird. Die Spalten sind bewusst breit: vier - schmale Karten nebeneinander waren auf dem Notebook nicht mehr lesbar. */ -.settings-grid { - column-width: 380px; - column-gap: var(--sp-4); -} -.settings-grid > * { - break-inside: avoid; - margin-bottom: var(--sp-4); - width: 100%; -} - /* Nutzer-Chip in der Seitenleisten-Fußzeile ist ein Link auf „Mein Konto". */ a.sidebar-user { text-decoration: none; diff --git a/web/src/pages/Account.jsx b/web/src/pages/Account.jsx index 470eb27..13b9795 100644 --- a/web/src/pages/Account.jsx +++ b/web/src/pages/Account.jsx @@ -6,6 +6,7 @@ import { api, ApiError } from "../api"; import { useToast } from "../toast"; import Icon from "../components/Icon"; import PasswordInput from "../components/PasswordInput"; +import Kartenspalten from "../components/Kartenspalten"; import PasswordRules from "../components/PasswordRules"; import Geraetemarken from "./settings/Geraetemarken"; import { DEFAULT_POLICY, meetsPolicy } from "../passwordPolicy"; @@ -56,7 +57,7 @@ export default function Account() { return (

{t("account.title")}

-
+

{t("account.password")}

{fehler && ( @@ -101,7 +102,7 @@ export default function Account() {
-
+ ); } diff --git a/web/src/pages/Settings.jsx b/web/src/pages/Settings.jsx index e2a052c..257dc51 100644 --- a/web/src/pages/Settings.jsx +++ b/web/src/pages/Settings.jsx @@ -5,6 +5,7 @@ import { useAuth } from "../auth"; import { useToast } from "../toast"; import { api } from "../api"; import Icon from "../components/Icon"; +import Kartenspalten from "../components/Kartenspalten"; import PolicyCard from "./settings/PolicyCard"; import Postfaecher from "./settings/Postfaecher"; import RestoreCard from "./settings/RestoreCard"; @@ -76,7 +77,7 @@ export default function Settings() { )} -
+

{t("settings.general")}

+
); }