The weeb for the next gen discord boat - Wamellow wamellow.com
bot discord

use cookies for devTools & reduceMotions

+84 -94
+3 -3
app/(home)/faq.component.tsx
··· 2 3 import { Accordion, AccordionItem, Code } from "@nextui-org/react"; 4 import Link from "next/link"; 5 import { HiCash, HiChat, HiExternalLink, HiLockClosed, HiUserAdd } from "react-icons/hi"; 6 7 - import { webStore } from "@/common/webstore"; 8 import cn from "@/utils/cn"; 9 10 const data = [ ··· 98 ]; 99 100 export default function Faq() { 101 - const web = webStore((w) => w); 102 103 return ( 104 <div className="my-4 w-full"> ··· 107 className="rounded-lg overflow-hidden" 108 variant="splitted" 109 defaultExpandedKeys={["0"]} 110 - disableAnimation={web.reduceMotions} 111 > 112 {data.map((item, index) => ( 113 <AccordionItem
··· 2 3 import { Accordion, AccordionItem, Code } from "@nextui-org/react"; 4 import Link from "next/link"; 5 + import { useCookies } from "next-client-cookies"; 6 import { HiCash, HiChat, HiExternalLink, HiLockClosed, HiUserAdd } from "react-icons/hi"; 7 8 import cn from "@/utils/cn"; 9 10 const data = [ ··· 98 ]; 99 100 export default function Faq() { 101 + const cookies = useCookies(); 102 103 return ( 104 <div className="my-4 w-full"> ··· 107 className="rounded-lg overflow-hidden" 108 variant="splitted" 109 defaultExpandedKeys={["0"]} 110 + disableAnimation={cookies.get("reduceMotions") === "true"} 111 > 112 {data.map((item, index) => ( 113 <AccordionItem
+4 -4
app/ai-gallery/[uploadId]/side.component.tsx
··· 2 3 import { Accordion, AccordionItem, Button, Chip, Tooltip } from "@nextui-org/react"; 4 import Link from "next/link"; 5 import { FaReddit, FaTwitter } from "react-icons/fa"; 6 import { HiHand, HiShare, HiUserGroup } from "react-icons/hi"; 7 8 - import { webStore } from "@/common/webstore"; 9 import Ad from "@/components/ad"; 10 import { CopyToClipboardButton } from "@/components/copy-to-clipboard"; 11 import ImageReduceMotion from "@/components/image-reduce-motion"; ··· 26 guild: ApiV1GuildsGetResponse | ApiError | undefined; 27 analytics: { results: AnalyticsResponse[] } | AnalyticsError | undefined; 28 }) { 29 - const web = webStore((w) => w); 30 31 const prompt = "prompt" in upload 32 ? truncate(upload.prompt.split(" ").map((str) => str.replace(/^\w/, (char) => char.toUpperCase())).join(" "), 32) ··· 76 className="bg-wamellow" 77 selectionMode="multiple" 78 defaultExpandedKeys={["1"]} 79 - disableAnimation={web.reduceMotions} 80 > 81 <AccordionItem 82 key="1" ··· 159 variant="shadow" 160 className="bg-wamellow" 161 selectionMode="multiple" 162 - disableAnimation={web.reduceMotions} 163 > 164 <AccordionItem 165 key="1"
··· 2 3 import { Accordion, AccordionItem, Button, Chip, Tooltip } from "@nextui-org/react"; 4 import Link from "next/link"; 5 + import { useCookies } from "next-client-cookies"; 6 import { FaReddit, FaTwitter } from "react-icons/fa"; 7 import { HiHand, HiShare, HiUserGroup } from "react-icons/hi"; 8 9 import Ad from "@/components/ad"; 10 import { CopyToClipboardButton } from "@/components/copy-to-clipboard"; 11 import ImageReduceMotion from "@/components/image-reduce-motion"; ··· 26 guild: ApiV1GuildsGetResponse | ApiError | undefined; 27 analytics: { results: AnalyticsResponse[] } | AnalyticsError | undefined; 28 }) { 29 + const cookies = useCookies(); 30 31 const prompt = "prompt" in upload 32 ? truncate(upload.prompt.split(" ").map((str) => str.replace(/^\w/, (char) => char.toUpperCase())).join(" "), 32) ··· 76 className="bg-wamellow" 77 selectionMode="multiple" 78 defaultExpandedKeys={["1"]} 79 + disableAnimation={cookies.get("reduceMotions") === "true"} 80 > 81 <AccordionItem 82 key="1" ··· 159 variant="shadow" 160 className="bg-wamellow" 161 selectionMode="multiple" 162 + disableAnimation={cookies.get("reduceMotions") === "true"} 163 > 164 <AccordionItem 165 key="1"
+1 -1
app/dashboard/[guildId]/layout.tsx
··· 194 </div> 195 196 <div className="md:ml-auto mt-6 md:mt-0"> 197 - {web.devToolsEnabled && 198 <CopyToClipboardButton 199 needsWait 200 text={getCanonicalUrl("leaderboard", params.guildId.toString())}
··· 194 </div> 195 196 <div className="md:ml-auto mt-6 md:mt-0"> 197 + {cookies.get("devTools") && 198 <CopyToClipboardButton 199 needsWait 200 text={getCanonicalUrl("leaderboard", params.guildId.toString())}
+1 -5
app/dashboard/[guildId]/leaderboards/page.tsx
··· 22 const cookies = useCookies(); 23 24 const guild = guildStore((g) => g); 25 - const web = webStore((w) => w); 26 const params = useParams(); 27 28 const url = `/guilds/${params.guildId}/modules/leaderboard` as const; ··· 66 icon={<HiChartBar />} 67 /> 68 69 - {web.devToolsEnabled && 70 <div className={"flex gap-4 border-2 border-violet-400 p-4 mb-4 rounded-lg"}> 71 72 <div className="lg:w-1/2 flex gap-2 w-full"> ··· 80 type="color" 81 defaultState={data.textColor ?? 0xe5e5e5} 82 resetState={0xe5e5e5} 83 - disabled={!web.devToolsEnabled} 84 /> 85 </div> 86 ··· 93 type="color" 94 defaultState={data.accentColor ?? 0x8b5cf6} 95 resetState={0x8b5cf6} 96 - disabled={!web.devToolsEnabled} 97 /> 98 </div> 99 ··· 108 type="color" 109 defaultState={data.backgroundColor ?? 0x0d0f11} 110 resetState={0x0d0f11} 111 - disabled={!web.devToolsEnabled} 112 /> 113 </div> 114
··· 22 const cookies = useCookies(); 23 24 const guild = guildStore((g) => g); 25 const params = useParams(); 26 27 const url = `/guilds/${params.guildId}/modules/leaderboard` as const; ··· 65 icon={<HiChartBar />} 66 /> 67 68 + {cookies.get("devTools") && 69 <div className={"flex gap-4 border-2 border-violet-400 p-4 mb-4 rounded-lg"}> 70 71 <div className="lg:w-1/2 flex gap-2 w-full"> ··· 79 type="color" 80 defaultState={data.textColor ?? 0xe5e5e5} 81 resetState={0xe5e5e5} 82 /> 83 </div> 84 ··· 91 type="color" 92 defaultState={data.accentColor ?? 0x8b5cf6} 93 resetState={0x8b5cf6} 94 /> 95 </div> 96 ··· 105 type="color" 106 defaultState={data.backgroundColor ?? 0x0d0f11} 107 resetState={0x0d0f11} 108 /> 109 </div> 110
+4 -4
app/dashboard/[guildId]/leaderboards/updating.component.tsx
··· 2 import { Tab, Tabs } from "@nextui-org/react"; 3 import Image from "next/image"; 4 import Link from "next/link"; 5 import { FunctionComponent, useState } from "react"; 6 import { HiExternalLink, HiPencil, HiTrash } from "react-icons/hi"; 7 8 import { Guild } from "@/common/guilds"; 9 - import { webStore } from "@/common/webstore"; 10 import SelectInput from "@/components/inputs/SelectMenu"; 11 import Switch from "@/components/inputs/Switch"; 12 import Modal from "@/components/modal"; ··· 24 } 25 26 const UpdatingLeaderboardCard: FunctionComponent<Props> = ({ guild, lb, type }) => { 27 - const web = webStore((w) => w); 28 29 const [leaderboard, setLeaderboard] = useState(lb); 30 const [modal, setModal] = useState<ModalType | undefined>(undefined); ··· 77 <span className="ml-1">{leaderboard?.channelId ? "Edit" : "Create"} leaderboard</span> 78 </button> 79 80 - {leaderboard?.channelId && web.devToolsEnabled && 81 <button 82 onClick={() => setModal(ModalType.Delete)} 83 className="flex dark:text-red-400/60 dark:hover:text-red-400/90 text-red-600/60 hover:text-red-600/90 duration-200" ··· 122 styles 123 }); 124 }} 125 - subChildren={leaderboard && web.devToolsEnabled && 126 <div className="text-xs flex flex-col"> 127 {leaderboard.createdAt && 128 <span>
··· 2 import { Tab, Tabs } from "@nextui-org/react"; 3 import Image from "next/image"; 4 import Link from "next/link"; 5 + import { useCookies } from "next-client-cookies"; 6 import { FunctionComponent, useState } from "react"; 7 import { HiExternalLink, HiPencil, HiTrash } from "react-icons/hi"; 8 9 import { Guild } from "@/common/guilds"; 10 import SelectInput from "@/components/inputs/SelectMenu"; 11 import Switch from "@/components/inputs/Switch"; 12 import Modal from "@/components/modal"; ··· 24 } 25 26 const UpdatingLeaderboardCard: FunctionComponent<Props> = ({ guild, lb, type }) => { 27 + const cookies = useCookies(); 28 29 const [leaderboard, setLeaderboard] = useState(lb); 30 const [modal, setModal] = useState<ModalType | undefined>(undefined); ··· 77 <span className="ml-1">{leaderboard?.channelId ? "Edit" : "Create"} leaderboard</span> 78 </button> 79 80 + {leaderboard?.channelId && cookies.get("devTools") && 81 <button 82 onClick={() => setModal(ModalType.Delete)} 83 className="flex dark:text-red-400/60 dark:hover:text-red-400/90 text-red-600/60 hover:text-red-600/90 duration-200" ··· 122 styles 123 }); 124 }} 125 + subChildren={leaderboard && cookies.get("devTools") && 126 <div className="text-xs flex flex-col"> 127 {leaderboard.createdAt && 128 <span>
+3 -3
app/dashboard/[guildId]/page.tsx
··· 4 import Image from "next/image"; 5 import Link from "next/link"; 6 import { useParams } from "next/navigation"; 7 import { useState } from "react"; 8 import { HiChartBar, HiMail } from "react-icons/hi"; 9 10 import { guildStore } from "@/common/guilds"; 11 - import { webStore } from "@/common/webstore"; 12 import SelectMenu from "@/components/inputs/SelectMenu"; 13 import Switch from "@/components/inputs/Switch"; 14 import Modal from "@/components/modal"; ··· 16 import OverviewLinkComponent from "../../../components/OverviewLinkComponent"; 17 18 export default function Home() { 19 - const web = webStore((w) => w); 20 const guild = guildStore((g) => g); 21 22 const [modal, setModal] = useState(false); ··· 133 <Accordion 134 className="lg:w-1/2" 135 defaultExpandedKeys={["1"]} 136 - disableAnimation={web.reduceMotions} 137 > 138 <AccordionItem 139 key="1"
··· 4 import Image from "next/image"; 5 import Link from "next/link"; 6 import { useParams } from "next/navigation"; 7 + import { useCookies } from "next-client-cookies"; 8 import { useState } from "react"; 9 import { HiChartBar, HiMail } from "react-icons/hi"; 10 11 import { guildStore } from "@/common/guilds"; 12 import SelectMenu from "@/components/inputs/SelectMenu"; 13 import Switch from "@/components/inputs/Switch"; 14 import Modal from "@/components/modal"; ··· 16 import OverviewLinkComponent from "../../../components/OverviewLinkComponent"; 17 18 export default function Home() { 19 + const cookies = useCookies(); 20 const guild = guildStore((g) => g); 21 22 const [modal, setModal] = useState(false); ··· 133 <Accordion 134 className="lg:w-1/2" 135 defaultExpandedKeys={["1"]} 136 + disableAnimation={cookies.get("reduceMotions") === "true"} 137 > 138 <AccordionItem 139 key="1"
+44 -44
app/layout.tsx
··· 94 const cookieStore = cookies(); 95 96 return ( 97 - <html 98 - suppressHydrationWarning 99 - data-theme="dark" 100 - lang="en" 101 - className="dark flex justify-center min-h-screen max-w-screen overflow-x-hidden" 102 - > 103 - 104 - <Script defer data-domain="wamellow.com" src="https://analytics.wamellow.com/js/script.js" /> 105 - 106 - <body className={cn("w-full max-w-7xl", outfit.className)}> 107 - <div id="bg" className="absolute top-0 right-0 w-screen h-screen -z-10" /> 108 109 - <nav className="p-4 flex items-center gap-2 text-base font-medium dark:text-neutral-300 text-neutral-700 select-none h-20"> 110 - <Link 111 - aria-label="Go to Wamellow's homepage" 112 - className={cn("font-semibold flex items-center mr-2", montserrat.className)} 113 - href="/?utm_source=wamellow.com&utm_medium=header" 114 - > 115 - <Image src="/waya-v3-small.webp" width={64} height={64} alt="" className="rounded-full mr-2 w-8 h-8 shrink-0" /> 116 - <span className="text-xl dark:text-neutral-100 text-neutral-900 hidden sm:block">Wamellow</span> 117 - </Link> 118 119 - <Divider 120 - className="h-10 rotate-6 mx-1" 121 - orientation="vertical" 122 - /> 123 124 - <div className="flex gap-1"> 125 <Link 126 - href="https://lunish.nl/kofi" 127 - className="dark:hover:bg-wamellow-alpha hover:bg-wamellow-100-alpha py-1 px-3 rounded-md duration-200 hidden sm:flex items-center gap-2 group" 128 > 129 - <SiKofi className="group-hover:text-[#ff6c6b] duration-200 mt-0.5" /> 130 - Donate 131 - </Link> 132 - <Link href="/vote" className="dark:hover:bg-wamellow-alpha hover:bg-wamellow-100-alpha py-1 px-3 rounded-md duration-200 flex items-center gap-2 group"> 133 - <TopggIcon className="group-hover:text-[#ff3366] duration-200 h-5 w-5 mt-0.5" /> 134 - Vote 135 </Link> 136 - </div> 137 138 - {cookieStore.get("hasSession")?.value === "true" ? 139 - <Header className="ml-auto" /> 140 - : 141 - <LoginButton /> 142 - } 143 - </nav> 144 145 - <CookiesProvider> 146 <Provider> 147 {children} 148 </Provider> 149 150 <StoreLastPage /> 151 - </CookiesProvider> 152 153 - </body> 154 - </html> 155 ); 156 }
··· 94 const cookieStore = cookies(); 95 96 return ( 97 + <CookiesProvider> 98 + <html 99 + suppressHydrationWarning 100 + data-theme="dark" 101 + lang="en" 102 + className="dark flex justify-center min-h-screen max-w-screen overflow-x-hidden" 103 + > 104 105 + <Script defer data-domain="wamellow.com" src="https://analytics.wamellow.com/js/script.js" /> 106 107 + <body className={cn("w-full max-w-7xl", outfit.className)}> 108 + <div id="bg" className="absolute top-0 right-0 w-screen h-screen -z-10" /> 109 110 + <nav className="p-4 flex items-center gap-2 text-base font-medium dark:text-neutral-300 text-neutral-700 select-none h-20"> 111 <Link 112 + aria-label="Go to Wamellow's homepage" 113 + className={cn("font-semibold flex items-center mr-2", montserrat.className)} 114 + href="/?utm_source=wamellow.com&utm_medium=header" 115 > 116 + <Image src="/waya-v3-small.webp" width={64} height={64} alt="" className="rounded-full mr-2 w-8 h-8 shrink-0" /> 117 + <span className="text-xl dark:text-neutral-100 text-neutral-900 hidden sm:block">Wamellow</span> 118 </Link> 119 120 + <Divider 121 + className="h-10 rotate-6 mx-1" 122 + orientation="vertical" 123 + /> 124 125 + <div className="flex gap-1"> 126 + <Link 127 + href="https://lunish.nl/kofi" 128 + className="dark:hover:bg-wamellow-alpha hover:bg-wamellow-100-alpha py-1 px-3 rounded-md duration-200 hidden sm:flex items-center gap-2 group" 129 + > 130 + <SiKofi className="group-hover:text-[#ff6c6b] duration-200 mt-0.5" /> 131 + Donate 132 + </Link> 133 + <Link href="/vote" className="dark:hover:bg-wamellow-alpha hover:bg-wamellow-100-alpha py-1 px-3 rounded-md duration-200 flex items-center gap-2 group"> 134 + <TopggIcon className="group-hover:text-[#ff3366] duration-200 h-5 w-5 mt-0.5" /> 135 + Vote 136 + </Link> 137 + </div> 138 + 139 + {cookieStore.get("hasSession")?.value === "true" ? 140 + <Header className="ml-auto" /> 141 + : 142 + <LoginButton /> 143 + } 144 + </nav> 145 + 146 <Provider> 147 {children} 148 </Provider> 149 150 <StoreLastPage /> 151 152 + </body> 153 + </html> 154 + </CookiesProvider> 155 ); 156 }
+4 -4
app/leaderboard/[guildId]/side.component.tsx
··· 3 import { Accordion, AccordionItem, Button, Code, Tooltip } from "@nextui-org/react"; 4 import Link from "next/link"; 5 import { useRouter } from "next/navigation"; 6 import { useState } from "react"; 7 import { BsDiscord } from "react-icons/bs"; 8 import { FaReddit, FaTwitter } from "react-icons/fa"; 9 import { HiAnnotation, HiLink, HiShare, HiTrash, HiViewGridAdd, HiVolumeUp } from "react-icons/hi"; 10 11 - import { webStore } from "@/common/webstore"; 12 import Ad from "@/components/ad"; 13 import { CopyToClipboardButton } from "@/components/copy-to-clipboard"; 14 import Modal from "@/components/modal"; ··· 28 pagination: ApiV1GuildsTopmembersPaginationGetResponse | ApiError | undefined; 29 currentCircular: "next" | "server" | undefined; 30 }) { 31 - const web = webStore((w) => w); 32 const router = useRouter(); 33 34 const [modal, setModal] = useState(false); ··· 86 <Accordion 87 selectionMode="multiple" 88 defaultExpandedKeys={["1", "2", "3"]} 89 - disableAnimation={web.reduceMotions} 90 > 91 92 - {guild && "id" in guild && web.devToolsEnabled ? 93 <AccordionItem 94 key="1" 95 aria-label="admin tools"
··· 3 import { Accordion, AccordionItem, Button, Code, Tooltip } from "@nextui-org/react"; 4 import Link from "next/link"; 5 import { useRouter } from "next/navigation"; 6 + import { useCookies } from "next-client-cookies"; 7 import { useState } from "react"; 8 import { BsDiscord } from "react-icons/bs"; 9 import { FaReddit, FaTwitter } from "react-icons/fa"; 10 import { HiAnnotation, HiLink, HiShare, HiTrash, HiViewGridAdd, HiVolumeUp } from "react-icons/hi"; 11 12 import Ad from "@/components/ad"; 13 import { CopyToClipboardButton } from "@/components/copy-to-clipboard"; 14 import Modal from "@/components/modal"; ··· 28 pagination: ApiV1GuildsTopmembersPaginationGetResponse | ApiError | undefined; 29 currentCircular: "next" | "server" | undefined; 30 }) { 31 + const cookies = useCookies(); 32 const router = useRouter(); 33 34 const [modal, setModal] = useState(false); ··· 86 <Accordion 87 selectionMode="multiple" 88 defaultExpandedKeys={["1", "2", "3"]} 89 + disableAnimation={cookies.get("reduceMotions") === "true"} 90 > 91 92 + {guild && "id" in guild && cookies.get("devTools") ? 93 <AccordionItem 94 key="1" 95 aria-label="admin tools"
-4
common/webstore.ts
··· 1 import { create } from "zustand"; 2 3 export interface Web { 4 - devToolsEnabled: boolean | undefined; 5 - reduceMotions: boolean; 6 width: number; 7 } 8 9 export const webStore = create<Web>(() => ({ 10 - devToolsEnabled: undefined, 11 - reduceMotions: false, 12 width: Infinity 13 }));
··· 1 import { create } from "zustand"; 2 3 export interface Web { 4 width: number; 5 } 6 7 export const webStore = create<Web>(() => ({ 8 width: Infinity 9 }));
+16 -19
components/header.tsx
··· 3 import { Button, Chip, Skeleton, Switch, Tooltip } from "@nextui-org/react"; 4 import { AnimatePresence, motion, MotionConfig } from "framer-motion"; 5 import Link from "next/link"; 6 import React, { useEffect, useState } from "react"; 7 import { HiBadgeCheck, HiBeaker, HiChartPie, HiChevronDown, HiEyeOff, HiIdentification, HiLogout, HiViewGridAdd } from "react-icons/hi"; 8 ··· 15 import ImageReduceMotion from "./image-reduce-motion"; 16 17 export default function Header(props: React.ComponentProps<"div">) { 18 19 const [menu, setMenu] = useState(false); 20 const [loginstate, setLoginstate] = useState<"LOADING" | "ERRORED" | undefined>("LOADING"); 21 22 const user = userStore((s) => s); 23 - const web = webStore((w) => w); 24 25 useEffect(() => { 26 ··· 32 }); 33 }); 34 35 - const devToolsEnabled = localStorage.getItem("devToolsEnabled"); 36 - const reduceMotions = localStorage.getItem("reduceMotions"); 37 - 38 webStore.setState({ 39 - ...web, 40 - width: window?.innerWidth, 41 - devToolsEnabled: !!devToolsEnabled, 42 - reduceMotions: !!reduceMotions 43 }); 44 }, []); 45 ··· 80 { 81 name: "Reduce Motion", 82 icon: <HiEyeOff />, 83 - value: web.reduceMotions, 84 onChange: () => { 85 - if (!web.reduceMotions) localStorage.setItem("reduceMotions", "true"); 86 - else localStorage.removeItem("reduceMotions"); 87 - 88 - webStore.setState({ ...web, reduceMotions: !web.reduceMotions }); 89 } 90 }, 91 ...(user?.HELLO_AND_WELCOME_TO_THE_DEV_TOOLS__PLEASE_GO_AWAY ? ··· 99 { 100 name: "Lunar Tools", 101 icon: <HiBeaker />, 102 - value: web.devToolsEnabled, 103 onChange: () => { 104 - if (!web.devToolsEnabled) localStorage.setItem("devToolsEnabled", "true"); 105 - else localStorage.removeItem("devToolsEnabled"); 106 - 107 - webStore.setState({ ...web, devToolsEnabled: !web.devToolsEnabled }); 108 } 109 } 110 ] ··· 223 } 224 225 <MotionConfig 226 - transition={web.reduceMotions ? 227 { duration: 0 } 228 : 229 { type: "spring", bounce: 0.4, duration: menu ? 0.7 : 0.4 }
··· 3 import { Button, Chip, Skeleton, Switch, Tooltip } from "@nextui-org/react"; 4 import { AnimatePresence, motion, MotionConfig } from "framer-motion"; 5 import Link from "next/link"; 6 + import { useRouter } from "next/navigation"; 7 + import { useCookies } from "next-client-cookies"; 8 import React, { useEffect, useState } from "react"; 9 import { HiBadgeCheck, HiBeaker, HiChartPie, HiChevronDown, HiEyeOff, HiIdentification, HiLogout, HiViewGridAdd } from "react-icons/hi"; 10 ··· 17 import ImageReduceMotion from "./image-reduce-motion"; 18 19 export default function Header(props: React.ComponentProps<"div">) { 20 + const cookies = useCookies(); 21 + const devTools = cookies.get("devTools") === "true"; 22 + const reduceMotions = cookies.get("reduceMotions") === "true"; 23 24 const [menu, setMenu] = useState(false); 25 const [loginstate, setLoginstate] = useState<"LOADING" | "ERRORED" | undefined>("LOADING"); 26 27 const user = userStore((s) => s); 28 + const router = useRouter(); 29 30 useEffect(() => { 31 ··· 37 }); 38 }); 39 40 webStore.setState({ 41 + width: window?.innerWidth 42 }); 43 }, []); 44 ··· 79 { 80 name: "Reduce Motion", 81 icon: <HiEyeOff />, 82 + value: reduceMotions, 83 onChange: () => { 84 + if (!reduceMotions) cookies.set("reduceMotions", "true", { expires: 365 }); 85 + else cookies.remove("reduceMotions"); 86 + router.refresh(); 87 } 88 }, 89 ...(user?.HELLO_AND_WELCOME_TO_THE_DEV_TOOLS__PLEASE_GO_AWAY ? ··· 97 { 98 name: "Lunar Tools", 99 icon: <HiBeaker />, 100 + value: devTools, 101 onChange: () => { 102 + if (!devTools) cookies.set("devTools", "true", { expires: 365 }); 103 + else cookies.remove("devTools"); 104 + router.refresh(); 105 } 106 } 107 ] ··· 220 } 221 222 <MotionConfig 223 + transition={reduceMotions ? 224 { duration: 0 } 225 : 226 { type: "spring", bounce: 0.4, duration: menu ? 0.7 : 0.4 }
+4 -3
components/image-reduce-motion.tsx
··· 1 "use client"; 2 import Image from "next/image"; 3 4 - import { webStore } from "@/common/webstore"; 5 6 interface Props { 7 url: string | null | undefined; ··· 17 className, 18 forceStatic 19 }: Props) { 20 - const web = webStore((w) => w); 21 22 return ( 23 <Image 24 itemProp="image" 25 - src={!url?.includes("null") && !url?.includes("undefined") && url ? `${url}.${url.includes("a_") && !web.reduceMotions && !forceStatic ? "gif" : "webp"}?size=${size}` : "/discord.webp"} 26 width={size} 27 height={size} 28 alt={alt}
··· 1 "use client"; 2 import Image from "next/image"; 3 + import { useCookies } from "next-client-cookies"; 4 5 6 interface Props { 7 url: string | null | undefined; ··· 17 className, 18 forceStatic 19 }: Props) { 20 + const cookies = useCookies(); 21 + const reduceMotions = cookies.get("reduceMotions") === "true"; 22 23 return ( 24 <Image 25 itemProp="image" 26 + src={!url?.includes("null") && !url?.includes("undefined") && url ? `${url}.${url.includes("a_") && !reduceMotions && !forceStatic ? "gif" : "webp"}?size=${size}` : "/discord.webp"} 27 width={size} 28 height={size} 29 alt={alt}