Skip to content

Commit

Permalink
feat(header): add a header component
Browse files Browse the repository at this point in the history
  • Loading branch information
rikhall1515 committed Apr 19, 2024
1 parent 6ebaf15 commit cffd153
Show file tree
Hide file tree
Showing 19 changed files with 695 additions and 0 deletions.
66 changes: 66 additions & 0 deletions components/header/header.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

:root {
--header-height: 8rem;
--header-height-scrolled: 4.5rem;
}

@layer base {
header.scrolled {
height: var(--header-height-scrolled);

@apply border-border;
@apply bg-background;
}

.menuBtn {
--size: 1.5rem;
--duration: 250ms;

position: relative;
transform: rotate(0deg);
transition: var(--duration) * 2 ease-in-out;
}

.menuBtn > span {
display: block;
height: calc(var(--size) / 4);
left: 0;
opacity: 1;
position: absolute;
transform: rotate(0deg);
transition: var(--duration) ease-in-out;
width: var(--size);

@apply bg-foreground;
}

.menuBtn span:nth-child(1) {
top: 0;
}

.menuBtn span:nth-child(2) {
top: calc(var(--size) / 4 + var(--size) / 8);
}

.menuBtn span:nth-child(3) {
top: calc(var(--size) / 2 + var(--size) / 4);
}

.menuBtn.opened span:nth-child(1) {
top: calc(var(--size) / 4 + var(--size) / 8);
transform: rotate(135deg);
}

.menuBtn.opened span:nth-child(2) {
left: -60px;
opacity: 0;
}

.menuBtn.opened span:nth-child(3) {
top: calc(var(--size) / 4 + var(--size) / 8);
transform: rotate(-135deg);
}
}
20 changes: 20 additions & 0 deletions components/header/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import Logo from "./logo";
import Nav from "./menu";
import Sidebar from "./sidebar";
import JumpToContent from "./util/jumpToContent";
import HeaderWrapper from "./util/wrapper";

export default function Header() {
return (
<>
<JumpToContent />
<HeaderWrapper>
<div className="flex items-center gap-12">
<Logo />
<Nav />
</div>
<Sidebar />
</HeaderWrapper>
</>
);
}
28 changes: 28 additions & 0 deletions components/header/logo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"use client";
import BaseLogo from "@/components/logo";
import { useSidebarContext } from "@/context/sidebar";
import { env } from "@/env/client";
import { cn } from "@/lib/utils";

export default function Logo() {
const sidebar = useSidebarContext();
return (
<>
<a
href="/"
className={cn(
"h-8",
"z-30 flex items-center gap-3",
"text-base font-extrabold tracking-[0.2em]",
sidebar.isExpanded
? "text-foreground md:text-white"
: "text-foreground"
)}
>
<BaseLogo />
<span className="text-3xl">/</span>
<span>{env.NEXT_PUBLIC_SITE_NAME}</span>
</a>
</>
);
}
53 changes: 53 additions & 0 deletions components/header/menu/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
"use client";
// import Link from "next/link";
// import { usePathname } from "next/navigation";

import {
NavigationMenu,
//NavigationMenuItem,
//NavigationMenuLink,
NavigationMenuList,
//navigationMenuTriggerStyle,
} from "@/components/ui/navigation-menu";
// import { cn } from "@/lib/utils";

export default function Nav() {
// const router = usePathname();
return (
<>
<NavigationMenu className="hidden lg:block">
<NavigationMenuList className="gap-6">
{/* <NavigationMenuItem>
<NavigationMenuTrigger>Item One</NavigationMenuTrigger>
<NavigationMenuContent>
<NavigationMenuLink>Link</NavigationMenuLink>
</NavigationMenuContent>
</NavigationMenuItem> */}
{/* <NavigationMenuItem>
<Link href="/archive" legacyBehavior passHref className="">
<NavigationMenuLink
className={cn(
navigationMenuTriggerStyle(),
"font-bold",
"data-[active]:bg-primary"
)}
active={"/archive" === router}
>
Archive
</NavigationMenuLink>
</Link>
</NavigationMenuItem> */}
{/* <NavigationMenuItem>
<Link href="/trendy" legacyBehavior passHref>
<NavigationMenuLink
className={cn(navigationMenuTriggerStyle(), "font-bold")}
>
What&apos;s Trendy
</NavigationMenuLink>
</Link>
</NavigationMenuItem> */}
</NavigationMenuList>
</NavigationMenu>
</>
);
}
21 changes: 21 additions & 0 deletions components/header/sidebar/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import Nav from "./nav";
import TopBar from "./topbar";
import BackDrop from "./util/backdrop";
import InnerWrapper from "./util/innerWrapper";
import { MenuButton } from "./util/menuButton";

export default function Sidebar() {
return (
<>
<div className="-mr-6 block h-[4.5rem] fill-[inherit] lg:hidden">
<MenuButton />
<BackDrop />
{/* <SwipeArea /> */}
<InnerWrapper>
<TopBar />
<Nav />
</InnerWrapper>
</div>
</>
);
}
34 changes: 34 additions & 0 deletions components/header/sidebar/nav/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
"use client";
import { FaBoxArchive, FaFileLines } from "react-icons/fa6";

import LogOut from "./logout";
import Privacy from "./privacy";
import SidebarItem from "./sidebarItem";
export default function Nav() {
return (
<>
<nav
aria-label="In-page jump links"
className="flex h-auto w-full flex-col font-bold"
>
{/* <LoginDashboard /> */}
<ul className="w-full">
<li className="w-full border-t-2 border-border">
<SidebarItem href="/archive" text="Archive">
<FaBoxArchive className="h-6 w-6" />
</SidebarItem>
</li>
<li className="w-full border-t-2 border-border">
<SidebarItem href="/terms" text="Terms of Service">
<FaFileLines className="h-6 w-6" />
</SidebarItem>
</li>
<li className="w-full border-y-2 border-border">
<Privacy />
</li>
</ul>
<LogOut />
</nav>
</>
);
}
57 changes: 57 additions & 0 deletions components/header/sidebar/nav/logout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
"use client";
import { type KeyboardEventHandler, useState } from "react";

import { useSidebarContext } from "@/context/sidebar";
import { cn } from "@/lib/utils";

export default function LogOut() {
const [isLoggedIn] = useState(false);
const sidebar = useSidebarContext();
const trapFocus: KeyboardEventHandler<HTMLAnchorElement> = (e) => {
if (e.code === "Tab" && sidebar.btnInSidebarRef.current) {
sidebar.isExpanded && sidebar.btnInSidebarRef.current.focus();
}
};
return (
<>
{isLoggedIn && (
<>
<a
href="/dashboard/logout"
className={cn(
"transition-all",
"m:mb-12 absolute bottom-0 left-0 mb-6 h-[3.75rem] w-full bg-white fill-black text-black",
"flex items-center gap-3",
"hover:bg-[#E0FCE7] hover:fill-primary hover:stroke-primary hover:text-primary"
)}
onKeyDown={trapFocus}
>
<div className="ml-[2.125rem] w-6">
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className="overflow-visible"
>
<path
d="M20 24H4C3.44772 24 3 23.5523 3 23V1C3 0.447715 3.44772 0 4 0H20C20.5523 0 21 0.447716 21 1V23C21 23.5523 20.5523 24 20 24Z"
fill="currentColor"
/>
<path
d="M15 14H8M8 14L9 12M8 14L9 16"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
stroke-linejoin="round"
/>
</svg>
</div>
<span>Logga Ut</span>
</a>
</>
)}
</>
);
}
30 changes: 30 additions & 0 deletions components/header/sidebar/nav/privacy.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
"use client";
import { type KeyboardEventHandler, useState } from "react";
import { FaPassport } from "react-icons/fa6";

import { useSidebarContext } from "@/context/sidebar";

import SidebarItem from "./sidebarItem";

export default function Privacy() {
const sidebar = useSidebarContext();
const [isLoggedIn] = useState(false);
const trapFocus: KeyboardEventHandler<HTMLAnchorElement> = (e) => {
if (e.code === "Tab" && !e.shiftKey && sidebar.mainMenuBtnRef.current) {
e.preventDefault();
sidebar.isExpanded && sidebar.mainMenuBtnRef.current.focus();
}
};
return (
<>
<SidebarItem
href="/privacy/"
text="Privacy Policy"
isLast={!isLoggedIn}
onKeyDown={trapFocus}
>
<FaPassport className="h-6 w-6" />
</SidebarItem>
</>
);
}
67 changes: 67 additions & 0 deletions components/header/sidebar/nav/sidebarItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
"use client";
import Link from "next/link";
import { usePathname } from "next/navigation";
import type { KeyboardEventHandler } from "react";

import { useSidebarContext } from "@/context/sidebar";
import { cn } from "@/lib/utils";

export default function SidebarItem({
href,
classes = "",
text,
isLast = false,
onKeyDown,
children,
}: {
href: string;
classes?: string;
text: string;
isLast?: boolean;
onKeyDown?: KeyboardEventHandler<HTMLAnchorElement> | undefined;
children?: React.ReactNode;
}) {
const sidebar = useSidebarContext();
const pathname = usePathname();
let attr = {};
attr = {
tabIndex: sidebar.isExpanded ? 0 : -1,
onClick: () => sidebar.toggle(),
};
if (isLast) {
attr = {
...attr,
onKeyDown,
};
}
return (
<>
<Link
href={href}
className={cn(
"group/sidebarItem relative h-[3.75rem] w-full transition-all",
"flex items-center gap-3",
pathname === href ? "bg-primary" : "",
"hover:bg-primary",
classes
)}
{...attr}
>
<div
className={cn("ml-[2.125rem] w-6 fill-[inherit] stroke-[inherit]")}
>
{children}
</div>
<span>{text}</span>
<span
aria-hidden="true"
className={cn(
"absolute left-0 h-full w-1 rounded-r-2xl bg-black transition-all",
pathname === href ? "opacity-100" : "opacity-0",
"group-hover/sidebarItem:opacity-100"
)}
></span>
</Link>
</>
);
}
Loading

0 comments on commit cffd153

Please sign in to comment.