fix(persons): use semantic color tokens in PersonTypeSelector for dark mode

Replaces hardcoded brand-navy/brand-sand/white classes with semantic
tokens (bg-primary/text-primary-fg, bg-surface/text-ink, border-line,
ring-focus-ring) so the segmented control adapts correctly in dark mode.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-04-26 00:16:26 +02:00
parent 92b082ec62
commit c9e9300216
2 changed files with 40 additions and 3 deletions

View File

@@ -37,9 +37,9 @@ function select(type: PersonType) {
aria-checked={selected === type}
tabindex={selected === type ? 0 : -1}
onclick={() => select(type)}
class="min-h-[48px] cursor-pointer rounded-sm border px-3 py-2 text-sm font-medium transition-colors focus-visible:ring-2 focus-visible:ring-brand-navy focus-visible:outline-none {selected === type
? 'border-brand-navy bg-brand-navy text-white'
: 'border-brand-sand bg-white text-brand-navy hover:border-brand-navy/50'}"
class="min-h-[48px] cursor-pointer rounded-sm border px-3 py-2 text-sm font-medium transition-colors focus-visible:ring-2 focus-visible:ring-focus-ring focus-visible:outline-none {selected === type
? 'border-primary bg-primary text-primary-fg'
: 'border-line bg-surface text-ink hover:border-primary/50'}"
>
{labels[type]()}
</button>

View File

@@ -0,0 +1,37 @@
import { describe, it, expect, afterEach } from 'vitest';
import { cleanup, render } from 'vitest-browser-svelte';
import PersonTypeSelector from './PersonTypeSelector.svelte';
afterEach(() => cleanup());
describe('PersonTypeSelector', () => {
it('selected button uses semantic bg-primary and text-primary-fg classes', () => {
const { container } = render(PersonTypeSelector, { value: 'PERSON' });
const buttons = container.querySelectorAll('[role="radio"]');
const selected = Array.from(buttons).find((b) => b.getAttribute('aria-checked') === 'true');
expect(selected).not.toBeNull();
expect(selected!.className).toContain('bg-primary');
expect(selected!.className).toContain('text-primary-fg');
});
it('unselected buttons use semantic bg-surface, text-ink, border-line classes', () => {
const { container } = render(PersonTypeSelector, { value: 'PERSON' });
const buttons = container.querySelectorAll('[role="radio"]');
const unselected = Array.from(buttons).filter((b) => b.getAttribute('aria-checked') !== 'true');
expect(unselected.length).toBeGreaterThan(0);
for (const btn of unselected) {
expect(btn.className).toContain('bg-surface');
expect(btn.className).toContain('text-ink');
expect(btn.className).toContain('border-line');
}
});
it('focus ring uses semantic ring-focus-ring class', () => {
const { container } = render(PersonTypeSelector, { value: 'PERSON' });
const buttons = container.querySelectorAll('[role="radio"]');
for (const btn of buttons) {
expect(btn.className).toContain('ring-focus-ring');
}
});
});