Menu

Change language

GitHub repo

Cookie Consent — Bar

blockmarketing

Bottom consent bar offering accept, reject, and manage as equally weighted actions, with a one-line statement of what is actually stored.

Installation

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

Variants

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

Raw manifest:https://uipkge.dev/r/angular/cookie-consent-bar.json