Skip to main content

Customization

Customize the interface

Climb the ladder one step at a time

Each step keeps everything the step below it gives you. Stop at the first one that makes the change you need:

  1. Props and presentation. Pick a shape, a position, button order or blocking. c15t keeps its markup, styles and behavior.
  2. Theme tokens. Change colors, type, radius, spacing, shadows and motion everywhere at once. Dark mode is a second set of tokens.
  3. Parts and classes. Add a class or inline style to one part of one component, such as the banner card. Tailwind, CSS Modules and CSS-in-JS classes go here.
  4. Compose. Rebuild a component from c15t's parts, in your own layout, while c15t still renders the actions the policy requires.
  5. Headless. Render your own markup from c15t's state and actions. You own the layout, focus handling and labels.

Most brand work needs tokens and a few part classes. See banner designs for five banners built at different steps, with screenshots and tested code.

Where each step lives in your framework

FrameworkProps and presentationTokensParts and classesComposeHeadless
Next.jsConsentBanner props, options.presentationConsentTheme in a Server Componentoptions.components, classNameComposeHeadless
TanStack StartConsentBanner props, options.presentationConsentTheme in the root routeoptions.components, classNameComposeHeadless
ReactConsentBanner props, presentationConsentTheme, or CSS variablescomponents, classNameComposeHeadless
Nuxtpresentation in nuxt.config.tstokens or theme in the module optionscomponents, classNoneHeadless
Vuepresentation in the c15tVue optionstokens or theme in the plugin optionscomponents, classNoneHeadless
Astropresentation in the integration optionstheme in the integration optionstheme.slots, class on ConsentBannerNoneNone
SvelteConsentBanner props, presentationCSS variables, or generateThemeCSS()theme.slots, class on ConsentBannerPrimitivesHeadless
SvelteKitConsentBanner props, presentationgenerateThemeCSS() in a server loadtheme.slots, class on ConsentBannerPrimitivesHeadless
HTMLpresentation.prompt in configui.themeui.theme.slots, ::part(), ui.cssNoneHeadless
JavaScriptpresentation.prompt in init()ui.themeui.theme.slots, ::part(), ui.cssNoneHeadless

Configuration shapes differ between frameworks. React's components.banner.card, Vue's components.banner.card with class, and the consentBannerCard key in theme.slots target the same part through different APIs. Check your framework's customize page before you move a configuration from one framework to another.

Keep behavior and appearance separate

Presentation controls the prompt's shape, position and blocking. The policy controls which actions and rights the visitor gets. Changing colors or button order does not change a saved choice or the policy's scope.

A choice wall always blocks. A notice never blocks and does not become a wall because you asked for variant: 'wall'. The preference dialog stays centered, whatever position the banner has. If a custom layout leaves out an action the policy requires, c15t puts it back.

Read the rest of this section