fix(quick-260921-bi2): a11y - Beschriftungen an Felder binden (22 Fundstellen)

noLabelWithoutControl (22) auf 0: jede Beschriftung ueber htmlFor/id an ihr
Feld gebunden, in Formularen mit wiederholten Zeilen ueber praefixierte,
seitenweit eindeutige Kennungen (z.B. ldap-*, user-*, tenant-*).

Sonderfall calendar-source-form.tsx: die Farbauswahl beschriftet eine ganze
Gruppe von Farb-Schaltflaechen, kein einzelnes Feld. Dafuer fieldset/legend
statt htmlFor/id (Rand/Abstand zurueckgesetzt, damit sich am Erscheinungsbild
nichts aendert) -- eine Umwandlung in <span> haette die Assoziation entfernt
statt sie herzustellen, darum nicht gewaehlt.

Damit steht der gesamte Lint-Rueckstand bei 465 (386 echt, 79 Test),
Fehlerstufe 0 -- Zielwert dieses Vorgangs erreicht. Die fuenf zurueck-
gestellten Regeln (noNoninteractiveElementInteractions, useKeyWithClick-
Events, noStaticElementInteractions, useAriaPropsSupportedByRole,
noAutofocus) stehen unveraendert bei 11/5/5/5/4.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TPPB4ApQxzSU1rwV2Ffj9J
This commit is contained in:
2026-09-21 09:38:14 +02:00
parent 21c85a8b88
commit c79bafa179
7 changed files with 50 additions and 25 deletions
+20 -10
View File
@@ -557,10 +557,11 @@ export default function AdminLdapPage() {
<form onSubmit={handleSave} className="space-y-4">
<div className="grid gap-4 md:grid-cols-2">
<div className="space-y-2">
<label className="text-sm font-medium text-foreground">
<label htmlFor="ldap-server-url" className="text-sm font-medium text-foreground">
{t('serverUrl')}
</label>
<input
id="ldap-server-url"
type="text"
value={formData.serverUrl}
onChange={(e) => setFormData({ ...formData, serverUrl: e.target.value })}
@@ -570,10 +571,11 @@ export default function AdminLdapPage() {
/>
</div>
<div className="space-y-2">
<label className="text-sm font-medium text-foreground">
<label htmlFor="ldap-base-dn" className="text-sm font-medium text-foreground">
{t('baseDn')}
</label>
<textarea
id="ldap-base-dn"
value={formData.baseDn}
onChange={(e) => setFormData({ ...formData, baseDn: e.target.value })}
placeholder={'dc=example,dc=com\nou=extern,dc=example,dc=com'}
@@ -584,10 +586,11 @@ export default function AdminLdapPage() {
<p className="text-xs text-muted-foreground">{t('baseDnHint')}</p>
</div>
<div className="space-y-2">
<label className="text-sm font-medium text-foreground">
<label htmlFor="ldap-bind-dn" className="text-sm font-medium text-foreground">
{t('bindDn')}
</label>
<input
id="ldap-bind-dn"
type="text"
value={formData.bindDn}
onChange={(e) => setFormData({ ...formData, bindDn: e.target.value })}
@@ -596,10 +599,11 @@ export default function AdminLdapPage() {
/>
</div>
<div className="space-y-2">
<label className="text-sm font-medium text-foreground">
<label htmlFor="ldap-bind-password" className="text-sm font-medium text-foreground">
{t('bindPassword')}
</label>
<input
id="ldap-bind-password"
type="password"
value={formData.bindPassword}
onChange={(e) => setFormData({ ...formData, bindPassword: e.target.value })}
@@ -609,10 +613,11 @@ export default function AdminLdapPage() {
</div>
</div>
<div className="space-y-2">
<label className="text-sm font-medium text-foreground">
<label htmlFor="ldap-search-filter" className="text-sm font-medium text-foreground">
{t('searchFilter')}
</label>
<input
id="ldap-search-filter"
type="text"
value={formData.searchFilter}
onChange={(e) => setFormData({ ...formData, searchFilter: e.target.value })}
@@ -753,10 +758,11 @@ export default function AdminLdapPage() {
{showMappingForm && (
<form onSubmit={handleAddMapping} className="mt-4 flex items-end gap-3">
<div className="space-y-1">
<label className="text-xs font-medium text-muted-foreground">
<label htmlFor="ldap-mapping-ldap-field" className="text-xs font-medium text-muted-foreground">
{t('fieldMapping.ldapField')}
</label>
<input
id="ldap-mapping-ldap-field"
type="text"
value={newMapping.ldapField}
onChange={(e) => setNewMapping({ ...newMapping, ldapField: e.target.value })}
@@ -765,10 +771,11 @@ export default function AdminLdapPage() {
/>
</div>
<div className="space-y-1">
<label className="text-xs font-medium text-muted-foreground">
<label htmlFor="ldap-mapping-tessera-field" className="text-xs font-medium text-muted-foreground">
{t('fieldMapping.tesseraField')}
</label>
<input
id="ldap-mapping-tessera-field"
type="text"
value={newMapping.tesseraField}
onChange={(e) => setNewMapping({ ...newMapping, tesseraField: e.target.value })}
@@ -860,10 +867,11 @@ export default function AdminLdapPage() {
<div className="flex items-end gap-3 mb-4">
<div className="flex-1 space-y-1">
<label className="text-xs font-medium text-muted-foreground">
<label htmlFor="ldap-group-manual-dn" className="text-xs font-medium text-muted-foreground">
{t('groupFilter.manualDn')}
</label>
<input
id="ldap-group-manual-dn"
type="text"
value={manualDn}
onChange={(e) => setManualDn(e.target.value)}
@@ -1168,10 +1176,11 @@ export default function AdminLdapPage() {
<div className="flex items-end gap-3 mb-4">
<div className="flex-1 space-y-1">
<label className="text-xs font-medium text-muted-foreground">
<label htmlFor="ldap-exclude-username" className="text-xs font-medium text-muted-foreground">
{t('userExclude.username')}
</label>
<input
id="ldap-exclude-username"
type="text"
value={newExcludeUser}
onChange={(e) => setNewExcludeUser(e.target.value)}
@@ -1243,11 +1252,12 @@ export default function AdminLdapPage() {
{/* Sync interval */}
<div className="flex items-center gap-4">
<div className="space-y-1">
<label className="text-sm font-medium text-foreground">
<label htmlFor="ldap-sync-interval" className="text-sm font-medium text-foreground">
{t('sync.interval')}
</label>
<div className="flex items-center gap-2">
<input
id="ldap-sync-interval"
type="number"
min={0}
value={formData.syncIntervalMin}