Skip to content

Commit

Permalink
Add main menu
Browse files Browse the repository at this point in the history
  • Loading branch information
krishaamer committed Jul 29, 2024
1 parent 50255cb commit 65d885e
Show file tree
Hide file tree
Showing 4 changed files with 305 additions and 3 deletions.
126 changes: 123 additions & 3 deletions components/shared/header.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
"use client";

import * as React from "react";
import Link from "next/link";
import { cn } from "@/lib/utils";
import {
NavigationMenu,
NavigationMenuContent,
NavigationMenuItem,
NavigationMenuLink,
NavigationMenuList,
NavigationMenuTrigger,
} from "@/components/ui/navigation-menu";
import ThemeSwitcher from "@/components/shared/theme";
import { useSession, signOut } from "next-auth/react";
import SignIn from "../llm-login";
Expand All @@ -12,14 +23,97 @@ import {
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";

const components: { title: string; href: string; description: string }[] = [
{
title: "工廠",
href: "?ask=%E5%8F%B0%E7%81%A3%E6%9C%89%E5%93%AA%E4%BA%9B%E5%B7%A5%E5%BB%A0%EF%BC%8C%E5%AE%83%E5%80%91%E4%BD%8D%E6%96%BC%E4%BD%95%E8%99%95%EF%BC%9F",
description:
"台灣有哪些工廠,它們位於何處?",
},
{
title: "空氣污染",
href: "?ask=%E5%B7%A5%E6%A5%AD%E7%94%9F%E7%94%A2%E5%92%8C%E5%B7%A5%E5%BB%A0%E5%A6%82%E4%BD%95%E5%BD%B1%E9%9F%BF%E5%8F%B0%E7%81%A3%E5%90%84%E5%9C%B0%E7%9A%84%E7%A9%BA%E6%B0%A3%E6%B1%A1%E6%9F%93%EF%BC%9F",
description: "工業生產和工廠如何影響台灣各地的空氣污染?",
},
{
title: "水污染",
href: "?ask=%E5%B7%A5%E6%A5%AD%E7%94%9F%E7%94%A2%E5%A6%82%E4%BD%95%E5%BD%B1%E9%9F%BF%E5%8F%B0%E7%81%A3%E5%90%84%E5%9C%B0%E7%9A%84%E6%B0%B4%E6%B1%A1%E6%9F%93%EF%BC%9F",
description: "工業生產如何影響台灣各地的水污染?",
},
{
title: "土壤污染",
href: "?ask=%E5%B7%A5%E6%A5%AD%E7%94%9F%E7%94%A2%E5%A6%82%E4%BD%95%E5%BD%B1%E9%9F%BF%E5%8F%B0%E7%81%A3%E5%90%84%E5%9C%B0%E7%9A%84%E5%9C%9F%E5%A3%A4%E6%B1%A1%E6%9F%93%EF%BC%9F",
description: "工業生產如何影響台灣各地的土壤污染?",
},
{
title: "氣候改變",
href: "?ask=%E6%88%91%E4%BD%BF%E7%94%A8%E9%87%91%E9%8C%A2%E8%B3%BC%E7%89%A9%E3%80%81%E5%84%B2%E8%93%84%E5%92%8C%E6%8A%95%E8%B3%87%E7%9A%84%E6%96%B9%E5%BC%8F%E5%A6%82%E4%BD%95%E5%BD%B1%E9%9F%BF%E7%92%B0%E5%A2%83%E5%92%8C%E6%B0%A3%E5%80%99%E8%AE%8A%E9%81%B7%EF%BC%9F",
description: "我使用金錢購物、儲蓄和投資的方式如何影響環境和氣候變遷?",
},
];

export default function Header() {
const session = useSession();

return (
<div className="sticky top-0 z-50 flex items-center justify-between w-full px-4 border-b h-8 shrink-0 text-white bg-gradient-to-br from-pink-500 to-orange-400 font-medium text-sm text-center">
<a href="/">綠濾助手</a>
<a href="/">錢花去支持了啥物呢?</a>
<NavigationMenu>
<NavigationMenuList>
<NavigationMenuItem>
<NavigationMenuTrigger>綠濾助手</NavigationMenuTrigger>
<NavigationMenuContent>
<ul className="grid gap-3 p-6 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">
綠濾助手
</div>
<p className="text-sm leading-tight text-muted-foreground">
Shop, save and invest with your mind at ease from
climate anxiety 😊 Green Filter helps you see your money
through the lens of sustainability
</p>
</a>
</NavigationMenuLink>
</li>
<ListItem
href="https://www.greenfilter.app/"
title="論文"
target="_blank"
>
從消費者到投資者的旅程:為年輕成人設計一個財務人工智慧夥伴,幫助他們進行可持續購物、儲蓄和投資
</ListItem>
<ListItem
href="https://chromewebstore.google.com/detail/%E7%B6%A0%E6%BF%BE-green-filter/jmpnmeefjlcbpmoklhhljcigffdmmjeg"
title="Chrome Extension"
target="_blank"
>
Install the 綠濾 Green Filter Chrome Extension
</ListItem>
</ul>
</NavigationMenuContent>
</NavigationMenuItem>
<NavigationMenuItem>
<NavigationMenuTrigger>錢花去支持了啥物呢?</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>
</NavigationMenuList>
</NavigationMenu>
<div className="flex space-x-4">
<div>
{session?.data?.user?.name ? (
Expand All @@ -44,3 +138,29 @@ export default function Header() {
</div>
);
}

const ListItem = React.forwardRef<
React.ElementRef<"a">,
React.ComponentPropsWithoutRef<"a">
>(({ className, title, children, ...props }, ref) => {
return (
<li>
<NavigationMenuLink asChild>
<a
ref={ref}
className={cn(
"block select-none space-y-1 rounded-md p-3 leading-none no-underline outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",
className
)}
{...props}
>
<div className="text-sm font-medium leading-none">{title}</div>
<p className="line-clamp-3 text-sm leading-snug text-muted-foreground">
{children}
</p>
</a>
</NavigationMenuLink>
</li>
);
});
ListItem.displayName = "ListItem";
128 changes: 128 additions & 0 deletions components/ui/navigation-menu.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import * as React from "react"
import { ChevronDownIcon } from "@radix-ui/react-icons"
import * as NavigationMenuPrimitive from "@radix-ui/react-navigation-menu"
import { cva } from "class-variance-authority"

import { cn } from "@/lib/utils"

const NavigationMenu = React.forwardRef<
React.ElementRef<typeof NavigationMenuPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Root>
>(({ className, children, ...props }, ref) => (
<NavigationMenuPrimitive.Root
ref={ref}
className={cn(
"relative z-10 flex max-w-max flex-1 items-center justify-center",
className
)}
{...props}
>
{children}
<NavigationMenuViewport />
</NavigationMenuPrimitive.Root>
))
NavigationMenu.displayName = NavigationMenuPrimitive.Root.displayName

const NavigationMenuList = React.forwardRef<
React.ElementRef<typeof NavigationMenuPrimitive.List>,
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.List>
>(({ className, ...props }, ref) => (
<NavigationMenuPrimitive.List
ref={ref}
className={cn(
"group flex flex-1 list-none items-center justify-center space-x-1",
className
)}
{...props}
/>
))
NavigationMenuList.displayName = NavigationMenuPrimitive.List.displayName

const NavigationMenuItem = NavigationMenuPrimitive.Item

const navigationMenuTriggerStyle = cva(
"group inline-flex h-9 w-max items-center justify-center rounded-md px-4 py-2 text-sm font-medium transition-colors focus:text-accent-foreground disabled:pointer-events-none disabled:opacity-50 data-[active]:bg-accent/20 data-[state=open]:bg-accent/20"
)

const NavigationMenuTrigger = React.forwardRef<
React.ElementRef<typeof NavigationMenuPrimitive.Trigger>,
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Trigger>
>(({ className, children, ...props }, ref) => (
<NavigationMenuPrimitive.Trigger
ref={ref}
className={cn(navigationMenuTriggerStyle(), "group", className)}
{...props}
>
{children}{" "}
<ChevronDownIcon
className="relative top-[1px] ml-1 h-3 w-3 transition duration-300 group-data-[state=open]:rotate-180"
aria-hidden="true"
/>
</NavigationMenuPrimitive.Trigger>
))
NavigationMenuTrigger.displayName = NavigationMenuPrimitive.Trigger.displayName

const NavigationMenuContent = React.forwardRef<
React.ElementRef<typeof NavigationMenuPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Content>
>(({ className, ...props }, ref) => (
<NavigationMenuPrimitive.Content
ref={ref}
className={cn(
"left-0 top-0 w-full data-[motion^=from-]:animate-in data-[motion^=to-]:animate-out data-[motion^=from-]:fade-in data-[motion^=to-]:fade-out data-[motion=from-end]:slide-in-from-right-52 data-[motion=from-start]:slide-in-from-left-52 data-[motion=to-end]:slide-out-to-right-52 data-[motion=to-start]:slide-out-to-left-52 md:absolute md:w-auto ",
className
)}
{...props}
/>
))
NavigationMenuContent.displayName = NavigationMenuPrimitive.Content.displayName

const NavigationMenuLink = NavigationMenuPrimitive.Link

const NavigationMenuViewport = React.forwardRef<
React.ElementRef<typeof NavigationMenuPrimitive.Viewport>,
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Viewport>
>(({ className, ...props }, ref) => (
<div className={cn("absolute left-0 top-full flex justify-center")}>
<NavigationMenuPrimitive.Viewport
className={cn(
"origin-top-center relative mt-1.5 h-[var(--radix-navigation-menu-viewport-height)] w-full overflow-hidden rounded-md border bg-popover text-popover-foreground shadow data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-90 md:w-[var(--radix-navigation-menu-viewport-width)]",
className
)}
ref={ref}
{...props}
/>
</div>
))
NavigationMenuViewport.displayName =
NavigationMenuPrimitive.Viewport.displayName

const NavigationMenuIndicator = React.forwardRef<
React.ElementRef<typeof NavigationMenuPrimitive.Indicator>,
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Indicator>
>(({ className, ...props }, ref) => (
<NavigationMenuPrimitive.Indicator
ref={ref}
className={cn(
"top-full z-[1] flex h-1.5 items-end justify-center overflow-hidden data-[state=visible]:animate-in data-[state=hidden]:animate-out data-[state=hidden]:fade-out data-[state=visible]:fade-in",
className
)}
{...props}
>
<div className="relative top-[60%] h-2 w-2 rotate-45 rounded-tl-sm bg-border shadow-md" />
</NavigationMenuPrimitive.Indicator>
))
NavigationMenuIndicator.displayName =
NavigationMenuPrimitive.Indicator.displayName

export {
navigationMenuTriggerStyle,
NavigationMenu,
NavigationMenuList,
NavigationMenuItem,
NavigationMenuContent,
NavigationMenuTrigger,
NavigationMenuLink,
NavigationMenuIndicator,
NavigationMenuViewport,
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"@radix-ui/react-dropdown-menu": "^2.1.1",
"@radix-ui/react-icons": "^1.3.0",
"@radix-ui/react-label": "^2.1.0",
"@radix-ui/react-navigation-menu": "^1.2.0",
"@radix-ui/react-scroll-area": "^1.1.0",
"@radix-ui/react-separator": "^1.1.0",
"@radix-ui/react-slot": "^1.1.0",
Expand Down
53 changes: 53 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 65d885e

Please sign in to comment.