e30e75b5d4
Changesets / Create Version PR (push) Has been cancelled
Deploy Shadcn Registry / Deploy Production (push) Has been cancelled
Template Metrics / LOC + Bundle Size (push) Has been cancelled
Code Quality / Oxlint + Oxfmt (push) Has been cancelled
Code Quality / Template Sync (push) Has been cancelled
Code Quality / Build Changed Packages (push) Has been cancelled
Code Quality / Test Changed Packages (push) Has been cancelled
Deploy Expo Example / Deploy Production (push) Has been cancelled
Deploy Ink Example / Deploy Production (push) Has been cancelled
Python Tests / pytest (assistant-stream, 3.10) (push) Has been cancelled
Python Tests / pytest (assistant-stream, 3.12) (push) Has been cancelled
Python Tests / pytest (assistant-ui-sync-server-api, 3.10) (push) Has been cancelled
Python Tests / pytest (assistant-ui-sync-server-api, 3.12) (push) Has been cancelled
179 lines
5.3 KiB
TypeScript
179 lines
5.3 KiB
TypeScript
import type { FC, ReactNode } from "react";
|
|
import Image from "next/image";
|
|
import Link from "next/link";
|
|
import { ArrowUpRight } from "lucide-react";
|
|
import { GitHubIcon } from "@/components/icons/github";
|
|
import { DiscordIcon } from "@/components/icons/discord";
|
|
import { ThemeToggle } from "@/components/shared/theme-toggle";
|
|
import { CLOUD_URL, PRODUCTS } from "@/lib/constants";
|
|
|
|
type FooterLinkItem = {
|
|
label: string;
|
|
href: string;
|
|
external?: boolean;
|
|
};
|
|
|
|
const FOOTER_LINKS: Record<string, FooterLinkItem[]> = {
|
|
Products: [
|
|
{
|
|
label: "Cloud",
|
|
href: CLOUD_URL,
|
|
external: true,
|
|
},
|
|
{ label: "Playground", href: "/playground" },
|
|
...PRODUCTS.map((p) => ({
|
|
label: p.label,
|
|
href: p.href,
|
|
...(p.external && { external: true }),
|
|
})),
|
|
],
|
|
Resources: [
|
|
{ label: "Documentation", href: "/docs" },
|
|
{ label: "Examples", href: "/examples" },
|
|
{ label: "Showcase", href: "/showcase" },
|
|
{ label: "Traction", href: "/traction" },
|
|
{ label: "Packages", href: "/packages" },
|
|
{ label: "Blog", href: "/blog" },
|
|
],
|
|
Company: [
|
|
{ label: "Careers", href: "/careers" },
|
|
{
|
|
label: "Contact Sales",
|
|
href: "https://cal.com/simon-farshid/assistant-ui",
|
|
external: true,
|
|
},
|
|
{ label: "Pricing", href: "/pricing" },
|
|
{ label: "Brand", href: "/brand" },
|
|
],
|
|
Legal: [
|
|
{
|
|
label: "Terms of Service",
|
|
href: "/terms-of-service",
|
|
},
|
|
{
|
|
label: "Privacy Policy",
|
|
href: "/privacy-policy",
|
|
},
|
|
],
|
|
};
|
|
|
|
export function Footer(): React.ReactElement {
|
|
return (
|
|
<footer className="py-10 md:py-16">
|
|
<div className="mx-auto flex w-full max-w-7xl flex-col gap-10 px-4 md:flex-row md:justify-between">
|
|
<div className="grid grid-cols-2 gap-x-12 gap-y-8 sm:grid-cols-4 md:order-2 lg:gap-x-16">
|
|
{Object.entries(FOOTER_LINKS).map(([category, links]) => (
|
|
<div key={category} className="flex flex-col gap-3">
|
|
<p className="text-sm font-medium">{category}</p>
|
|
{links.map((link) => (
|
|
<FooterLink
|
|
key={link.href}
|
|
href={link.href}
|
|
{...(link.external && { external: true })}
|
|
>
|
|
{link.label}
|
|
</FooterLink>
|
|
))}
|
|
</div>
|
|
))}
|
|
</div>
|
|
|
|
<div className="flex flex-col gap-4 md:order-1">
|
|
<Link href="/" className="flex items-center gap-2">
|
|
<Image
|
|
src="/favicon/icon.svg"
|
|
alt="logo"
|
|
width={24}
|
|
height={24}
|
|
className="size-6 dark:hue-rotate-180 dark:invert"
|
|
/>
|
|
<span className="text-xl font-medium">assistant-ui</span>
|
|
</Link>
|
|
|
|
<div className="flex items-center gap-3">
|
|
<a
|
|
href="https://x.com/assistantui"
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
className="text-muted-foreground hover:text-foreground transition-colors"
|
|
aria-label="X (Twitter)"
|
|
>
|
|
<svg
|
|
aria-hidden="true"
|
|
className="size-5"
|
|
viewBox="0 0 24 24"
|
|
fill="currentColor"
|
|
>
|
|
<path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z" />
|
|
</svg>
|
|
</a>
|
|
<a
|
|
href="https://github.com/assistant-ui"
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
className="text-muted-foreground hover:text-foreground transition-colors"
|
|
aria-label="GitHub"
|
|
>
|
|
<GitHubIcon className="size-5" />
|
|
</a>
|
|
<a
|
|
href="https://discord.gg/S9dwgCNEFs"
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
className="text-muted-foreground hover:text-foreground transition-colors"
|
|
aria-label="Discord"
|
|
>
|
|
<DiscordIcon className="size-5" />
|
|
</a>
|
|
</div>
|
|
|
|
<div className="mt-auto flex flex-col gap-3">
|
|
<div className="-ml-2">
|
|
<ThemeToggle />
|
|
</div>
|
|
<a
|
|
href="https://agentbase.dev"
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
className="text-muted-foreground hover:text-foreground text-sm transition-colors"
|
|
>
|
|
© {new Date().getFullYear()} AgentbaseAI Inc.
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</footer>
|
|
);
|
|
}
|
|
|
|
const FooterLink: FC<{
|
|
href: string;
|
|
external?: boolean;
|
|
children: ReactNode;
|
|
}> = ({ href, external, children }) => {
|
|
const isExternal = external ?? href.startsWith("http");
|
|
|
|
if (isExternal) {
|
|
return (
|
|
<a
|
|
className="text-muted-foreground hover:text-foreground inline-flex items-center gap-1 text-sm transition-colors"
|
|
href={href}
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
>
|
|
{children}
|
|
<ArrowUpRight className="size-3 opacity-40" />
|
|
</a>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<Link
|
|
className="text-muted-foreground hover:text-foreground text-sm transition-colors"
|
|
href={href}
|
|
>
|
|
{children}
|
|
</Link>
|
|
);
|
|
};
|