diff --git a/frontend/src/lib/timeline/EventTypeSelect.svelte b/frontend/src/lib/timeline/EventTypeSelect.svelte
new file mode 100644
index 00000000..18a6f347
--- /dev/null
+++ b/frontend/src/lib/timeline/EventTypeSelect.svelte
@@ -0,0 +1,69 @@
+
+
+
{
+ if (TYPES.includes(v as EventType)) select(v as EventType);
+ }}
+>
+ {#each TYPES as type (type)}
+
+ {/each}
+
+
+
+
+{announcement}
diff --git a/frontend/src/lib/timeline/EventTypeSelect.svelte.spec.ts b/frontend/src/lib/timeline/EventTypeSelect.svelte.spec.ts
new file mode 100644
index 00000000..f95708c5
--- /dev/null
+++ b/frontend/src/lib/timeline/EventTypeSelect.svelte.spec.ts
@@ -0,0 +1,27 @@
+import { afterEach, describe, expect, it } from 'vitest';
+import { cleanup, render } from 'vitest-browser-svelte';
+import { page } from 'vitest/browser';
+import EventTypeSelect from './EventTypeSelect.svelte';
+
+afterEach(() => cleanup());
+
+describe('EventTypeSelect — segmented PERSONAL/HISTORICAL radio', () => {
+ it('renders exactly two radio options', async () => {
+ render(EventTypeSelect, { value: 'PERSONAL' });
+ const radios = document.querySelectorAll('[role="radio"]');
+ expect(radios.length).toBe(2);
+ });
+
+ it('marks the initial value as checked and seeds the hidden input', async () => {
+ render(EventTypeSelect, { value: 'HISTORICAL', name: 'type' });
+ const hidden = document.querySelector('input[type="hidden"][name="type"]') as HTMLInputElement;
+ expect(hidden.value).toBe('HISTORICAL');
+ });
+
+ it('selects HISTORICAL and updates the hidden input when clicked', async () => {
+ render(EventTypeSelect, { value: 'PERSONAL', name: 'type' });
+ await page.getByRole('radio', { name: 'Historisch' }).click();
+ const hidden = document.querySelector('input[type="hidden"][name="type"]') as HTMLInputElement;
+ expect(hidden.value).toBe('HISTORICAL');
+ });
+});