diff --git a/frontend/messages/de.json b/frontend/messages/de.json
index 8a08c280..60916b8e 100644
--- a/frontend/messages/de.json
+++ b/frontend/messages/de.json
@@ -32,6 +32,9 @@
"layout_menu_close": "Menü schließen",
"theme_toggle_to_light": "Zu hellem Design wechseln",
"theme_toggle_to_dark": "Zu dunklem Design wechseln",
+ "theme_toggle_label": "Farbschema",
+ "theme_segment_light": "Hell",
+ "theme_segment_dark": "Dunkel",
"btn_save": "Speichern",
"btn_cancel": "Abbrechen",
"btn_confirm": "Bestätigen",
diff --git a/frontend/messages/en.json b/frontend/messages/en.json
index 2e498c39..a6bf401d 100644
--- a/frontend/messages/en.json
+++ b/frontend/messages/en.json
@@ -32,6 +32,9 @@
"layout_menu_close": "Close menu",
"theme_toggle_to_light": "Switch to light mode",
"theme_toggle_to_dark": "Switch to dark mode",
+ "theme_toggle_label": "Color scheme",
+ "theme_segment_light": "Light",
+ "theme_segment_dark": "Dark",
"btn_save": "Save",
"btn_cancel": "Cancel",
"btn_confirm": "Confirm",
diff --git a/frontend/messages/es.json b/frontend/messages/es.json
index b4883eb2..080e25a0 100644
--- a/frontend/messages/es.json
+++ b/frontend/messages/es.json
@@ -32,6 +32,9 @@
"layout_menu_close": "Cerrar menú",
"theme_toggle_to_light": "Cambiar a modo claro",
"theme_toggle_to_dark": "Cambiar a modo oscuro",
+ "theme_toggle_label": "Esquema de color",
+ "theme_segment_light": "Claro",
+ "theme_segment_dark": "Oscuro",
"btn_save": "Guardar",
"btn_cancel": "Cancelar",
"btn_confirm": "Confirmar",
diff --git a/frontend/src/lib/shared/primitives/ThemeToggle.svelte b/frontend/src/lib/shared/primitives/ThemeToggle.svelte
index 834f765c..df3264d3 100644
--- a/frontend/src/lib/shared/primitives/ThemeToggle.svelte
+++ b/frontend/src/lib/shared/primitives/ThemeToggle.svelte
@@ -1,6 +1,7 @@
-
+
+
+
+
diff --git a/frontend/src/lib/shared/primitives/ThemeToggle.svelte.spec.ts b/frontend/src/lib/shared/primitives/ThemeToggle.svelte.spec.ts
index 546a22ab..f0ce5687 100644
--- a/frontend/src/lib/shared/primitives/ThemeToggle.svelte.spec.ts
+++ b/frontend/src/lib/shared/primitives/ThemeToggle.svelte.spec.ts
@@ -8,38 +8,59 @@ afterEach(() => {
localStorage.removeItem('theme');
});
-describe('ThemeToggle — label derivation (light mode)', () => {
+describe('ThemeToggle — renders segments (light mode)', () => {
beforeEach(() => {
localStorage.setItem('theme', 'light');
});
- it('aria-label invites switching to dark mode when theme is light', async () => {
+ it('renders a radiogroup with Hell and Dunkel segments', async () => {
render(ThemeToggle);
- const btn = await page.getByRole('button').element();
- expect(btn.getAttribute('aria-label')).toBe('Zu dunklem Design wechseln');
+ expect(document.querySelector('[role="radiogroup"]')).not.toBeNull();
+ await expect.element(page.getByRole('radio', { name: 'Hell' })).toBeVisible();
+ await expect.element(page.getByRole('radio', { name: 'Dunkel' })).toBeVisible();
});
- it('title equals aria-label in light mode', async () => {
+ it('Hell segment is aria-checked="true" in light mode', async () => {
render(ThemeToggle);
- const btn = await page.getByRole('button').element();
- expect(btn.getAttribute('title')).toBe(btn.getAttribute('aria-label'));
+ await expect
+ .element(page.getByRole('radio', { name: 'Hell' }))
+ .toHaveAttribute('aria-checked', 'true');
+ await expect
+ .element(page.getByRole('radio', { name: 'Dunkel' }))
+ .toHaveAttribute('aria-checked', 'false');
});
});
-describe('ThemeToggle — label derivation (dark mode)', () => {
+describe('ThemeToggle — renders segments (dark mode)', () => {
beforeEach(() => {
localStorage.setItem('theme', 'dark');
});
- it('aria-label invites switching to light mode when theme is dark', async () => {
+ it('Dunkel segment is aria-checked="true" in dark mode', async () => {
render(ThemeToggle);
- const btn = await page.getByRole('button').element();
- expect(btn.getAttribute('aria-label')).toBe('Zu hellem Design wechseln');
- });
-
- it('title equals aria-label in dark mode', async () => {
- render(ThemeToggle);
- const btn = await page.getByRole('button').element();
- expect(btn.getAttribute('title')).toBe(btn.getAttribute('aria-label'));
+ await expect
+ .element(page.getByRole('radio', { name: 'Dunkel' }))
+ .toHaveAttribute('aria-checked', 'true');
+ await expect
+ .element(page.getByRole('radio', { name: 'Hell' }))
+ .toHaveAttribute('aria-checked', 'false');
+ });
+});
+
+describe('ThemeToggle — theme switching', () => {
+ beforeEach(() => {
+ localStorage.setItem('theme', 'light');
+ });
+
+ it('clicking Dunkel sets data-theme=dark on documentElement', async () => {
+ render(ThemeToggle);
+ await page.getByRole('radio', { name: 'Dunkel' }).click();
+ expect(document.documentElement.getAttribute('data-theme')).toBe('dark');
+ });
+
+ it('clicking Dunkel persists theme in localStorage', async () => {
+ render(ThemeToggle);
+ await page.getByRole('radio', { name: 'Dunkel' }).click();
+ expect(localStorage.getItem('theme')).toBe('dark');
});
});