fix: fixed ataturk-widget-modal dark/light problem
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
import { Icon } from "@iconify/react";
|
import { Icon } from "@iconify/react";
|
||||||
import { usePathname } from "@/i18n/routing";
|
import { usePathname } from "@/i18n/routing";
|
||||||
import { AnnouncementBar } from "poyraz-ui/organisms";
|
import { AnnouncementBar } from "poyraz-ui/organisms";
|
||||||
@@ -19,13 +19,31 @@ type AppShellProps = {
|
|||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type ThemeMode = "light" | "dark";
|
||||||
|
|
||||||
|
function getInitialTheme(): ThemeMode {
|
||||||
|
if (typeof window === "undefined") return "light";
|
||||||
|
|
||||||
|
const storedTheme = localStorage.getItem("poyraz-theme");
|
||||||
|
if (storedTheme === "dark" || storedTheme === "light") return storedTheme;
|
||||||
|
|
||||||
|
return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
||||||
|
}
|
||||||
|
|
||||||
export function AppShell({ children }: AppShellProps) {
|
export function AppShell({ children }: AppShellProps) {
|
||||||
const pathname = usePathname();
|
const pathname = usePathname();
|
||||||
const locale = useLocale();
|
const locale = useLocale();
|
||||||
const announcement = ANNOUNCEMENT_ITEMS[0];
|
const announcement = ANNOUNCEMENT_ITEMS[0];
|
||||||
|
const [theme, setTheme] = useState<ThemeMode>(getInitialTheme);
|
||||||
const isStandaloneLinksPage =
|
const isStandaloneLinksPage =
|
||||||
pathname === "/links" || pathname.startsWith("/links/");
|
pathname === "/links" || pathname.startsWith("/links/");
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
document.documentElement.dataset.poyrazTheme = theme;
|
||||||
|
document.documentElement.style.colorScheme = theme;
|
||||||
|
localStorage.setItem("poyraz-theme", theme);
|
||||||
|
}, [theme]);
|
||||||
|
|
||||||
if (isStandaloneLinksPage) {
|
if (isStandaloneLinksPage) {
|
||||||
return children;
|
return children;
|
||||||
}
|
}
|
||||||
@@ -34,10 +52,10 @@ export function AppShell({ children }: AppShellProps) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<AtaturkWidgetModal />
|
<AtaturkWidgetModal theme={theme} />
|
||||||
{ENABLE_NEKO_FOLLOWER ? <NekoFollower /> : null}
|
{ENABLE_NEKO_FOLLOWER ? <NekoFollower /> : null}
|
||||||
<div className="mx-auto flex w-full max-w-4xl flex-col px-4 py-4 ">
|
<div className="mx-auto flex w-full max-w-4xl flex-col px-4 py-4 ">
|
||||||
<SiteNavbar />
|
<SiteNavbar theme={theme} onThemeChange={setTheme} />
|
||||||
{announcement ? (
|
{announcement ? (
|
||||||
<AnnouncementBar
|
<AnnouncementBar
|
||||||
variant="branded"
|
variant="branded"
|
||||||
|
|||||||
@@ -6,8 +6,13 @@ import Image from "next/image";
|
|||||||
import { Modal, ModalContent, ModalTrigger, ModalTitle } from "poyraz-ui/molecules";
|
import { Modal, ModalContent, ModalTrigger, ModalTitle } from "poyraz-ui/molecules";
|
||||||
import { Skeleton } from "poyraz-ui/atoms";
|
import { Skeleton } from "poyraz-ui/atoms";
|
||||||
import { useLocale, useTranslations } from "next-intl";
|
import { useLocale, useTranslations } from "next-intl";
|
||||||
|
import type { ThemeMode } from "@/components/app-shell";
|
||||||
|
|
||||||
export function AtaturkWidgetModal() {
|
type AtaturkWidgetModalProps = {
|
||||||
|
theme: ThemeMode;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function AtaturkWidgetModal({ theme }: AtaturkWidgetModalProps) {
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
const t = useTranslations("AtaturkWidget");
|
const t = useTranslations("AtaturkWidget");
|
||||||
const locale = useLocale();
|
const locale = useLocale();
|
||||||
@@ -48,12 +53,12 @@ export function AtaturkWidgetModal() {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
<div className={`w-full ${isLoading ? "hidden" : "block"}`}>
|
<div className={`w-full ${isLoading ? "hidden" : "block"}`}>
|
||||||
<div data-ataturk-quote-widget data-language={locale} data-theme="light"></div>
|
<div data-ataturk-quote-widget data-language={locale} data-theme={theme}></div>
|
||||||
<Script
|
<Script
|
||||||
src="https://ataturk-kronolojisi.org/widget/quote.js"
|
src="https://ataturk-kronolojisi.org/widget/quote.js"
|
||||||
strategy="lazyOnload"
|
strategy="lazyOnload"
|
||||||
data-language={locale}
|
data-language={locale}
|
||||||
data-theme="light"
|
data-theme={theme}
|
||||||
onReady={() => setIsLoading(false)}
|
onReady={() => setIsLoading(false)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+12
-26
@@ -5,7 +5,7 @@ import dynamic from "next/dynamic";
|
|||||||
import { Link, usePathname } from "@/i18n/routing";
|
import { Link, usePathname } from "@/i18n/routing";
|
||||||
import { useLocale, useTranslations } from "next-intl";
|
import { useLocale, useTranslations } from "next-intl";
|
||||||
import { LanguageSwitcher } from "@/components/language-switcher";
|
import { LanguageSwitcher } from "@/components/language-switcher";
|
||||||
import { useEffect, useState } from "react";
|
import { useState } from "react";
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
ButtonIcon,
|
ButtonIcon,
|
||||||
@@ -36,6 +36,7 @@ import {
|
|||||||
import { NavbarTopBar, NavbarTopBarSection } from "poyraz-ui/organisms";
|
import { NavbarTopBar, NavbarTopBarSection } from "poyraz-ui/organisms";
|
||||||
import { useKeyboardShortcutLabel } from "@/lib/use-keyboard-shortcut-label";
|
import { useKeyboardShortcutLabel } from "@/lib/use-keyboard-shortcut-label";
|
||||||
import { getResumeHref, NAV_LINKS, SOCIAL_LINKS, TOP_ICON_LINKS } from "@/lib/links";
|
import { getResumeHref, NAV_LINKS, SOCIAL_LINKS, TOP_ICON_LINKS } from "@/lib/links";
|
||||||
|
import type { ThemeMode } from "@/components/app-shell";
|
||||||
|
|
||||||
const SearchCommand = dynamic(
|
const SearchCommand = dynamic(
|
||||||
() => import("@/components/search-command").then((mod) => mod.SearchCommand),
|
() => import("@/components/search-command").then((mod) => mod.SearchCommand),
|
||||||
@@ -53,32 +54,15 @@ function getNavLinkClass(isActive: boolean) {
|
|||||||
].join(" ");
|
].join(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
type ThemeMode = "light" | "dark";
|
type ThemeToggleProps = {
|
||||||
|
theme: ThemeMode;
|
||||||
|
onThemeChange: (theme: ThemeMode) => void;
|
||||||
|
};
|
||||||
|
|
||||||
function applyTheme(theme: ThemeMode) {
|
function ThemeToggle({ theme, onThemeChange }: ThemeToggleProps) {
|
||||||
document.documentElement.dataset.poyrazTheme = theme;
|
|
||||||
document.documentElement.style.colorScheme = theme;
|
|
||||||
localStorage.setItem("poyraz-theme", theme);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getInitialTheme(): ThemeMode {
|
|
||||||
if (typeof window === "undefined") return "light";
|
|
||||||
|
|
||||||
const storedTheme = localStorage.getItem("poyraz-theme");
|
|
||||||
if (storedTheme === "dark" || storedTheme === "light") return storedTheme;
|
|
||||||
|
|
||||||
return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
|
||||||
}
|
|
||||||
|
|
||||||
function ThemeToggle() {
|
|
||||||
const [theme, setTheme] = useState<ThemeMode>(getInitialTheme);
|
|
||||||
const nextTheme = theme === "dark" ? "light" : "dark";
|
const nextTheme = theme === "dark" ? "light" : "dark";
|
||||||
const label = theme === "dark" ? "Light mode" : "Dark mode";
|
const label = theme === "dark" ? "Light mode" : "Dark mode";
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
applyTheme(theme);
|
|
||||||
}, [theme]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
@@ -88,7 +72,7 @@ function ThemeToggle() {
|
|||||||
effect="shine"
|
effect="shine"
|
||||||
aria-label={label}
|
aria-label={label}
|
||||||
className={`cursor-pointer ${slowShineClassName}`}
|
className={`cursor-pointer ${slowShineClassName}`}
|
||||||
onClick={() => setTheme(nextTheme)}
|
onClick={() => onThemeChange(nextTheme)}
|
||||||
>
|
>
|
||||||
<Icon
|
<Icon
|
||||||
icon={theme === "dark" ? "mdi:white-balance-sunny" : "mdi:moon-waning-crescent"}
|
icon={theme === "dark" ? "mdi:white-balance-sunny" : "mdi:moon-waning-crescent"}
|
||||||
@@ -99,7 +83,9 @@ function ThemeToggle() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function SiteNavbar() {
|
type SiteNavbarProps = ThemeToggleProps;
|
||||||
|
|
||||||
|
export function SiteNavbar({ theme, onThemeChange }: SiteNavbarProps) {
|
||||||
const pathname = usePathname();
|
const pathname = usePathname();
|
||||||
const [searchOpen, setSearchOpen] = useState(false);
|
const [searchOpen, setSearchOpen] = useState(false);
|
||||||
const shortcut = useKeyboardShortcutLabel();
|
const shortcut = useKeyboardShortcutLabel();
|
||||||
@@ -165,7 +151,7 @@ export function SiteNavbar() {
|
|||||||
|
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<ThemeToggle />
|
<ThemeToggle theme={theme} onThemeChange={onThemeChange} />
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipContent side="bottom" surface="soft" radius="sm" size="sm">
|
<TooltipContent side="bottom" surface="soft" radius="sm" size="sm">
|
||||||
{locale === "tr" ? "Tema değiştir" : "Toggle theme"}
|
{locale === "tr" ? "Tema değiştir" : "Toggle theme"}
|
||||||
|
|||||||
Reference in New Issue
Block a user