Skip to content
Brok UI

Loading…

No results

Offer Modal

Open source

Promotional discount modals — a two-pane dialog pairing a bold offer panel with an email-capture form.

Preview

resources/views/blocks/offer-modal-discount.blade.php Blade
@props([
    'badge' => 'Limited time',
    'discount' => '15% OFF',
    'discountNote' => 'your first order',
    'heading' => 'Join the list, save 15%',
    'subheading' => 'Sign up for our newsletter and we\'ll send a one-time discount code straight to your inbox.',
    'placeholder' => 'you@example.com',
    'cta' => 'Claim my discount',
    'dismiss' => 'No thanks, I\'ll pay full price',
    'finePrint' => 'By subscribing you agree to receive marketing emails. Unsubscribe anytime.',
    'action' => '#',
    'closeHref' => '#',
])

<section
    x-data="{ open: true }"
    {{ $attributes->merge(['class' => 'flex min-h-svh items-center justify-center bg-muted/40 px-4 py-12 text-foreground']) }}
>
    <x-ui.card
        x-show="open"
        role="dialog"
        aria-modal="true"
        aria-label="{{ __('Promotional offer') }}"
        class="relative w-full max-w-2xl overflow-hidden rounded-lg border border-border bg-card p-0 shadow-xl"
    >
        {{-- Close (top end) --}}
        <x-ui.button
            :href="$closeHref"
            x-on:click.prevent="open = false"
            variant="ghost"
            size="icon"
            class="absolute end-3 top-3 z-10 size-9 rounded-full text-muted-foreground hover:text-foreground"
            aria-label="{{ __('Close') }}"
        >
            <svg class="size-5" 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 18" />
                <path d="m6 6 12 12" />
            </svg>
        </x-ui.button>

        <div class="grid grid-cols-1 sm:grid-cols-2">
            {{-- Decorative promo panel --}}
            <div class="flex flex-col items-center justify-center gap-2 bg-gradient-to-br from-primary to-accent px-6 py-8 text-center text-primary-foreground sm:py-12">
                <span class="text-5xl font-bold leading-none tracking-tight sm:text-6xl">{{ __($discount) }}</span>
                <span class="text-sm font-medium uppercase tracking-wide text-primary-foreground">{{ __($discountNote) }}</span>
            </div>

            {{-- Content pane --}}
            <div class="flex flex-col gap-4 p-6 sm:p-8">
                @if ($badge)
                    <x-ui.badge variant="secondary" class="w-fit">{{ __($badge) }}</x-ui.badge>
                @endif

                <div class="flex flex-col gap-2 pe-8">
                    <h2 class="text-pretty text-xl font-semibold leading-tight tracking-tight sm:text-2xl">{{ __($heading) }}</h2>
                    <p class="text-pretty text-sm leading-relaxed text-muted-foreground">{{ __($subheading) }}</p>
                </div>

                <form method="POST" action="{{ $action }}" class="flex flex-col gap-4">
                    @csrf

                    <x-ui.field>
                        <x-ui.label for="offer-modal-01-email">{{ __('Email address') }}</x-ui.label>
                        <x-ui.input
                            id="offer-modal-01-email"
                            type="email"
                            name="email"
                            autocomplete="email"
                            required
                            :placeholder="__($placeholder)"
                            class="w-full"
                        />
                    </x-ui.field>

                    <x-ui.button type="submit" size="lg" class="w-full">
                        {{ __($cta) }}
                    </x-ui.button>
                </form>

                <a
                    href="{{ $closeHref }}"
                    x-on:click.prevent="open = false"
                    class="text-center text-sm font-medium text-muted-foreground hover:text-foreground hover:underline"
                >
                    {{ __($dismiss) }}
                </a>

                <p class="text-pretty text-sm leading-relaxed text-muted-foreground">{{ __($finePrint) }}</p>
            </div>
        </div>
    </x-ui.card>
</section>

Installation

terminal
php artisan ui:add blocks/offer-modal-discount

Installs these dependencies automatically:

Registry contract

Install confidence

php artisan ui:add blocks/offer-modal-discount 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.0.3
License
open
Stability
stable
Contract
v1
Foundation
≥ 1.0.0
Type Generated target
blade resources/views/blocks/offer-modal-discount.blade.php

Registry dependencies

card button input field label badge

Package dependencies

composer: jml/brok:^0.2

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.

offer-modal-discount.md
# Brok UI block: Offer Modal (`offer-modal-discount`)

A centered promotional offer modal on a muted backdrop with a top-end close button: a decorative gradient panel showing a big discount on the left, and a content pane on the right with a limited-time badge, heading, muted subline, an email subscribe form, a dismiss link, and fine print.

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/offer-modal-discount
```

## Render it

```blade
<x-blocks.offer-modal-discount />
```

## Props

- `badge` (string, default `Limited time`) — Small label shown above the heading; falsy hides the badge.
- `discount` (string, default `15% OFF`) — Large discount value shown in the decorative gradient panel.
- `discount-note` (string, default `your first order`) — Caption under the discount value in the gradient panel.
- `heading` (string, default `Join the list, save 15%`) — Primary offer headline in the content pane.
- `subheading` (string, default `Sign up for our newsletter and we\'ll send a one-time discount code straight to your inbox.`) — Supporting copy under the heading explaining the offer.
- `placeholder` (string, default `[email protected]`) — Placeholder text for the email input.
- `cta` (string, default `Claim my discount`) — Submit button label for the email capture form.
- `dismiss` (string, default `No thanks, I\'ll pay full price`) — Label for the soft dismiss link below the form.
- `fine-print` (string, default `By subscribing you agree to receive marketing emails. Unsubscribe anytime.`) — Small consent/legal copy shown at the bottom of the content pane.
- `action` (string, default `#`) — Form submission URL for the email capture.
- `close-href` (string, default `#`) — Fallback href for the close button and dismiss link when JavaScript is unavailable.

## Use when

- Use to present a time-limited discount or promotional offer as a centered modal dialog over the page, pairing a decorative gradient discount panel with an email capture form.
- Suited to lead-generation campaigns where a visitor can subscribe for a one-time code or dismiss the offer without leaving the page.

## Avoid when

- Avoid when the page needs a true accessible modal with focus trapping and an Escape-key handler, or when no discount/subscribe offer is involved; compose a dialog primitive with a plain newsletter form instead.

## Rules

- Render the installed block with `<x-blocks.offer-modal-discount />` 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/offer-modal-discount
- Registry JSON (files, props, contract): https://brokui.dev/r/open/blocks/offer-modal-discount.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

  • Use to present a time-limited discount or promotional offer as a centered modal dialog over the page, pairing a decorative gradient discount panel with an email capture form.
  • Suited to lead-generation campaigns where a visitor can subscribe for a one-time code or dismiss the offer without leaving the page.

Avoid when

  • Avoid when the page needs a true accessible modal with focus trapping and an Escape-key handler, or when no discount/subscribe offer is involved; compose a dialog primitive with a plain newsletter form instead.

Anti-patterns

  • Do not replace semantic props with conflicting utility classes.
  • Do not remove labels, focus styles, or state attributes.
Anatomy
backdrop close button discount panel offer badge heading subheading email form dismiss link fine print

Usage

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

resources/views/welcome.blade.php Blade
<x-blocks.offer-modal-discount />

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/offer-modal-discount.blade.php Blade
@props([
    'badge' => 'Limited time',
    'discount' => '15% OFF',
    'discountNote' => 'your first order',
    'heading' => 'Join the list, save 15%',
    'subheading' => 'Sign up for our newsletter and we\'ll send a one-time discount code straight to your inbox.',
    'placeholder' => 'you@example.com',
    'cta' => 'Claim my discount',
    'dismiss' => 'No thanks, I\'ll pay full price',
    'finePrint' => 'By subscribing you agree to receive marketing emails. Unsubscribe anytime.',
    'action' => '#',
    'closeHref' => '#',
])

<section
    x-data="{ open: true }"
    {{ $attributes->merge(['class' => 'flex min-h-svh items-center justify-center bg-muted/40 px-4 py-12 text-foreground']) }}
>
    <x-ui.card
        x-show="open"
        role="dialog"
        aria-modal="true"
        aria-label="{{ __('Promotional offer') }}"
        class="relative w-full max-w-2xl overflow-hidden rounded-lg border border-border bg-card p-0 shadow-xl"
    >
        {{-- Close (top end) --}}
        <x-ui.button
            :href="$closeHref"
            x-on:click.prevent="open = false"
            variant="ghost"
            size="icon"
            class="absolute end-3 top-3 z-10 size-9 rounded-full text-muted-foreground hover:text-foreground"
            aria-label="{{ __('Close') }}"
        >
            <svg class="size-5" 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 18" />
                <path d="m6 6 12 12" />
            </svg>
        </x-ui.button>

        <div class="grid grid-cols-1 sm:grid-cols-2">
            {{-- Decorative promo panel --}}
            <div class="flex flex-col items-center justify-center gap-2 bg-gradient-to-br from-primary to-accent px-6 py-8 text-center text-primary-foreground sm:py-12">
                <span class="text-5xl font-bold leading-none tracking-tight sm:text-6xl">{{ __($discount) }}</span>
                <span class="text-sm font-medium uppercase tracking-wide text-primary-foreground">{{ __($discountNote) }}</span>
            </div>

            {{-- Content pane --}}
            <div class="flex flex-col gap-4 p-6 sm:p-8">
                @if ($badge)
                    <x-ui.badge variant="secondary" class="w-fit">{{ __($badge) }}</x-ui.badge>
                @endif

                <div class="flex flex-col gap-2 pe-8">
                    <h2 class="text-pretty text-xl font-semibold leading-tight tracking-tight sm:text-2xl">{{ __($heading) }}</h2>
                    <p class="text-pretty text-sm leading-relaxed text-muted-foreground">{{ __($subheading) }}</p>
                </div>

                <form method="POST" action="{{ $action }}" class="flex flex-col gap-4">
                    @csrf

                    <x-ui.field>
                        <x-ui.label for="offer-modal-01-email">{{ __('Email address') }}</x-ui.label>
                        <x-ui.input
                            id="offer-modal-01-email"
                            type="email"
                            name="email"
                            autocomplete="email"
                            required
                            :placeholder="__($placeholder)"
                            class="w-full"
                        />
                    </x-ui.field>

                    <x-ui.button type="submit" size="lg" class="w-full">
                        {{ __($cta) }}
                    </x-ui.button>
                </form>

                <a
                    href="{{ $closeHref }}"
                    x-on:click.prevent="open = false"
                    class="text-center text-sm font-medium text-muted-foreground hover:text-foreground hover:underline"
                >
                    {{ __($dismiss) }}
                </a>

                <p class="text-pretty text-sm leading-relaxed text-muted-foreground">{{ __($finePrint) }}</p>
            </div>
        </div>
    </x-ui.card>
</section>

Ownership & lifecycle

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