diff --git a/web/src/components/DataTable.jsx b/web/src/components/DataTable.jsx index 0cca1c2..c154c28 100644 --- a/web/src/components/DataTable.jsx +++ b/web/src/components/DataTable.jsx @@ -11,7 +11,8 @@ import { Skeleton } from "./Skeleton"; * * Spalten-Def: { key, header, render(row)→JSX, filterText(row)? (aktiviert Filter), * sortValue(row)? (Sortierung), align:"num", grow:true (füllt Restbreite), - * fixed:true (kein Reorder/Resize), width, min }. + * fixed:true (kein Reorder/Resize), pin:"right" (klebt am rechten Rand + * und steht immer ganz hinten), width, min }. */ const DEFAULT_WIDTH = 150; @@ -96,7 +97,12 @@ export default function DataTable({ return () => ro.disconnect(); }, []); - const allOrdered = order.map((k) => colByKey[k]).filter(Boolean); + const gespeichert = order.map((k) => colByKey[k]).filter(Boolean); + // Angeheftete Spalten gehoeren ans Ende, egal was gespeichert ist. Sonst + // klebte etwa die Knopfspalte mitten im Scrollbereich und deckte ihre + // Nachbarn zu – und neu hinzugekommene Spalten landen ohnehin dahinter. + const allOrdered = [...gespeichert.filter((c) => !c.pin), + ...gespeichert.filter((c) => c.pin)]; const orderedCols = allOrdered.filter((c) => !hidden.has(c.key)); const chooserBtn = useRef(null); @@ -285,7 +291,7 @@ export default function DataTable({ {orderedCols.map((c) => ( onDragStart(e, c)} onDragOver={(e) => onDragOver(e, c)} @@ -301,7 +307,7 @@ export default function DataTable({ {filterShown && ( {orderedCols.map((c) => ( - + {(c.filterText || c.filterValues) ? ( onRowClick(row, e) : undefined} style={onRowClick ? { cursor: "pointer" } : undefined}> {orderedCols.map((c) => ( - {c.render(row)} + {c.render(row)} ))} ))} diff --git a/web/src/finance.css b/web/src/finance.css index eae5f87..b59f3de 100644 --- a/web/src/finance.css +++ b/web/src/finance.css @@ -774,6 +774,26 @@ tr.row-dup { cursor: pointer; } +/* Angeheftete Spalte: klebt am rechten Rand, wenn die Tabelle breiter ist als + das Fenster. Der Hintergrund muss deckend sein, sonst scrollen die anderen + Zellen sichtbar darunter durch. */ +.datatable th.dt-pin, +.datatable td.dt-pin { + position: sticky; + right: 0; + z-index: 2; + background: var(--surface); +} +.datatable tbody tr:hover td.dt-pin { background: var(--surface-2); } +/* Eine Kante nach links, damit man sieht, dass dahinter weitergeht. */ +.datatable th.dt-pin::before, +.datatable td.dt-pin::before { + content: ""; + position: absolute; + left: 0; top: 0; bottom: 0; + border-left: 1px solid var(--border); +} + /* DataTable-Zellen einzeilig halten, damit „…" greift (Excel-artig). */ .datatable td { white-space: nowrap; vertical-align: middle; } .datatable td .named-text { min-width: 0; } diff --git a/web/src/pages/Transactions.jsx b/web/src/pages/Transactions.jsx index 94cedb0..0e0eb95 100644 --- a/web/src/pages/Transactions.jsx +++ b/web/src/pages/Transactions.jsx @@ -624,7 +624,10 @@ export default function Transactions() { }, }, { - key: "actions", header: "", width: 118, fixed: true, + // Angeheftet: Seit Notiz und Tags dazugekommen sind, ist die Tabelle + // breiter als der Bildschirm – ohne das scrollten Bearbeiten und + // Loeschen einfach aus dem Bild. + key: "actions", header: "", width: 118, fixed: true, pin: "right", render: (tx) => (