feat(t5): Darstellung hell/dunkel/Sonne ohne Flackern (T5a A2)
Blockierendes Skript im <head> setzt Darstellung, Kontrast und Bewegung vor dem ersten Zeichnen (gleiche Logik wie resolveAppearance, für alle Eingaben getestet), theme-color je Satz, Wahl je Gerät in localStorage mit Rückfall bei gesperrtem Speicher; Abgleich über Tabs, Systemeinstellungen und Seitenwechsel an einer Stelle. Profil-Karte „Darstellung“, Sonnenmodus im Benutzermenü; Dunkel bleibt bis A4 hinter NEXT_PUBLIC_APPEARANCE_DARK. next-themes entfernt. ARCHITECTURE §9: 'unsafe-inline' der Frontend-CSP als getragenes Risiko mit Begründung. Refs #26 Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
1 parent
947a46f435
commit
cf53cf35ac
22 files changed
+980
-97
No files matched your search
@@ -3,8 +3,10 @@
|
||||
import { ReactNode, useEffect, useRef, useState } from "react";
|
||||
import Link from "next/link";
|
||||
import { usePathname, useRouter } from "next/navigation";
|
||||
import { Hexagon } from "lucide-react";
|
||||
import { Hexagon, Sun } from "lucide-react";
|
||||
import { toast } from "sonner";
|
||||
import { useAuth } from "@/lib/auth/auth-context";
|
||||
import { useAppearance } from "@/lib/appearance/appearance";
|
||||
import { finishHandOvers, purgeStaleDraftPhotos } from "@/lib/photos/store";
|
||||
import { LogoutConfirmDialog } from "@/components/auth/logout-confirm-dialog";
|
||||
import { NotificationBell } from "@/components/notification-bell";
|
||||
@@ -12,6 +14,7 @@ import { OfflineBand } from "@/components/offline/offline-band";
|
||||
import { UserAvatar } from "@/components/user-avatar";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuCheckboxItem,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuGroup,
|
||||
DropdownMenuItem,
|
||||
@@ -32,6 +35,7 @@ export default function AppLayout({ children }: { children: ReactNode }) {
|
||||
const pathname = usePathname();
|
||||
const { user, isLoading, sessionMode } = useAuth();
|
||||
const [isLogoutOpen, setIsLogoutOpen] = useState(false);
|
||||
const { sunActive, setContrast } = useAppearance();
|
||||
// Focus lands here when the offline queue sheet closes and nothing else is left.
|
||||
const pageContentRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
@@ -113,6 +117,17 @@ export default function AppLayout({ children }: { children: ReactNode }) {
|
||||
</DropdownMenuLabel>
|
||||
</DropdownMenuGroup>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuCheckboxItem
|
||||
checked={sunActive}
|
||||
onCheckedChange={(checked) => {
|
||||
setContrast(checked ? "sun" : "normal");
|
||||
toast.success(checked ? "Sonnenmodus an" : "Sonnenmodus aus");
|
||||
}}
|
||||
className="min-h-11"
|
||||
>
|
||||
<Sun aria-hidden="true" />
|
||||
Sonnenmodus
|
||||
</DropdownMenuCheckboxItem>
|
||||
<DropdownMenuItem render={<Link href="/profile" />}>
|
||||
Profil
|
||||
</DropdownMenuItem>
|
||||
|
||||
Reference in new issue
Block a user