Cookie Consent — Bar
blockmarketingBottom consent bar offering accept, reject, and manage as equally weighted actions, with a one-line statement of what is actually stored.
Installation
$pnpm dlx uipkge-ng@latest add cookie-consent-bar$npx uipkge-ng@latest add cookie-consent-bar$yarn dlx uipkge-ng@latest add cookie-consent-bar$bunx uipkge-ng@latest add cookie-consent-barManifest:
https://uipkge.dev/r/angular/cookie-consent-bar.jsonInstalls to:src/app/components/blocks/cookie-consent-bar/Variants
Loading interactive previews…
Loading interactive previews…
npm dependencies
Files installed (2)
src/app/components/blocks/cookie-consent-bar/cookie-consent-bar.component.ts3.3 kB
// Bottom consent bar offering accept, reject, and manage as equally weighted actions, with a // one-line statement of what is actually stored. Reject carries the same visual weight as // accept — a ghost "reject" beside a solid "accept" is a dark pattern with extra steps. // Port of the Vue/React block 1:1. import { ChangeDetectionStrategy, Component, Input, OnInit, signal } from '@angular/core' import { Cookie, LucideAngularModule } from 'lucide-angular' import { UiBadgeComponent } from '@/ui/badge/badge.component' import { UiButtonComponent } from '@/ui/button/button.component' import { UiSeparatorComponent } from '@/ui/separator/separator.component' export type CookieConsentChoice = 'accepted' | 'rejected' @Component({ changeDetection: ChangeDetectionStrategy.Eager, selector: 'ui-cookie-consent-bar, [ui-cookie-consent-bar]', standalone: true, // The block renders its own fixed root <div>: keep this wrapper out of the layout. host: { '[attr.class]': '"contents"' }, imports: [LucideAngularModule, UiBadgeComponent, UiButtonComponent, UiSeparatorComponent], template: ` @if (visible()) { <div data-slot="cookie-consent-bar" class="border-border bg-card/95 fixed inset-x-0 bottom-0 z-50 border-t backdrop-blur" role="region" aria-label="Cookie consent" > <div class="mx-auto flex max-w-6xl flex-col gap-4 px-6 py-4 lg:flex-row lg:items-center lg:gap-8"> <div class="flex min-w-0 items-start gap-3"> <lucide-icon [img]="Cookie" class="text-muted-foreground mt-0.5 size-4 shrink-0" aria-hidden="true" /> <div class="min-w-0"> <div class="flex flex-wrap items-center gap-2"> <p class="text-sm font-medium">We store two things</p> <span ui-badge variant="outline">No ad tracking</span> </div> <p class="text-muted-foreground mt-1 text-sm leading-relaxed"> A session cookie so you stay signed in, and an analytics cookie recording which pages get read. Rejecting keeps the first and drops the second. </p> </div> </div> <ui-separator orientation="vertical" class="hidden h-10 lg:block" /> <!-- Reject carries the same visual weight as accept. A ghost "reject" beside a solid "accept" is a dark pattern with extra steps. --> <div class="flex shrink-0 flex-wrap items-center gap-2"> <button ui-button variant="outline" (click)="decide('rejected')">Reject analytics</button> <button ui-button (click)="decide('accepted')">Accept</button> <button ui-button variant="ghost" size="sm">Manage</button> </div> </div> </div> } `, }) export class UiCookieConsentBarComponent implements OnInit { protected readonly Cookie = Cookie @Input() storageKey = 'uipkge:consent' readonly visible = signal(false) ngOnInit(): void { try { this.visible.set(!window.localStorage.getItem(this.storageKey)) } catch { this.visible.set(true) } } decide(choice: CookieConsentChoice): void { this.visible.set(false) try { window.localStorage.setItem(this.storageKey, choice) } catch { // Blocked storage: the choice holds for this page view only. } } }src/app/components/blocks/cookie-consent-bar/index.ts0.1 kB
export { UiCookieConsentBarComponent, type CookieConsentChoice } from './cookie-consent-bar.component'
Raw manifest:https://uipkge.dev/r/angular/cookie-consent-bar.json