Footer Links
Multi-column site footer with a brand block, titled link groups, copyright line and social icons — all consumer-supplied.
Install
One command copies the item's source into your project, where you own and edit it.
npx manteen add @house/footer-linksDependencies
@mantine/core@^9npm
Installing this item also installs @house/mantine-ui-license from the registry.
Preview
Usage
A copy-ready example published by the registry author. Imports use the aliases Manteen configures at init.
import { Text } from "@mantine/core";import { IconBrandInstagram, IconBrandTwitter, IconBrandYoutube } from "@tabler/icons-react";import { FooterLinks, type FooterLinksGroup, type FooterLinksSocialLink,} from "@/components/ui/footer-links";
const groups: FooterLinksGroup[] = [ { title: "About", links: [ { label: "Features", href: "/features" }, { label: "Pricing", href: "/pricing" }, { label: "Support", href: "/support" }, { label: "Forums", href: "/forums" }, ], }, { title: "Project", links: [ { label: "Contribute", href: "/contribute" }, { label: "Media assets", href: "/media" }, { label: "Changelog", href: "/changelog" }, { label: "Releases", href: "/releases" }, ], }, { title: "Community", links: [ { label: "Join Discord", href: "https://discord.gg/acme" }, { label: "Follow on Twitter", href: "https://twitter.com/acme" }, { label: "Email newsletter", href: "/newsletter" }, { label: "GitHub discussions", href: "https://github.com/acme/acme/discussions" }, ], },];
const socialLinks: FooterLinksSocialLink[] = [ { href: "https://twitter.com/acme", label: "Twitter", icon: <IconBrandTwitter size={18} stroke={1.5} />, }, { href: "https://youtube.com/@acme", label: "Youtube", icon: <IconBrandYoutube size={18} stroke={1.5} />, }, { href: "https://instagram.com/acme", label: "Instagram", icon: <IconBrandInstagram size={18} stroke={1.5} />, },];
export function SiteFooter() { return ( <FooterLinks logo={ <Text fw={700} size="lg"> Acme </Text> } tagline="Build fully functional accessible web applications faster than ever" groups={groups} copyright="© 2026 Acme. All rights reserved." socialLinks={socialLinks} /> );}Props
Author-documented props, carried verbatim from the registry item.
| Prop | Type | Default | Description |
|---|---|---|---|
logo | ReactNode | — | Rendered at the start of the brand block; nothing renders when omitted. |
tagline | string | — | Short description under the logo; omitted when unset. |
groups* | readonly FooterLinksGroup[] | — | Titled link columns, each { title: string; links: readonly FooterLinksLink[] }; this is the component's whole point. |
copyright | string | — | Copyright/legal line in the bottom bar; omitted when unset. |
socialLinks | readonly FooterLinksSocialLink[] | — | { href, icon, label } per entry; label becomes the icon link's aria-label. The entire bottom-bar social row is omitted when unset or empty. |
* required
Styling
No public Styles API is declared. Installed CSS remains editable because your project owns the source; internal class names are implementation details, not a customization contract.
Source
2 installable files ship with this item.
registry/mantine-ui/footer-links/footer-links.tsxcomponent · 3.1 kB · tsx
/** * Adapted from Mantine UI's FooterLinks at * ffbf61c559f374a7ea28fcf00355e84dcbe9a908. MIT licensed; see * LICENSES/MANTINE-UI.txt after installation. */
import { ActionIcon, Container, Group, Text } from "@mantine/core";import type { ReactNode } from "react";
import classes from "./footer-links.module.css";
export interface FooterLinksLink { label: string; href: string;}
export interface FooterLinksGroup { title: string; links: readonly FooterLinksLink[];}
export interface FooterLinksSocialLink { href: string; icon: ReactNode; /** Accessible name for the icon-only link, e.g. "Twitter". */ label: string;}
export interface FooterLinksProps { /** Rendered at the start of the brand block; nothing renders when omitted. */ logo?: ReactNode; /** Short description under the logo; omitted when unset. */ tagline?: string; /** Titled link columns. This is the component's whole point. */ groups: readonly FooterLinksGroup[]; /** Copyright / legal line; omitted when unset. */ copyright?: string; /** Social icon links; the row is omitted when unset or empty. */ socialLinks?: readonly FooterLinksSocialLink[];}
export function FooterLinks({ logo, tagline, groups, copyright, socialLinks }: FooterLinksProps) { const hasBrand = Boolean(logo || tagline); const hasSocial = Boolean(socialLinks && socialLinks.length > 0);
const groupItems = groups.map((group) => { const links = group.links.map((link) => ( <Text key={link.label} className={classes.link} component="a" href={link.href}> {link.label} </Text> ));
return ( <div className={classes.wrapper} key={group.title}> <Text className={classes.title}>{group.title}</Text> {links} </div> ); });
return ( <footer className={classes.footer}> <Container className={classes.inner}> {hasBrand && ( <div className={classes.logo}> {logo} {tagline && ( <Text size="xs" c="dimmed" className={classes.description}> {tagline} </Text> )} </div> )} <div className={classes.groups}>{groupItems}</div> </Container>
{(copyright || hasSocial) && ( <Container className={classes.afterFooter}> {copyright && ( <Text c="dimmed" size="sm"> {copyright} </Text> )}
{hasSocial && ( <Group gap={0} className={classes.social} justify="flex-end" wrap="nowrap"> {socialLinks?.map((social) => ( <ActionIcon key={social.href} size="lg" color="gray" variant="subtle" aria-label={social.label} component="a" href={social.href} > {social.icon} </ActionIcon> ))} </Group> )} </Container> )} </footer> );}registry/mantine-ui/footer-links/footer-links.module.cssstyle · 2.5 kB · css
/* * Adapted from Mantine UI's FooterLinks at * ffbf61c559f374a7ea28fcf00355e84dcbe9a908. MIT licensed; see * LICENSES/MANTINE-UI.txt after installation. */
/* Upstream used postcss-preset-mantine's `$mantine-breakpoint-sm`; this * registry ships plain CSS modules with no PostCSS preset, so the literal * 48em default `sm` breakpoint value is inlined here (`var()` is invalid * inside a media condition). See header-mega-menu.module.css for the same * convention. Upstream's `margin-top: 120px` on `.footer` was outer layout * margin imposed on the host page and is dropped here — a registry item * must not push the page around. */.footer { padding-top: calc(var(--mantine-spacing-xl) * 2); padding-bottom: calc(var(--mantine-spacing-xl) * 2); background-color: light-dark(var(--mantine-color-gray-0), var(--mantine-color-dark-6)); border-top: 1px solid light-dark(var(--mantine-color-gray-2), var(--mantine-color-dark-5));}
.logo { max-width: 200px;}
@media (max-width: 48em) { .logo { display: flex; flex-direction: column; align-items: center; }}
.description { margin-top: 5px;}
@media (max-width: 48em) { .description { margin-top: var(--mantine-spacing-xs); text-align: center; }}
.inner { display: flex; justify-content: space-between;}
@media (max-width: 48em) { .inner { flex-direction: column; align-items: center; }}
.groups { display: flex; flex-wrap: wrap;}
@media (max-width: 48em) { .groups { display: none; }}
.wrapper { width: 160px;}
.link { display: block; color: light-dark(var(--mantine-color-gray-6), var(--mantine-color-dark-1)); font-size: var(--mantine-font-size-sm); padding-top: 3px; padding-bottom: 3px;}
.link:hover { text-decoration: underline;}
.title { font-size: var(--mantine-font-size-lg); font-weight: 500; font-family: var(--mantine-font-family-headings); margin-bottom: calc(var(--mantine-spacing-xs) / 2); color: light-dark(var(--mantine-color-black), var(--mantine-color-white));}
.afterFooter { display: flex; justify-content: space-between; align-items: center; margin-top: var(--mantine-spacing-xl); padding-top: var(--mantine-spacing-xl); padding-bottom: var(--mantine-spacing-xl); border-top: 1px solid light-dark(var(--mantine-color-gray-2), var(--mantine-color-dark-4));}
@media (max-width: 48em) { .afterFooter { flex-direction: column; }}
@media (max-width: 48em) { .social { margin-top: var(--mantine-spacing-xs); }}Author notes
Adapted from Mantine UI FooterLinks at ffbf61c559…; the three hardcoded link groups became the groups prop, the upstream MantineLogo import became an optional logo slot, the tagline/copyright strings became optional props with no fake placeholder default, and the fixed social icons became a consumer-supplied socialLinks array.