Editorial Footer
A complete editorial 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/editorial-footer.jsonUse it
Scroll horizontally for long lines
"use client";
import { EditorialFooter } from "@/components/jez-ui/blocks/editorial-footer";
export default function Example() {
return (
<>
<EditorialFooter />
</>
);
}
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 { EditorialFooter, EditorialFooterContent, EditorialFooterTitle, EditorialFooterDescription } from "@/components/jez-ui/blocks/editorial-footer";Props & types
Scroll horizontally for long lines
export type EditorialFooterOptions = {
className?: string;
brand?: string;
description?: string;
groups?: FooterLinkGroup[];
};
export type EditorialFooterProps = Omit<
React.ComponentProps<"footer">,
keyof EditorialFooterOptions
> &
EditorialFooterOptions;
EditorialFooterPropsSource
View 3 source files
registry/blocks/editorial-footer.tsx
Scroll horizontally for long lines
"use client";
import * as React from "react";
import { cn } from "../ui/utils";
import { FooterLinks, type FooterLinkGroup } from "./footer-links";
export type EditorialFooterOptions = {
className?: string;
brand?: string;
description?: string;
groups?: FooterLinkGroup[];
};
export type EditorialFooterProps = Omit<
React.ComponentProps<"footer">,
keyof EditorialFooterOptions
> &
EditorialFooterOptions;
export function EditorialFooter({
className,
brand = "The Sunday Edit.",
description = "Notes on design, culture, and paying closer attention.",
groups,
children,
...rootProps
}: EditorialFooterProps) {
return (
<footer
{...rootProps}
className={cn("border-t border-border py-10", className)}
>
{children !== undefined ? (
children
) : (
<>
<EditorialFooterContent>
<div>
<EditorialFooterTitle>{brand}</EditorialFooterTitle>
<p className="mt-5 max-w-xs text-sm leading-relaxed text-muted-foreground">
{description}
</p>
</div>
<FooterLinks groups={groups} />
</EditorialFooterContent>
<EditorialFooterDescription>
An illustrative publication · Made with Jez UI
</EditorialFooterDescription>
</>
)}
</footer>
);
}
export function EditorialFooterContent({
className,
...props
}: React.ComponentProps<"div">) {
return (
<div
data-slot="editorial-footer-content"
className={cn("grid gap-10 md:grid-cols-2", className)}
{...props}
/>
);
}
export function EditorialFooterTitle({
className,
...props
}: React.ComponentProps<"h2">) {
return (
<h2
data-slot="editorial-footer-title"
className={cn("max-w-sm font-serif text-5xl leading-tight", className)}
{...props}
/>
);
}
export function EditorialFooterDescription({
className,
...props
}: React.ComponentProps<"p">) {
return (
<p
data-slot="editorial-footer-description"
className={cn(
"mt-12 border-t border-border pt-5 text-xs text-muted-foreground",
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
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 →