# Footer-2

> A simple footer with social media buttons and language switching

A shadcn/ui block from the [@hexui](https://hexui.sh) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/hexui/footer-2).

- Page, with a live preview: https://shadcn.exchange/r/hexui/footer-2
- Screenshot: https://abzjhwgwpdpz7ua5.public.blob.vercel-storage.com/shots/hexui/footer-2-light-6ecf61cb649fc25b.png
- Registry item: https://hexui.sh/r/footer-2.json
- Categories: footer
- Listed: 2026-10-13, source last changed 2026-10-13

## Install

```bash
npx shadcn@latest add https://hexui.sh/r/footer-2.json
```

Run it in a project that has shadcn/ui set up. It adds the files below and installs what they depend on.

## Dependencies

- npm packages: `@icons-pack/react-simple-icons`, `lucide-react`
- Registry items: `button`, `select`

## Files

### `registry/blocks/footer/footer-2/source/app/footer/page.tsx`

```tsx
import { SiteFooter } from "../../components/site-footer"

export default function Page() {
    return (
        <div className="flex flex-col w-full min-h-dvh items-center justify-center">
            <SiteFooter />
        </div>
    )
}
```

### `registry/blocks/footer/footer-2/source/components/site-footer.tsx`

```tsx
import Link from "next/link"
import { Command } from "lucide-react"
import { NavLinks } from "./nav-links"
import { LanguageSelect } from "./language-select"
import { SocialLinks } from "./social-links"
import { SiX, SiInstagram, SiFacebook, SiGithub, SiBluesky } from "@icons-pack/react-simple-icons"

const SOCIAL_LINKS = [
    { icon: SiX, label: "X" },
    { icon: SiInstagram, label: "Instagram" },
    { icon: SiFacebook, label: "Facebook" },
    { icon: SiGithub, label: "GitHub" },
    { icon: SiBluesky, label: "Bluesky" },
]

const footerSections = [
    {
        title: "Product",
        links: [
            { label: "Features", href: "#" },
            { label: "Pricing", href: "#" },
            { label: "Case Studies", href: "#" },
            { label: "Changelog", href: "#" },
        ],
    },
    {
        title: "Company",
        links: [
            { label: "About Us", href: "#" },
            { label: "Careers", href: "#" },
            { label: "Blog", href: "#" },
            { label: "Contact", href: "#" },
        ],
    },
    {
        title: "Resources",
        links: [
            { label: "Documentation", href: "#" },
            { label: "API Reference", href: "#" },
            { label: "Guides", href: "#" },
            { label: "Support", href: "#" },
        ],
    },
    {
        title: "Legal",
        links: [
            { label: "Terms of Service", href: "#" },
            { label: "Privacy Policy", href: "#" },
            { label: "Cookie Settings", href: "#" },
        ],
    },
]

export function SiteFooter() {
    return (
        <footer className="w-full border-t border-border">
            <div className="mx-auto max-w-7xl px-6 py-12 md:px-8 md:pb-16 md:pt-12">
                <div className="flex flex-col xl:flex-row gap-8 sm:gap-12">
                    <div className="flex flex-col h-full justify-between space-y-6 xl:w-1/4 xl:max-w-sm">
                        <div className="flex flex-col space-y-4">
                            <Link href="#" className="flex items-center gap-2">
                                <Command />
                                <span className="text-xl font-semibold text-foreground">Acme Inc.</span>
                            </Link>

                            <SocialLinks links={SOCIAL_LINKS} />
                        </div>

                        <LanguageSelect />

                        <div className="flex flex-col gap-4">
                            <Link href="#" className="text-xs text-muted-foreground transition-colors hover:text-foreground">
                                Cookie Setting
                            </Link>
                            <p className="text-xs text-muted-foreground">
                                &copy; {new Date().getFullYear()} Acme Inc. All rights reserved.
                            </p>
                        </div>
                    </div>

                    <NavLinks sections={footerSections} />
                </div>
            </div>
        </footer>
    )
}
```

### `registry/blocks/footer/footer-2/source/components/language-select.tsx`

```tsx
"use client"

import { useState } from "react"
import { Languages } from "lucide-react"
import { Select, SelectContent, SelectItem, SelectTrigger } from "@/components/ui/select"

const items = [
    { label: "English", value: "en" },
    { label: "日本語", value: "ja" },
    { label: "한국어", value: "ko" },
    { label: "中文", value: "zh" },
];

export function LanguageSelect() {
    const [selectedValue, setSelectedValue] = useState("en")
    // Derive the human-readable label shown in the trigger from the selected value.
    const selectedLabel = items.find((item) => item.value === selectedValue)?.label || "English"

    return (
        <Select value={selectedValue} onValueChange={(value) => {
            if (value) setSelectedValue(value)
        }}>
            <SelectTrigger className="h-7 xl:h-9 w-40 rounded-md border-border/70 bg-background/80 px-3 shadow-xs">
                <div className="flex min-w-0 items-center gap-2">
                    <Languages className="size-4 shrink-0 text-muted-foreground" />
                    <span className="truncate text-sm">{selectedLabel}</span>
                </div>
            </SelectTrigger>
            {/* Opens upward: this select sits near the page bottom, so a downward popup would overflow. */}
            <SelectContent side="top" sideOffset={8} align="start" alignItemWithTrigger={false}>
                {items.map((item) => (
                    <SelectItem key={item.value} value={item.value}>
                        {item.label}
                    </SelectItem>
                ))}
            </SelectContent>
        </Select>
    )
}
```

### `registry/blocks/footer/footer-2/source/components/nav-links.tsx`

```tsx
import Link from "next/link"

type FooterLinkItem = {
  label: string
  href: string
}

type FooterSection = {
  title: string
  links: FooterLinkItem[]
}

type NavLinksProps = {
  sections: FooterSection[]
}

export function NavLinks({ sections }: NavLinksProps) {
  return (
    <div className="grid gap-6 sm:gap-8 grid-cols-2 xl:w-2/3 xl:flex-1 xl:grid-cols-4">
      {sections.map((section) => (
        <div key={section.title}>
          <h3 className="text-sm font-semibold text-foreground">{section.title}</h3>
          {/* role="list" keeps list semantics; Tailwind preflight strips default list styles. */}
          <ul role="list" className="mt-4 space-y-2 sm:space-y-3">
            {section.links.map((item) => (
              <li key={item.label}>
                <Link
                  href={item.href}
                  className="text-sm text-muted-foreground transition-colors hover:text-foreground"
                >
                  {item.label}
                </Link>
              </li>
            ))}
          </ul>
        </div>
      ))}
    </div>
  )
}
```

### `registry/blocks/footer/footer-2/source/components/social-links.tsx`

```tsx
import { Button } from "@/components/ui/button"

interface SocialLink {
    icon: React.ComponentType<{ className?: string }>
    label: string
}

interface SocialLinksProps {
    links: SocialLink[]
}

export function SocialLinks({ links }: SocialLinksProps) {
    return (
        <div className="flex gap-0.5 text-muted-foreground -ml-1.5">
            {links.map((link) => {
                const Icon = link.icon
                return (
                    <Button
                        key={link.label}
                        variant={"ghost"}
                        size="icon"
                        className="size-8 [&_svg]:size-4 xl:size-10 xl:[&_svg]:size-4.5"
                        aria-label={link.label}
                    >
                        <Icon className="size-5" />
                    </Button>
                )
            })}
        </div>
    )
}
```
