Skip to content

Commit 94be5a7

Browse files
seting up dark theme toggle options
1 parent a9b1b35 commit 94be5a7

11 files changed

+1281
-39
lines changed

app/layout.tsx

+19-13
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,30 @@
1+
import type { Metadata } from "next";
2+
import "./globals.css";
3+
import { ThemeProvider } from "@/components/theme-provider";
4+
import Navbar from "@/components/Navbar";
15

2-
import type { Metadata } from "next"
3-
import { poppins, roboto } from "./utils/font";
46

57
export const metadata: Metadata = {
6-
title: 'Mark Portfolio',
7-
description : 'this is description'
8-
}
9-
10-
11-
8+
title: "Create Next App",
9+
description: "Generated by create next app",
10+
};
1211

13-
export default function RootLayout({ children, }: {
12+
export default function RootLayout({
13+
children,
14+
}: Readonly<{
1415
children: React.ReactNode;
15-
}) {
16+
}>) {
1617
return (
1718
<html lang="en">
18-
<head />
19-
<body className={`${roboto} ${poppins}`}>
19+
<body>
20+
<ThemeProvider attribute="class"
21+
defaultTheme="system"
22+
enableSystem
23+
disableTransitionOnChange>
24+
<Navbar />
2025
{children}
26+
</ThemeProvider>
2127
</body>
2228
</html>
23-
)
29+
);
2430
}

app/page.tsx

+12-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,20 @@
1-
import { poppins, roboto } from "./utils/font";
1+
import { ThemeToggle } from "@/components/theme-toggle";
2+
import { poppins, roboto } from "@/font/fonts";
23

34

45
export default function Home() {
56
return (
67
<main>
7-
<h1 className={roboto}>Hello World</h1>
8-
<h1 className={poppins}>Hello World</h1>
8+
9+
10+
11+
12+
{/* <div className='m-5'>
13+
<p className={roboto.className}>Lorem ipsum dolor sit amet consectetur adipisicing elit. Natus at voluptatum est sint corporis ea dolorem tenetur? Voluptatibus quisquam atque perspiciatis, veritatis enim harum omnis! Iste atque, sunt eveniet, id porro voluptatum eum ipsum quia magni modi beatae placeat! Veritatis eligendi distinctio animi inventore fuga quo odit corrupti perferendis consectetur repudiandae quibusdam, ut, consequuntur quasi totam est incidunt optio quaerat culpa a id necessitatibus vero labore deserunt esse. Quos ullam officia, provident dolores unde saepe delectus quidem sit nihil, necessitatibus amet voluptates quisquam. Ducimus, labore fugiat. Minima sunt ipsum illum dolore quos iure, dolor incidunt dignissimos libero eius eum dolores.</p>
14+
</div>
15+
<div className='m-5'>
16+
<p className={poppins.className}>Lorem ipsum dolor sit amet consectetur adipisicing elit. Quibusdam ad error quidem maxime! Commodi veniam accusantium earum facere aut reprehenderit.</p>
17+
</div> */}
918
</main>
1019
);
1120
}

app/utils/font.ts

-18
This file was deleted.

components/Navbar.tsx

+146
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
'use client';
2+
import { Fragment } from 'react';
3+
import { Disclosure, Menu, Transition } from '@headlessui/react';
4+
import { Bars3Icon, BellIcon, XMarkIcon } from '@heroicons/react/24/outline';
5+
import { ThemeToggle } from './theme-toggle';
6+
7+
const navigation = [
8+
{ name: 'Home', href: '#', current: true },
9+
{ name: 'About Me', href: '#', current: false },
10+
{ name: 'My Works', href: '#', current: false },
11+
{ name: 'Contact Me', href: '#', current: false },
12+
];
13+
14+
function classNames(...classes: (string | undefined | null | false)[]): string {
15+
return classes.filter(Boolean).join(' ');
16+
}
17+
18+
export default function Navbar() {
19+
return (
20+
<Disclosure as="nav" className="">
21+
{({ open }) => (
22+
<>
23+
<div className="mx-auto max-w-7xl px-2 sm:px-6 lg:px-8">
24+
<div className="relative flex h-16 items-center justify-between">
25+
<div className="absolute inset-y-0 left-0 flex items-center sm:hidden">
26+
{/* Mobile menu button*/}
27+
<Disclosure.Button className="relative inline-flex items-center justify-center rounded-md p-2 text-gray-400 hover:bg-gray-700 hover:text-white focus:outline-none focus:ring-2 focus:ring-inset focus:ring-white">
28+
<span className="absolute -inset-0.5" />
29+
<span className="sr-only">Open main menu</span>
30+
{open ? (
31+
<XMarkIcon className="block h-6 w-6" aria-hidden="true" />
32+
) : (
33+
<Bars3Icon className="block h-6 w-6" aria-hidden="true" />
34+
)}
35+
</Disclosure.Button>
36+
</div>
37+
<div className="flex flex-1 items-center justify-center sm:items-stretch sm:justify-start">
38+
<div className="flex flex-shrink-0 items-center">
39+
<h1 className="">Mark.Z</h1>
40+
</div>
41+
<div className="hidden sm:ml-6 sm:block">
42+
<div className="flex space-x-4">
43+
{navigation.map(item => (
44+
<a
45+
key={item.name}
46+
href={item.href}
47+
className={classNames(
48+
item.current
49+
? 'bg-gray-900 text-white'
50+
: 'text-gray-300 hover:bg-gray-700 hover:text-white',
51+
'rounded-md px-3 py-2 text-sm font-medium'
52+
)}
53+
aria-current={item.current ? 'page' : undefined}
54+
>
55+
{item.name}
56+
</a>
57+
))}
58+
</div>
59+
</div>
60+
</div>
61+
<div className="absolute inset-y-0 right-0 flex items-center pr-2 sm:static sm:inset-auto sm:ml-6 sm:pr-0">
62+
<Menu as="div" className="relative ml-3">
63+
<div>
64+
<ThemeToggle />
65+
</div>
66+
<Transition
67+
as={Fragment}
68+
enter="transition ease-out duration-100"
69+
enterFrom="transform opacity-0 scale-95"
70+
enterTo="transform opacity-100 scale-100"
71+
leave="transition ease-in duration-75"
72+
leaveFrom="transform opacity-100 scale-100"
73+
leaveTo="transform opacity-0 scale-95"
74+
>
75+
<Menu.Items className="absolute right-0 z-10 mt-2 w-48 origin-top-right rounded-md bg-white py-1 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none">
76+
<Menu.Item>
77+
{({ active }) => (
78+
<a
79+
href="#"
80+
className={classNames(
81+
active ? 'bg-gray-100' : '',
82+
'block px-4 py-2 text-sm text-gray-700'
83+
)}
84+
>
85+
Your Profile
86+
</a>
87+
)}
88+
</Menu.Item>
89+
<Menu.Item>
90+
{({ active }) => (
91+
<a
92+
href="#"
93+
className={classNames(
94+
active ? 'bg-gray-100' : '',
95+
'block px-4 py-2 text-sm text-gray-700'
96+
)}
97+
>
98+
Settings
99+
</a>
100+
)}
101+
</Menu.Item>
102+
<Menu.Item>
103+
{({ active }) => (
104+
<a
105+
href="#"
106+
className={classNames(
107+
active ? 'bg-gray-100' : '',
108+
'block px-4 py-2 text-sm text-gray-700'
109+
)}
110+
>
111+
Sign out
112+
</a>
113+
)}
114+
</Menu.Item>
115+
</Menu.Items>
116+
</Transition>
117+
</Menu>
118+
</div>
119+
</div>
120+
</div>
121+
122+
<Disclosure.Panel className="sm:hidden">
123+
<div className="space-y-1 px-2 pb-3 pt-2">
124+
{navigation.map(item => (
125+
<Disclosure.Button
126+
key={item.name}
127+
as="a"
128+
href={item.href}
129+
className={classNames(
130+
item.current
131+
? 'bg-gray-900 text-white'
132+
: 'text-gray-300 hover:bg-gray-700 hover:text-white',
133+
'block rounded-md px-3 py-2 text-base font-medium'
134+
)}
135+
aria-current={item.current ? 'page' : undefined}
136+
>
137+
{item.name}
138+
</Disclosure.Button>
139+
))}
140+
</div>
141+
</Disclosure.Panel>
142+
</>
143+
)}
144+
</Disclosure>
145+
);
146+
}

components/theme-provider.tsx

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
"use client"
2+
3+
import * as React from "react"
4+
import { ThemeProvider as NextThemesProvider } from "next-themes"
5+
import { type ThemeProviderProps } from "next-themes/dist/types"
6+
7+
export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
8+
return <NextThemesProvider {...props}>{children}</NextThemesProvider>
9+
}

components/theme-toggle.tsx

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
"use client"
2+
3+
import * as React from "react"
4+
import { MoonIcon, SunIcon } from "lucide-react"
5+
import { useTheme } from "next-themes"
6+
7+
import { Button } from "@/components/ui/button"
8+
import {
9+
DropdownMenu,
10+
DropdownMenuContent,
11+
DropdownMenuItem,
12+
DropdownMenuTrigger,
13+
} from "@/components/ui/dropdown-menu"
14+
15+
export function ThemeToggle() {
16+
const { setTheme } = useTheme()
17+
18+
return (
19+
<DropdownMenu>
20+
<DropdownMenuTrigger asChild>
21+
<Button variant="outline" size="icon">
22+
<SunIcon className="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
23+
<MoonIcon className="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
24+
<span className="sr-only">Toggle theme</span>
25+
</Button>
26+
</DropdownMenuTrigger>
27+
<DropdownMenuContent align="end">
28+
<DropdownMenuItem onClick={() => setTheme("light")}>
29+
Light
30+
</DropdownMenuItem>
31+
<DropdownMenuItem onClick={() => setTheme("dark")}>
32+
Dark
33+
</DropdownMenuItem>
34+
<DropdownMenuItem onClick={() => setTheme("system")}>
35+
System
36+
</DropdownMenuItem>
37+
</DropdownMenuContent>
38+
</DropdownMenu>
39+
)
40+
}

components/ui/button.tsx

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import * as React from "react"
2+
import { Slot } from "@radix-ui/react-slot"
3+
import { cva, type VariantProps } from "class-variance-authority"
4+
5+
import { cn } from "@/lib/utils"
6+
7+
const buttonVariants = cva(
8+
"inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
9+
{
10+
variants: {
11+
variant: {
12+
default: "bg-primary text-primary-foreground hover:bg-primary/90",
13+
destructive:
14+
"bg-destructive text-destructive-foreground hover:bg-destructive/90",
15+
outline:
16+
"border border-input bg-background hover:bg-accent hover:text-accent-foreground",
17+
secondary:
18+
"bg-secondary text-secondary-foreground hover:bg-secondary/80",
19+
ghost: "hover:bg-accent hover:text-accent-foreground",
20+
link: "text-primary underline-offset-4 hover:underline",
21+
},
22+
size: {
23+
default: "h-10 px-4 py-2",
24+
sm: "h-9 rounded-md px-3",
25+
lg: "h-11 rounded-md px-8",
26+
icon: "h-10 w-10",
27+
},
28+
},
29+
defaultVariants: {
30+
variant: "default",
31+
size: "default",
32+
},
33+
}
34+
)
35+
36+
export interface ButtonProps
37+
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
38+
VariantProps<typeof buttonVariants> {
39+
asChild?: boolean
40+
}
41+
42+
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
43+
({ className, variant, size, asChild = false, ...props }, ref) => {
44+
const Comp = asChild ? Slot : "button"
45+
return (
46+
<Comp
47+
className={cn(buttonVariants({ variant, size, className }))}
48+
ref={ref}
49+
{...props}
50+
/>
51+
)
52+
}
53+
)
54+
Button.displayName = "Button"
55+
56+
export { Button, buttonVariants }

0 commit comments

Comments
 (0)