theme switcher
All checks were successful
Deploy / deploy (ubuntu-latest, 2.44.0) (push) Successful in 58s

Took 18 minutes
This commit is contained in:
Braydon 2024-10-06 16:30:18 -04:00
parent 87394abe03
commit 80425ee7c8
5 changed files with 78 additions and 5 deletions

View File

@ -10,8 +10,8 @@ import Sidebar from "@/components/sidebar/sidebar";
*/
export const metadata: Metadata = {
title: {
default: "Pulse App Docs",
template: "%s • Pulse App Docs",
default: "Pulse Docs",
template: "%s • Pulse Docs",
},
description:
"A lightweight service monitoring solution for tracking the availability of whatever service your heart desires!",

View File

@ -81,7 +81,7 @@ const CategoryItem = ({
{hasChildren && (
<motion.div
initial={false}
animate={{ rotate: isOpen ? 180 : 0 }}
animate={{ rotate: isOpen ? 90 : 180 }}
transition={{ duration: 0.2 }}
>
<ChevronRight className="h-4 w-4" />

View File

@ -2,11 +2,12 @@ import { ReactElement } from "react";
import { Separator } from "@/components/ui/separator";
import { getDocsContent } from "@/lib/mdx";
import SidebarLinks from "@/components/sidebar/sidebar-links";
import ThemeSwitcher from "@/components/theme-switcher";
const Sidebar = (): ReactElement => {
const pages: DocsContentMetadata[] = getDocsContent();
return (
<div className="w-52 py-3 flex flex-col justify-between">
<div className="min-w-32 w-44 py-3 flex flex-col justify-between">
{/* Links */}
<div className="flex flex-col">
<SidebarLinks pages={pages} />
@ -15,7 +16,7 @@ const Sidebar = (): ReactElement => {
{/* Theme Switcher */}
<div className="flex flex-col">
<Separator className="mb-3" />
<span>Theme Switcher</span>
<ThemeSwitcher />
</div>
</div>
);

View File

@ -0,0 +1,62 @@
"use client";
import { ReactElement, useEffect, useState } from "react";
import { MoonStar, Sun } from "lucide-react";
import { useTheme } from "next-themes";
import { Button } from "@/components/ui/button";
import { motion } from "framer-motion";
import { UseThemeProps } from "next-themes/dist/types";
import { capitalizeWords } from "@/lib/string";
/**
* The theme switcher component.
*
* @return the switcher jsx
*/
const ThemeSwitcher = (): ReactElement => {
const [mounted, setMounted] = useState(false);
const { theme, setTheme }: UseThemeProps = useTheme();
const isLight = theme === "light";
useEffect(() => {
setMounted(true);
}, []);
return mounted ? (
<Button
className="p-1.5 flex gap-7 items-center hover:opacity-85"
variant="ghost"
onClick={() => setTheme(isLight ? "dark" : "light")}
>
<div className="relative flex items-center">
<motion.div
className="absolute"
initial={{ rotate: 0, scale: 1 }}
animate={{
rotate: isLight ? 0 : -90,
scale: isLight ? 1 : 0,
}}
transition={{ duration: 0.5 }}
>
<Sun className="w-[1.2rem] h-[1.2rem]" />
</motion.div>
<motion.div
className="absolute"
initial={{ rotate: 90, scale: 0 }}
animate={{
rotate: isLight ? 90 : 0,
scale: isLight ? 0 : 1,
}}
transition={{ duration: 0.5 }}
>
<MoonStar className="w-[1.2rem] h-[1.2rem]" />
</motion.div>
</div>
<span className="font-semibold">{capitalizeWords(theme)}</span>
</Button>
) : (
<></>
);
};
export default ThemeSwitcher;

10
src/lib/string.ts Normal file
View File

@ -0,0 +1,10 @@
/**
* Capitalize the first letter of
* each word in the given string.
*
* @param str the string to capitalize
* @return the capitalized string
*/
export const capitalizeWords = (str: string | undefined): string | undefined =>
str &&
str.toLowerCase().replace(/\b\w/g, (char: string) => char.toUpperCase());