Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Navbar fixed and setup in a clean fashion #37

Merged
merged 3 commits into from
Mar 23, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/app/globals.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
@import "tailwindcss";

@plugin "tailwindcss-animate";

@custom-variant dark (&:is(.dark *));

@theme {
Expand Down
1 change: 0 additions & 1 deletion src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import QueryClientProvider from "@/components/QueryClientProvider";
import "./globals.css";
import { client } from "@/api";
import { NavigationMenuDemo } from "../components/NavBar";
import initTranslations, { type Locale, type Namespace } from "./i18n";
import TranslationsProvider from "@/components/TranslationsProvider";

Expand Down
4 changes: 2 additions & 2 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import Link from "next/link";
import { NavigationMenuDemo } from "../components/NavBar";
import { NavBar } from "../components/NavBar";

export default function MainLanding() {
return (
<>
<NavigationMenuDemo />
<NavBar />
<div>
<p>
Hej! 👋 Du 🫵 ser 👀 denna 📄 sida 📘 för 💡 att ✨ du 🫶 är 🧊 cool
Expand Down
189 changes: 86 additions & 103 deletions src/components/NavBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import * as React from "react";
import Link from "next/link";

import { cn } from "@/lib/utils";
import {
NavigationMenu,
Expand All @@ -13,72 +12,85 @@ import {
NavigationMenuTrigger,
navigationMenuTriggerStyle,
} from "@/components/ui/navigation-menu";
import FLogga from "@/assets/f-logga";
import { LogIn } from "lucide-react";
import { Button } from "@/components/ui/button";
import { useTranslation } from "react-i18next";

// Define types for navigation items and sections
type NavItem = {
self: string;
desc: string;
href?: string;
};

type NavSection = {
self: string;
} & Record<string, NavItem>;

export function NavBar() {
return (
<div className="flex justify-between">
<FLogga className="mt-2 ml-2" />
<NavBarMenu />
<LoginAndLang />
</div>
);
}

function LoginAndLang() {
const { t } = useTranslation();

return (
<Button className="mt-6 mr-2">
<LogIn />
<span>{t("navbar.login")}</span>
</Button>
);
}

const components: { title: string; href: string; description: string }[] = [
{
title: "Alert Dialog",
href: "/docs/primitives/alert-dialog",
description:
"A modal dialog that interrupts the user with important content and expects a response.",
},
{
title: "Hover Card",
href: "/docs/primitives/hover-card",
description:
"For sighted users to preview content available behind a link.",
},
{
title: "Progress",
href: "/docs/primitives/progress",
description:
"Displays an indicator showing the completion progress of a task, typically displayed as a progress bar.",
},
{
title: "Scroll-area",
href: "/docs/primitives/scroll-area",
description: "Visually or semantically separates content.",
},
{
title: "Tabs",
href: "/docs/primitives/tabs",
description:
"A set of layered sections of content—known as tab panels—that are displayed one at a time.",
},
{
title: "Tooltip",
href: "/docs/primitives/tooltip",
description:
"A popup that displays information related to an element when the element receives keyboard focus or the mouse hovers over it.",
},
];
export function NavBarMenu() {
const { t } = useTranslation();
// Assert the translation result as a record of NavSections
const navbarData = t("navbar", { returnObjects: true }) as Record<
string,
NavSection
>;

// Filter out keys that are objects (the dropdown sections)
const sections = Object.entries(navbarData).filter(
([, value]) =>
typeof value === "object" && value !== null && !Array.isArray(value),
);

export function NavigationMenuDemo() {
function onNavChange() {
setTimeout(() => {
// Select elements with the state "open"
const triggers = document.querySelectorAll(
'.submenu-trigger[data-state="open"]',
'[data-slot="navigation-menu-trigger"][data-state="open"]',
);
const dropdowns = document.querySelectorAll(
'.nav-viewport[data-state="open"]',
'[data-slot="navigation-menu-viewport"][data-state="open"]',
);

if (!triggers.length || !dropdowns.length) return;

const padding = 16;
const { x, width } = (triggers[0] as HTMLElement).getBoundingClientRect();
const menuWidth = dropdowns[0].children[0].clientWidth;
let menuLeftPosition = x + width / 2 - menuWidth / 2;
if (menuLeftPosition < padding) {
menuLeftPosition = padding;
} else if (menuLeftPosition + menuWidth > window.innerWidth - padding) {
menuLeftPosition = window.innerWidth - menuWidth - padding;
const dropdown = dropdowns[0] as HTMLElement;
const menuWidth = dropdown.children[0].clientWidth;
const parentLeft =
dropdown.offsetParent?.getBoundingClientRect().left || 0;

let viewportLeft = x + width / 2 - menuWidth / 2;
if (viewportLeft < padding) {
viewportLeft = padding;
} else if (viewportLeft + menuWidth > window.innerWidth - padding) {
viewportLeft = window.innerWidth - menuWidth - padding;
}

// Apply the calculated position
document.documentElement.style.setProperty(
"--menu-left-position",
`${menuLeftPosition}px`,
`${viewportLeft - parentLeft}px`,
);
});
}
Expand All @@ -87,61 +99,32 @@ export function NavigationMenuDemo() {
<div>
<NavigationMenu
onValueChange={onNavChange}
className="w-full max-w-full py-2"
className="w-full max-w-full py-2 mt-4"
>
<NavigationMenuList>
<NavigationMenuItem>
<NavigationMenuTrigger className="submenu-trigger">
Getting started
</NavigationMenuTrigger>
<NavigationMenuContent>
<ul className="grid gap-3 p-4 md:w-[400px] lg:w-[500px] lg:grid-cols-[.75fr_1fr]">
<li className="row-span-3">
<NavigationMenuLink asChild>
<a
className="flex h-full w-full select-none flex-col justify-end rounded-md bg-gradient-to-b from-muted/50 to-muted p-6 no-underline outline-none focus:shadow-md"
href="/"
>
<div className="mb-2 mt-4 text-lg font-medium">
shadcn/ui
</div>
<p className="text-sm leading-tight text-muted-foreground">
Beautifully designed components built with Radix UI and
Tailwind CSS.
</p>
</a>
</NavigationMenuLink>
</li>
<ListItem href="/docs" title="Introduction">
Re-usable components built using Radix UI and Tailwind CSS.
</ListItem>
<ListItem href="/docs/installation" title="Installation">
How to install dependencies and structure your app.
</ListItem>
<ListItem href="/docs/primitives/typography" title="Typography">
Styles for headings, paragraphs, lists...etc
</ListItem>
</ul>
</NavigationMenuContent>
</NavigationMenuItem>
<NavigationMenuItem>
<NavigationMenuTrigger className="submenu-trigger">
Components
</NavigationMenuTrigger>
<NavigationMenuContent>
<ul className="grid w-[400px] gap-3 p-4 md:w-[500px] md:grid-cols-2 lg:w-[600px] ">
{components.map((component) => (
<ListItem
key={component.title}
title={component.title}
href={component.href}
>
{component.description}
</ListItem>
))}
</ul>
</NavigationMenuContent>
</NavigationMenuItem>
{sections.map(([sectionKey, section]) => {
const items = Object.entries(section).filter(
([key]) => key !== "self",
) as [string, NavItem][];
return (
<NavigationMenuItem key={sectionKey}>
<NavigationMenuTrigger>{section.self}</NavigationMenuTrigger>
<NavigationMenuContent>
<ul className="grid w-[400px] gap-3 p-4 md:w-[500px] md:grid-cols-2 lg:w-[600px]">
{items.map(([itemKey, item]) => (
<ListItem
key={itemKey}
title={item.self}
href={item.href || "#"}
>
{item.desc}
</ListItem>
))}
</ul>
</NavigationMenuContent>
</NavigationMenuItem>
);
})}
<NavigationMenuItem>
<Link href="/docs" legacyBehavior passHref>
<NavigationMenuLink className={navigationMenuTriggerStyle()}>
Expand Down
Loading