Process
How-it-works sections — a horizontal step row and a vertical numbered timeline.
Preview
@props([
'eyebrow' => 'How it works',
'heading' => 'Three simple steps to get started',
'lead' => 'Everything you need to go from idea to launch — without the guesswork. Follow these steps and you will be up and running in no time.',
'steps' => null,
])
@php
$steps ??= [
['icon' => 'search', 'title' => 'Discover & plan', 'body' => 'Explore the library, bookmark the components you need, and sketch out your layout. Our interactive docs make planning straightforward.', 'duration' => '~5 min'],
['icon' => 'install', 'title' => 'Install in one command', 'body' => 'Run a single artisan command and the component drops straight into your project — no build step, no runtime dependency.', 'duration' => '~1 min'],
['icon' => 'compose', 'title' => 'Compose & customise', 'body' => 'Edit the generated Blade directly. Every token, every class, every slot is yours. Adjust colours, copy, and layout to match your brand.', 'duration' => '~10 min'],
['icon' => 'ship', 'title' => 'Ship with confidence', 'body' => 'Deploy as you normally would. Zero runtime coupling means updates to this library never break your production app.', 'duration' => 'Ongoing'],
];
$icons = [
'search' => '<circle cx="11" cy="11" r="8"/><path d="m21 21-4.35-4.35"/>',
'install' => '<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/>',
'compose' => '<path d="M12 20h9"/><path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z"/>',
'ship' => '<path d="M12 2 2 7l10 5 10-5-10-5Z"/><path d="m2 17 10 5 10-5"/><path d="m2 12 10 5 10-5"/>',
];
@endphp
<x-ui.section space="xl" {{ $attributes }} aria-labelledby="process-vertical-01-heading">
<x-ui.container size="md" gutter="sm">
<div class="mx-auto max-w-2xl text-center">
@if (! empty($eyebrow))
<x-ui.badge variant="secondary" class="mb-6">{{ __($eyebrow) }}</x-ui.badge>
@endif
<h2 id="process-vertical-01-heading" class="text-balance text-3xl font-bold tracking-tight sm:text-4xl">{{ __($heading) }}</h2>
@if (! empty($lead))
<p class="mt-4 text-pretty text-lg text-muted-foreground">{{ __($lead) }}</p>
@endif
</div>
<ol class="mt-16 sm:mt-20" aria-label="{{ __('Process steps') }}">
@foreach ($steps as $i => $step)
<li class="relative flex gap-6 sm:gap-8">
<div class="flex flex-col items-center">
<span class="relative z-10 inline-flex size-10 shrink-0 items-center justify-center rounded-full bg-primary font-semibold tabular-nums text-primary-foreground" aria-hidden="true">{{ $i + 1 }}</span>
@unless ($loop->last)
<span class="mt-2 w-px grow border-s border-dashed border-border" aria-hidden="true"></span>
@endunless
</div>
<div class="{{ $loop->last ? 'pb-0' : 'pb-10 sm:pb-12' }} flex-1">
<x-ui.card>
<x-ui.card.header class="flex-row items-start gap-4 pb-4">
@if (! empty($step['icon']) && isset($icons[$step['icon']]))
<x-ui.icon.tile>
<svg class="size-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">{!! $icons[$step['icon']] !!}</svg>
</x-ui.icon.tile>
@endif
<div class="flex min-w-0 flex-1 flex-wrap items-center justify-between gap-x-4 gap-y-2">
<x-ui.card.title class="text-sm font-semibold leading-snug">{{ __($step['title']) }}</x-ui.card.title>
@if (! empty($step['duration']))
<x-ui.badge variant="outline" size="sm" class="shrink-0 whitespace-nowrap">{{ __($step['duration']) }}</x-ui.badge>
@endif
</div>
</x-ui.card.header>
<x-ui.card.content>
<p class="text-pretty text-sm text-muted-foreground">{{ __($step['body']) }}</p>
</x-ui.card.content>
</x-ui.card>
</div>
</li>
@endforeach
</ol>
</x-ui.container>
</x-ui.section>
Installation
php artisan ui:add blocks/process-vertical
Registry contract
Install confidence
php artisan ui:add blocks/process-vertical
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/process-vertical.blade.php |
Registry dependencies
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.
# Brok UI block: Process Vertical (`process-vertical`)
A vertical how-it-works timeline of numbered steps connected by a dashed rail, each step a card with an icon, title, duration badge and description.
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/process-vertical
```
## Render it
```blade
<x-blocks.process-vertical />
```
## Props
- `eyebrow` (string, default `How it works`) — Small label shown above the heading inside a badge.
- `heading` (string, default `Three simple steps to get started`) — Section heading.
- `lead` (string, default `Everything you need to go from idea to launch — without the guesswork. Follow these steps and you will be up and running in no time.`) — Supporting copy under the heading.
- `steps` (mixed|null, default `null`) — Array of {icon, title, body, duration} step entries; null falls back to a default 4-step sample.
## Use when
- Explaining a sequential process as a vertical timeline of numbered steps connected by a dashed line, each step in a card with an icon, title, body and an optional duration badge.
- Wanting to communicate how long each step takes (e.g. "~5 min") alongside the step description.
## Avoid when
- Needing a compact horizontal 3-column step grid instead of a vertical timeline; use process-horizontal.
## Rules
- Render the installed block with `<x-blocks.process-vertical />` 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/process-vertical
- Registry JSON (files, props, contract): https://brokui.dev/r/open/blocks/process-vertical.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
- Explaining a sequential process as a vertical timeline of numbered steps connected by a dashed line, each step in a card with an icon, title, body and an optional duration badge.
- Wanting to communicate how long each step takes (e.g. "~5 min") alongside the step description.
Avoid when
- Needing a compact horizontal 3-column step grid instead of a vertical timeline; use process-horizontal.
Anti-patterns
- Do not replace semantic props with conflicting utility classes.
- Do not remove labels, focus styles, or state attributes.
- Anatomy
Usage
Render the block as a component, passing data where useful:
<x-blocks.process-vertical />
Built from primitives
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.
@props([
'eyebrow' => 'How it works',
'heading' => 'Three simple steps to get started',
'lead' => 'Everything you need to go from idea to launch — without the guesswork. Follow these steps and you will be up and running in no time.',
'steps' => null,
])
@php
$steps ??= [
['icon' => 'search', 'title' => 'Discover & plan', 'body' => 'Explore the library, bookmark the components you need, and sketch out your layout. Our interactive docs make planning straightforward.', 'duration' => '~5 min'],
['icon' => 'install', 'title' => 'Install in one command', 'body' => 'Run a single artisan command and the component drops straight into your project — no build step, no runtime dependency.', 'duration' => '~1 min'],
['icon' => 'compose', 'title' => 'Compose & customise', 'body' => 'Edit the generated Blade directly. Every token, every class, every slot is yours. Adjust colours, copy, and layout to match your brand.', 'duration' => '~10 min'],
['icon' => 'ship', 'title' => 'Ship with confidence', 'body' => 'Deploy as you normally would. Zero runtime coupling means updates to this library never break your production app.', 'duration' => 'Ongoing'],
];
$icons = [
'search' => '<circle cx="11" cy="11" r="8"/><path d="m21 21-4.35-4.35"/>',
'install' => '<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/>',
'compose' => '<path d="M12 20h9"/><path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z"/>',
'ship' => '<path d="M12 2 2 7l10 5 10-5-10-5Z"/><path d="m2 17 10 5 10-5"/><path d="m2 12 10 5 10-5"/>',
];
@endphp
<x-ui.section space="xl" {{ $attributes }} aria-labelledby="process-vertical-01-heading">
<x-ui.container size="md" gutter="sm">
<div class="mx-auto max-w-2xl text-center">
@if (! empty($eyebrow))
<x-ui.badge variant="secondary" class="mb-6">{{ __($eyebrow) }}</x-ui.badge>
@endif
<h2 id="process-vertical-01-heading" class="text-balance text-3xl font-bold tracking-tight sm:text-4xl">{{ __($heading) }}</h2>
@if (! empty($lead))
<p class="mt-4 text-pretty text-lg text-muted-foreground">{{ __($lead) }}</p>
@endif
</div>
<ol class="mt-16 sm:mt-20" aria-label="{{ __('Process steps') }}">
@foreach ($steps as $i => $step)
<li class="relative flex gap-6 sm:gap-8">
<div class="flex flex-col items-center">
<span class="relative z-10 inline-flex size-10 shrink-0 items-center justify-center rounded-full bg-primary font-semibold tabular-nums text-primary-foreground" aria-hidden="true">{{ $i + 1 }}</span>
@unless ($loop->last)
<span class="mt-2 w-px grow border-s border-dashed border-border" aria-hidden="true"></span>
@endunless
</div>
<div class="{{ $loop->last ? 'pb-0' : 'pb-10 sm:pb-12' }} flex-1">
<x-ui.card>
<x-ui.card.header class="flex-row items-start gap-4 pb-4">
@if (! empty($step['icon']) && isset($icons[$step['icon']]))
<x-ui.icon.tile>
<svg class="size-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">{!! $icons[$step['icon']] !!}</svg>
</x-ui.icon.tile>
@endif
<div class="flex min-w-0 flex-1 flex-wrap items-center justify-between gap-x-4 gap-y-2">
<x-ui.card.title class="text-sm font-semibold leading-snug">{{ __($step['title']) }}</x-ui.card.title>
@if (! empty($step['duration']))
<x-ui.badge variant="outline" size="sm" class="shrink-0 whitespace-nowrap">{{ __($step['duration']) }}</x-ui.badge>
@endif
</div>
</x-ui.card.header>
<x-ui.card.content>
<p class="text-pretty text-sm text-muted-foreground">{{ __($step['body']) }}</p>
</x-ui.card.content>
</x-ui.card>
</div>
</li>
@endforeach
</ol>
</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.0.5 - Status
- Stable
- License
-
open - Deprecation
- Not deprecated
- Contract
-
v1 - Foundation
-
≥ 1.0.0