Skip to content

Commit 77dde6b

Browse files
committed
[TOOL-3909] Dashboard: Add footer links to project pages
1 parent 5faaf1b commit 77dde6b

File tree

23 files changed

+703
-477
lines changed

23 files changed

+703
-477
lines changed

apps/dashboard/src/@/components/blocks/SidebarLayout.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { NavLink } from "../ui/NavLink";
1717
import { Separator } from "../ui/separator";
1818
import { MobileSidebar, useActiveSidebarLink } from "./MobileSidebar";
1919
import { CustomSidebar, type SidebarLink } from "./Sidebar";
20+
import { AppFooter } from "./app-footer";
2021

2122
export function SidebarLayout(props: {
2223
sidebarLinks: SidebarLink[];
@@ -54,7 +55,6 @@ export function FullWidthSidebarLayout(props: {
5455
footerSidebarLinks?: SidebarLink[];
5556
children: React.ReactNode;
5657
className?: string;
57-
footer?: React.ReactNode;
5858
}) {
5959
const { contentSidebarLinks, children, footerSidebarLinks } = props;
6060
return (
@@ -65,7 +65,7 @@ export function FullWidthSidebarLayout(props: {
6565
)}
6666
>
6767
{/* left - sidebar */}
68-
<Sidebar collapsible="icon" side="left">
68+
<Sidebar collapsible="icon" side="left" className="pt-2">
6969
<SidebarContent>
7070
<SidebarGroup>
7171
<SidebarGroupContent>
@@ -95,10 +95,10 @@ export function FullWidthSidebarLayout(props: {
9595
links={[...contentSidebarLinks, ...(footerSidebarLinks || [])]}
9696
/>
9797

98-
<main className="container z-0 flex min-w-0 max-w-[1280px] grow flex-col pb-20 max-sm:w-full lg:pt-6">
98+
<main className="z-0 flex min-w-0 grow flex-col max-sm:w-full">
9999
{children}
100100
</main>
101-
{props.footer}
101+
<AppFooter containerClassName="max-w-7xl" />
102102
</div>
103103
</div>
104104
);
@@ -156,7 +156,7 @@ function MobileSidebarTrigger(props: { links: SidebarLink[] }) {
156156
const activeLink = useActiveSidebarLink(props.links);
157157

158158
return (
159-
<div className="mb-4 flex items-center gap-3 border-b px-4 py-4 lg:hidden">
159+
<div className="flex items-center gap-3 border-b px-4 py-4 lg:hidden">
160160
<SidebarTrigger className="size-4" />
161161
<Separator orientation="vertical" className="h-4" />
162162
{activeLink && <span className="text-sm">{activeLink.label}</span>}

apps/dashboard/src/@/components/blocks/app-footer.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,23 @@ import Link from "next/link";
1212

1313
type AppFooterProps = {
1414
className?: string;
15+
containerClassName?: string;
1516
};
1617

1718
export function AppFooter(props: AppFooterProps) {
1819
return (
1920
<footer
2021
className={cn(
21-
"w-full border-border border-t bg-card py-6 md:py-8",
22+
"w-full border-border border-t py-6 md:py-8",
2223
props.className,
2324
)}
2425
>
25-
<div className="container flex flex-col gap-4 md:gap-6">
26+
<div
27+
className={cn(
28+
"container flex flex-col gap-4 md:gap-6",
29+
props.containerClassName,
30+
)}
31+
>
2632
{/* top row */}
2733
<div className="flex flex-col gap-4 md:flex-row md:items-center md:justify-between">
2834
<div className="flex flex-row items-center gap-3">

apps/dashboard/src/@/components/ui/tabs.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export function TabLinks(props: {
2020
className?: string;
2121
tabContainerClassName?: string;
2222
shadowColor?: string;
23+
scrollableClassName?: string;
2324
}) {
2425
const { containerRef, lineRef, activeTabRef } =
2526
useUnderline<HTMLAnchorElement>();
@@ -30,7 +31,7 @@ export function TabLinks(props: {
3031
<div className="absolute right-0 bottom-0 left-0 h-[1px] bg-border" />
3132

3233
<ScrollShadow
33-
scrollableClassName="pb-[8px] relative"
34+
scrollableClassName={cn("pb-[8px] relative", props.scrollableClassName)}
3435
shadowColor={props.shadowColor}
3536
>
3637
<div
@@ -159,9 +160,11 @@ function useUnderline<El extends HTMLElement>() {
159160
const containerRect = containerRef.current.getBoundingClientRect();
160161
const lineEl = lineRef.current;
161162
const rect = activeTabEl.getBoundingClientRect();
163+
const containerPaddingLeft =
164+
containerRect.left - containerRef.current.offsetLeft;
162165
lineEl.style.width = `${rect.width}px`;
163166
lineEl.style.transform = `translateX(${
164-
rect.left - containerRect.left
167+
rect.left - containerPaddingLeft
165168
}px)`;
166169
setTimeout(() => {
167170
lineEl.style.transition = "transform 0.3s, width 0.3s";
@@ -205,6 +208,7 @@ export function TabPathLinks(props: {
205208
className?: string;
206209
tabContainerClassName?: string;
207210
shadowColor?: string;
211+
scrollableClassName?: string;
208212
}) {
209213
const pathname = usePathname() || "";
210214
const { links, ...restProps } = props;

apps/dashboard/src/app/account/contracts/DeployedContractsPageHeader.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export function DeployedContractsPageHeader(props: {
1313
const [importModalOpen, setImportModalOpen] = useState(false);
1414

1515
return (
16-
<div>
16+
<div className="border-b">
1717
<ImportModal
1818
isOpen={importModalOpen}
1919
onClose={() => {
@@ -23,9 +23,11 @@ export function DeployedContractsPageHeader(props: {
2323
projectId={props.projectId}
2424
/>
2525

26-
<div className="flex flex-col gap-3 pt-2 pb-8 lg:flex-row lg:items-center lg:justify-between">
26+
<div className="container flex max-w-7xl flex-col gap-3 py-10 lg:flex-row lg:items-center lg:justify-between">
2727
<div>
28-
<h1 className="font-semibold text-3xl tracking-tight">Contracts</h1>
28+
<h1 className="font-semibold text-2xl tracking-tight lg:text-3xl">
29+
Contracts
30+
</h1>
2931
</div>
3032
<div className="flex gap-3 [&>*]:grow">
3133
<Button

apps/dashboard/src/app/account/contracts/_components/DeployedContractsPage.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ export function DeployedContractsPage(props: {
1717
teamId={props.teamId}
1818
projectId={props.projectId}
1919
/>
20-
<div className="flex grow flex-col">
20+
<div className="h-6" />
21+
<div className="container flex max-w-7xl grow flex-col">
2122
<Suspense fallback={<Loading />}>
2223
<DeployedContractsPageAsync {...props} />
2324
</Suspense>
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import { TrackedLinkTW } from "@/components/ui/tracked-link";
2+
import { LinkIcon } from "lucide-react";
3+
4+
type FooterSectionProps = {
5+
title: string;
6+
links: {
7+
href: string;
8+
label: string;
9+
}[];
10+
};
11+
12+
type FooterCardProps = {
13+
left: FooterSectionProps;
14+
center: FooterSectionProps;
15+
right: FooterSectionProps;
16+
trackingCategory: string;
17+
};
18+
19+
export default function FooterCard(props: FooterCardProps) {
20+
return (
21+
<div className="py-6">
22+
<div className="grid grid-cols-1 gap-6 xl:grid-cols-3 xl:gap-0 xl:divide-x xl:divide-border">
23+
<div className="xl:pr-6">
24+
<FooterSection
25+
{...props.left}
26+
trackingCategory={props.trackingCategory}
27+
/>
28+
</div>
29+
30+
<div className="xl:px-6">
31+
<FooterSection
32+
{...props.center}
33+
trackingCategory={props.trackingCategory}
34+
/>
35+
</div>
36+
37+
<div className="xl:pl-6">
38+
<FooterSection
39+
{...props.right}
40+
trackingCategory={props.trackingCategory}
41+
/>
42+
</div>
43+
</div>
44+
</div>
45+
);
46+
}
47+
48+
function FooterSection(
49+
props: FooterSectionProps & { trackingCategory: string },
50+
) {
51+
return (
52+
<div>
53+
<h3 className="mb-2.5 font-medium">{props.title}</h3>
54+
<div className="flex flex-col gap-2.5">
55+
{props.links.map((link) => (
56+
<FooterLink
57+
key={link.label}
58+
href={link.href}
59+
trackingCategory={props.trackingCategory}
60+
label={link.label}
61+
/>
62+
))}
63+
</div>
64+
</div>
65+
);
66+
}
67+
68+
function FooterLink({
69+
href,
70+
label,
71+
trackingCategory,
72+
}: {
73+
href: string;
74+
label: string;
75+
trackingCategory: string;
76+
}) {
77+
return (
78+
<TrackedLinkTW
79+
href={href}
80+
category={trackingCategory}
81+
label={label.replace(/ /g, "-").toLowerCase()}
82+
target="_blank"
83+
className="flex items-start gap-2 text-balance text-muted-foreground text-sm hover:text-foreground"
84+
>
85+
<LinkIcon className="mt-1 size-3 shrink-0 opacity-70" />
86+
{label}
87+
</TrackedLinkTW>
88+
);
89+
}

apps/dashboard/src/app/team/[team_slug]/[project_slug]/components/ProjectSidebarLayout.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
"use client";
22
import { FullWidthSidebarLayout } from "@/components/blocks/SidebarLayout";
3-
import { AppFooter } from "@/components/blocks/app-footer";
43
import {
54
BookTextIcon,
65
BoxIcon,
@@ -29,7 +28,6 @@ export function ProjectSidebarLayout(props: {
2928

3029
return (
3130
<FullWidthSidebarLayout
32-
footer={<AppFooter />}
3331
contentSidebarLinks={[
3432
{
3533
href: layoutPath,

0 commit comments

Comments
 (0)