Skip to content

Commit

Permalink
Merge pull request #86 from dolthub/taylor/nav
Browse files Browse the repository at this point in the history
components: Navbar
  • Loading branch information
tbantle22 authored Mar 29, 2024
2 parents 7c281c1 + 5421901 commit 41b1ed2
Show file tree
Hide file tree
Showing 10 changed files with 588 additions and 2 deletions.
2 changes: 1 addition & 1 deletion packages/components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"name": "DoltHub"
},
"description": "A collection of React components for common tasks",
"version": "0.1.11",
"version": "0.1.12",
"repository": {
"type": "git",
"url": "git+https://github.com/dolthub/react-library.git"
Expand Down
79 changes: 79 additions & 0 deletions packages/components/src/Navbar/ForDesktop/index.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
.container {
@apply hidden lg:block w-full text-white pt-2 h-12 z-50 mx-auto pb-2;
}

.inner {
@apply flex justify-between items-center h-full px-6 w-full;

a,
button {
@apply text-sm font-normal tracking-wide text-white/90 hover:text-blue-200;
}

a {
@apply flex items-center;
> svg {
@apply mr-3;
}
}
}

.large {
@apply h-16 px-8;

a,
button {
@apply text-base;
}
}

.left {
@apply flex w-1/3 ml-2 order-first;

a {
@apply ml-2 mr-10;
}
}

.logo {
img {
@apply max-h-6 max-w-60;
}
}

.right {
@apply flex justify-end mr-2 w-1/3;

a {
@apply mr-2 ml-10;
}
}

.dark {
@apply text-background-acc-1;

a,
button {
@apply text-background-acc-1 font-semibold;

&:hover {
@apply text-primary text-opacity-80;
}
}
}

.logoLeft {
@apply justify-start relative;

.left {
@apply order-2 w-auto ml-6;
}

.logo {
@apply order-first ml-3 mr-3;
}

.right {
@apply order-3 w-auto absolute right-0 mr-8;
}
}
35 changes: 35 additions & 0 deletions packages/components/src/Navbar/ForDesktop/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import cx from "classnames";
import React, { ReactNode } from "react";
import css from "./index.module.css";

type Props = {
leftLinks: ReactNode;
logo: ReactNode;
rightLinks: ReactNode;
bgColor?: string;
large?: boolean;
dark?: boolean;
logoLeft?: boolean;
};

export default function DesktopNavbar(props: Props) {
return (
<header
className={cx(css.container, props.bgColor ?? "bg-background-acc-1", {
[css.large]: props.large,
[css.dark]: props.dark,
})}
>
<div
className={cx(css.inner, {
[css.dark]: props.dark,
[css.logoLeft]: props.logoLeft,
})}
>
<div className={css.left}>{props.leftLinks}</div>
<div className={css.logo}>{props.logo}</div>
<div className={css.right}>{props.rightLinks}</div>
</div>
</header>
);
}
60 changes: 60 additions & 0 deletions packages/components/src/Navbar/ForMobile/index.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
.container {
@apply lg:hidden;
}

.topContainer {
@apply w-full text-white px-5 py-2 h-14;
}

.top {
@apply flex justify-between items-center;

button {
@apply text-xl p-2.5 text-white hover:text-white/70;
}
}

.darkTop {
button {
@apply text-background-acc-1 hover:text-primary;
}
}

.emptyTop {
@apply w-10;
}

.logo {
img {
@apply max-h-7 max-w-56;
}
}

.openMenu {
@apply fixed top-0 bottom-0 left-0 right-0 z-100;
}

.links {
@apply flex flex-col items-center mx-0 mt-10;

a,
button {
@apply text-xl my-4 mx-0 font-semibold tracking-widest text-white/90 hover:text-blue-200;
}
}

.bottomLinks {
@apply absolute left-0 right-0 bottom-8 flex justify-between mx-auto px-8 max-w-xs;

img,
svg {
@apply text-white h-9 w-9;
}
}

.links a {
@apply flex items-center;
> svg {
@apply mr-3;
}
}
114 changes: 114 additions & 0 deletions packages/components/src/Navbar/ForMobile/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import { AiOutlineClose } from "@react-icons/all-files/ai/AiOutlineClose";
import { AiOutlineMenu } from "@react-icons/all-files/ai/AiOutlineMenu";
import cx from "classnames";
import React, { ReactNode, useState } from "react";
import Btn from "../../Btn";
import css from "./index.module.css";

type CommonProps = {
logo: ReactNode;
bgColor?: string;
};

type Props = CommonProps & {
dark?: boolean;
children: ReactNode;
mobileBottomLinks?: ReactNode;
};

export default function ForMobile(props: Props) {
const [open, setOpen] = useState(false);

return (
<header className={css.container}>
<Top
{...props}
className={cx({
[css.darkTop]: props.dark,
})}
icon={
<Btn
onClick={() => setOpen(true)}
data-cy="mobile-navbar-menu-button"
aria-label="open mobile navbar menu"
>
<AiOutlineMenu />
</Btn>
}
/>
{open && (
<NavMenu {...props} onClose={() => setOpen(false)}>
{props.children}
</NavMenu>
)}
</header>
);
}

type NavProps = CommonProps & {
onClose: () => void;
children: ReactNode;
mobileBottomLinks?: ReactNode;
};

function NavMenu(props: NavProps) {
return (
<div
className={cx(css.openMenu, getBgColor(props.bgColor, true))}
aria-label="mobile nav menu"
>
<Top
{...props}
icon={
<Btn
onClick={props.onClose}
data-cy="mobile-navbar-close-button"
aria-label="close mobile navbar menu"
>
<AiOutlineClose />
</Btn>
}
/>
<div className={css.links}>{props.children}</div>
{props.mobileBottomLinks && (
<div className={css.bottomLinks} data-cy="mobile-navbar-social-links">
{props.mobileBottomLinks}
</div>
)}
</div>
);
}

type TopProps = CommonProps & {
icon: ReactNode;
className?: string;
};

function Top(props: TopProps) {
return (
<div
className={cx(
css.topContainer,
getBgColor(props.bgColor),
props.className,
)}
aria-label="mobile navbar top"
>
<div className={css.top}>
{props.icon}
<div className={css.logo}>{props.logo}</div>
<div className={css.emptyTop} />
</div>
</div>
);
}

function getBgColor(bgColor?: string, forMenu = false): string {
if (bgColor) {
if (bgColor === "bg-transparent" && forMenu) {
return "bg-background-acc-1";
}
return bgColor;
}
return "bg-background-acc-1";
}
44 changes: 44 additions & 0 deletions packages/components/src/Navbar/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import React, { ReactNode } from "react";
import DesktopNavbar from "./ForDesktop";
import MobileNavbar from "./ForMobile";

type Props = {
leftLinks: ReactNode;
rightLinks: ReactNode;
logo: ReactNode;
bgColor?: string;
dark?: boolean;

// Desktop-only
large?: boolean;
logoLeft?: boolean;

// Mobile-only
mobileBottomLinks?: ReactNode;
rightLinksMobile?: ReactNode; // Overrides `rightLinks` for mobile
};

export default function Navbar(props: Props) {
return (
<>
<DesktopNavbar
leftLinks={props.leftLinks}
rightLinks={props.rightLinks}
bgColor={props.bgColor}
logo={props.logo}
dark={props.dark}
large={props.large}
logoLeft={props.logoLeft}
/>
<MobileNavbar
bgColor={props.bgColor}
logo={props.logo}
mobileBottomLinks={props.mobileBottomLinks}
dark={props.dark}
>
{props.leftLinks}
{props.rightLinksMobile ?? props.rightLinks}
</MobileNavbar>
</>
);
}
27 changes: 26 additions & 1 deletion packages/components/src/__stories__/MobileFormModal.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { FaDiscord } from "@react-icons/all-files/fa/FaDiscord";
import { FaGithub } from "@react-icons/all-files/fa/FaGithub";
import type { Meta, StoryObj } from "@storybook/react";
import React from "react";
import Button from "../Button";
import ForMobile from "../CommentForm/ForMobile";
import MobileFormModal from "../MobileFormModal";
import MobileNavbar from "../Navbar/ForMobile";

const meta: Meta<typeof MobileFormModal> = {
title: "MobileFormModal",
Expand All @@ -19,7 +22,29 @@ export default meta;
type Story = StoryObj<typeof MobileFormModal>;

const Nav = (
<div className="w-full bg-ld-darkerblue text-white py-1 text-center">Nav</div>
<MobileNavbar
logo={
<img
src="https://dolthub.awsdev.ld-corp.com/blog/static/bd834a2859f2246200c1692940ff1409/222b7/dolt-logo-1.png"
alt="LOGO"
/>
}
mobileBottomLinks={
<>
<a>
<FaGithub />
</a>
<a>
<FaDiscord />
</a>
</>
}
>
<a>Pricing</a>
<a>Blog</a>
<a>Documentation</a>
<Button.Outlined>Sign out</Button.Outlined>
</MobileNavbar>
);

const Form = (
Expand Down
Loading

0 comments on commit 41b1ed2

Please sign in to comment.