Footer
betaThe bottom of a site: brand, a line about you, social links, columns of links, the legal line, and drawn ridges.
Preview
two columns, no art
narrow container
Install
1. Add the registry to
components.json, once per app. Without it, the shadcn CLI looks up@txbrendanin a public list that txbrendan/ui does not control.npx shadcn@latest registry add "@txbrendan=https://txbrendan.dev/r/{name}.json"2. Add the theme, once per app. It replaces your color tokens with ones checked for contrast.
npx shadcn@latest add @txbrendan/theme3. Add the website component. It also adds every component it uses. Its own files go in your
componentsfolder, and they are yours to edit.npx shadcn@latest add @txbrendan/footer
Use it for
- The bottom of every page on a marketing site.
- Two to five columns of links, each with a short title like Product or Legal.
- Put your copyright in `legal`, and social icon links, each with a name, in `social`.
- Pass your router's link through `renderLink`, like next/link.
- Leave `art` off to get the drawn ridges. Pass an empty element to show none.
Avoid it for
- The main way to get around. Put the important links in the Navbar too.
- More than about eight links in a column. Split it, or link to a site map.
- Footers inside an app's own screens. Keep app chrome in the app shell.
Props
- brand
Your logo or name. It links to brandHref.
ReactNode
- brandHref
Where the brand links.
string · default "/"
- description
A line or two about what you do, under the brand.
ReactNode
- social
Social links under the description. Give each one an aria-label.
ReactNode
- columns
Columns of links, left to right. Titles must be unique, and so must each column's hrefs.
{ title: string; links: { href: string; label: string }[] }[]
- legal
The bottom line, like the copyright.
ReactNode
- renderLink
Draws the brand and each link. Spread the props onto your router's link: (props) => <Link {...props} />.
(props: FooterLinkProps) => ReactNode · default a plain <a>
- art
Your own art in the strip along the bottom. It fills the strip.
ReactNode · default drawn ridges
- label
The name screen readers give the link columns' nav.
string · default "Footer"
- className
Extra classes on the footer, which holds the container query.
string
| Prop | Type | Default | What it does |
|---|---|---|---|
| brand | ReactNode | - | Your logo or name. It links to brandHref. |
| brandHref | string | "/" | Where the brand links. |
| description | ReactNode | - | A line or two about what you do, under the brand. |
| social | ReactNode | - | Social links under the description. Give each one an aria-label. |
| columns | { title: string; links: { href: string; label: string }[] }[] | - | Columns of links, left to right. Titles must be unique, and so must each column's hrefs. |
| legal | ReactNode | - | The bottom line, like the copyright. |
| renderLink | (props: FooterLinkProps) => ReactNode | a plain <a> | Draws the brand and each link. Spread the props onto your router's link: (props) => <Link {...props} />. |
| art | ReactNode | drawn ridges | Your own art in the strip along the bottom. It fills the strip. |
| label | string | "Footer" | The name screen readers give the link columns' nav. |
| className | string | - | Extra classes on the footer, which holds the container query. |
Accessibility
- It renders a footer landmark, with the link columns in a nav named by `label`.
- Each column title is an h2, so screen readers can jump between them.
- The art has its own strip under the text, so no text sits on it. The drawn ridges are aria-hidden.
- If you pass your own `art`, give it empty alt text, since it is decoration.
Examples
A site footer
<Footer
brand="Workspace"
description="Plan the week together."
columns={[
{ title: "Product", links: [{ href: "/features", label: "Features" }, { href: "/pricing", label: "Pricing" }] },
{ title: "Legal", links: [{ href: "/privacy", label: "Privacy" }, { href: "/terms", label: "Terms" }] },
]}
legal="© 2026 Workspace"
renderLink={(props) => <Link {...props} />}
/>