diff --git a/apps/portal-shell/src/app/components/footer/footer.html b/apps/portal-shell/src/app/components/footer/footer.html index 233d27e..78fd94e 100644 --- a/apps/portal-shell/src/app/components/footer/footer.html +++ b/apps/portal-shell/src/app/components/footer/footer.html @@ -3,10 +3,9 @@ aria-label="Page footer" class="flex h-10 shrink-0 items-center justify-between border-t border-gray-200 bg-white px-4 text-xs text-gray-500 dark:border-gray-800 dark:bg-gray-900 dark:text-gray-400 sm:px-6" > -

© {{ year }} APF France handicap

- -
- +
+

© {{ year }} APF France handicap

+
+ +
+ + +
diff --git a/apps/portal-shell/src/app/components/footer/footer.spec.ts b/apps/portal-shell/src/app/components/footer/footer.spec.ts index 768d06c..e8aa9dc 100644 --- a/apps/portal-shell/src/app/components/footer/footer.spec.ts +++ b/apps/portal-shell/src/app/components/footer/footer.spec.ts @@ -42,4 +42,24 @@ describe('Footer', () => { await fixture.whenStable(); expect(fixture.nativeElement.querySelector('app-locale-switcher')).not.toBeNull(); }); + + it('embeds the theme switcher (moved here from the header)', async () => { + const fixture = TestBed.createComponent(Footer); + await fixture.whenStable(); + expect(fixture.nativeElement.querySelector('app-theme-switcher')).not.toBeNull(); + }); + + it('groups copyright + accessibility on the left, switchers on the right', async () => { + const fixture = TestBed.createComponent(Footer); + await fixture.whenStable(); + const root = fixture.nativeElement as HTMLElement; + const clusters = Array.from(root.querySelectorAll('footer > div')); + expect(clusters).toHaveLength(2); + // Left cluster — info / legal. + expect(clusters[0]?.querySelector('p')?.textContent).toContain('APF France handicap'); + expect(clusters[0]?.querySelector('a[href="/accessibility"]')).not.toBeNull(); + // Right cluster — device preferences. + expect(clusters[1]?.querySelector('app-locale-switcher')).not.toBeNull(); + expect(clusters[1]?.querySelector('app-theme-switcher')).not.toBeNull(); + }); }); diff --git a/apps/portal-shell/src/app/components/footer/footer.ts b/apps/portal-shell/src/app/components/footer/footer.ts index ea2d6c6..0479089 100644 --- a/apps/portal-shell/src/app/components/footer/footer.ts +++ b/apps/portal-shell/src/app/components/footer/footer.ts @@ -1,24 +1,30 @@ import { ChangeDetectionStrategy, Component } from '@angular/core'; import { RouterLink } from '@angular/router'; import { LocaleSwitcher } from '../locale-switcher/locale-switcher'; +import { ThemeSwitcher } from '../theme-switcher/theme-switcher'; /** * Thin full-width footer pinned to the bottom of the shell. * - * v1 ships: - * - APF France handicap copyright with the current year. - * - Locale switcher (FR / EN) — per ADR-0019, hard-refreshes to - * the matching `/fr/...` or `/en/...` prefix. - * - Accessibility statement link — single i18n-marked link - * pointing to the canonical `/accessibility` path. + * Layout — two clusters separated by `justify-between`: + * - **Left cluster** — APF France handicap copyright + accessibility + * statement link, joined by a typographic separator. Static + * informational content that anchors the page (who owns it, where + * to find legal info). + * - **Right cluster** — device preferences the reader controls: + * locale switcher (per ADR-0019) and theme switcher (light / dark + * / system). The theme switcher is in the footer rather than the + * header so the same trigger location works for anonymous and + * authenticated readers; moving it between auth states would + * break consistency for a control whose purpose (changing read + * conditions) is identical across both. * - * The footer is reserved for cross-cutting page furniture. A - * dev-only version badge lands here once `SERVICE_VERSION` is wired + * A dev-only version badge lands here once `SERVICE_VERSION` is wired * to a build-time injection. */ @Component({ selector: 'app-footer', - imports: [RouterLink, LocaleSwitcher], + imports: [RouterLink, LocaleSwitcher, ThemeSwitcher], templateUrl: './footer.html', changeDetection: ChangeDetectionStrategy.OnPush, }) diff --git a/apps/portal-shell/src/app/components/header/header.html b/apps/portal-shell/src/app/components/header/header.html index 2c8631c..d8bc409 100644 --- a/apps/portal-shell/src/app/components/header/header.html +++ b/apps/portal-shell/src/app/components/header/header.html @@ -61,16 +61,6 @@ > - - - @switch (authState().kind) { @case ('loading') {