fix(quick-260921-bi2): a11y - Modul-Bereich (Kategorie-Seiten, Cert-Manager)

useButtonType: alle Aktions-Buttons in Cert-Manager-Tabs (kein Formular in
diesen Dateien) erhalten type="button".

noSvgWithoutTitle: Modul-Icons neben dem Modulnamen, Leer- und Nicht-
gefunden-Zustaende neben ihrer Ueberschrift werden dekorativ
(aria-hidden="true"); die Augen-Icons im Passwortfeld sind bereits ueber das
aria-label des umschliessenden Buttons benannt.

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:21:24 +02:00
parent ae821254ef
commit 278aedb201
8 changed files with 13 additions and 0 deletions
@@ -40,6 +40,7 @@ export function ModuleShell({ category, moduleSlug }: ModuleShellProps) {
<div className="flex flex-col items-center justify-center py-16 text-center">
<div className="rounded-lg bg-muted p-4 mb-4">
<svg
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
width="48"
height="48"
@@ -81,6 +82,7 @@ export function ModuleShell({ category, moduleSlug }: ModuleShellProps) {
className="inline-flex items-center gap-1.5 text-sm font-medium text-muted-foreground hover:text-foreground transition-colors"
>
<svg
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
@@ -23,6 +23,7 @@ function ModuleIcon({ icon }: { icon?: string }) {
if (icon === 'Globe') {
return (
<svg
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
@@ -44,6 +45,7 @@ function ModuleIcon({ icon }: { icon?: string }) {
// Default puzzle-piece icon for generic modules
return (
<svg
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
@@ -121,6 +121,7 @@ export default function CategoryPage() {
<div className="flex flex-col items-center justify-center py-16 text-center">
<div className="rounded-lg bg-muted p-4 mb-4">
<svg
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
width="48"
height="48"
@@ -73,6 +73,7 @@ export function ConvertTab({ file, pemText, password, onTargetFormatChange }: Co
{/* Primary action button */}
<button
type="button"
onClick={handleConvert}
disabled={loading || !canConvert}
className="bg-primary text-primary-foreground px-4 py-2 rounded text-sm font-medium disabled:opacity-50 hover:opacity-90 transition-opacity"
@@ -43,6 +43,7 @@ export function InspectTab({ file, pemText, password }: InspectTabProps) {
<div className="space-y-4">
{/* Primary action button */}
<button
type="button"
onClick={handleInspect}
disabled={loading || !canInspect}
className="bg-primary text-primary-foreground px-4 py-2 rounded text-sm font-medium disabled:opacity-50 hover:opacity-90 transition-opacity"
@@ -38,6 +38,7 @@ export function PasswordField({ value, onChange, show }: PasswordFieldProps) {
{revealed ? (
/* Eye-off inline SVG */
<svg
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
@@ -55,6 +56,7 @@ export function PasswordField({ value, onChange, show }: PasswordFieldProps) {
) : (
/* Eye inline SVG */
<svg
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
@@ -70,6 +70,7 @@ export function SplitTab({ file, pemText: _pemText, password: _password }: Split
<div className="space-y-4">
<div className="flex items-center gap-3">
<button
type="button"
onClick={handleSplit}
disabled={loading || !file}
className="bg-primary text-primary-foreground px-4 py-2 rounded text-sm font-medium disabled:opacity-50 hover:opacity-90 transition-opacity"
@@ -79,6 +80,7 @@ export function SplitTab({ file, pemText: _pemText, password: _password }: Split
{result && result.certs.length > 1 && (
<button
type="button"
onClick={() => downloadAllAsZip(result.certs)}
className="border border-border px-4 py-2 rounded text-sm font-medium hover:bg-secondary transition-colors"
>
@@ -117,6 +119,7 @@ export function SplitTab({ file, pemText: _pemText, password: _password }: Split
</span>
</div>
<button
type="button"
onClick={() =>
downloadBase64(cert.filename, cert.content, 'application/x-pem-file')
}
@@ -22,6 +22,7 @@ export function ModuleAccessDenied({ title, body, backToDashboard }: ModuleAcces
<div className="flex flex-col items-center justify-center py-16 text-center">
<div className="rounded-lg bg-muted p-4 mb-4">
<svg
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
width="48"
height="48"