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
| Property | Type | Use |
|---|---|---|
activeUI | 'none' | 'banner' | 'dialog' | Which consent UI is currently visible |
consents | Record<string, boolean> | Current consent state per category |
selectedConsents | Record<string, boolean> | Staged toggle state (unsaved) |
consentTypes | ConsentType[] | Categories to display with title/description |
model | string | null | Current consent model (opt-in, opt-out, iab) |
locationInfo | LocationInfo | null | Detected location (country, region) |
Key Store Actions for UI
| Action | Signature | Use |
|---|---|---|
saveConsents | (type: 'all' | 'custom' | 'necessary') => Promise<void> | Save consent choices |
setSelectedConsent | (name, value) => void | Toggle a category (staged, not saved) |
setConsent | (name, value) => void | Set + auto-save a single category |
setActiveUI | (ui: 'none' | 'banner' | 'dialog', options?) => void | Show/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:
- Create a provider — Initialize
getOrCreateConsentRuntime()and expose the store via your framework's context system (Vueprovide/inject, Svelte context, etc.) - Build reactive bindings — Subscribe to store changes and bridge them to your framework's reactivity system
- Wrap UI components — Use
@c15t/uitokens and slots for consistent theming, render with your framework's component model - Export hooks/composables — Expose store actions through framework-idiomatic APIs (Vue composables, Svelte stores, etc.)