fix: Einstellungskarten in feste Spalten statt Spaltenfluss
Beim Abrufen und beim Bearbeiten sprang die halbe Seite. Ursache war der CSS-Spaltenfluss: Aendert eine Karte ihre Hoehe, verteilt der Browser ALLE Karten neu auf die Spalten. Ich hatte das zweimal am Symptom kuriert (Formular in den Dialog verschoben), aber die naechste wachsende Karte brachte es zurueck. Jetzt bekommt jede Karte fest ihre Spalte. Waechst eine, verschiebt sich nur, was in derselben Spalte darunter steht. Die Spaltenzahl kommt aus der tatsaechlichen Containerbreite (ResizeObserver), nicht aus der Fensterbreite – in der schmalen Seitenleisten-Ansicht stimmte das sonst nicht. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -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 (
|
||||
<div ref={container} style={{ display: "flex", alignItems: "flex-start", gap }}>
|
||||
{verteilt.map((spalte, i) => (
|
||||
<div key={i} style={{ flex: "1 1 0", minWidth: 0, display: "flex",
|
||||
flexDirection: "column", gap }}>
|
||||
{spalte}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user