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 shadcn-svelte@latest add https://uipkge.dev/r/svelte/cookie-consent-bar.json
Manifest:https://uipkge.dev/r/svelte/cookie-consent-bar.jsonInstalls to:src/lib/components/blocks/cookie-consent-bar/

Variants

Loading interactive previews…

npm dependencies

Files installed (1)

  • src/lib/components/blocks/cookie-consent-bar/CookieConsentBar.svelte2.4 kB
    <script lang="ts" module>
      export interface CookieConsentBarProps {
        storageKey?: string
      }
    </script>
    
    <script lang="ts">
      import { onMount } from 'svelte'
      import { fly } from 'svelte/transition'
      import { Cookie } from '@lucide/svelte'
      import { Badge } from '$lib/components/ui/badge'
      import { Button } from '$lib/components/ui/button'
      import { Separator } from '$lib/components/ui/separator'
    
      let { storageKey = 'uipkge:consent' }: CookieConsentBarProps = $props()
    
      let visible = $state(false)
    
      function decide(choice: 'accepted' | 'rejected') {
        visible = false
        try {
          window.localStorage.setItem(storageKey, choice)
        } catch {
          // Blocked storage: the choice holds for this page view only.
        }
      }
    
      onMount(() => {
        try {
          visible = !window.localStorage.getItem(storageKey)
        } catch {
          visible = true
        }
      })
    </script>
    
    {#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"
        transition:fly={{ y: 64, duration: 200 }}
      >
        <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">
            <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>
                <Badge variant="outline">No ad tracking</Badge>
              </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>
    
          <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 variant="outline" onclick={() => decide('rejected')}>Reject analytics</Button>
            <Button onclick={() => decide('accepted')}>Accept</Button>
            <Button variant="ghost" size="sm">Manage</Button>
          </div>
        </div>
      </div>
    {/if}
    

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