P2: Einheitliche Fokus-Ringe global

- .focus-ring Utility via Tailwind-Play-CDN (@apply) in base.html
- Globaler :focus-visible-Fallback (emerald Outline) für alle
  Bedienelemente ohne explizite Fokus-Klassen
- Benutzer-Formular und Audit-Log-Filter nutzen .focus-ring
This commit is contained in:
Flo Hartmann
2026-08-26 09:04:45 +00:00
parent fee5f8b9a3
commit d6ed8fa56e
3 changed files with 24 additions and 8 deletions

View File

@@ -19,7 +19,7 @@
<label class="block text-sm">
<span class="text-slate-500 block mb-1">Benutzer</span>
<select name="benutzer"
class="w-full border border-slate-300 rounded-lg px-2 py-2 bg-white">
class="w-full border border-slate-300 rounded-lg px-2 py-2 bg-white focus-ring">
<option value="">Alle</option>
{% for name in benutzer_auswahl %}
<option value="{{ name }}" {% if name == filter_benutzer %}selected{% endif %}>{{ name }}</option>
@@ -29,7 +29,7 @@
<label class="block text-sm">
<span class="text-slate-500 block mb-1">Aktionstyp</span>
<select name="aktion"
class="w-full border border-slate-300 rounded-lg px-2 py-2 bg-white">
class="w-full border border-slate-300 rounded-lg px-2 py-2 bg-white focus-ring">
<option value="">Alle</option>
{% for a in aktionen_auswahl %}
<option value="{{ a }}" {% if a == filter_aktion %}selected{% endif %}>
@@ -41,12 +41,12 @@
<label class="block text-sm">
<span class="text-slate-500 block mb-1">Von</span>
<input type="date" name="von" value="{{ filter_von }}"
class="w-full border border-slate-300 rounded-lg px-2 py-2">
class="w-full border border-slate-300 rounded-lg px-2 py-2 focus-ring">
</label>
<label class="block text-sm">
<span class="text-slate-500 block mb-1">Bis</span>
<input type="date" name="bis" value="{{ filter_bis }}"
class="w-full border border-slate-300 rounded-lg px-2 py-2">
class="w-full border border-slate-300 rounded-lg px-2 py-2 focus-ring">
</label>
<div class="flex gap-2">
<button type="submit"

View File

@@ -8,6 +8,22 @@
<script src="https://unpkg.com/htmx.org@2.0.4"></script>
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.14.9/dist/cdn.min.js"></script>
<style>[x-cloak] { display: none !important; }</style>
<style type="text/tailwindcss">
/* Einheitlicher Fokus-Ring für Formularelemente und Button-Links */
.focus-ring { @apply focus:outline-none focus:ring-2 focus:ring-emerald-500 focus:border-emerald-500; }
</style>
<style>
/* Fallback ohne Klassen-Anpassung: sichtbarer Fokus auf allen
Bedienelementen (Tailwind-Ring überlagert diesen, wo vorhanden). */
input:focus-visible, select:focus-visible, textarea:focus-visible,
button:focus-visible, summary:focus-visible, a:focus-visible {
outline: 2px solid #10b981;
outline-offset: 1px;
}
input:focus-visible, select:focus-visible, textarea:focus-visible {
border-color: #10b981;
}
</style>
</head>
<body class="bg-slate-100 text-slate-800 min-h-screen flex flex-col">
<header class="bg-white border-b border-slate-200" x-data="{ menue: false }">

View File

@@ -19,7 +19,7 @@
<label for="username" class="block text-sm font-medium mb-1">Benutzername</label>
<input id="username" name="username" value="{{ form.username }}" required aria-required="true" minlength="3"
{% if aktion != 'neu' %}disabled{% endif %}
class="w-full border border-slate-300 rounded-lg px-3 py-2 {% if aktion != 'neu' %}bg-slate-100{% endif %}">
class="w-full border border-slate-300 rounded-lg px-3 py-2 focus-ring {% if aktion != 'neu' %}bg-slate-100{% endif %}">
{% if aktion != 'neu' %}
<p class="text-xs text-slate-400 mt-1">Der Benutzername kann nicht ge&auml;ndert werden.</p>
{% endif %}
@@ -28,7 +28,7 @@
<div>
<label for="display_name" class="block text-sm font-medium mb-1">Anzeigename</label>
<input id="display_name" name="display_name" value="{{ form.display_name }}"
class="w-full border border-slate-300 rounded-lg px-3 py-2">
class="w-full border border-slate-300 rounded-lg px-3 py-2 focus-ring">
</div>
<div>
@@ -41,7 +41,7 @@
<input type="hidden" name="role" value="{{ form.role }}">
{% else %}
<select id="role" name="role"
class="w-full border border-slate-300 rounded-lg px-3 py-2 bg-white">
class="w-full border border-slate-300 rounded-lg px-3 py-2 bg-white focus-ring">
{% for rollen_wert, rollen_text in rollen_anzeige.items() %}
<option value="{{ rollen_wert }}" {% if form.role == rollen_wert %}selected{% endif %}>{{ rollen_text }}</option>
{% endfor %}
@@ -63,7 +63,7 @@
{% if aktion == 'neu' %}Passwort{% else %}Neues Passwort (leer = unver&auml;ndert){% endif %}
</label>
<input id="password" name="password" type="password" {% if aktion == 'neu' %}required aria-required="true"{% endif %} minlength="8"
class="w-full border border-slate-300 rounded-lg px-3 py-2">
class="w-full border border-slate-300 rounded-lg px-3 py-2 focus-ring">
</div>
<div class="flex flex-col sm:flex-row gap-3 pt-2">