From ab6b9f237276c0700e0b2e5ae87ed1daaa8d3b19 Mon Sep 17 00:00:00 2001 From: Sascha Wolf Date: Wed, 9 Sep 2026 15:30:35 +0200 Subject: [PATCH] fix(ui): Beschriftungszeile mit Diktatknopf richtet die Felder daneben aus Im Abschnitt "Verlauf" der Opportunity begann "Was wurde besprochen?" tiefer als "Letzte Interaktion" daneben. Ursache war die Beschriftungszeile: rechts steht ein Diktatknopf darin, links nur Text - die Zeile war damit 26,5 statt 16,5 Pixel hoch und schob das Eingabefeld nach unten. Der Knopf bekommt eine feste Hoehe (h-7, 28 px) statt sich aus Zeilenhoehe, Innenabstand und Rahmen zu ergeben; auf 26,5 px laesst sich keine Zeile ausrichten. Dazu labelRowClass mit min-h-7: damit ist die Zeile in beiden Spalten gleich hoch, mit Knopf oder ohne. Gemessen sind es jetzt 0,0 px Abweichung statt 8. Zweiter Fund derselben Stelle: die drei Beschriftungen im Dialog waren von Hand abgeschrieben statt labelClass zu nehmen. Damit fehlte ihnen die Klasse "field-label", die seit den Themes die Schrift der Feldbeschriftungen traegt - in "Pixel Art" blieben sie ohne Pixelschrift. Die Auszeichnung steht jetzt einmal in leadUi.tsx (labelTextClass) und wird nicht mehr kopiert; DictateTextarea benutzt sie ebenso. Co-Authored-By: Claude Opus 5 (1M context) --- docs/08-anleitung-entwickler.md | 3 ++- docs/09-quellcode.md | 2 +- src/components/leads/leadUi.tsx | 21 ++++++++++++++--- .../opportunities/OpportunityModal.tsx | 23 ++++++++++++------- src/components/ui/DictationField.tsx | 22 +++++++++++------- 5 files changed, 50 insertions(+), 21 deletions(-) diff --git a/docs/08-anleitung-entwickler.md b/docs/08-anleitung-entwickler.md index 11be383..b078946 100644 --- a/docs/08-anleitung-entwickler.md +++ b/docs/08-anleitung-entwickler.md @@ -227,7 +227,8 @@ Browser-Download. neues Theme stehen in [05 Frontend](05-frontend.md#themes-ohne-dark-varianten) - wichtigste davon: auf `brand-500`/`brand-600` steht weisse Schrift. * **Gemeinsame Klassen** statt kopierter Utility-Ketten: `inputClass`, - `labelClass` aus `components/leads/leadUi.tsx`, dazu `cardClass`, + `labelClass`, `labelTextClass`, `labelRowClass` aus + `components/leads/leadUi.tsx`, dazu `cardClass`, `primaryButtonClass` aus `components/scanner/scannerUi.tsx`. * **Meldungen als Toast**, Rückfragen über `ConfirmDialog` - nie `alert()` oder `confirm()`. Rot (`tone="danger"`, Standard) nur, wenn etwas verloren diff --git a/docs/09-quellcode.md b/docs/09-quellcode.md index f1802e8..81896b8 100644 --- a/docs/09-quellcode.md +++ b/docs/09-quellcode.md @@ -278,7 +278,7 @@ Warum genau diese Konstanten festgelegt sind, steht in | `components/acquisition/AcquisitionTrash.tsx` | Papierkorb der Akquise: zurückholen, endgültig löschen, leeren. Die Meldung nach dem Zurückholen nennt das Ziel (Eingang oder Archiv) - das Funddatum bleibt, also landet ein alter Fund im Archiv | | `components/acquisition/acquisitionUi.tsx` | `fieldClass` (abgesetzte Felder) und `OptionSelect` - zeigt einen Wert, der nicht mehr in der Liste steht, als solchen; `alwaysOffer` hält den eigenen Namen für *Von* immer wählbar. *Anbieter* nutzt es nicht: Freitext mit ``. Dazu `ConsultantSelect` (mehrere Berater: Auswahlfeld hängt an, Plaketten nehmen weg) und `ConsultantList` für die Anzeige in der Liste | | `components/settings/AcquisitionSettings.tsx` | Reiter *Einstellungen → Akquise*: die vier Auswahllisten pflegen | -| `components/leads/leadUi.tsx` | `inputClass`, `labelClass`, `KindBadge`, `Avatar`, Farben der Kontaktart | +| `components/leads/leadUi.tsx` | `inputClass`, `labelClass` (Beschriftung als eigene Zeile), `labelTextClass` + `labelRowClass` (Zeile mit Knopf rechts, z. B. Diktat - `min-h-7` haelt sie so hoch wie den Knopf, damit Felder in Nachbarspalten auf einer Linie beginnen), `KindBadge`, `Avatar`, Farben der Kontaktart | | `components/leads/mailPool.ts` | `findMailPoolMatch()`, `diffFields()`, `isConflict()`, `MAIL_POOL_FIELDS` - Dublettenabgleich des Vorbereichs | | `components/leads/MailPoolLeads.tsx` | Ansicht „Aus Mails": Goldmarkierung, Abweichungen, Übernehmen, Sammelübernahme | | `components/leads/MailPoolMergeDialog.tsx` | Feldauswahl beim Ergänzen eines vorhandenen Kontakts | diff --git a/src/components/leads/leadUi.tsx b/src/components/leads/leadUi.tsx index 83e7aec..6a8d476 100644 --- a/src/components/leads/leadUi.tsx +++ b/src/components/leads/leadUi.tsx @@ -32,10 +32,25 @@ export const inputClass = /* * `field-label` ist keine Utility-Klasse, sondern ein Anker: darueber gibt ein * Theme allen Feldbeschriftungen eine andere Schrift (siehe index.css). Ohne - * sie muesste jedes Label im Markup angefasst werden. + * sie muesste jedes Label im Markup angefasst werden - genau deshalb steht die + * Auszeichnung hier einmal und wird nicht abgeschrieben. */ -export const labelClass = - 'field-label mb-1.5 block text-[11px] font-extrabold uppercase tracking-wider text-ink-500'; +export const labelTextClass = + 'field-label text-[11px] font-extrabold uppercase tracking-wider text-ink-500'; + +/** Beschriftung als eigene Zeile - der Normalfall. */ +export const labelClass = `${labelTextClass} mb-1.5 block`; + +/** + * Beschriftungszeile mit Platz fuer einen Knopf rechts (Diktat). + * + * `min-h-7` ist der Punkt: der Diktatknopf ist 28 px hoch, eine nackte + * Beschriftung nur 16,5 px. Ohne die Mindesthoehe beginnt das Eingabefeld + * daneben ueber 10 px tiefer als das in der Nachbarspalte - im Abschnitt + * "Verlauf" der Opportunity war genau das zu sehen. Die Hoehe des Knopfes ist + * dafuer in DictationField.tsx auf denselben Wert festgelegt. + */ +export const labelRowClass = 'mb-1.5 flex min-h-7 items-center justify-between gap-3'; export const Avatar: React.FC<{ src?: string | null; diff --git a/src/components/opportunities/OpportunityModal.tsx b/src/components/opportunities/OpportunityModal.tsx index dddf249..01ebf10 100644 --- a/src/components/opportunities/OpportunityModal.tsx +++ b/src/components/opportunities/OpportunityModal.tsx @@ -2,7 +2,7 @@ import React, { useEffect, useMemo, useState } from 'react'; import { Modal } from '../ui/Modal'; import { LeadModal } from '../leads/LeadModal'; import { DictateTextarea, DictateButton, DictationHint } from '../ui/DictationField'; -import { Avatar, inputClass, labelClass } from '../leads/leadUi'; +import { Avatar, inputClass, labelClass, labelRowClass, labelTextClass } from '../leads/leadUi'; import { STAGE_COLORS, STAGE_HINTS, STAGE_LABELS } from './opportunityUi'; import { useToast } from '../Toast'; import { acquisitionOptionsApi, opportunitiesApi } from '../../lib/api'; @@ -590,9 +590,16 @@ export const OpportunityModal: React.FC = ({
- + {/* + Dieselbe Zeile wie beim Feld daneben (labelRowClass), obwohl hier + kein Knopf steht: sonst beginnt das Datumsfeld 8 px hoeher als + die Notiz rechts - der Diktatknopf macht die Nachbarzeile hoeher. + */} +
+ +
= ({ />
-
-