Building UI

Build your own consent UI on top of the headless c15t store — with vanilla DOM, any framework, or the @c15t/ui theme system.

Headless by Design

The c15t core package provides no pre-built UI components. It gives you a Zustand vanilla store with all the consent state and actions you need — you bring the rendering layer. This makes it the foundation for building consent UI in any framework: vanilla JS, Vue, Svelte, Solid, or anything else.

Vanilla DOM Example

Here's a complete consent banner built with plain JavaScript and DOM APIs:

Reactive State Subscriptions

The store fires on every state change. Compare with the previous state to react only to specific changes:

Key Store Properties for UI

PropertyTypeUse
activeUI'none' | 'banner' | 'dialog'Which consent UI is currently visible
consentsRecord<string, boolean>Current consent state per category
selectedConsentsRecord<string, boolean>Staged toggle state (unsaved)
consentTypesConsentType[]Categories to display with title/description
modelstring | nullCurrent consent model (opt-in, opt-out, iab)
locationInfoLocationInfo | nullDetected location (country, region)

Key Store Actions for UI

ActionSignatureUse
saveConsents(type: 'all' | 'custom' | 'necessary') => Promise<void>Save consent choices
setSelectedConsent(name, value) => voidToggle a category (staged, not saved)
setConsent(name, value) => voidSet + auto-save a single category
setActiveUI(ui: 'none' | 'banner' | 'dialog', options?) => voidShow/hide the banner or dialog
getDisplayedConsents() => ConsentType[]Get visible consent categories

Using @c15t/ui for Theming

The @c15t/ui package provides a framework-agnostic theme and style system. It defines design tokens, slot-based styling, and CSS primitives that you can use in any rendering layer.

Theme Tokens

Use the token types to build a consistent theme system:

Style Utilities

@c15t/ui exports DOM utilities for working with class names and styles:

CSS Primitives

Import style primitives for consent UI elements:

These functions return CSS module class name generators and auto-inject the associated styles into the document when imported.

Building a Framework Library

Info

Building a Vue, Svelte, or other framework library? Use c15t for the consent logic and @c15t/ui for the theme/style system. See the @c15t/react source code for a reference implementation of how to wrap the core store in a framework-specific API.

The pattern for building a framework wrapper:

  1. Create a provider — Initialize getOrCreateConsentRuntime() and expose the store via your framework's context system (Vue provide/inject, Svelte context, etc.)
  2. Build reactive bindings — Subscribe to store changes and bridge them to your framework's reactivity system
  3. Wrap UI components — Use @c15t/ui tokens and slots for consistent theming, render with your framework's component model
  4. Export hooks/composables — Expose store actions through framework-idiomatic APIs (Vue composables, Svelte stores, etc.)