Studio Footer
A complete studio footer section, ready to adapt to your product.
Make it yours.
Install the editable source and its dependencies into your React + Tailwind project.
Scroll horizontally for long lines
pnpm dlx shadcn@4.0.8 add http://localhost:3000/r/studio-footer.jsonUse it
Scroll horizontally for long lines
"use client";
import { StudioFooter } from "@/components/jez-ui/blocks/studio-footer";
export default function Example() {
return (
<>
<StudioFooter />
</>
);
}
Compose your own
These styled parts are included in the same install. Use children to build your layout; add className only when you want an override.
Scroll horizontally for long lines
import { StudioFooter, StudioFooterTitle, StudioFooterContent } from "@/components/jez-ui/blocks/studio-footer";Props & types
Scroll horizontally for long lines
export type StudioFooterOptions = {
className?: string;
brand?: string;
title?: string;
href?: string;
actionLabel?: string;
groups?: FooterLinkGroup[];
};
export type StudioFooterProps = Omit<
React.ComponentProps<"footer">,
keyof StudioFooterOptions
> &
StudioFooterOptions;
StudioFooterPropsSource
View 3 source files
registry/blocks/studio-footer.tsx
Scroll horizontally for long lines
"use client";
import * as React from "react";
import { cn } from "../ui/utils";
import { ArrowUpRight } from "lucide-react";
import { FooterLinks, type FooterLinkGroup } from "./footer-links";
export type StudioFooterOptions = {
className?: string;
brand?: string;
title?: string;
href?: string;
actionLabel?: string;
groups?: FooterLinkGroup[];
};
export type StudioFooterProps = Omit<
React.ComponentProps<"footer">,
keyof StudioFooterOptions
> &
StudioFooterOptions;
export function StudioFooter({
className,
brand = "Good company.",
title = "Have something in mind?",
href = "mailto:hello@example.com",
actionLabel = "Let’s talk",
groups,
children,
...rootProps
}: StudioFooterProps) {
return (
<footer
{...rootProps}
className={cn(
"rounded-xl bg-[#26362c] p-7 text-[#e7eddf] md:p-12",
className,
)}
>
{children !== undefined ? (
children
) : (
<>
<StudioFooterTitle>{title}</StudioFooterTitle>
<a
href={href}
className="mt-7 inline-flex items-center gap-4 border-b border-current pb-2 text-2xl hover:opacity-80"
>
{actionLabel}
<ArrowUpRight aria-hidden size={28} />
</a>
<StudioFooterContent>
<p className="text-2xl">{brand}</p>
<FooterLinks groups={groups} />
</StudioFooterContent>
</>
)}
</footer>
);
}
export function StudioFooterTitle({
className,
...props
}: React.ComponentProps<"h2">) {
return (
<h2
data-slot="studio-footer-title"
className={cn(
"max-w-xl text-4xl leading-tight tracking-tight md:text-6xl",
className,
)}
{...props}
/>
);
}
export function StudioFooterContent({
className,
...props
}: React.ComponentProps<"div">) {
return (
<div
data-slot="studio-footer-content"
className={cn(
"mt-16 grid gap-10 border-t border-[#aabca3]/40 pt-8 md:grid-cols-2",
className,
)}
{...props}
/>
);
}
registry/ui/utils.ts
Scroll horizontally for long lines
import { clsx, type ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";
export function cn(...values: ClassValue[]) {
return twMerge(clsx(values));
}
registry/blocks/footer-links.tsx
Scroll horizontally for long lines
"use client";
import * as React from "react";
export type FooterLinkGroup = {
title: string;
links: { label: string; href: string }[];
};
export const defaultFooterGroups: FooterLinkGroup[] = [
{
title: "Explore",
links: [
{ label: "Components", href: "/components" },
{ label: "Blocks", href: "/blocks" },
{ label: "Templates", href: "/templates" },
],
},
{
title: "Resources",
links: [
{ label: "Documentation", href: "/docs" },
{ label: "Installation", href: "/docs/installation" },
],
},
];
export function FooterLinks({
groups = defaultFooterGroups,
}: {
groups?: FooterLinkGroup[];
}) {
return (
<nav aria-label="Footer" className="grid grid-cols-2 gap-8">
{groups.map((g) => (
<div key={g.title}>
<h3 className="mb-4 text-sm font-medium">{g.title}</h3>
<ul className="space-y-3">
{g.links.map((l) => (
<li key={l.href}>
<a
className="text-sm opacity-80 hover:underline hover:opacity-100"
href={l.href}
>
{l.label}
</a>
</li>
))}
</ul>
</div>
))}
</nav>
);
}
Dependencies
lucide-react@0.577.0 · clsx@2.1.1 · tailwind-merge@3.5.0
Accessibility & behaviour
Provide meaningful labels and preserve keyboard focus styles. Check contrast when customising theme colours.
Read the accessibility and performance guide →