Skip to content
Brok UI

Loading…

No results

Hero

Open source

Marketing hero sections: centred, split, search, form, video, stats, screenshot and more; the centred hero takes a switchable backdrop.

Preview

7 of 15

resources/views/blocks/hero-form.blade.php Blade
@props([
    'eyebrow'     => 'Early access, Limited spots',
    'heading'     => "Build something people\nactually want to use.",
    'subheading'  => 'Join thousands of developers who ship polished Laravel interfaces in half the time. Get notified when we open the next cohort.',
    'formAction'  => '#',
    'formMethod'  => 'POST',
    'placeholder' => 'you@example.com',
    'submitLabel' => 'Join the waitlist',
    'reassurance' => 'No spam. Unsubscribe anytime.',
    'socialProof' => 'Joined by 2,000+ builders',
    'avatars'     => null,
])

@php
    $avatars ??= [
        ['src' => null, 'alt' => 'Builder one', 'fallback' => 'AJ'],
        ['src' => null, 'alt' => 'Builder two', 'fallback' => 'MK'],
        ['src' => null, 'alt' => 'Builder three', 'fallback' => 'RL'],
        ['src' => null, 'alt' => 'Builder four', 'fallback' => 'SP'],
    ];
@endphp

<x-ui.section space="none" class="relative isolate overflow-hidden" {{ $attributes }}>
    <div class="pointer-events-none absolute inset-x-0 -top-32 -z-10 flex justify-center" aria-hidden="true">
        <div class="h-[32rem] w-[64rem] rounded-full bg-primary/5 blur-3xl"></div>
    </div>

    <div class="mx-auto max-w-3xl px-4 py-24 text-center sm:py-32">
        <div class="mb-6 flex justify-center">
            <x-ui.badge variant="secondary" class="gap-2 px-4 py-2 text-sm font-medium tracking-wide">
                <svg class="size-3 shrink-0" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true">
                    <path d="M8 1.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8Z" />
                    <path d="M8 4.25a.75.75 0 0 1 .75.75v3.25H11a.75.75 0 0 1 0 1.5H8a.75.75 0 0 1-.75-.75V5A.75.75 0 0 1 8 4.25Z" />
                </svg>
                {{ __($eyebrow) }}
            </x-ui.badge>
        </div>

        <h1 class="text-balance text-4xl font-bold tracking-tight text-foreground sm:text-5xl lg:text-6xl">{!! nl2br(e(__($heading))) !!}</h1>

        <p class="mx-auto mt-6 max-w-xl text-pretty text-lg leading-relaxed text-muted-foreground">{{ __($subheading) }}</p>

        <div class="mt-10">
            <form action="{{ $formAction }}" method="{{ strtolower($formMethod) === 'get' ? 'get' : 'post' }}" class="relative mx-auto flex max-w-md flex-col gap-4 sm:flex-row">
                @if (strtolower($formMethod) !== 'get')
                    @csrf
                @endif
                <label for="hero-form-email" class="sr-only">{{ __('Email address') }}</label>
                <x-ui.input id="hero-form-email" type="email" name="email" :placeholder="__($placeholder)" aria-label="{{ __('Email address') }}" autocomplete="email" required class="w-full flex-1" />
                <x-ui.button type="submit" variant="default" class="w-full shrink-0 sm:w-auto">
                    {{ __($submitLabel) }}
                    <x-slot:iconTrailing>
                        <svg class="size-4 rtl:-scale-x-100" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
                            <path d="M5 12h14M13 6l6 6-6 6" />
                        </svg>
                    </x-slot:iconTrailing>
                </x-ui.button>
            </form>
            <p class="mt-4 text-sm text-muted-foreground">{{ __($reassurance) }}</p>
        </div>

        <div class="mt-10 flex flex-col items-center gap-4">
            <x-ui.avatar-group :avatars="array_map(fn ($avatar) => ['src' => $avatar['src'] ?? null, 'name' => $avatar['alt'] ?? '', 'initials' => $avatar['fallback'] ?? null], $avatars)" :max="count($avatars)" size="sm" :label="__('Recent members')" />
            <div class="flex flex-col items-center gap-2">
                <x-ui.rating display :value="5" size="sm" />
                <p class="text-sm font-medium text-foreground">{{ __($socialProof) }}</p>
            </div>
        </div>
    </div>
</x-ui.section>

Installation

terminal
php artisan ui:add blocks/hero-form

Installs these dependencies automatically:

Registry contract

Install confidence

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

Registry dependencies

avatar-group badge button input rating section

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.

hero-form.md
# Brok UI block: Hero Form (`hero-form`)

A centered hero whose primary call-to-action is an inline email-capture form, with an announcement pill, headline, reassurance line and an avatar social-proof row.

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/hero-form
```

## Render it

```blade
<x-blocks.hero-form />
```

## Props

- `eyebrow` (string, default `Early access, Limited spots`) — Small label shown above the heading inside a badge.
- `heading` (string, default `Build something people\nactually want to use.`) — Primary headline; a \n renders as a manual line break.
- `subheading` (string, default `Join thousands of developers who ship polished Laravel interfaces in half the time. Get notified when we open the next cohort.`) — Supporting copy under the heading.
- `form-action` (string, default `#`) — Form submission URL.
- `form-method` (string, default `POST`) — Form HTTP method; anything other than GET renders a CSRF token and posts.
- `placeholder` (string, default `[email protected]`) — Placeholder text shown inside the email input.
- `submit-label` (string, default `Join the waitlist`) — Submit button label.
- `reassurance` (string, default `No spam. Unsubscribe anytime.`) — Small reassurance line shown under the form.
- `social-proof` (string, default `Joined by 2,000+ builders`) — Caption shown under the avatar row and rating.
- `avatars` (mixed|null, default `null`) — Rows of {src, alt, fallback} rendered in the avatar stack; null falls back to a default 4-person sample.

## Use when

- Opening an early-access or waitlist landing page whose primary action is capturing an email address inline, right below the headline.
- Wanting a lightweight social-proof cluster — an avatar row plus a star rating — under the form instead of full customer reviews.

## Avoid when

- Needing a search query instead of an email capture; use hero-search for a search-led hero.

## Rules

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

  • Opening an early-access or waitlist landing page whose primary action is capturing an email address inline, right below the headline.
  • Wanting a lightweight social-proof cluster — an avatar row plus a star rating — under the form instead of full customer reviews.

Avoid when

  • Needing a search query instead of an email capture; use hero-search for a search-led hero.

Anti-patterns

  • Do not replace semantic props with conflicting utility classes.
  • Do not remove labels, focus styles, or state attributes.
Anatomy
announcement badge heading subheading email capture form submit button reassurance line avatar row rating social proof line

Usage

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

resources/views/welcome.blade.php Blade
<x-blocks.hero-form />

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/hero-form.blade.php Blade
@props([
    'eyebrow'     => 'Early access, Limited spots',
    'heading'     => "Build something people\nactually want to use.",
    'subheading'  => 'Join thousands of developers who ship polished Laravel interfaces in half the time. Get notified when we open the next cohort.',
    'formAction'  => '#',
    'formMethod'  => 'POST',
    'placeholder' => 'you@example.com',
    'submitLabel' => 'Join the waitlist',
    'reassurance' => 'No spam. Unsubscribe anytime.',
    'socialProof' => 'Joined by 2,000+ builders',
    'avatars'     => null,
])

@php
    $avatars ??= [
        ['src' => null, 'alt' => 'Builder one', 'fallback' => 'AJ'],
        ['src' => null, 'alt' => 'Builder two', 'fallback' => 'MK'],
        ['src' => null, 'alt' => 'Builder three', 'fallback' => 'RL'],
        ['src' => null, 'alt' => 'Builder four', 'fallback' => 'SP'],
    ];
@endphp

<x-ui.section space="none" class="relative isolate overflow-hidden" {{ $attributes }}>
    <div class="pointer-events-none absolute inset-x-0 -top-32 -z-10 flex justify-center" aria-hidden="true">
        <div class="h-[32rem] w-[64rem] rounded-full bg-primary/5 blur-3xl"></div>
    </div>

    <div class="mx-auto max-w-3xl px-4 py-24 text-center sm:py-32">
        <div class="mb-6 flex justify-center">
            <x-ui.badge variant="secondary" class="gap-2 px-4 py-2 text-sm font-medium tracking-wide">
                <svg class="size-3 shrink-0" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true">
                    <path d="M8 1.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8Z" />
                    <path d="M8 4.25a.75.75 0 0 1 .75.75v3.25H11a.75.75 0 0 1 0 1.5H8a.75.75 0 0 1-.75-.75V5A.75.75 0 0 1 8 4.25Z" />
                </svg>
                {{ __($eyebrow) }}
            </x-ui.badge>
        </div>

        <h1 class="text-balance text-4xl font-bold tracking-tight text-foreground sm:text-5xl lg:text-6xl">{!! nl2br(e(__($heading))) !!}</h1>

        <p class="mx-auto mt-6 max-w-xl text-pretty text-lg leading-relaxed text-muted-foreground">{{ __($subheading) }}</p>

        <div class="mt-10">
            <form action="{{ $formAction }}" method="{{ strtolower($formMethod) === 'get' ? 'get' : 'post' }}" class="relative mx-auto flex max-w-md flex-col gap-4 sm:flex-row">
                @if (strtolower($formMethod) !== 'get')
                    @csrf
                @endif
                <label for="hero-form-email" class="sr-only">{{ __('Email address') }}</label>
                <x-ui.input id="hero-form-email" type="email" name="email" :placeholder="__($placeholder)" aria-label="{{ __('Email address') }}" autocomplete="email" required class="w-full flex-1" />
                <x-ui.button type="submit" variant="default" class="w-full shrink-0 sm:w-auto">
                    {{ __($submitLabel) }}
                    <x-slot:iconTrailing>
                        <svg class="size-4 rtl:-scale-x-100" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
                            <path d="M5 12h14M13 6l6 6-6 6" />
                        </svg>
                    </x-slot:iconTrailing>
                </x-ui.button>
            </form>
            <p class="mt-4 text-sm text-muted-foreground">{{ __($reassurance) }}</p>
        </div>

        <div class="mt-10 flex flex-col items-center gap-4">
            <x-ui.avatar-group :avatars="array_map(fn ($avatar) => ['src' => $avatar['src'] ?? null, 'name' => $avatar['alt'] ?? '', 'initials' => $avatar['fallback'] ?? null], $avatars)" :max="count($avatars)" size="sm" :label="__('Recent members')" />
            <div class="flex flex-col items-center gap-2">
                <x-ui.rating display :value="5" size="sm" />
                <p class="text-sm font-medium text-foreground">{{ __($socialProof) }}</p>
            </div>
        </div>
    </div>
</x-ui.section>

Ownership & lifecycle

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