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

Sidebar filters #2

Merged
merged 6 commits into from
Oct 20, 2024
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
6 changes: 6 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,15 @@
"start": "next start"
},
"dependencies": {
"@radix-ui/react-collapsible": "^1.1.1",
"@radix-ui/react-dialog": "^1.1.2",
"@radix-ui/react-dropdown-menu": "^2.1.2",
"@radix-ui/react-icons": "^1.3.0",
"@radix-ui/react-navigation-menu": "^1.2.1",
"@radix-ui/react-select": "^2.1.2",
"@radix-ui/react-separator": "^1.1.0",
"@radix-ui/react-slot": "^1.1.0",
"@radix-ui/react-tooltip": "^1.1.3",
"@t3-oss/env-nextjs": "^0.11.1",
"@tanstack/react-query": "^5.59.15",
"@trpc/client": "^11.0.0-rc.446",
Expand Down
292 changes: 292 additions & 0 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

86 changes: 86 additions & 0 deletions src/app/collection/_components/filters.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import { ChevronRight } from "lucide-react";

import {
Collapsible,
CollapsibleTrigger,
CollapsibleContent,
} from "~/components/ui/collapsible";
import { Separator } from "~/components/ui/separator";
import {
Sidebar,
SidebarContent,
SidebarGroup,
SidebarGroupContent,
SidebarGroupLabel,
SidebarHeader,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
SidebarRail,
} from "~/components/ui/sidebar";

// This is sample data.
const data = {
versions: ["1.0.1", "1.1.0-alpha", "2.0.0-beta1"],
navMain: [
{
title: "Getting Started",
url: "#",
items: [
{
title: "Installation",
url: "#",
},
{
title: "Project Structure",
url: "#",
},
],
},
],
};

export function Filters() {
return (
<Sidebar className="top-14 h-[92vh]" variant="floating">
<SidebarHeader>
<h2 className="text-lg font-semibold">Filters</h2>
</SidebarHeader>
<SidebarContent className="gap-0">
{data.navMain.map((item) => (
<Collapsible
key={item.title}
title={item.title}
defaultOpen
className="group/collapsible"
>
<SidebarGroup>
<SidebarGroupLabel
asChild
className="group/label text-sm text-sidebar-foreground hover:bg-sidebar-accent hover:text-sidebar-accent-foreground"
>
<CollapsibleTrigger>
{item.title}{" "}
<ChevronRight className="ml-auto transition-transform group-data-[state=open]/collapsible:rotate-90" />
</CollapsibleTrigger>
</SidebarGroupLabel>
<CollapsibleContent>
<SidebarGroupContent>
<SidebarMenu>
{item.items.map((item) => (
<SidebarMenuItem key={item.title}>
<SidebarMenuButton asChild>
<a href={item.url}>{item.title}</a>
</SidebarMenuButton>
</SidebarMenuItem>
))}
</SidebarMenu>
</SidebarGroupContent>
</CollapsibleContent>
</SidebarGroup>
</Collapsible>
))}
</SidebarContent>
</Sidebar>
);
}
2 changes: 1 addition & 1 deletion src/app/collection/_components/product-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { api } from "~/trpc/react";
import { ProductCard } from "~/components/product/card";
import { Button } from "~/components/ui/button";

export default function ProductList() {
export function ProductList() {
const productQuery = api.collection.getProducts.useInfiniteQuery(
{
limit: 80,
Expand Down
18 changes: 13 additions & 5 deletions src/app/collection/page.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
import ProductList from "~/app/collection/_components/product-list";
import { Filters } from "~/app/collection/_components/filters";
import { ProductList } from "~/app/collection/_components/product-list";
import { SidebarProvider, SidebarTrigger } from "~/components/ui/sidebar";

export default async function CollectionPage() {
return (
<main className="flex min-h-screen flex-col items-center justify-center pb-48 pt-3">
<h1 className="py-5 text-4xl font-bold">Collection</h1>
<ProductList />
</main>
<SidebarProvider className="flex flex-row items-center justify-center pb-48 pt-3">
<Filters />
<section className="flex w-full flex-col items-center justify-center">
<div className="flex w-full flex-row items-center justify-between px-3">
<SidebarTrigger />
<h1 className="w-full text-center text-4xl font-bold">Collection</h1>
</div>
<ProductList />
</section>
</SidebarProvider>
);
}
5 changes: 4 additions & 1 deletion src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { type Metadata } from "next";
import { TRPCReactProvider } from "~/trpc/react";
import { ThemeProvider } from "next-themes";
import { HydrateClient } from "~/trpc/server";
import { Navigation } from "~/components/navigation";

export const metadata: Metadata = {
title: "Test",
Expand All @@ -24,9 +25,11 @@ export default async function RootLayout({
<ThemeProvider
attribute="class"
defaultTheme="dark"
// enableSystem
enableSystem
disableTransitionOnChange
>
<Navigation />
<div className="relative h-14 w-full" />
{children}
</ThemeProvider>
</HydrateClient>
Expand Down
146 changes: 146 additions & 0 deletions src/components/navigation.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
"use client";

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

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

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 Navigation() {
return (
<header className="bg-base-foreground fixed top-0 z-50 flex w-full items-center justify-center bg-background px-2 pb-3 pt-2 shadow-md">
<NavigationMenu>
<NavigationMenuList>
<NavigationMenuItem>
<NavigationMenuTrigger>Getting started</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">
shadcn/ui
</div>
<p className="text-sm leading-tight text-muted-foreground">
Beautifully designed components that you can copy and
paste into your apps. Accessible. Customizable. Open
Source.
</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>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>
<NavigationMenuItem>
<Link href="/docs" legacyBehavior passHref>
<NavigationMenuLink className={navigationMenuTriggerStyle()}>
Documentation
</NavigationMenuLink>
</Link>
</NavigationMenuItem>
</NavigationMenuList>
</NavigationMenu>
</header>
);
}

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-2 text-sm leading-snug text-muted-foreground">
{children}
</p>
</a>
</NavigationMenuLink>
</li>
);
});
ListItem.displayName = "ListItem";
11 changes: 11 additions & 0 deletions src/components/ui/collapsible.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
"use client";

import * as CollapsiblePrimitive from "@radix-ui/react-collapsible";

const Collapsible = CollapsiblePrimitive.Root;

const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger;

const CollapsibleContent = CollapsiblePrimitive.CollapsibleContent;

export { Collapsible, CollapsibleTrigger, CollapsibleContent };
Loading