Menu

Change language

GitHub repo

Multi-Column Footer

blockmarketing

Site footer with brand mark + newsletter form on the left and four link columns (Product / Company / Resources / Legal) on the right. Separator divides into a copyright + social icon row. Each link is spelled out inline so copy lives in one place.

Installation

$npx uipkge-ng@latest add footer-01
Manifest:https://uipkge.dev/r/angular/footer-01.jsonInstalls to:src/app/components/blocks/footer-01/

Variants

Loading interactive previews…

npm dependencies

Files installed (2)

  • src/app/components/blocks/footer-01/footer-01.component.ts7 kB
    // Site footer with brand mark + newsletter form on the left and four link columns
    // (Product / Company / Resources / Legal) on the right. Port of the React block 1:1.
    import { ChangeDetectionStrategy, Component, Input, signal } from '@angular/core'
    import { Boxes, Github, Linkedin, LucideAngularModule, Twitter } from 'lucide-angular'
    import { cn } from '@/lib/utils'
    import { UiButtonComponent } from '@/ui/button/button.component'
    import { UiInputComponent } from '@/ui/input/input.component'
    import { UiSeparatorComponent } from '@/ui/separator/separator.component'
    
    @Component({
      changeDetection: ChangeDetectionStrategy.Eager,
      selector: 'ui-footer-01, [ui-footer-01]',
      standalone: true,
      // React renders the root <footer> itself: the host stays out of layout and `class` goes to the root.
      host: { '[attr.class]': '"contents"' },
      imports: [LucideAngularModule, UiButtonComponent, UiInputComponent, UiSeparatorComponent],
      template: `
        <footer data-slot="footer-01" [class]="rootClass">
          <div class="mx-auto max-w-6xl px-6 py-16">
            <div class="grid gap-10 lg:grid-cols-12">
              <div class="space-y-4 lg:col-span-4">
                <div class="flex items-center gap-2">
                  <div class="bg-primary text-primary-foreground flex size-8 items-center justify-center rounded-md">
                    <lucide-icon [img]="Boxes" class="size-4" />
                  </div>
                  <span class="text-base font-semibold">Acme</span>
                </div>
                <p class="text-muted-foreground max-w-sm text-sm">Built on shadcn-vue. Get product updates monthly.</p>
                <form class="flex max-w-sm gap-2" (submit)="subscribe($event)">
                  <ui-input
                    [value]="newsletter()"
                    (valueChange)="newsletter.set($event)"
                    type="email"
                    placeholder="you@company.com"
                    required
                    class="flex-1"
                  />
                  <button ui-button type="submit">Subscribe</button>
                </form>
                @if (subscribed()) {
                  <p class="text-success text-xs">Thanks — check your inbox to confirm.</p>
                }
              </div>
    
              <div class="grid grid-cols-2 gap-6 sm:grid-cols-4 lg:col-span-8">
                <div class="space-y-3">
                  <h3 class="text-sm font-semibold">Product</h3>
                  <ul class="space-y-2">
                    <li>
                      <a href="#" class="text-muted-foreground hover:text-foreground text-sm transition-colors">Features</a>
                    </li>
                    <li>
                      <a href="#" class="text-muted-foreground hover:text-foreground text-sm transition-colors">Pricing</a>
                    </li>
                    <li>
                      <a href="#" class="text-muted-foreground hover:text-foreground text-sm transition-colors"
                        >Changelog</a
                      >
                    </li>
                    <li>
                      <a href="#" class="text-muted-foreground hover:text-foreground text-sm transition-colors">Roadmap</a>
                    </li>
                  </ul>
                </div>
                <div class="space-y-3">
                  <h3 class="text-sm font-semibold">Company</h3>
                  <ul class="space-y-2">
                    <li>
                      <a href="#" class="text-muted-foreground hover:text-foreground text-sm transition-colors">About</a>
                    </li>
                    <li>
                      <a href="#" class="text-muted-foreground hover:text-foreground text-sm transition-colors">Blog</a>
                    </li>
                    <li>
                      <a href="#" class="text-muted-foreground hover:text-foreground text-sm transition-colors">Careers</a>
                    </li>
                    <li>
                      <a href="#" class="text-muted-foreground hover:text-foreground text-sm transition-colors">Contact</a>
                    </li>
                  </ul>
                </div>
                <div class="space-y-3">
                  <h3 class="text-sm font-semibold">Resources</h3>
                  <ul class="space-y-2">
                    <li>
                      <a href="#" class="text-muted-foreground hover:text-foreground text-sm transition-colors">
                        Documentation
                      </a>
                    </li>
                    <li>
                      <a href="#" class="text-muted-foreground hover:text-foreground text-sm transition-colors">API</a>
                    </li>
                    <li>
                      <a href="#" class="text-muted-foreground hover:text-foreground text-sm transition-colors">
                        Help center
                      </a>
                    </li>
                    <li>
                      <a href="#" class="text-muted-foreground hover:text-foreground text-sm transition-colors">Status</a>
                    </li>
                  </ul>
                </div>
                <div class="space-y-3">
                  <h3 class="text-sm font-semibold">Legal</h3>
                  <ul class="space-y-2">
                    <li>
                      <a href="#" class="text-muted-foreground hover:text-foreground text-sm transition-colors">Terms</a>
                    </li>
                    <li>
                      <a href="#" class="text-muted-foreground hover:text-foreground text-sm transition-colors">Privacy</a>
                    </li>
                    <li>
                      <a href="#" class="text-muted-foreground hover:text-foreground text-sm transition-colors">Security</a>
                    </li>
                    <li>
                      <a href="#" class="text-muted-foreground hover:text-foreground text-sm transition-colors">DPA</a>
                    </li>
                  </ul>
                </div>
              </div>
            </div>
    
            <div ui-separator class="my-10"></div>
    
            <div class="flex flex-wrap items-center justify-between gap-4">
              <p class="text-muted-foreground text-xs">© 2026 Acme. All rights reserved.</p>
              <div class="flex items-center gap-3">
                <a href="#" aria-label="GitHub" class="text-muted-foreground hover:text-foreground transition-colors">
                  <lucide-icon [img]="Github" class="size-4" />
                </a>
                <a href="#" aria-label="Twitter" class="text-muted-foreground hover:text-foreground transition-colors">
                  <lucide-icon [img]="Twitter" class="size-4" />
                </a>
                <a href="#" aria-label="LinkedIn" class="text-muted-foreground hover:text-foreground transition-colors">
                  <lucide-icon [img]="Linkedin" class="size-4" />
                </a>
              </div>
            </div>
          </div>
        </footer>
      `,
    })
    export class UiFooter01Component {
      protected readonly Boxes = Boxes
      protected readonly Github = Github
      protected readonly Linkedin = Linkedin
      protected readonly Twitter = Twitter
    
      @Input('class') className?: string
    
      readonly newsletter = signal('')
      readonly subscribed = signal(false)
    
      get rootClass(): string {
        return cn('bg-background border-t', this.className)
      }
    
      subscribe(event?: Event): void {
        event?.preventDefault()
        if (!this.newsletter()) return
        this.subscribed.set(true)
        this.newsletter.set('')
      }
    }
    
  • src/app/components/blocks/footer-01/index.ts0.1 kB

Raw manifest:https://uipkge.dev/r/angular/footer-01.json