Skip to content

Commit

Permalink
Navigation for frontend projects (#353)
Browse files Browse the repository at this point in the history
  • Loading branch information
Franck Gaudin authored Jul 18, 2024
2 parents e43931d + 65b01cc commit 23337b8
Show file tree
Hide file tree
Showing 6 changed files with 158 additions and 7 deletions.
87 changes: 81 additions & 6 deletions apps/docs/app/ui/layout/header/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,97 @@
"use client";

import { useContext, useEffect, useState, useRef, type ReactNode } from "react";
import Link from "next/link";
import { SlotProvider } from "@hopper-ui/components";

import ThemeSwitch from "@/components/themeSwitch/ThemeSwitch";
import IconButton from "@/components/iconButton/IconButton";
import { Icon, ProductMenuIcon } from "@/components/icon";
import { ToggleButton, ToggleButtonContext } from "@/components/toggleButton/ToggleButton.tsx";
import MobileMenu from "@/app/ui/layout/mobileMenu/MobileMenu";
import MobileMenuTrigger from "@/app/ui/layout/mobileMenu/MobileMenuTrigger";
import Nav from "@/app/ui/layout/nav/Nav";
import Wrapper from "@/app/ui/layout/wrapper/Wrapper";
import { Popover, PopoverTrigger, PopoverContext } from "@/components/popover/Popover";
import { useIsMobile } from "@/hooks/useIsMobile";
import { navigation } from "@/configs/navigation";
import { useContext, useEffect, useState } from "react";
import { type ColorScheme, ThemeContext } from "@/context/theme/ThemeProvider.tsx";

import HopperLogo from "./assets/hopper-logo.svg";
import "./header.css";
import { type ColorScheme, ThemeContext } from "@/context/theme/ThemeProvider.tsx";
import { useIsMobile } from "@/hooks/useIsMobile";

const designSystemLinks = [
{
title: "Orbit",
url: "https://orbit.sharegate.design/?path=/docs/installation--page"
},
{
title: "Orbiter",
url: "https://wl-orbiter-website.netlify.app/?path=/docs/installation--page"
},
{
title: "Igloo",
url: "https://igloo.officevibe.design"
}
];

const ToggleTrigger = ({ children }: { children: ReactNode }) => {
const triggerRef = useRef(null);
const [isPopoverOpen, setIsPopoverOpen] = useState(false);

return (
<SlotProvider values={[
[PopoverContext, {
isOpen: isPopoverOpen,
onOpenChange: setIsPopoverOpen,
placement: "bottom start",
offset: 20
}],
[ToggleButtonContext, {
onPress: () => setIsPopoverOpen(!isPopoverOpen),
ref: triggerRef,
isSelected: isPopoverOpen
}]
]}
>
{children}
</SlotProvider>
);
};

const ProductMenuAndBrand = () => {
return (
<span className="hd-product">
<ToggleTrigger>
<PopoverTrigger>
<ToggleButton>
<Icon slot="icon" src={ProductMenuIcon} />
</ToggleButton>
<Popover
className="hd-product__menu"
aria-label="product menu link"
>
<span className="hd-product__title">Frontend tools</span>
<Link className="hd-product__link"
href="https://gsoft-inc.github.io/wl-idp-docs-hub/"
>IDP hub</Link>
<ul className="hd-product__items">
<span className="hd-product__title">Design System</span>
{designSystemLinks.map(link => (
<li className="hd-product__item" key={link.title}>
<Link className="hd-product__link" href={link.url}>{link.title}</Link>
</li>
))}
</ul>
</Popover>
<Link href="/" className="hd-brand" aria-label="Hopper Brand">
<HopperLogo />
</Link>
</PopoverTrigger>
</ToggleTrigger>
</span>
);
};

const Header = () => {
const { colorMode, setColorMode } = useContext(ThemeContext);
Expand Down Expand Up @@ -52,9 +129,7 @@ const Header = () => {
<header className="hd-header">
<Wrapper className="hd-flex">
<div className="hd-header__nav">
<Link href="/" className="hd-brand" aria-label="Hopper Brand">
<HopperLogo />
</Link>
<ProductMenuAndBrand />
<Nav items={navigation} />
</div>
<div className="hd-header__quick-actions">
Expand Down
57 changes: 57 additions & 0 deletions apps/docs/app/ui/layout/header/header.css
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,63 @@
--hd-header-shadow-3-top-position: -19.5rem;
}

.hd-product {
display: flex;
align-items: center;
gap: var(--hd-space-1);
}

.hd-product__menu {
width: 11.5rem;
box-sizing: border-box;
}

.hd-product__menu [role="dialog"] {
padding-inline: var(--hd-space-2);
padding-block: var(--hd-space-3);
border-color: transparent;
}

.hd-product__menu [role="dialog"]:focus-visible {
outline: 0;
box-shadow: var(--hd-focus-ring);
border-radius: var(--hd-space-05);
}

.hd-product__items {
display: flex;
flex-direction: column;
gap: 0.5rem;
list-style: none;
margin-top: var(--hd-space-2);
}

.hd-product__title {
font-size: 0.75rem;
text-transform: uppercase;
color: var(--hd-color-neutral-text-weakest);
}

.hd-product__title + .hd-product__link {
margin-top: var(--hd-space-1);
}

.hd-product__link {
display: block;
padding: var(--hd-space-1) var(--hd-space-1);
border-radius: var(--hd-border-radius-sm);
background-color: var(--hd-color-neutral-surface);
}

.hd-product__link:hover {
background-color: var(--hd-color-neutral-surface-weak);
}

.hd-product__link:focus-visible {
outline: 0;
box-shadow: var(--hd-focus-ring);
}

.hd-header {
display: flex;
align-items: center;
Expand Down
11 changes: 11 additions & 0 deletions apps/docs/components/icon/assets/product-menu.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions apps/docs/components/icon/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import ErrorIcon from "./assets/error.svg";
import InfoIcon from "./assets/info.svg";
import MessageIcon from "./assets/message.svg";
import WarningIcon from "./assets/warning.svg";
import ProductMenuIcon from "./assets/product-menu.svg";

import Icon, { type IconProps } from "./Icon.tsx";

Expand All @@ -46,6 +47,7 @@ export {
InfoIcon,
MessageIcon,
WarningIcon,
ProductMenuIcon,
Icon,
IconProps
};
6 changes: 6 additions & 0 deletions apps/docs/components/popover/popover.css
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,9 @@
box-shadow: var(--hd-popover-shadow);
outline: none;
}

.hd-popover:focus-visible {
outline: 0;
box-shadow: var(--hd-focus-ring);
border-radius: var(--hd-space-05);
}
2 changes: 1 addition & 1 deletion apps/docs/hooks/useIsMobile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export function useIsMobile(maxWidth: string) {
const maxWidthInPixels = parseFloat(maxWidth) * 16;

const checkIsMobile = () => {
setIsMobile(window.innerWidth <= maxWidthInPixels);
setIsMobile(window.innerWidth < maxWidthInPixels);
};

checkIsMobile();
Expand Down

0 comments on commit 23337b8

Please sign in to comment.