Footer — Mega with Newsletter
blockmarketingLarge footer pairing a newsletter signup and status line with five link columns, a social row, and a legal bar carrying the copyright and a compliance badge.
Installation
$pnpm dlx uipkge-ng@latest add footer-mega-newsletter$npx uipkge-ng@latest add footer-mega-newsletter$yarn dlx uipkge-ng@latest add footer-mega-newsletter$bunx uipkge-ng@latest add footer-mega-newsletterManifest:
https://uipkge.dev/r/angular/footer-mega-newsletter.jsonInstalls to:src/app/components/blocks/footer-mega-newsletter/Variants
Loading interactive previews…
Loading interactive previews…
Schema
Type aliases exported from this item's source. Use these to shape the data you pass in.
MegaNewsletterSectioninterface MegaNewsletterSection {
heading: string
links: string[]
}npm dependencies
Files installed (2)
src/app/components/blocks/footer-mega-newsletter/footer-mega-newsletter.component.ts6 kB
// Large footer pairing a newsletter signup and status line with five link columns, // a social row, and a legal bar carrying the copyright and a compliance badge. // Port of the React block 1:1. import { ChangeDetectionStrategy, Component, Input, signal } from '@angular/core' import { ArrowRight, Check, Github, Layers, Linkedin, LucideAngularModule, Youtube } from 'lucide-angular' import { cn } from '@/lib/utils' import { UiBadgeComponent } from '@/ui/badge/badge.component' import { UiButtonComponent } from '@/ui/button/button.component' import { UiInputComponent } from '@/ui/input/input.component' import { UiSeparatorComponent } from '@/ui/separator/separator.component' interface MegaNewsletterSection { heading: string links: string[] } const sections: MegaNewsletterSection[] = [ { heading: 'Product', links: ['Metric layer', 'Dashboards', 'Alerting', 'Embedding', 'Changelog'] }, { heading: 'Solutions', links: ['Finance', 'RevOps', 'Analytics', 'Engineering'] }, { heading: 'Developers', links: ['Documentation', 'API reference', 'CLI', 'Status'] }, { heading: 'Company', links: ['About', 'Careers', 'Customers', 'Press kit'] }, { heading: 'Legal', links: ['Privacy', 'Terms', 'DPA', 'Subprocessors'] }, ] @Component({ changeDetection: ChangeDetectionStrategy.Eager, selector: 'ui-footer-mega-newsletter, [ui-footer-mega-newsletter]', 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, UiBadgeComponent, UiButtonComponent, UiInputComponent, UiSeparatorComponent], template: ` <footer data-slot="footer-mega-newsletter" [class]="rootClass"> <div class="mx-auto max-w-6xl px-6 py-14"> <div class="grid gap-12 lg:grid-cols-[22rem_1fr] lg:gap-16"> <div> <a href="#top" class="flex items-center gap-2 font-semibold tracking-tight"> <lucide-icon [img]="Layers" class="text-primary size-5" aria-hidden="true" /> Northwind </a> <p class="text-muted-foreground mt-3 max-w-sm text-sm leading-relaxed"> One certified metric layer between your warehouse and everything downstream. </p> <form class="mt-6" (submit)="subscribe($event)"> <label for="footer-email" class="text-sm font-medium">Monthly engineering notes</label> <div class="mt-2 flex gap-2"> <ui-input id="footer-email" [value]="email()" (valueChange)="email.set($event)" type="email" placeholder="you@company.com" autoComplete="email" class="max-w-64" /> <button ui-button type="submit"> Subscribe <lucide-icon [img]="ArrowRight" class="ml-1.5 size-3.5" aria-hidden="true" /> </button> </div> <!-- Status line reserves its own row, so confirming does not shift the columns. --> <p class="text-muted-foreground mt-2 min-h-5 text-xs"> @if (submitted()) { <span class="text-success inline-flex items-center gap-1.5"> <lucide-icon [img]="Check" class="size-3" aria-hidden="true" /> Check your inbox to confirm. </span> } @else { <span>One email a month. Unsubscribe in one click.</span> } </p> </form> </div> <div class="grid grid-cols-2 gap-8 sm:grid-cols-3 lg:grid-cols-5"> @for (section of sectionList; track section.heading) { <div> <p class="text-muted-foreground/70 text-xs font-medium tracking-wide uppercase"> {{ section.heading }} </p> <ul class="mt-3 space-y-2"> @for (link of section.links; track link) { <li> <a href="#" class="text-muted-foreground hover:text-foreground text-sm transition-colors"> {{ link }} </a> </li> } </ul> </div> } </div> </div> <div ui-separator class="my-10"></div> <div class="flex flex-col gap-4 sm:flex-row sm:items-center"> <p class="text-muted-foreground text-xs">© 2026 Northwind Data, Inc. All rights reserved.</p> <span ui-badge variant="outline" class="w-fit">SOC 2 Type II</span> <div class="flex items-center gap-1 sm:ml-auto"> <button ui-button variant="ghost" size="icon" class="size-8" aria-label="GitHub"> <lucide-icon [img]="Github" class="size-4" aria-hidden="true" /> </button> <button ui-button variant="ghost" size="icon" class="size-8" aria-label="LinkedIn"> <lucide-icon [img]="Linkedin" class="size-4" aria-hidden="true" /> </button> <button ui-button variant="ghost" size="icon" class="size-8" aria-label="YouTube"> <lucide-icon [img]="Youtube" class="size-4" aria-hidden="true" /> </button> </div> </div> </div> </footer> `, }) export class UiFooterMegaNewsletterComponent { protected readonly ArrowRight = ArrowRight protected readonly Check = Check protected readonly Github = Github protected readonly Layers = Layers protected readonly Linkedin = Linkedin protected readonly Youtube = Youtube protected readonly sectionList = sections readonly email = signal('') readonly submitted = signal(false) @Input('class') className?: string get rootClass(): string { return cn('border-border bg-background border-t', this.className) } subscribe(event?: Event): void { event?.preventDefault() if (!this.email().trim()) return this.submitted.set(true) } }src/app/components/blocks/footer-mega-newsletter/index.ts0.1 kB
export { UiFooterMegaNewsletterComponent } from './footer-mega-newsletter.component'
Raw manifest:https://uipkge.dev/r/angular/footer-mega-newsletter.json