Karten-Darstellung der Tabellen entzerrt, Erklaerungen als Tooltip

Tabellen (Uebersicht, Einheiten, Kategorien):
Wird der Container schmal, stellen sich Tabellen auf Karten um. Dort trennte
"space-between" Beschriftung und Wert an die beiden Zeilenenden - der Wert stand
weit rechts und wirkte durch die unterschiedlichen Zeilenhoehen nicht auf einer
Linie. Jetzt zwei feste Spalten (Beschriftung, Wert direkt daneben) mit
Ausrichtung an der Schriftlinie. Zahlenspalten stehen in der Karte linksbuendig.

Artikelseite:
Die Erklaerungen unter "MHD-Angabe", "Gruppe" und "Kategorie" standen dauerhaft
im Formular und machten es lang. Sie haengen jetzt als Tooltip an der
Beschriftung; eine gepunktete Linie zeigt an, dass dort eine Erklaerung steht.
(Kategorie hatte denselben Text-Block - der Einheitlichkeit halber mit
umgestellt.)

Geprueft: "npm run build" laeuft durch.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Scarriffle
2026-07-23 07:59:52 +02:00
parent 32d49b47bd
commit e4e22c7822
3 changed files with 25 additions and 18 deletions

View File

@@ -315,15 +315,14 @@ export default function ProductForm() {
</select> </select>
</label> </label>
<label className="grow"> <label className="grow">
<span className="tip" title="Voreinstellung beim Einlagern z.B. Konserven tragen oft nur „09/2026“.">
MHD-Angabe MHD-Angabe
</span>
<select value={form.date_precision} onChange={(e) => set("date_precision", e.target.value)} <select value={form.date_precision} onChange={(e) => set("date_precision", e.target.value)}
disabled={readOnly}> disabled={readOnly}>
<option value="day">Tagesdatum</option> <option value="day">Tagesdatum</option>
<option value="month">nur Monat/Jahr</option> <option value="month">nur Monat/Jahr</option>
</select> </select>
<span className="muted small">
Voreinstellung beim Einlagern z.B. Konserven tragen oft nur 09/2026.
</span>
</label> </label>
</div> </div>
<div className="row"> <div className="row">
@@ -346,20 +345,20 @@ export default function ProductForm() {
</div> </div>
</label> </label>
<label className="grow"> <label className="grow">
<span className="tip" title="Zählt Bestände mehrerer Marken zusammen. Der EAN-Code dieses Artikels erscheint danach automatisch bei der Gruppe.">
Gruppe Gruppe
</span>
<select value={form.group_id} onChange={(e) => set("group_id", e.target.value)} disabled={readOnly}> <select value={form.group_id} onChange={(e) => set("group_id", e.target.value)} disabled={readOnly}>
<option value=""> keine </option> <option value=""> keine </option>
{groups.map((g) => <option key={g.id} value={g.id}>{g.name}</option>)} {groups.map((g) => <option key={g.id} value={g.id}>{g.name}</option>)}
</select> </select>
<span className="muted small">
Zählt Bestände mehrerer Marken zusammen. Der EAN-Code dieses Artikels
erscheint danach automatisch bei der Gruppe.
</span>
</label> </label>
</div> </div>
<div className="row"> <div className="row">
<label className="grow"> <label className="grow">
<span className="tip" title="Nur für den Überblick in der Artikelliste ohne Einfluss auf Bestände.">
Kategorie Kategorie
</span>
<select value={form.category_id} onChange={(e) => set("category_id", e.target.value)} <select value={form.category_id} onChange={(e) => set("category_id", e.target.value)}
disabled={readOnly}> disabled={readOnly}>
<option value=""> keine </option> <option value=""> keine </option>
@@ -367,9 +366,6 @@ export default function ProductForm() {
<option key={c.id} value={c.id}>{"— ".repeat(c.depth)}{c.name}</option> <option key={c.id} value={c.id}>{"— ".repeat(c.depth)}{c.name}</option>
))} ))}
</select> </select>
<span className="muted small">
Nur für den Überblick in der Artikelliste ohne Einfluss auf Bestände.
</span>
</label> </label>
<div className="grow" /> <div className="grow" />
</div> </div>

View File

@@ -121,7 +121,7 @@ export default function Products() {
{fmt(p.stock / (p.unit_factor || 1))} {p.unit_name || unitShort(p.base_unit)} {fmt(p.stock / (p.unit_factor || 1))} {p.unit_name || unitShort(p.base_unit)}
</td> </td>
<td data-label="Einheiten" className="num"> <td data-label="Einheiten" className="num">
<span className="cell-row" style={{ justifyContent: "flex-end" }}> <span className="cell-row">
<span> <span>
{fmt(p.stock / unitCount(p))} {fmt(p.stock / unitCount(p))}
{p.min_stock != null ? ` / ${fmt(p.min_stock / unitCount(p))}` : ""}{" "} {p.min_stock != null ? ` / ${fmt(p.min_stock / unitCount(p))}` : ""}{" "}

View File

@@ -266,6 +266,11 @@ td select { width: auto; min-width: 0; max-width: 100%; }
/* Zelle mit Eingabe plus Kennzeichen (z.B. "niedrig"): eine Zeile, damit das /* Zelle mit Eingabe plus Kennzeichen (z.B. "niedrig"): eine Zeile, damit das
Kennzeichen immer an derselben Stelle sitzt statt mal darunter zu rutschen. */ Kennzeichen immer an derselben Stelle sitzt statt mal darunter zu rutschen. */
.cell-row { display: flex; align-items: center; gap: 6px; } .cell-row { display: flex; align-items: center; gap: 6px; }
/* Beschriftung mit Erklaerung im Tooltip: die gepunktete Linie zeigt an, dass
dort etwas steht - so bleibt das Formular kurz, ohne Wissen zu verstecken. */
.tip { border-bottom: 1px dotted var(--border-strong); cursor: help; }
/* In Zahlenspalten sitzt der Inhalt rechts, passend zur Ausrichtung der Spalte. */
.table td.num .cell-row { justify-content: flex-end; }
.table tbody tr:last-child td { border-bottom: none; } .table tbody tr:last-child td { border-bottom: none; }
.table tbody tr:hover { background: var(--surface-2); } .table tbody tr:hover { background: var(--surface-2); }
.num { text-align: right; font-variant-numeric: tabular-nums; } .num { text-align: right; font-variant-numeric: tabular-nums; }
@@ -357,21 +362,27 @@ td select { width: auto; min-width: 0; max-width: 100%; }
padding: var(--sp-2) var(--sp-3); margin-bottom: var(--sp-3); padding: var(--sp-2) var(--sp-3); margin-bottom: var(--sp-3);
background: var(--surface); background: var(--surface);
} }
/* Zwei feste Spalten statt "space-between": Beschriftung links, Wert direkt
daneben. Vorher wurde der Wert an den rechten Rand geschoben, wodurch
Beschriftung und Wert weit auseinanderstanden und die Zeile unruhig wirkte. */
.table td { .table td {
border: none; padding: 5px 0; border: none; padding: 4px 0;
display: flex; align-items: center; justify-content: space-between; display: grid;
grid-template-columns: minmax(84px, 34%) minmax(0, 1fr);
align-items: baseline;
gap: var(--sp-3); text-align: left; gap: var(--sp-3); text-align: left;
} }
.table td::before { .table td::before {
content: attr(data-label); content: attr(data-label);
flex: 0 0 auto;
color: var(--muted); font-size: 0.7rem; font-weight: 600; color: var(--muted); font-size: 0.7rem; font-weight: 600;
text-transform: uppercase; letter-spacing: 0.05em; text-transform: uppercase; letter-spacing: 0.05em;
} }
/* Zellen ohne Beschriftung (Bild, Aktionen) brauchen keine Zeile fuer sich. */ /* Zellen ohne Beschriftung (Bild, Aktionen) brauchen keine Zeile fuer sich. */
.table td:not([data-label])::before { content: none; } .table td:not([data-label])::before { content: none; }
.table td:not([data-label]) { justify-content: flex-end; } .table td:not([data-label]) { display: flex; justify-content: flex-end; }
/* In der Karte stehen auch Zahlen linksbuendig am Wert-Rand. */
.table td.num { text-align: left; } .table td.num { text-align: left; }
.table td.num .cell-row { justify-content: flex-start; }
.table td input, .table td select { width: auto; max-width: 60%; margin-top: 0; } .table td input, .table td select { width: auto; max-width: 60%; margin-top: 0; }
.table .empty { text-align: center; } .table .empty { text-align: center; }
/* Reine Nachschlagelisten (Begriff -> Erklaerung) bleiben zweispaltig, /* Reine Nachschlagelisten (Begriff -> Erklaerung) bleiben zweispaltig,