Eingabefelder: Grundlagen
Zurück: Demo-Übersicht
1. Übersicht und Zweck
Status: [Live] — gemeinsamer Vertrag, den alle acht Kategorien-Seiten voraussetzen, statt ihn einzeln zu wiederholen.
Definiert den gemeinsamen $opts-Kontrakt, das erzeugte Markup und die
Optik, die jede der acht Eingabefeld-Kategorien
(Button, Calendar,
CheckBox, ComboBox, DateTime, Dropdown, ListEditor, ProgressBar) teilen
soll.
2. Voraussetzungen
Keine über den bestehenden Helper- API-Kontrakt hinaus — dieselbe Escaping-/Markup-Konvention.
3. Konzepte
Ein Vokabular für „Feld„ in der ganzen Bibliothek: angelehnt an das
bereits [Live] Zeilen-Schema von
propertyGrid() (gleiche
Namen für required/state/stateText).
Native Formularelemente, keine Custom-Engine: das Control ist immer
ein natives HTML-Formularelement mit dem passenden type/input mode
— kein Feld dieser Kategorie-Familie baut eine eigene Tastatur-/Fokus-Engine
nach (gleicher Grundsatz wie bei dataGrid(), s.
layout →
Layout-Mechanik). JavaScript darf Verhalten ergänzen (Datepicker-
Popup, Such-Filter im Dropdown, …), nie die native Semantik ersetzen — das
ist der No-JS-Fallback jeder Kategorie.
4. Erste Schritte
echo $widgets->checkbox([ 'name' => 'aktiv', 'label' => 'Zugriff aktiv', 'value' => true, ]);
5. Verwendung
| Einsatz | Muster |
|---|---|
| Einzelnes Feld außerhalb eines Rasters (Suchleiste, Toolbar-Filter) | eine Kategorie-Methode dieser Gruppe |
| Mehrere Felder als Formular oder Eigenschaften-Inspektor | propertyGrid() mit dem Kategorie-Markup als controlHtml je Zeile — mit 'bare' => true liefert die Kategorie-Methode nur das Control, nicht den .wk-field-Wrapper (Label/Hint/State übernimmt dann die Raster-Zeile) |
6. API-Referenz: Gemeinsamer $opts-Kontrakt
| Schlüssel | Typ | Bedeutung |
|---|---|---|
name | string | Formularfeldname (Pflicht — jedes Feld ist ein natives Formularelement) |
value | mixed | Startwert, typspezifisch je Kategorie |
label | string | sichtbare Beschriftung (hsc()-escaped) |
hint | string | optionaler Hilfetext unter dem Control |
required | bool | rotes Sternchen am Label; setzt zusätzlich das native required-Attribut am Control (anders als bei propertyGrid(), wo der Aufrufer das Attribut selbst setzt — hier gibt es kein separates controlHtml, das Feld rendert das Control selbst) |
disabled | bool | natives disabled-Attribut |
state | 'error'|'warning' | 3px-Akzentbalken, dieselbe Optik wie propertyGrid()-Zeilen |
stateText | string | Meldungstext unter dem Control bei aktivem state |
ariaLabel | string | Fallback-Beschriftung, wenn label leer bleibt (Icon-only-Varianten) |
id | string | explizite Control-ID; ohne Angabe deterministisch aus name abgeleitet (wkf-<name> — stabil über Renders, für label[for]/aria-describedby) |
bare | bool | liefert nur das Control ohne .wk-field-Wrapper — für die Einbettung als controlHtml in propertyGrid()-Zeilen |
stackBelow | int (px) | Label kippt unterhalb dieser Container-Breite über das Control (scripts/adaptive.js) — Adaptivity |
7. Parameter, Optionen und Zustände: Erzeugtes Markup
<div class="wk-field" data-wk-field="<name>"> →
<label class="wk-field__label" for="<id>"> (+
<span class="wk-field__required"> bei required) → das
kategorie-spezifische Control (native <input>/<select>/
<textarea> — kein Custom-Element ohne natives Äquivalent) →
optional <p class="wk-field__hint"> → optional
<p class="wk-field__statetext"> bei aktivem state.
Optik: alle Felder folgen der Fluent-Formularmetrik
(_admin-forms.css, siehe
FluentUI: Admin-Bereich (vertieft)): Label klein/halbfett/
gedämpft, Control-Höhe/Radius/Fokusring identisch zu den bestehenden
Admin-Formularen, Fehlerzustand über --wk-error, Warnzustand über
--wk-warning (Contract-Tokens, dieselben wie bei propertyGrid()-
Zeilen).
8. Vollständige Beispiele
echo $widgets->dateTime([ 'name' => 'geplant_ab', 'label' => 'Geplant ab', 'required' => true, 'hint' => 'Format: TT.MM.JJJJ HH:MM', ]);
9. Einschränkungen und Randfälle
- Der gemeinsame Kontrakt gilt als Mindestvertrag; jede Kategorie-Seite kann zusätzliche, kategorie-spezifische Schlüssel ergänzen.
10. Accessibility und Kompatibilität
Vollständiger Überblick: Accessibility (konsolidiert, nicht hier dupliziert).
11. Troubleshooting
Entfällt — kein über den gemeinsamen Kontrakt hinausgehender, beobachtbarer Fehlerfall.
12. Verwandte Themen
- Demo-Übersicht — alle Kategorien
- FluentUI: Vertical Grid (Property Grid) — Demo-Übersicht — Zeilen-Schema, aus dem dieser Vertrag übernommen ist
- Eingabefelder: Accessibility — ARIA-/Tastatur-Gesamtüberblick
Gemeinsame Steuerelement-Attribute
Diese Schlüssel wirken in jedem Feld der Familie, weil sie im gemeinsamen Attributbauer sitzen:
| Schlüssel | Typ | Wirkung |
|---|---|---|
readonly | bool | readonly + aria-readonly=„true“ |
placeholder | string | placeholder |
maxLength | int | maxlength (nur bei Werten > 0) |
pattern | string | pattern |
autocomplete | string | autocomplete |
disabled und readonly sind nicht austauschbar. Ein disabled-Feld wird vom Browser
nicht mitgesendet; ein readonly-Feld schon. Ein Formular, das einen abgeleiteten Wert nur
anzeigen und unverändert zurückschreiben will, verliert ihn mit disabled stillschweigend — der
Handler sieht ihn als geleert.
Beide sind deshalb sichtbar unterschiedlich gestaltet: disabled gedimmt und erkennbar außer Betrieb, readonly in voller Schriftstärke auf getöntem Grund mit gestricheltem Rahmen. Der Wert bleibt lesbar und markierbar; nur der Rahmen sagt „nicht deins zu ändern“.
Wie die Zustände gezeichnet werden
Die Zustandsfarben werden aus den Feldtokens abgeleitet, nicht aus der Grundpalette benannt.
Der Grund ist ein Betriebsfall und keine Vorliebe: eine Fläche darf --wk-field-bg,
--wk-field-fg und --wk-field-border für alles in ihr neu belegen — die
Anmeldekarte tut das und verlegt die Felder in ihre eigene dunkle Palette. Ein Zustand, der eine
helle Fläche der Grundpalette benennt, ergäbe dort ein leuchtendes Rechteck.
| Zustand | Gezeichnet durch | Warum so |
|---|---|---|
hover | aus den Feldtokens gemischter Grund, Anteil --wk-state-hover-tint | die Mischung ist selbstrichtend: im hellen Schema ist die Schrift dunkel und die Fläche wandert nach dunkel, im dunklen Schema umgekehrt. Eine Deklaration deckt damit alle drei Schemata ab, statt je Schema wiederholt zu werden. |
active | dieselbe Mischung, Anteil --wk-state-press-tint | rund doppelt so stark wie hover. Die beiden werden unmittelbar nacheinander gelesen — der Zeiger steht immer über einem Feld, während es gedrückt wird —, der Abstand muss also gegen hover bestehen, nicht gegen die Ruhelage. |
disabled | opacity | dämpft, ohne eine Farbe zu kennen, und folgt damit jeder Palette, jedem Schema und jeder Haut von selbst. Braucht keine Farbfunktion, kann also in keinem Browser stillschweigend ausfallen. |
readonly | gestrichelter Rahmen, dazu ein aus den Feldtokens gemischter Tönungsgrund | opacity scheidet aus, weil der Wert voll lesbar bleiben muss. Der Rahmen trägt die Aussage und kostet ebenfalls keine Farbe; fällt die Mischung aus, bleibt er stehen. |
Am kompilierten Bündel gemessen (5. August 2026, helles Schema): Ruhelage #fdfcfa, hover
#eeedeb, active #deddda. Der Schriftkontrast bleibt über alle drei Zustände zwischen
13,78:1 und 10,37:1, also durchgehend weit über den 4,5:1 aus WCAG 2.2, Erfolgskriterium 1.4.3.
Bis zum 5. August 2026 hatte diese Familie überhaupt keine hover-Regel — 58 Regeln beschrieben sie, keine davon sagte, wie ein Feld unter dem Mauszeiger aussieht. In einem Formular mit mehreren untereinanderliegenden Feldern gab es damit keine Rückmeldung darüber, welches Feld ein Klick treffen würde.
Genau das ist hier passiert und am 4. August 2026 auf der Anmeldeseite in beiden Schemata nachgemessen worden: Grund, Schrift, Kantenfarbe und Kantenart eines gesperrten und eines nur lesbaren Feldes waren zeichengleich mit einem bedienbaren. Übrig blieb allein der Mauszeiger, den weder Tastatur- noch Tippnutzer je sehen — und readonly hatte nicht einmal den. Die Regeln existierten, waren richtig und waren beschrieben; sie haben nur verloren.
Es erzeugt keinen Fehler. Die Seite rendert, das Bündel baut, das Feld funktioniert — es sagt bloß nicht mehr, in welchem Zustand es ist, und das liest sich wie eine Gestaltungsentscheidung. Geprüft wird es deshalb mechanisch: keine Zustandsregel der Feldfamilie darf schwächer sein als die Ruhelage-Regel, die sie überschreiben muss.
aria-readonly wird ausdrücklich mitgesetzt: das native Attribut wird von Hilfsmitteln nur bei
einem Teil der Steuerelementarten ausgewertet — bei select und checkbox bewirkt es nichts.
pattern ist reine Bequemlichkeit im Browser. Verbindlich prüft der Server; ein pattern
ist trivial zu umgehen und darf nie die einzige Prüfung eines Wertes sein, der in die Ablage geht.
Ein placeholder ist ein Hinweis auf das Format, kein Ersatz für die Beschriftung — er
verschwindet, sobald jemand tippt. Wer eine dauerhafte Erläuterung braucht, nimmt hint.