Skip to content
Brok UI

Loading…

No results

Sale

Open source

Promotional sale sections — a bold gradient panel with countdown pills, dual CTAs and a discount code, and a dismissible full-width promo bar with a copyable code.

Preview

resources/views/blocks/promo-banner.blade.php Blade
@props([
    'eyebrow' => 'Limited time',
    'heading' => 'Summer sale — up to 30% off',
    'subheading' => 'Stock up on everyday essentials before the season ends. Free returns on all orders.',
    'promoLabel' => 'Use code at checkout',
    'promoCode' => 'SAVE30',
    'primaryCta' => 'Shop the sale',
    'primaryHref' => '#',
    'dismissible' => true,
])

<x-ui.section
    aria-label="{{ __('Promotional offer') }}"
    data-slot="promo-banner"
    x-data="{ open: true }"
    x-show="open"
    space="lg" {{ $attributes }}
>
    <x-ui.container gutter="sm">
        <div class="relative overflow-hidden rounded-lg bg-gradient-to-br from-primary to-primary/80 px-6 py-10 text-primary-foreground shadow-sm sm:px-10 sm:py-12">
            {{-- Decorative ambient glow (flip-safe via logical inset) --}}
            <div
                class="pointer-events-none absolute -top-16 end-[-4rem] size-56 rounded-full bg-primary-foreground/10 blur-3xl"
                aria-hidden="true"
            ></div>

            @if ($dismissible)
                <x-ui.button
                    variant="ghost"
                    size="icon-sm"
                    type="button"
                    aria-label="{{ __('Dismiss') }}"
                    x-on:click="open = false"
                    class="absolute end-3 top-3 rounded-full text-primary-foreground hover:bg-primary-foreground/10 hover:text-primary-foreground"
                >
                    <svg class="size-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
                        <path d="M18 6 6 18M6 6l12 12" />
                    </svg>
                </x-ui.button>
            @endif

            <div class="relative flex flex-col gap-8 lg:flex-row lg:items-center lg:justify-between">
                {{-- Message --}}
                <div class="max-w-2xl">
                    @if ($eyebrow)
                        <x-ui.badge
                            variant="secondary"
                            class="mb-4 border-primary-foreground/20 bg-primary-foreground/15 text-primary-foreground"
                        >
                            {{ __($eyebrow) }}
                        </x-ui.badge>
                    @endif

                    <h2 class="text-balance text-3xl font-bold tracking-tight sm:text-4xl">
                        {{ __($heading) }}
                    </h2>

                    @if ($subheading)
                        <p class="mt-4 max-w-xl text-pretty text-base text-primary-foreground sm:text-lg">
                            {{ __($subheading) }}
                        </p>
                    @endif
                </div>

                {{-- Code + CTA --}}
                <div class="flex shrink-0 flex-col items-stretch gap-4 sm:flex-row sm:items-center lg:flex-col lg:items-stretch">
                    @if ($promoCode)
                        <dl class="text-center sm:text-start lg:text-center">
                            <dt class="text-xs font-medium uppercase tracking-wide text-primary-foreground">
                                {{ __($promoLabel) }}
                            </dt>
                            <dd class="mt-2 inline-flex items-center gap-2 rounded-md border-2 border-dashed border-primary-foreground/40 bg-primary-foreground/10 ps-4 pe-2 py-2 font-mono text-base font-semibold tracking-widest text-primary-foreground">
                                {{ $promoCode }}
                                <x-ui.copy-button :value="$promoCode" :label="__('Copy code :code', ['code' => $promoCode])" class="text-primary-foreground hover:bg-primary-foreground/15 hover:text-primary-foreground" />
                            </dd>
                        </dl>
                    @endif

                    <x-ui.button
                        :href="$primaryHref"
                        size="lg"
                        :with-arrow="true"
                        class="w-full bg-primary-foreground text-primary hover:bg-primary-foreground/90 sm:w-auto lg:w-full"
                    >
                        {{ __($primaryCta) }}
                    </x-ui.button>
                </div>
            </div>
        </div>
    </x-ui.container>
</x-ui.section>

Installation

terminal
php artisan ui:add blocks/promo-banner

Installs these dependencies automatically:

Registry contract

Install confidence

php artisan ui:add blocks/promo-banner writes only the generated targets below. The CLI validates each file hash before writing and prompts before replacing local changes unless --force is used.

Version
1.2.2
License
open
Stability
stable
Contract
v1
Foundation
≥ 1.0.0
Type Generated target
blade resources/views/blocks/promo-banner.blade.php

Registry dependencies

badge button container copy-button section

Package dependencies

composer: jml/brok:^0.2

npm: alpinejs

Use with AI

A brief for your coding agent: what the block is, the install command, how to render it, its props and the rules. Copy it, or open a prompt about this block in an assistant.

promo-banner.md
# Brok UI block: Promo Banner (`promo-banner`)

A full-width gradient promotional banner with an eyebrow badge, headline, copyable promo code chip, primary CTA, and dismiss control.

Brok UI is a Laravel Blade registry. `ui:add` copies this block into the app as plain Blade the app owns; it composes installed `<brok:*>` primitives and semantic design tokens.

## Install

```bash
php artisan ui:add blocks/promo-banner
```

## Render it

```blade
<x-blocks.promo-banner />
```

## Props

- `eyebrow` (string, default `Limited time`) — Small label shown above the heading.
- `heading` (string, default `Summer sale — up to 30% off`) — Banner headline.
- `subheading` (string, default `Stock up on everyday essentials before the season ends. Free returns on all orders.`) — Supporting copy under the heading.
- `promo-label` (string, default `Use code at checkout`) — Label shown above the promo code chip.
- `promo-code` (string, default `SAVE30`) — Promo code text rendered in the chip and copied by the copy button; falsy hides the code chip.
- `primary-cta` (string, default `Shop the sale`) — Primary button label.
- `primary-href` (string, default `#`) — Primary button destination.
- `dismissible` (bool, default `true`) — Shows the top-end dismiss button when true; the consumer wires up its actual dismiss behaviour.

## Use when

- Announcing a sitewide promotion with a gradient banner, eyebrow badge, headline, a copyable promo code chip and a primary CTA.
- Use when the promotion needs a one-click copyable code, not just a plain announcement bar.

## Avoid when

- Needing a plain sitewide announcement bar with no promo code or gradient treatment; use banner-announcement instead.

## Rules

- Render the installed block with `<x-blocks.promo-banner />` and pass data through its props; edit the copied file only for structural changes.
- Keep the semantic design tokens (`bg-background`, `text-muted-foreground`); never swap in raw colour utilities.
- Keep the `data-slot` attributes and the logical (start/end) spacing so the markup still mirrors under `dir="rtl"`.

## Links

- Docs: https://brokui.dev/blocks/promo-banner
- Registry JSON (files, props, contract): https://brokui.dev/r/open/blocks/promo-banner.json

Working in Claude Code, Cursor or Codex? Give the agent the whole registry through the MCP server or the Brok UI skill.

Guidance

Use when

  • Announcing a sitewide promotion with a gradient banner, eyebrow badge, headline, a copyable promo code chip and a primary CTA.
  • Use when the promotion needs a one-click copyable code, not just a plain announcement bar.

Avoid when

  • Needing a plain sitewide announcement bar with no promo code or gradient treatment; use banner-announcement instead.

Anti-patterns

  • Do not replace semantic props with conflicting utility classes.
  • Do not remove labels, focus styles, or state attributes.
Anatomy
gradient panel dismiss button eyebrow badge heading and subheading promo code chip with copy button primary CTA

Usage

Render the block as a component, passing data where useful:

resources/views/welcome.blade.php Blade
<x-blocks.promo-banner />

Built from primitives

Composes <brok:*> Semantic tokens Re-themeable RTL-ready

This block composes installed <brok:*> primitives and semantic design tokens only — it does not reimplement any primitive. Re-theme it (light, dark, admin, customer) by editing CSS variables; flip the preview to RTL to confirm it mirrors.

Source

The exact, editable file ui:add writes into your app. The preview above renders this same source — there are no preview-only blocks.

resources/views/blocks/promo-banner.blade.php Blade
@props([
    'eyebrow' => 'Limited time',
    'heading' => 'Summer sale — up to 30% off',
    'subheading' => 'Stock up on everyday essentials before the season ends. Free returns on all orders.',
    'promoLabel' => 'Use code at checkout',
    'promoCode' => 'SAVE30',
    'primaryCta' => 'Shop the sale',
    'primaryHref' => '#',
    'dismissible' => true,
])

<x-ui.section
    aria-label="{{ __('Promotional offer') }}"
    data-slot="promo-banner"
    x-data="{ open: true }"
    x-show="open"
    space="lg" {{ $attributes }}
>
    <x-ui.container gutter="sm">
        <div class="relative overflow-hidden rounded-lg bg-gradient-to-br from-primary to-primary/80 px-6 py-10 text-primary-foreground shadow-sm sm:px-10 sm:py-12">
            {{-- Decorative ambient glow (flip-safe via logical inset) --}}
            <div
                class="pointer-events-none absolute -top-16 end-[-4rem] size-56 rounded-full bg-primary-foreground/10 blur-3xl"
                aria-hidden="true"
            ></div>

            @if ($dismissible)
                <x-ui.button
                    variant="ghost"
                    size="icon-sm"
                    type="button"
                    aria-label="{{ __('Dismiss') }}"
                    x-on:click="open = false"
                    class="absolute end-3 top-3 rounded-full text-primary-foreground hover:bg-primary-foreground/10 hover:text-primary-foreground"
                >
                    <svg class="size-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
                        <path d="M18 6 6 18M6 6l12 12" />
                    </svg>
                </x-ui.button>
            @endif

            <div class="relative flex flex-col gap-8 lg:flex-row lg:items-center lg:justify-between">
                {{-- Message --}}
                <div class="max-w-2xl">
                    @if ($eyebrow)
                        <x-ui.badge
                            variant="secondary"
                            class="mb-4 border-primary-foreground/20 bg-primary-foreground/15 text-primary-foreground"
                        >
                            {{ __($eyebrow) }}
                        </x-ui.badge>
                    @endif

                    <h2 class="text-balance text-3xl font-bold tracking-tight sm:text-4xl">
                        {{ __($heading) }}
                    </h2>

                    @if ($subheading)
                        <p class="mt-4 max-w-xl text-pretty text-base text-primary-foreground sm:text-lg">
                            {{ __($subheading) }}
                        </p>
                    @endif
                </div>

                {{-- Code + CTA --}}
                <div class="flex shrink-0 flex-col items-stretch gap-4 sm:flex-row sm:items-center lg:flex-col lg:items-stretch">
                    @if ($promoCode)
                        <dl class="text-center sm:text-start lg:text-center">
                            <dt class="text-xs font-medium uppercase tracking-wide text-primary-foreground">
                                {{ __($promoLabel) }}
                            </dt>
                            <dd class="mt-2 inline-flex items-center gap-2 rounded-md border-2 border-dashed border-primary-foreground/40 bg-primary-foreground/10 ps-4 pe-2 py-2 font-mono text-base font-semibold tracking-widest text-primary-foreground">
                                {{ $promoCode }}
                                <x-ui.copy-button :value="$promoCode" :label="__('Copy code :code', ['code' => $promoCode])" class="text-primary-foreground hover:bg-primary-foreground/15 hover:text-primary-foreground" />
                            </dd>
                        </dl>
                    @endif

                    <x-ui.button
                        :href="$primaryHref"
                        size="lg"
                        :with-arrow="true"
                        class="w-full bg-primary-foreground text-primary hover:bg-primary-foreground/90 sm:w-auto lg:w-full"
                    >
                        {{ __($primaryCta) }}
                    </x-ui.button>
                </div>
            </div>
        </div>
    </x-ui.container>
</x-ui.section>

Ownership & lifecycle

Owner, release state, review evidence and adoption for this item.
Owner
Platform UI (@JoshJML)
Current version
1.2.2
Status
Stable
License
open
Deprecation
Not deprecated
Contract
v1
Foundation
≥ 1.0.0