---
title: ConsentBanner
description: Render the c15t consent banner in a TanStack Start app, set its
  variant and position, and override its labels.
group: frameworks
lastModified: "2026-10-10T16:01:45+01:00"
---
## Render the banner

Render `ConsentBanner` once inside `ConsentRoot`, next to `ConsentDialog`. The
[quickstart](/docs/frameworks/tanstack-start/quickstart#resolve-consent-in-the-root-route)
does this in the root route. With an awaited root loader, the banner is part of
the server HTML for visitors who owe a choice.

```tsx title="src/routes/__root.tsx"
import { ConsentBanner } from 'c15t/tanstack-start';

// Inside ConsentRoot:
<ConsentBanner variant="bar" position="bottom" />;
```

The banner renders what the active policy requires. A `choice` prompt shows
reject and accept at equal prominence, plus customize when the policy offers it.
A `notice` prompt shows an "OK" button and a "Do not sell or share my data"
button that opens preferences. A policy with `prompt: 'none'` renders nothing,
and so does a visitor whose policy has not resolved.

## Props

|Prop|Type|Default|Description|
|--|--|--|--|
|`title`|`ReactNode`|translation|Overrides the title. Under a notice the default is `cookieBanner.noticeTitle`.|
|`description`|`ReactNode`|translation|Overrides the description. Under a notice the default is `cookieBanner.noticeDescription`.|
|`acceptButtonText`|`ReactNode`|`common.acceptAll`|Accept label.|
|`rejectButtonText`|`ReactNode`|`common.rejectAll`|Reject label.|
|`customizeButtonText`|`ReactNode`|`common.customize`|Customize label.|
|`dismissButtonText`|`ReactNode`|`common.acknowledge`|Label of the notice acknowledgement.|
|`variant`|`PromptVariant`|`floating`|Shape of the prompt. See [Variants](#variants).|
|`position`|`PromptPosition`|per variant|Where the prompt sits. Must be valid for the variant.|
|`blocking`|`boolean`|`true` on `wall`|Backdrop, scroll lock, focus trap, and no outside dismissal, as one value.|
|`layout`|`ConsentBannerLayout`|policy default|Orders and groups actions. Required actions the layout omits are restored.|
|`primaryButton`|`ConsentBannerButton \|ConsentBannerButton[]`|`'customize'`|Which actions get the primary treatment. On a notice, dismiss is primary when it is the only action.|
|`direction`|`'row' \|'column'`|`'row'`|How action groups flow.|
|`legalLinks`|`(keyof LegalLinks)[] \|null`|none|Which configured legal links render inline.|
|`hideBranding`|`boolean`|`false`|Hides the "Secured by" tag.|
|`scrollLock`|`boolean`|unset|Deprecated. Use `blocking` to control scrolling, focus and backdrop together.|
|`trapFocus`|`boolean`|unset|Deprecated. Use `blocking`.|
|`disableAnimation`|`boolean`|`false`|Skips enter and exit animations.|
|`noStyle`|`boolean`|`false`|Removes the built-in styling from every part.|

## Variants

The policy decides which actions the banner offers. The variant decides their
shape. Set `variant` on the banner, or `options.presentation.prompt` on
`ConsentRoot` for every banner. The prop wins.

|Variant|Positions|Default|
|--|--|--|
|`floating`|`bottom-left`, `bottom-right`, `top-left`, `top-right`, `bottom-center`, `top-center`|`bottom-left`|
|`bar`|`top`, `bottom`|`bottom`|
|`widget`|`bottom-left`, `bottom-right`, `top-left`, `top-right`|`bottom-right`|
|`wall`|`center`|`center`|

A `wall` blocks the page until the visitor answers. A notice never blocks, so a
notice `wall` falls back to `floating`. Every part is also available as
`ConsentBanner.<Part>` for custom layouts, such as `ConsentBanner.Root`,
`ConsentBanner.Card` and `ConsentBanner.PolicyActions`.
[Customize](/docs/frameworks/tanstack-start/customize) covers tokens and slots.
