Menue nicht mehr abschneiden, Zeile teilt sich nach dem Ausblenden neu auf

Zwei Fehler aus dem Sparring, beide an der Diagrammkarte.

**Das Optionsmenue war abgeschnitten.** Die Karte trug `overflow-hidden`, das
Menue klappt aus dem Kopf heraus, und der zweite Eintrag war nur zur Haelfte
zu sehen. Das Beschneiden ist entfallen; die runden Ecken brauchen es nicht,
weil Kopf und Koerper 16 px Innenabstand haben und nichts an der Kante anliegt.

**Nach dem Ausblenden blieb eine Luecke.** Die Zeilen waren ein Raster mit
festen Spalten. Blendet man eine Karte aus, gibt ChartCard `null` zurueck, die
Spalte bleibt aber stehen und die Nachbarkarte behaelt ihre zwei Drittel.

Neu ist `ChartReihe` in PageContainer.tsx: eine Flexzeile statt eines Rasters.
Die verbliebenen Karten verteilen den Platz unter sich neu, ohne dass jemand
mitzaehlen muesste, wie viele gerade sichtbar sind. Nachgemessen auf
/analytics: Der Zahlungsverlauf geht von 574 px auf 1164 px, sobald die
Nachbarkachel verschwindet.

Zehn Zeilen auf allen fuenf Analyse-Seiten umgestellt. `gleichHoch` haelt die
Unterscheidung aus dem letzten Sparring fest: gestreckt nur, wo die Karten
dieselbe Bauart haben.

Beim Umbau eine Regression gebaut und durch Nachmessen gefunden: Aus 885/443
wurde 664/664. `[&>*]:flex-1` erzeugt den Selektor `.zeile > *`, und der ist
spezifischer als eine Klasse am Kind, also verlor `xl:flex-[2]`. Jetzt
`xl:flex-[2]!`, mit dem Grund als Kommentar an der Komponente.

Nachgemessen nach der Aenderung, alle Zeilen: 885/443 wo zwei zu eins gewollt
ist, 389/389 und 409/409 und 595/595 wo gleiche Hoehe gewollt ist.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QPeZNwSeU7qG3RRCwaxEZX
This commit is contained in:
dejanandClaude Opus 5 committed 2026-08-31 23:09:39 +02:00
1 parent f5a3ccd634
commit bada5db344
7 files changed
+84 -31

No files matched your search

@@ -68,8 +68,14 @@ export function ChartCard({
if (!istSichtbar(id)) return null;
return (
/* Kein `overflow-hidden`: Das Optionsmenü klappt aus dem Kartenkopf heraus
und wurde an der Kartenkante abgeschnitten. Ein Menü, von dem man den
zweiten Eintrag nur zur Hälfte sieht, ist unbenutzbar.
Die Kante braucht das Beschneiden auch nicht: Kopf und Körper haben
16 px Innenabstand, es liegt nichts an den runden Ecken an. */
<section
className={`flex flex-col overflow-hidden rounded-lg border border-solid border-border-default bg-white shadow-sm ${className}`}
className={`flex flex-col rounded-lg border border-solid border-border-default bg-white shadow-sm ${className}`}
>
<header className="flex flex-none items-start justify-between gap-3 px-4 pb-3 pt-4">
<div className="flex min-w-0 flex-col">
@@ -56,3 +56,50 @@ export function Raster({
<div className={`${klassen[spalten]} ${obenBuendig ? "items-start" : ""}`}>{children}</div>
);
}
/**
* Eine Zeile aus Diagrammkarten.
*
* Bewusst Flexbox und kein Raster. Karten lassen sich ueber das Menü
* ausblenden; `ChartCard` gibt dann `null` zurueck. In einem Raster mit festen
* Spalten bleibt an dieser Stelle eine Luecke stehen, und die Nachbarkarte
* behaelt ihre zwei Drittel. Im Flexbereich verteilen die verbliebenen Karten
* den Platz unter sich neu, ohne dass jemand mitzaehlen muesste, wie viele
* gerade sichtbar sind.
*
* `[&>*]:flex-1` gibt jeder Karte denselben Anteil und ist zugleich das
* Sicherheitsnetz: Ohne eigene Breitenangabe schrumpfte ein Flexkind auf seine
* Inhaltsbreite, und ein Diagramm mit `ResponsiveContainer` faellt dann in sich
* zusammen.
*
* Eine breitere Karte bekommt `xl:flex-[2]!` mit. Das Ausrufezeichen ist noetig
* und kein Reflex: `[&>*]:flex-1` erzeugt den Selektor `.zeile > *`, und der
* ist spezifischer als eine Klasse am Kind. Ohne `!` gewinnt die Zeilenregel,
* und aus zwei Dritteln zu einem Drittel wird die Haelfte zur Haelfte. Genau
* das ist beim Umbau hier passiert und wurde durch Nachmessen gefunden.
*
* `min-w-0` ist Pflicht: Ohne das nimmt ein Flexkind seine Inhaltsbreite als
* Untergrenze, und ein Diagramm mit langer Achsenbeschriftung drueckt die
* Zeile ueber den Rand.
*/
export function ChartReihe({
/** Ab welcher Breite die Karten nebeneinander stehen. */
umbruch = "xl",
/**
* Gleiche Hoehe fuer alle Karten der Zeile. Nur richtig, wenn sie dieselbe
* Bauart haben (zwei Listen, zwei Diagramme). Sonst oben buendig,
* siehe docs/DESIGN-SYSTEM.md, Abschnitt "Kartenhoehen in einer Zeile".
*/
gleichHoch = false,
children,
}: {
umbruch?: "lg" | "xl";
gleichHoch?: boolean;
children: React.ReactNode;
}) {
const klassen =
umbruch === "lg"
? `flex flex-col gap-4 lg:flex-row ${gleichHoch ? "lg:items-stretch" : "lg:items-start"} [&>*]:min-w-0 lg:[&>*]:flex-1`
: `flex flex-col gap-4 xl:flex-row ${gleichHoch ? "xl:items-stretch" : "xl:items-start"} [&>*]:min-w-0 xl:[&>*]:flex-1`;
return <div className={klassen}>{children}</div>;
}
+6 -6
View File
@@ -1,7 +1,7 @@
"use client";
import React from "react";
import { PageContainer, Raster } from "../components/layout/PageContainer";
import { ChartReihe, PageContainer, Raster } from "../components/layout/PageContainer";
import { KPICard } from "../components/cards/KPICard";
import { ChartCard } from "../components/cards/ChartCard";
import { StatZeile } from "../components/cards/StatZeile";
@@ -142,12 +142,12 @@ export function AuftraegeSeite({ vm }: { vm: VMState<AuftraegeDaten> }) {
/>
</Raster>
<div className="grid grid-cols-1 items-start gap-4 xl:grid-cols-3">
<ChartReihe umbruch="xl">
<ChartCard
id="auftraege-eingang"
titel="Auftragseingang"
untertitel="Neu angelegte Vorgänge im Zeitverlauf"
className="xl:col-span-2"
className="xl:flex-[2]!"
>
<BalkenVertikal daten={d.eingang} formatWert={(w) => formatZahl(w)} hoehe={250} nurGanzzahlen />
<StatZeile
@@ -170,9 +170,9 @@ export function AuftraegeSeite({ vm }: { vm: VMState<AuftraegeDaten> }) {
>
<Trichter stufen={d.trichter} formatWert={(w) => formatZahl(w)} />
</ChartCard>
</div>
</ChartReihe>
<div className="grid grid-cols-1 items-start gap-4 lg:grid-cols-3">
<ChartReihe umbruch="lg">
<ChartCard
id="auftraege-status"
titel="Vorgänge nach Status"
@@ -224,7 +224,7 @@ export function AuftraegeSeite({ vm }: { vm: VMState<AuftraegeDaten> }) {
]}
/>
</ChartCard>
</div>
</ChartReihe>
<ChartCard
id="auftraege-liste"
+7 -7
View File
@@ -1,7 +1,7 @@
"use client";
import React from "react";
import { PageContainer, Raster } from "../components/layout/PageContainer";
import { ChartReihe, PageContainer, Raster } from "../components/layout/PageContainer";
import { KPICard } from "../components/cards/KPICard";
import { ChartCard } from "../components/cards/ChartCard";
import { StatZeile } from "../components/cards/StatZeile";
@@ -140,13 +140,13 @@ export function FinanzenSeite({ vm }: { vm: VMState<FinanzenDaten> }) {
/>
</Raster>
<div className="grid grid-cols-1 gap-4 xl:grid-cols-3">
<ChartReihe umbruch="xl" gleichHoch>
<ChartCard
id="finanzen-verlauf"
titel="Zahlungseingang im Zeitverlauf"
untertitel="Aktueller Zeitraum gegen Vorjahr"
hinweis="Grundlage sind bezahlte Ausgangsrechnungen zum Zahlungsdatum."
className="xl:col-span-2"
className="xl:flex-[2]!"
legende={
<ChartLegende
eintraege={[
@@ -189,11 +189,11 @@ export function FinanzenSeite({ vm }: { vm: VMState<FinanzenDaten> }) {
formatMitte={formatEuro}
/>
</ChartCard>
</div>
</ChartReihe>
<div className="grid grid-cols-1 items-start gap-4 lg:grid-cols-3">
<ChartReihe umbruch="lg">
<ChartCard
className="lg:col-span-2"
className="lg:flex-[2]!"
id="finanzen-alter"
titel="Offene Forderungen nach Alter"
untertitel={`Gesamt ${formatEuro(d.posten.gesamt)}`}
@@ -234,7 +234,7 @@ export function FinanzenSeite({ vm }: { vm: VMState<FinanzenDaten> }) {
/>
</ChartCard>
</div>
</ChartReihe>
<ChartCard
id="finanzen-offene-liste"
+8 -8
View File
@@ -1,7 +1,7 @@
"use client";
import React from "react";
import { PageContainer, Raster } from "../components/layout/PageContainer";
import { ChartReihe, PageContainer, Raster } from "../components/layout/PageContainer";
import { KPICard } from "../components/cards/KPICard";
import { ChartCard } from "../components/cards/ChartCard";
import { BalkenVertikal } from "../components/charts/BalkenVertikal";
@@ -133,12 +133,12 @@ export function KundenSeite({ vm }: { vm: VMState<KundenDaten> }) {
/>
</Raster>
<div className="grid grid-cols-1 items-start gap-4 xl:grid-cols-3">
<ChartReihe umbruch="xl">
<ChartCard
id="kunden-entwicklung"
titel="Neukunden im Zeitverlauf"
untertitel="Anlagedatum des Kundendatensatzes"
className="xl:col-span-2"
className="xl:flex-[2]!"
>
<BalkenVertikal daten={d.entwicklung} formatWert={(w) => formatZahl(w)} hoehe={250} nurGanzzahlen />
</ChartCard>
@@ -156,9 +156,9 @@ export function KundenSeite({ vm }: { vm: VMState<KundenDaten> }) {
mitteLabel="Kunden"
/>
</ChartCard>
</div>
</ChartReihe>
<div className="grid grid-cols-1 items-start gap-4 lg:grid-cols-2">
<ChartReihe umbruch="lg">
<ChartCard id="kunden-typ" titel="Kundenstruktur" untertitel="Privat, Gewerbe, Verwaltung">
<Donut
daten={d.nachTyp}
@@ -176,9 +176,9 @@ export function KundenSeite({ vm }: { vm: VMState<KundenDaten> }) {
>
<BalkenHorizontal daten={d.topKunden} formatWert={formatEuroKompakt} />
</ChartCard>
</div>
</ChartReihe>
<div className="grid grid-cols-1 items-start gap-4 xl:grid-cols-2">
<ChartReihe umbruch="xl">
<ChartCard
id="kunden-inaktiv"
titel={`Reaktivierungspotenzial (${d.inaktive.length})`}
@@ -206,7 +206,7 @@ export function KundenSeite({ vm }: { vm: VMState<KundenDaten> }) {
leerText="Keine Auffälligkeiten"
/>
</ChartCard>
</div>
</ChartReihe>
</PageContainer>
</>
+3 -3
View File
@@ -1,7 +1,7 @@
"use client";
import React from "react";
import { PageContainer, Raster } from "../components/layout/PageContainer";
import { ChartReihe, PageContainer, Raster } from "../components/layout/PageContainer";
import { KPICard } from "../components/cards/KPICard";
import { ChartCard } from "../components/cards/ChartCard";
import { AuslastungsBalken } from "../components/charts/AuslastungsBalken";
@@ -159,7 +159,7 @@ export function TeamSeite({ vm }: { vm: VMState<TeamDaten> }) {
/>
</ChartCard>
<div className="grid grid-cols-1 items-start gap-4 lg:grid-cols-2">
<ChartReihe umbruch="lg">
<ChartCard
id="team-abschluesse"
titel="Abschlüsse je Mitarbeiter"
@@ -190,7 +190,7 @@ export function TeamSeite({ vm }: { vm: VMState<TeamDaten> }) {
mitteLabel="Stunden"
/>
</ChartCard>
</div>
</ChartReihe>
<ChartCard
id="team-tabelle"
+6 -6
View File
@@ -1,7 +1,7 @@
"use client";
import React from "react";
import { PageContainer, Raster } from "../components/layout/PageContainer";
import { ChartReihe, PageContainer, Raster } from "../components/layout/PageContainer";
import { KPICard } from "../components/cards/KPICard";
import { ChartCard } from "../components/cards/ChartCard";
import { AlertList } from "../components/cards/AlertList";
@@ -131,13 +131,13 @@ export function UebersichtSeite({ vm }: { vm: VMState<UebersichtDaten> }) {
<AlertList eintraege={d.alerts} spalten={2} />
</ChartCard>
<div className="grid grid-cols-1 items-start gap-4 xl:grid-cols-3">
<ChartReihe umbruch="xl">
<ChartCard
id="uebersicht-umsatzverlauf"
titel="Zahlungseingang im Zeitverlauf"
untertitel="Aktueller Zeitraum gegen den Vorjahreszeitraum"
hinweis="Gezählt wird der Tag des Zahlungseingangs, nicht das Rechnungsdatum. Dadurch entspricht die Kurve dem tatsächlichen Geldfluss."
className="xl:col-span-2"
className="xl:flex-[2]!"
legende={
<ChartLegende
eintraege={[
@@ -179,9 +179,9 @@ export function UebersichtSeite({ vm }: { vm: VMState<UebersichtDaten> }) {
einfarbig={false}
/>
</ChartCard>
</div>
</ChartReihe>
<div className="grid grid-cols-1 gap-4 lg:grid-cols-2">
<ChartReihe umbruch="lg" gleichHoch>
<ChartCard
id="uebersicht-trichter"
titel="Vertriebstrichter"
@@ -206,7 +206,7 @@ export function UebersichtSeite({ vm }: { vm: VMState<UebersichtDaten> }) {
/>
</ChartCard>
</div>
</ChartReihe>
<ChartCard
id="uebersicht-ueberfaellig"