Skip to content

Commit

Permalink
add theme switcher
Browse files Browse the repository at this point in the history
  • Loading branch information
sownt committed Jun 17, 2024
1 parent f08bce0 commit 64ec349
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 67 deletions.
17 changes: 9 additions & 8 deletions app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./globals.css";
import type { Metadata } from 'next';
import { Inter } from 'next/font/google';
import './globals.css';

const inter = Inter({ subsets: ["latin"] });
const inter = Inter({ subsets: ['latin'] });

export const metadata: Metadata = {
title: "Google I/O Extended Cloud Hanoi 2024",
description: "I/O Extended is a series of community-hosted, global events by Google Developer Groups and each event can vary in its format.",
title: 'Google I/O Extended Cloud Hanoi 2024',
description:
'I/O Extended is a series of community-hosted, global events by Google Developer Groups and each event can vary in its format.',
};

export default function RootLayout({
Expand All @@ -15,8 +16,8 @@ export default function RootLayout({
children: React.ReactNode;
}>) {
return (
<html lang="en">
<body className={[inter.className, ''].join(' ')}>{children}</body>
<html className="scroll-smooth" lang="en">
<body className={inter.className}>{children}</body>
</html>
);
}
107 changes: 60 additions & 47 deletions app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,43 +16,49 @@ import hero_mobile_dark from '@/public/hero/home_hero_mobile_dark.svg';
import googlefordevelopers from '@/public/googlefordevelopers.svg';
import MobileNavBar from '@/components/navbar/MobileNavBar';
import Link from 'next/link';
import ThemeSwitcher from '@/components/ThemeSwitcher';

export default function Home() {
return (
<div className="relative isolate flex flex-col min-h-svh w-full bg-white lg:bg-zinc-100 dark:bg-zinc-900 dark:lg:bg-zinc-950">
{/* Nav */}
<div className="inset-x-0 top-0 max-lg:hidden dark:text-white">
<nav className="mx-auto max-w-6xl px-4 flex flex-1 items-center gap-8 py-2.5">
<span className="relative">
<Image
className="dark:hidden w-64"
src={logo}
alt="Google I/O Extended Cloud Hanoi 2024"
/>
<Image
className="hidden dark:inline w-64"
src={logo_white}
alt="Google I/O Extended Cloud Hanoi 2024"
/>
</span>
{/* <div className="max-lg:hidden h-6 w-px bg-zinc-950/10 dark:bg-white/10"></div> */}
<Link href={'/'}>
<span className="relative">
<Image
className="dark:hidden w-64"
src={logo}
alt="Google I/O Extended Cloud Hanoi 2024"
/>
<Image
className="hidden dark:inline w-64"
src={logo_white}
alt="Google I/O Extended Cloud Hanoi 2024"
/>
</span>
</Link>
<div className="max-lg:hidden h-6 w-px bg-zinc-950/10 dark:bg-white/10"></div>
<div className="max-lg:hidden flex items-center gap-8">
{/* <span className="relative">
<Link href="#">Explore</Link>
<span className="relative">
<Link href="#info">Thông tin</Link>
</span>
<span className="relative">
<Link href="#">Lịch trình</Link>
</span>
<span className="relative">
<Link href="#">Community</Link>
<Link href="#">Diễn giả</Link>
</span>
<span className="relative">
<Link href="#">About</Link>
</span> */}
<Link href="#">Tham gia</Link>
</span>
<span className="relative">
<Link href="#">Liên hệ</Link>
</span>
</div>
<div className="-ml-4 flex-1"></div>
<div className="flex items-center">
<Button>
<TicketIcon />
Đăng ký
</Button>
<div className="flex items-center gap-4">
<ThemeSwitcher />
</div>
</nav>
</div>
Expand All @@ -62,12 +68,15 @@ export default function Home() {
<main>
{/* Hero Section */}
<div className="mx-auto max-w-6xl flex flex-col md:flex-row overflow-hidden bg-grey-bg dark:bg-grey border-b-[1px] md:border-b-2 border-grey dark:border-grey-bg">
<div className="flex flex-col md:justify-center px-8 py-5 w-full md:w-2/5 md:p-10 md:pr-0 dark:text-white z-10 text-center md:text-left items-center md:items-start">
<div className="flex flex-col md:justify-center px-8 py-16 w-full md:w-2/5 md:p-10 md:pr-0 dark:text-white z-10 text-center md:text-left items-center md:items-start">
<h1 className="text-2xl sm:text-4xl font-semibold mb-4 sm:s-h3 md:l-h1-2">
Cùng cập nhật những công nghệ mới nhất về Cloud, AI và ML từ Google I/O
Cùng cập nhật những công nghệ mới nhất về Cloud, AI và ML từ
Google I/O
</h1>
<p className="font-normal text-justify sm:s-h6 md:l-h6 mb-4">
Tại sự kiện Google I/O Extended Cloud Hanoi 2024, phiên bản mở rộng của sự kiện Google I/O dành cho các lập trình viên và những người yêu thích công nghệ tại Việt Nam.
Tại sự kiện Google I/O Extended Cloud Hanoi 2024, phiên bản mở
rộng của sự kiện Google I/O dành cho các lập trình viên và những
người yêu thích công nghệ tại Việt Nam.
</p>
<Button>
<TicketIcon />
Expand Down Expand Up @@ -98,38 +107,40 @@ export default function Home() {
</div>
</div>
{/* End Hero Section */}
<div className="rounded-4xl bg-neutral-950 dark:bg-slate-50 py-20 sm:py-32">
<div className="rounded-4xl bg-neutral-900 py-20 sm:py-32">
<div className="mx-auto max-w-6xl px-8">
<div className="flex items-center gap-x-8">
<h2 className="text-center font-display text-sm font-semibold tracking-wider text-white dark:text-zinc-900 sm:text-left">
<h2 className="text-center font-display text-sm font-semibold tracking-wider text-white sm:text-left">
Đồng hành cùng chúng tôi
</h2>
<div className="h-px flex-auto bg-neutral-800"></div>
</div>
<div>
<ul className="mt-10 grid grid-cols-2 gap-x-8 gap-y-10 lg:grid-cols-4">
{Array.from({ length: 8 }, (_, i) => (
{Array.from({ length: 7 }, (_, i) => (
<li key={i}>
<span className="relative">
<Image
className="dark:hidden w-64"
className="w-64"
src={logo_white}
alt="Google I/O Extended Cloud Hanoi 2024"
/>
<Image
className="hidden dark:inline w-64"
src={logo}
alt="Google I/O Extended Cloud Hanoi 2024"
/>
</span>
</li>
))}
<li key={8} className='justify-center items-center'>
<span className="relative text-white font-bold w-64">
Salonpas
</span>
</li>
</ul>
</div>
</div>
</div>

<div className="mx-auto max-w-6xl px-8 mt-24 sm:mt-32 lg:mt-40 text-neutral-950 dark:text-gray-50">
<div
id="info"
className="mx-auto max-w-6xl px-8 mt-24 sm:mt-32 lg:mt-40 text-neutral-950 dark:text-gray-50">
<h2>
<span className="block font-display tracking-tight [text-wrap:balance] text-4xl font-medium sm:text-5xl">
Hẹn gặp bạn
Expand All @@ -140,15 +151,17 @@ export default function Home() {
</div>
<div className="grid grid-cols-1 gap-8 lg:grid-cols-3 mt-16">
<div className="flex">
<article className="relative flex w-full flex-col rounded-3xl p-6 ring-1 ring-neutral-950/5 transition bg-neutral-50 hover:bg-white dark:bg-zinc-900 dark:hover:bg-zinc-800 sm:p-8">
<MapPinIcon className="w-8" />
<p className="mt-6 font-display text-2xl font-semibold ">
Hội trường A2, Học viện Công nghệ Bưu chính viễn thông
</p>
<p className="mt-4 text-base">
Km 10 đường Nguyễn Trãi, P.Mộ Lao, Q.Hà Đông, Hà Nội
</p>
</article>
<Link href={'https://maps.app.goo.gl/G2hxgtVqWbVGmb5R9'} rel="noopener noreferrer" target="_blank">
<article className="relative flex w-full flex-col rounded-3xl p-6 ring-1 ring-neutral-950/5 transition bg-neutral-50 hover:bg-white dark:bg-zinc-900 dark:hover:bg-zinc-800 sm:p-8">
<MapPinIcon className="w-8" />
<p className="mt-6 font-display text-2xl font-semibold ">
Hội trường A2, Học viện Công nghệ Bưu chính viễn thông
</p>
<p className="mt-4 text-base">
96A Đường Trần Phú, P. Mộ Lao, Hà Đông, Hà Nội
</p>
</article>
</Link>
</div>
<div className="flex">
<article className="relative flex w-full flex-col rounded-3xl p-6 ring-1 ring-neutral-950/5 transition bg-neutral-50 hover:bg-white dark:bg-zinc-900 dark:hover:bg-zinc-800 sm:p-8">
Expand Down Expand Up @@ -177,15 +190,15 @@ export default function Home() {
</main>
<footer className="mt-24 sm:mt-32 lg:mt-40 pt-10 pb-16 lg:py-10 px-7 lg:px-16 bg-black flex flex-col lg:flex-row lg:justify-between lg:items-center w-max-full">
<div className="flex flex-col lg:flex-row items-start lg:items-center space-y-6 lg:space-y-0 lg:space-x-6 text-grey-500 text-[16px] font-medium flex-1">
<div className="text-2xl font-semibold lg:mr-6 text-grey-500 flex justify-between w-full mb-4 lg:mb-0 lg:w-auto items-center">
<div className="text-2xl font-semibold lg:mr-6 text-grey-500 flex justify-center lg:justify-between w-full mb-4 lg:mb-0 lg:w-auto items-center">
<Image
className="w-32"
src={googlefordevelopers}
alt="Google for Developers"
/>
</div>
</div>
<div className="flex lg:justify-self-end lg:justify-end mt-12 lg:mt-0 text-slate-200">
<div className="flex items-center justify-center lg:justify-self-end lg:justify-end mt-8 lg:mt-0 text-slate-200">
<Link href="#" className="p-3">
Facebook
</Link>
Expand Down
32 changes: 32 additions & 0 deletions components/ThemeSwitcher.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { useTheme } from '@/hooks/useTheme';

const ThemeSwitcher = () => {
const { toggleMode } = useTheme();

return (
<button
onClick={toggleMode}
className="inline-flex text-zinc-300 outline-blue-500 hover:text-zinc-400 dark:text-zinc-500 dark:hover:text-zinc-400">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
className="size-5 dark:hidden">
<path
fillRule="evenodd"
d="M9.528 1.718a.75.75 0 0 1 .162.819A8.97 8.97 0 0 0 9 6a9 9 0 0 0 9 9 8.97 8.97 0 0 0 3.463-.69.75.75 0 0 1 .981.98 10.503 10.503 0 0 1-9.694 6.46c-5.799 0-10.5-4.7-10.5-10.5 0-4.368 2.667-8.112 6.46-9.694a.75.75 0 0 1 .818.162Z"
clipRule="evenodd"
/>
</svg>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
className="size-5 hidden dark:inline">
<path d="M12 2.25a.75.75 0 0 1 .75.75v2.25a.75.75 0 0 1-1.5 0V3a.75.75 0 0 1 .75-.75ZM7.5 12a4.5 4.5 0 1 1 9 0 4.5 4.5 0 0 1-9 0ZM18.894 6.166a.75.75 0 0 0-1.06-1.06l-1.591 1.59a.75.75 0 1 0 1.06 1.061l1.591-1.59ZM21.75 12a.75.75 0 0 1-.75.75h-2.25a.75.75 0 0 1 0-1.5H21a.75.75 0 0 1 .75.75ZM17.834 18.894a.75.75 0 0 0 1.06-1.06l-1.59-1.591a.75.75 0 1 0-1.061 1.06l1.59 1.591ZM12 18a.75.75 0 0 1 .75.75V21a.75.75 0 0 1-1.5 0v-2.25A.75.75 0 0 1 12 18ZM7.758 17.303a.75.75 0 0 0-1.061-1.06l-1.591 1.59a.75.75 0 0 0 1.06 1.061l1.591-1.59ZM6 12a.75.75 0 0 1-.75.75H3a.75.75 0 0 1 0-1.5h2.25A.75.75 0 0 1 6 12ZM6.697 7.757a.75.75 0 0 0 1.06-1.06l-1.59-1.591a.75.75 0 0 0-1.061 1.06l1.59 1.591Z" />
</svg>
</button>
);
};

export default ThemeSwitcher;
26 changes: 14 additions & 12 deletions components/navbar/MobileNavBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import logo from '@/public/logo.png';
import logo_white from '@/public/logo_white.png';
import Image from 'next/image';
import Link from 'next/link';
import ThemeSwitcher from '../ThemeSwitcher';

export default function MobileNavBar() {
const [isOpen, setIsOpen] = useState(false);
Expand All @@ -25,7 +26,20 @@ export default function MobileNavBar() {
</Button>
</span>
</div>
<span className="w-32 inline-grid shrink-0 align-middle *:col-start-1 *:row-start-1">
<Image
className="dark:hidden w-64"
src={logo}
alt="Google I/O Extended Cloud Hanoi 2024"
/>
<Image
className="hidden dark:inline w-64"
src={logo_white}
alt="Google I/O Extended Cloud Hanoi 2024"
/>
</span>
<div className="flex-1"></div>
<ThemeSwitcher />
<Dialog
open={isOpen}
onClose={() => setIsOpen(false)}
Expand All @@ -39,18 +53,6 @@ export default function MobileNavBar() {
{/* Header */}
<div className="flex flex-col border-b border-zinc-950/5 p-4 dark:border-white/5 [&>[data-slot=section]+[data-slot=section]]:mt-2.5">
<div className="cursor-default flex w-full items-center gap-3 rounded-lg px-2 py-2.5 text-left text-base/6 font-medium text-zinc-950 sm:py-2 sm:text-sm/5 data-[slot=icon]:*:size-6 data-[slot=icon]:*:shrink-0 data-[slot=icon]:*:fill-zinc-500 sm:data-[slot=icon]:*:size-5 data-[slot=icon]:last:*:ml-auto data-[slot=icon]:last:*:size-5 sm:data-[slot=icon]:last:*:size-4 data-[slot=avatar]:*:-m-0.5 data-[slot=avatar]:*:size-7 data-[slot=avatar]:*:[--ring-opacity:10%] sm:data-[slot=avatar]:*:size-6 data-[hover]:bg-zinc-950/5 data-[slot=icon]:*:data-[hover]:fill-zinc-950 data-[active]:bg-zinc-950/5 data-[slot=icon]:*:data-[active]:fill-zinc-950 data-[slot=icon]:*:data-[current]:fill-zinc-950 dark:text-white dark:data-[slot=icon]:*:fill-zinc-400 dark:data-[hover]:bg-white/5 dark:data-[slot=icon]:*:data-[hover]:fill-white dark:data-[active]:bg-white/5 dark:data-[slot=icon]:*:data-[active]:fill-white dark:data-[slot=icon]:*:data-[current]:fill-white">
<span className="w-32 inline-grid shrink-0 align-middle *:col-start-1 *:row-start-1">
<Image
className="dark:hidden w-64"
src={logo}
alt="Google I/O Extended Cloud Hanoi 2024"
/>
<Image
className="hidden dark:inline w-64"
src={logo_white}
alt="Google I/O Extended Cloud Hanoi 2024"
/>
</span>
<span className="truncate flex-grow"></span>
<span className="relative">
<Button
Expand Down
30 changes: 30 additions & 0 deletions hooks/useTheme.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { useEffect, useState } from 'react';

export function useTheme() {
const [colorScheme, setState] = useState(() => {
try {
if (typeof window !== 'undefined') {
const theme = window.localStorage.theme;
return theme;
}
} catch (error) {
return 'light';
}
});

useEffect(() => {
const root = window.document.documentElement;
if (colorScheme === 'dark') {
root.classList.add('dark');
} else {
root.classList.remove('dark');
}
localStorage.setItem('theme', colorScheme);
}, [colorScheme]);

const toggleMode = () => {
setState(colorScheme === 'dark' ? 'light' : 'dark');
};

return { colorScheme, toggleMode };
}

0 comments on commit 64ec349

Please sign in to comment.