feat(11-01): MD3 focus-visible ring-3 indicators on all interactive elements

- md3-buttons.ts: upgrade ring-2/50 to ring-3 on all three constants (FILLED, OUTLINED, TEXT)
- BackendCard: add focus-visible:outline-none focus-visible:ring-3 focus-visible:ring-primary
- StepIndicator: upgrade group-focus-visible completed-step circle from ring-2/50 to ring-3
- ThemeToggle: add focus-visible ring-3 with ring-inset to both selected/unselected branches
- FieldRenderer: select uses focus-visible:ring-2 (was focus:ring-2); tooltip buttons get focus-visible:ring-2 rounded
This commit is contained in:
2026-04-01 13:25:00 +02:00
parent 07f97d9f25
commit 9015db565e
5 changed files with 10 additions and 10 deletions
+1 -1
View File
@@ -14,7 +14,7 @@ export function BackendCard({ name, description, selected = false, onClick, ...r
onClick={onClick} onClick={onClick}
data-selected={selected} data-selected={selected}
className={[ className={[
'w-full flex flex-col items-start gap-1 rounded-xl border-2 p-4 text-left transition-all', 'w-full flex flex-col items-start gap-1 rounded-xl border-2 p-4 text-left transition-all focus-visible:outline-none focus-visible:ring-3 focus-visible:ring-primary',
selected selected
? 'border-primary bg-primary/10 shadow-md' ? 'border-primary bg-primary/10 shadow-md'
: 'border-outline bg-surface-container shadow hover:border-primary hover:bg-surface hover:shadow-md', : 'border-outline bg-surface-container shadow hover:border-primary hover:bg-surface hover:shadow-md',
+3 -3
View File
@@ -53,7 +53,7 @@ export function FieldRenderer({ field, register, error }: FieldRendererProps) {
onMouseEnter={() => setHoverTooltip(true)} onMouseEnter={() => setHoverTooltip(true)}
onMouseLeave={() => setHoverTooltip(false)} onMouseLeave={() => setHoverTooltip(false)}
aria-label={`More info about ${field.label}`} aria-label={`More info about ${field.label}`}
className="text-primary hover:text-primary text-xs leading-none" className="text-primary hover:text-primary text-xs leading-none focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary rounded"
> >
</button> </button>
@@ -67,7 +67,7 @@ export function FieldRenderer({ field, register, error }: FieldRendererProps) {
<select <select
id={field.key} id={field.key}
className={[ className={[
'w-full rounded-md border px-3 py-2 text-sm focus:outline-none focus:ring-2', 'w-full rounded-md border px-3 py-2 text-sm focus:outline-none focus-visible:ring-2',
error ? 'border-error focus:ring-error/50' : 'border-outline focus:ring-primary/50', error ? 'border-error focus:ring-error/50' : 'border-outline focus:ring-primary/50',
].join(' ')} ].join(' ')}
{...register(field.key)} {...register(field.key)}
@@ -90,7 +90,7 @@ export function FieldRenderer({ field, register, error }: FieldRendererProps) {
onMouseEnter={() => setHoverTooltip(true)} onMouseEnter={() => setHoverTooltip(true)}
onMouseLeave={() => setHoverTooltip(false)} onMouseLeave={() => setHoverTooltip(false)}
aria-label={`More info about ${field.label}`} aria-label={`More info about ${field.label}`}
className="text-primary hover:text-primary/80 text-xs leading-none mt-px shrink-0" className="text-primary hover:text-primary/80 text-xs leading-none mt-px shrink-0 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary rounded"
> >
</button> </button>
+2 -2
View File
@@ -58,8 +58,8 @@ export function ThemeToggle() {
aria-pressed={theme === v} aria-pressed={theme === v}
className={ className={
theme === v theme === v
? 'flex-1 px-3 py-1 bg-primary text-on-primary font-medium' ? 'flex-1 px-3 py-1 bg-primary text-on-primary font-medium focus-visible:outline-none focus-visible:ring-3 focus-visible:ring-primary focus-visible:ring-inset'
: 'flex-1 px-3 py-1 bg-surface-container text-on-surface-container hover:bg-surface' : 'flex-1 px-3 py-1 bg-surface-container text-on-surface-container hover:bg-surface focus-visible:outline-none focus-visible:ring-3 focus-visible:ring-primary focus-visible:ring-inset'
} }
> >
{LABELS[v]} {LABELS[v]}
+1 -1
View File
@@ -39,7 +39,7 @@ export function StepIndicator() {
aria-label={`Go to step ${i + 1}: ${label}`} aria-label={`Go to step ${i + 1}: ${label}`}
className="flex flex-col items-center gap-1 group focus-visible:outline-none" className="flex flex-col items-center gap-1 group focus-visible:outline-none"
> >
<span className="w-8 h-8 rounded-full bg-primary text-on-primary flex items-center justify-center text-sm font-medium group-focus-visible:ring-2 group-focus-visible:ring-primary/50"> <span className="w-8 h-8 rounded-full bg-primary text-on-primary flex items-center justify-center text-sm font-medium group-focus-visible:ring-3 group-focus-visible:ring-primary">
&#10003; &#10003;
</span> </span>
<span className="text-xs text-primary hidden sm:block">{label}</span> <span className="text-xs text-primary hidden sm:block">{label}</span>
+3 -3
View File
@@ -11,16 +11,16 @@ export const MD3_BTN_FILLED =
'px-6 py-2.5 rounded-full bg-primary text-on-primary text-sm font-medium ' + 'px-6 py-2.5 rounded-full bg-primary text-on-primary text-sm font-medium ' +
'hover:opacity-90 active:opacity-80 transition-opacity ' + 'hover:opacity-90 active:opacity-80 transition-opacity ' +
'disabled:opacity-40 disabled:cursor-not-allowed ' + 'disabled:opacity-40 disabled:cursor-not-allowed ' +
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/50'; 'focus-visible:outline-none focus-visible:ring-3 focus-visible:ring-primary';
export const MD3_BTN_OUTLINED = export const MD3_BTN_OUTLINED =
'px-6 py-2.5 rounded-full border border-outline text-on-surface text-sm font-medium ' + 'px-6 py-2.5 rounded-full border border-outline text-on-surface text-sm font-medium ' +
'hover:bg-primary/8 active:bg-primary/12 transition-colors ' + 'hover:bg-primary/8 active:bg-primary/12 transition-colors ' +
'disabled:opacity-40 disabled:cursor-not-allowed ' + 'disabled:opacity-40 disabled:cursor-not-allowed ' +
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/50'; 'focus-visible:outline-none focus-visible:ring-3 focus-visible:ring-primary';
export const MD3_BTN_TEXT = export const MD3_BTN_TEXT =
'px-4 py-2.5 rounded-full text-primary text-sm font-medium ' + 'px-4 py-2.5 rounded-full text-primary text-sm font-medium ' +
'hover:bg-primary/8 active:bg-primary/12 transition-colors ' + 'hover:bg-primary/8 active:bg-primary/12 transition-colors ' +
'disabled:opacity-40 disabled:cursor-not-allowed ' + 'disabled:opacity-40 disabled:cursor-not-allowed ' +
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/50'; 'focus-visible:outline-none focus-visible:ring-3 focus-visible:ring-primary';