ui: Station Control masonry layout — pack cards into balanced columns

flex-wrap with fixed-width cards started each new row below the TALLEST card of
the previous row, leaving big gaps under short panels (e.g. the amplifier alone
on a second line). Switch the dashboard to balanced CSS columns (column-width
430px, break-inside-avoid): cards flow top-to-bottom and pack tightly by height.
"Auto" fits as many columns as the window allows; 1-4 cap the column count via
the container max-width. Grip-drag reorder unchanged. Changelog 0.21.1.
This commit is contained in:
2026-07-25 01:49:18 +02:00
parent 3f15608c59
commit 88202efddb
2 changed files with 12 additions and 9 deletions
+4 -2
View File
@@ -4,11 +4,13 @@
"date": "2026-07-24",
"en": [
"Fixed the colour theme sometimes reverting to the default when reopening OpsLog — it's now restored reliably.",
"ADIF export field picker: the per-group All / None buttons work again."
"ADIF export field picker: the per-group All / None buttons work again.",
"Station Control: cards now pack tightly into balanced columns instead of leaving big gaps under shorter panels — a cleaner, more even dashboard."
],
"fr": [
"Correction du thème qui revenait parfois au défaut à la réouverture d'OpsLog — il est maintenant restauré de façon fiable.",
"Sélecteur de champs à l'export ADIF : les boutons Tout / Aucun par groupe refonctionnent."
"Sélecteur de champs à l'export ADIF : les boutons Tout / Aucun par groupe refonctionnent.",
"Station Control : les cartes se rangent en colonnes équilibrées et se tassent au lieu de laisser de gros trous sous les panneaux plus courts — tableau de bord plus propre et régulier."
]
},
{
@@ -442,14 +442,15 @@ export function StationControlPanel({ centerLat, centerLon, bearing }: RotatorPr
</div>
)}
{/* Dashboard of FIXED-WIDTH cards that wrap. "Auto" fills the window; a fixed
column count caps the container width so cards wrap onto more lines. Each
card has a grip handle (left rail) as the drag initiator (the card body is
full of buttons, so dragging the whole card was unreliable). */}
<div className="flex flex-wrap gap-4 items-start"
style={cols !== 'auto' ? { maxWidth: `${Number(cols) * 446}px` } : undefined}>
{/* Masonry dashboard: fixed-width cards flow into balanced CSS columns so
they pack tightly by height (no ragged gaps under short cards). "Auto"
fits as many ~430px columns as the window allows; a fixed count caps the
container width to that many columns. Each card has a grip handle (left
rail) as the drag initiator (the body is full of buttons). */}
<div style={{ columnWidth: '430px', columnGap: '1rem', columnFill: 'balance',
...(cols !== 'auto' ? { maxWidth: `${Number(cols) * 446}px` } : {}) }}>
{ordered.map((w) => (
<div key={w.id} className="flex items-stretch w-[430px]"
<div key={w.id} className="flex items-stretch break-inside-avoid mb-4"
onDragOver={(e) => { if (dragId.current) { e.preventDefault(); e.dataTransfer.dropEffect = 'move'; } }}
onDrop={(e) => { if (dragId.current) { e.preventDefault(); onDrop(w.id); } }}>
<div draggable