Sidebar and team header cleanups (#4612)

## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
The focus of this PR is to refactor layout components and improve sidebar navigation in the dashboard app.

### Detailed summary
- Refactored layout components for better structure
- Updated sidebar navigation in various pages
- Improved handling of sidebar links and layout components

> ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}`

<!-- end pr-codex -->
This commit is contained in:
MananTank
2024-09-16 16:45:22 +00:00
parent 6e5d89bf2a
commit 1d0291fb9e
15 changed files with 80 additions and 120 deletions
@@ -18,7 +18,7 @@ export function SettingsCard(props: {
};
}) {
return (
<div className="border rounded-lg bg-muted/50 relative">
<div className="border border-border rounded-lg bg-muted/50 relative">
<div
className={cn(
"border-b border-border px-4 lg:px-6 py-6 relative",
@@ -42,7 +42,7 @@ export function AccountAbstractionPage(props: {
const isOpChain = chain?.id ? isOpChainId(chain.id) : false;
return (
<div className="max-sm:pt-6 pb-10">
<div>
<h1 className="text-2xl lg:text-3xl font-semibold tracking-tight mb-1">
Account Abstraction
</h1>
@@ -19,7 +19,7 @@ export default async function Page(props: {
}
return (
<div className="pb-10 max-sm:pt-6">
<div>
<div>
<h1 className="text-2xl md:text-3xl font-semibold tracking-tight mb-1">
Connect Analytics
@@ -5,11 +5,9 @@ export default async function Page(props: {
}) {
const { team_slug, project_slug } = props.params;
return (
<div className="max-sm:pt-6">
<EcosystemLandingPage
ecosystemLayoutPath={`/team/${team_slug}/${project_slug}/connect/ecosystem`}
/>
</div>
<EcosystemLandingPage
ecosystemLayoutPath={`/team/${team_slug}/${project_slug}/connect/ecosystem`}
/>
);
}
@@ -23,7 +23,7 @@ export default async function Page(props: {
const TRACKING_CATEGORY = "team/in-app-wallets";
return (
<div className="pb-10 max-sm:pt-6">
<div>
<h1 className="font-semibold text-2xl md:text-3xl tracking-tight mb-3">
In-App Wallets
</h1>
@@ -1,5 +1,4 @@
import { MobileSidebar } from "@/components/blocks/MobileSidebar";
import { Sidebar } from "@/components/blocks/Sidebar";
import { SidebarLayout } from "@/components/blocks/SidebarLayout";
export default function Layout(props: {
params: {
@@ -37,13 +36,5 @@ export default function Layout(props: {
},
];
return (
<div className="h-full container flex gap-4">
<Sidebar links={links} />
<div className="grow py-6 max-sm:w-full">
<MobileSidebar links={links} triggerClassName="max-sm:mb-6" />
{props.children}
</div>
</div>
);
return <SidebarLayout sidebarLinks={links}>{props.children}</SidebarLayout>;
}
@@ -19,35 +19,33 @@ export default async function Page(props: {
}
return (
<div className="max-sm:pt-6 pb-10">
<div className="flex flex-col gap-8 w-full">
<div className="flex flex-col lg:flex-row gap-6 justify-between items-start">
<div className="max-w-[700px]">
<h1 className="text-3xl md:text-4xl tracking-tight font-bold mb-3">
Pay
</h1>
<p className="text-sm md:text-base text-muted-foreground leading-relaxed">
Pay allows your users to purchase cryptocurrencies and execute
transactions with their credit card or debit card, or with any
token via cross-chain routing.{" "}
<Link
target="_blank"
href="https://portal.thirdweb.com/connect/pay/overview"
className="!text-link-foreground"
>
Learn more
</Link>
</p>
</div>
<div className="flex flex-col gap-8 w-full">
<div className="flex flex-col lg:flex-row gap-6 justify-between items-start">
<div className="max-w-[700px]">
<h1 className="text-3xl md:text-4xl tracking-tight font-bold mb-3">
Pay
</h1>
<p className="text-sm md:text-base text-muted-foreground leading-relaxed">
Pay allows your users to purchase cryptocurrencies and execute
transactions with their credit card or debit card, or with any token
via cross-chain routing.{" "}
<Link
target="_blank"
href="https://portal.thirdweb.com/connect/pay/overview"
className="!text-link-foreground"
>
Learn more
</Link>
</p>
</div>
<PayPageUI
apiKey={{
...project,
key: project.publishableKey, // clientId
}}
/>
</div>
<PayPageUI
apiKey={{
...project,
key: project.publishableKey, // clientId
}}
/>
</div>
);
}
@@ -1,21 +0,0 @@
import type { SidebarLink } from "@/components/blocks/Sidebar";
export function getEngineGeneralSidebarLinks(
linkPrefix: string,
): SidebarLink[] {
return [
{
label: "Overview",
href: `${linkPrefix}`,
exactMatch: true,
},
{
label: "Create",
href: `${linkPrefix}/create`,
},
{
label: "Import",
href: `${linkPrefix}/import`,
},
];
}
@@ -1,6 +1,5 @@
import { MobileSidebar } from "@/components/blocks/MobileSidebar";
import { Sidebar } from "@/components/blocks/Sidebar";
import { getEngineGeneralSidebarLinks } from "./getEngineGeneralSidebarLinks";
import type { SidebarLink } from "@/components/blocks/Sidebar";
import { SidebarLayout } from "@/components/blocks/SidebarLayout";
export default function Layout(props: {
params: {
@@ -11,15 +10,23 @@ export default function Layout(props: {
children: React.ReactNode;
}) {
const linkPrefix = `/team/${props.params.team_slug}/${props.params.project_slug}/engine`;
const sidebarLinks = getEngineGeneralSidebarLinks(linkPrefix);
const sidebarLinks: SidebarLink[] = [
{
label: "Overview",
href: `${linkPrefix}`,
exactMatch: true,
},
{
label: "Create",
href: `${linkPrefix}/create`,
},
{
label: "Import",
href: `${linkPrefix}/import`,
},
];
return (
<div className="container flex gap-6">
<Sidebar links={sidebarLinks} />
<div className="pt-6 grow max-sm:w-full">
<MobileSidebar links={sidebarLinks} triggerClassName="max-sm:mb-6" />
{props.children}
</div>
</div>
<SidebarLayout sidebarLinks={sidebarLinks}>{props.children}</SidebarLayout>
);
}
@@ -34,7 +34,15 @@ export function ProjectSelectorMobileMenuButton(
</Button>
</DialogTrigger>
<DialogContent dialogCloseClassName="hidden" className="p-0">
<DialogContent
dialogCloseClassName="hidden"
className="p-0"
onClick={(e) => {
if (e.target instanceof HTMLAnchorElement) {
setOpen(false);
}
}}
>
<DynamicHeight>
<ProjectSelectorUI
currentProject={props.currentProject}
@@ -24,7 +24,7 @@ export function ProjectSelectorUI(props: {
: projects;
return (
<div className="flex flex-col border-l fade-in-0 animate-in duration-300">
<div className="flex flex-col border-l border-border fade-in-0 animate-in duration-300">
<SearchInput
placeholder="Search Projects"
value={searchProjectTerm}
@@ -74,7 +74,7 @@ export function ProjectSelectorUI(props: {
</div>
</ScrollShadow>
<div className="p-2 border-t">
<div className="p-2 border-t border-border">
<Button
className="px-2 w-full gap-2 justify-start disabled:opacity-100 disabled:pointer-events-auto disabled:cursor-not-allowed"
variant="ghost"
@@ -65,6 +65,11 @@ export function TeamAndProjectSelectorPopoverButton(props: TeamSwitcherProps) {
sideOffset={5}
className="p-0 w-auto rounded-xl shadow-xl"
align={props.focus === "project-selection" ? "center" : "start"}
onClick={(e) => {
if (e.target instanceof HTMLAnchorElement) {
setOpen(false);
}
}}
>
<DynamicHeight>
<div className="flex [&>div]:min-w-[280px] no-scrollbar">
@@ -109,7 +109,7 @@ export function TeamSelectionUI(props: {
{/* TODO - what do we do on this button click? */}
{/* Bottom */}
{teamPlan && teamPlan !== "pro" && (
<div className="p-2 border-t">
<div className="p-2 border-t border-border">
<Button
variant="primary"
className="w-full"
@@ -21,15 +21,13 @@ export function createEnginePage(
}
return (
<div className="container px-4">
<EngineSidebarLayout rootPath="/dashboard/engine" engineId={engineId}>
<WithEngineInstance
engineId={engineId}
content={PageContent}
rootPath="/dashboard/engine"
/>
</EngineSidebarLayout>
</div>
<EngineSidebarLayout rootPath="/dashboard/engine" engineId={engineId}>
<WithEngineInstance
engineId={engineId}
content={PageContent}
rootPath="/dashboard/engine"
/>
</EngineSidebarLayout>
);
};
@@ -1,7 +1,6 @@
"use client";
import { MobileSidebar } from "@/components/blocks/MobileSidebar";
import { Sidebar, type SidebarLink } from "@/components/blocks/Sidebar";
import type { SidebarLink } from "@/components/blocks/Sidebar";
import { CopyTextButton } from "@/components/ui/CopyTextButton";
import { Spinner } from "@/components/ui/Spinner/Spinner";
import { Button } from "@/components/ui/button";
@@ -11,10 +10,10 @@ import {
type EngineInstance,
useEngineInstances,
} from "@3rdweb-sdk/react/hooks/useEngine";
import { ArrowLeftIcon, ChevronDownIcon, CircleAlertIcon } from "lucide-react";
import { ArrowLeftIcon, CircleAlertIcon } from "lucide-react";
import Link from "next/link";
import { usePathname } from "next/navigation";
import invariant from "tiny-invariant";
import { SidebarLayout } from "../../@/components/blocks/SidebarLayout";
import { EngineVersionBadge } from "./badges/version";
import { useHasEnginePermission } from "./useHasEnginePermission";
@@ -64,7 +63,6 @@ export function EngineSidebarLayout(props: {
rootPath: string;
children: React.ReactNode;
}) {
const pathname = usePathname();
const links: SidebarLink[] = sidebarLinkMeta.map((linkMeta) => {
return {
href: `${props.rootPath}/${props.engineId}${linkMeta.pathId === "" ? "" : `/${linkMeta.pathId}`}`,
@@ -78,29 +76,7 @@ export function EngineSidebarLayout(props: {
};
});
const activeLink = links.find((link) => pathname === link.href);
return (
<div className="flex gap-6">
<Sidebar links={links} />
<div className="grow max-sm:w-full pt-6 pb-10">
<MobileSidebar
links={links}
trigger={
<Button
className="w-full lg:hidden text-left justify-between gap-2 mb-6"
variant="outline"
>
{activeLink?.label || "Connect"}
<ChevronDownIcon className="size-5 text-muted-foreground" />
</Button>
}
/>
{props.children}
</div>
</div>
);
return <SidebarLayout sidebarLinks={links}>{props.children}</SidebarLayout>;
}
export function WithEngineInstance(props: {