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:
@@ -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')
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user