Skip to content
Brok UI

Loading…

No results

Comparison

Open source

Comparison sections — a two-column us-vs-them layout contrasting your product with the alternative, and feature-comparison tables across your own plans or against competitors.

Preview

2 of 5

resources/views/blocks/comparison-competitor-table.blade.php Blade
@props([
    'heading'     => 'How we stack up',
    'subheading'  => 'See exactly what you get with Acme versus the alternatives. No spin — just the facts.',
    'yourBrand'   => 'Acme',
    'competitors' => null,
    'rows'        => null,
    'ctaLabel'    => 'Get started free',
    'ctaHref'     => '#',
])

@php
    $competitors ??= [
        ['name' => 'Competitor A'],
        ['name' => 'Competitor B'],
    ];

    // Each row: 'label' + 'values' (index 0 = your brand, 1+ = competitors).
    // true → check, false → dash, string → verbatim value.
    $rows ??= [
        ['label' => 'Pricing', 'values' => ['$29/mo', '$79/mo', '$59/mo']],
        ['label' => 'Free plan', 'values' => [true, false, false]],
        ['label' => 'Users included', 'values' => ['Unlimited', '5 seats', '10 seats']],
        ['label' => 'API access', 'values' => [true, true, false]],
        ['label' => 'Custom domain', 'values' => [true, true, true]],
        ['label' => 'SSO / SAML', 'values' => [true, false, false]],
        ['label' => 'Priority support', 'values' => [true, false, true]],
        ['label' => 'Data export', 'values' => ['Any format', 'CSV only', 'CSV only']],
        ['label' => 'Uptime SLA', 'values' => ['99.99%', '99.9%', '99.5%']],
        ['label' => 'White-label option', 'values' => [true, false, false]],
    ];
@endphp

<x-ui.section data-slot="comparison-table" aria-labelledby="ct01-heading" space="xl" {{ $attributes }}>
    <x-ui.container gutter="sm">
        <div class="mx-auto max-w-2xl text-center">
            <h2 id="ct01-heading" class="text-balance text-3xl font-bold tracking-tight sm:text-4xl">{{ __($heading) }}</h2>
            @if ($subheading)
                <p class="mt-4 text-pretty text-base text-muted-foreground sm:text-lg">{{ __($subheading) }}</p>
            @endif
        </div>

        @php
            // true → check, false → dash, string → verbatim value. One helper
            // for both the highlighted column and the competitor columns.
            $mark = fn ($value, string $tone) => is_string($value)
                ? null
                : ($value === true
                    ? ['path' => '<path fill-rule="evenodd" d="M16.704 4.153a.75.75 0 01.143 1.052l-8 10.5a.75.75 0 01-1.127.075l-4.5-4.5a.75.75 0 011.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 011.05-.143z" clip-rule="evenodd" />', 'label' => __('Yes'), 'tone' => $tone]
                    : ['path' => '<path d="M4 10a.75.75 0 01.75-.75h10.5a.75.75 0 010 1.5H4.75A.75.75 0 014 10z" />', 'label' => __('No'), 'tone' => 'text-muted-foreground']);
        @endphp

        <x-ui.table variant="striped" bordered class="mt-12 min-w-[48rem] text-xs shadow-sm">
            <caption class="sr-only">{{ __('Feature comparison: :brand vs competitors', ['brand' => $yourBrand]) }}</caption>
            <colgroup>
                <col class="w-2/5">
                <col class="w-[18%]">
                @foreach ($competitors as $comp)
                    <col class="w-[18%]">
                @endforeach
            </colgroup>
            <x-ui.table.header>
                <x-ui.table.row class="bg-muted/40 hover:bg-muted/40">
                    <x-ui.table.head scope="col" class="font-semibold uppercase tracking-wide">{{ __('Feature') }}</x-ui.table.head>
                    <x-ui.table.head scope="col" align="center" class="h-auto bg-primary/5 !py-4">
                        <div class="flex flex-col items-center gap-2">
                            <span class="text-base font-bold text-foreground">{{ __($yourBrand) }}</span>
                            <x-ui.badge variant="default" size="sm">{{ __('Recommended') }}</x-ui.badge>
                        </div>
                    </x-ui.table.head>
                    @foreach ($competitors as $comp)
                        <x-ui.table.head scope="col" align="center" class="h-auto !py-4"><span class="text-base font-semibold text-muted-foreground">{{ __($comp['name']) }}</span></x-ui.table.head>
                    @endforeach
                </x-ui.table.row>
            </x-ui.table.header>
            <x-ui.table.body>
                @foreach ($rows as $row)
                    <x-ui.table.row>
                        <x-ui.table.head scope="row" class="h-auto py-2 font-medium text-foreground">{{ __($row['label']) }}</x-ui.table.head>
                        @foreach (array_merge([$row['values'][0] ?? false], array_map(fn ($ci) => $row['values'][$ci + 1] ?? false, array_keys($competitors))) as $col => $value)
                            @php $ours = $col === 0; $glyph = $mark($value, $ours ? 'text-primary' : 'text-muted-foreground'); @endphp
                            <x-ui.table.cell align="center" @class(['bg-primary/5' => $ours])>
                                @if ($glyph === null)
                                    <span @class(['font-medium text-foreground' => $ours, 'text-muted-foreground' => ! $ours])>{{ __($value) }}</span>
                                @else
                                    <svg viewBox="0 0 20 20" fill="currentColor" class="mx-auto size-5 {{ $glyph['tone'] }}" aria-hidden="true">{!! $glyph['path'] !!}</svg>
                                    <span class="sr-only">{{ $glyph['label'] }}</span>
                                @endif
                            </x-ui.table.cell>
                        @endforeach
                    </x-ui.table.row>
                @endforeach
                <x-ui.table.row class="bg-muted/10 hover:bg-muted/10">
                    <x-ui.table.cell class="!py-6"></x-ui.table.cell>
                    <x-ui.table.cell align="center" class="bg-primary/5 !py-6">
                        <x-ui.button :href="$ctaHref" variant="default" class="w-full max-w-[160px]">{{ __($ctaLabel) }}</x-ui.button>
                    </x-ui.table.cell>
                    @foreach ($competitors as $comp)
                        <x-ui.table.cell align="center" class="!py-6"><span class="text-xs text-muted-foreground">—</span></x-ui.table.cell>
                    @endforeach
                </x-ui.table.row>
            </x-ui.table.body>
        </x-ui.table>

        <p class="mt-4 text-center text-xs text-muted-foreground">{{ __('Competitor data is sourced from public pricing pages and may not reflect recent changes.') }}</p>
    </x-ui.container>
</x-ui.section>

Installation

terminal
php artisan ui:add blocks/comparison-competitor-table

Installs these dependencies automatically:

Registry contract

Install confidence

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

Registry dependencies

badge button container section table

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.

comparison-competitor-table.md
# Brok UI block: Comparison Table (`comparison-competitor-table`)

A feature comparison table pitting your highlighted product against named competitors across many rows of checks, dashes and values, scrollable on mobile.

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/comparison-competitor-table
```

## Render it

```blade
<x-blocks.comparison-competitor-table />
```

## Props

- `heading` (string, default `How we stack up`)
- `subheading` (string, default `See exactly what you get with Acme versus the alternatives. No spin — just the facts.`)
- `your-brand` (string, default `Acme`)
- `competitors` (mixed|null, default `null`)
- `rows` (mixed|null, default `null`)
- `cta-label` (string, default `Get started free`)
- `cta-href` (string, default `#`)

## Use when

- Pitting your highlighted product against one or more named competitors across many rows of checks, dashes and values.
- Scrolling the table horizontally on mobile so every competitor column stays reachable.

## Avoid when

- Use comparison-versus for a two-card pros/cons layout, or comparison-toggle to let the visitor switch which competitor is shown.

## Rules

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

  • Pitting your highlighted product against one or more named competitors across many rows of checks, dashes and values.
  • Scrolling the table horizontally on mobile so every competitor column stays reachable.

Avoid when

  • Use comparison-versus for a two-card pros/cons layout, or comparison-toggle to let the visitor switch which competitor is shown.

Anti-patterns

  • Do not replace semantic props with conflicting utility classes.
  • Do not remove labels, focus styles, or state attributes.
Anatomy
root comparison-table

Usage

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

resources/views/welcome.blade.php Blade
<x-blocks.comparison-competitor-table />

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/comparison-competitor-table.blade.php Blade
@props([
    'heading'     => 'How we stack up',
    'subheading'  => 'See exactly what you get with Acme versus the alternatives. No spin — just the facts.',
    'yourBrand'   => 'Acme',
    'competitors' => null,
    'rows'        => null,
    'ctaLabel'    => 'Get started free',
    'ctaHref'     => '#',
])

@php
    $competitors ??= [
        ['name' => 'Competitor A'],
        ['name' => 'Competitor B'],
    ];

    // Each row: 'label' + 'values' (index 0 = your brand, 1+ = competitors).
    // true → check, false → dash, string → verbatim value.
    $rows ??= [
        ['label' => 'Pricing', 'values' => ['$29/mo', '$79/mo', '$59/mo']],
        ['label' => 'Free plan', 'values' => [true, false, false]],
        ['label' => 'Users included', 'values' => ['Unlimited', '5 seats', '10 seats']],
        ['label' => 'API access', 'values' => [true, true, false]],
        ['label' => 'Custom domain', 'values' => [true, true, true]],
        ['label' => 'SSO / SAML', 'values' => [true, false, false]],
        ['label' => 'Priority support', 'values' => [true, false, true]],
        ['label' => 'Data export', 'values' => ['Any format', 'CSV only', 'CSV only']],
        ['label' => 'Uptime SLA', 'values' => ['99.99%', '99.9%', '99.5%']],
        ['label' => 'White-label option', 'values' => [true, false, false]],
    ];
@endphp

<x-ui.section data-slot="comparison-table" aria-labelledby="ct01-heading" space="xl" {{ $attributes }}>
    <x-ui.container gutter="sm">
        <div class="mx-auto max-w-2xl text-center">
            <h2 id="ct01-heading" class="text-balance text-3xl font-bold tracking-tight sm:text-4xl">{{ __($heading) }}</h2>
            @if ($subheading)
                <p class="mt-4 text-pretty text-base text-muted-foreground sm:text-lg">{{ __($subheading) }}</p>
            @endif
        </div>

        @php
            // true → check, false → dash, string → verbatim value. One helper
            // for both the highlighted column and the competitor columns.
            $mark = fn ($value, string $tone) => is_string($value)
                ? null
                : ($value === true
                    ? ['path' => '<path fill-rule="evenodd" d="M16.704 4.153a.75.75 0 01.143 1.052l-8 10.5a.75.75 0 01-1.127.075l-4.5-4.5a.75.75 0 011.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 011.05-.143z" clip-rule="evenodd" />', 'label' => __('Yes'), 'tone' => $tone]
                    : ['path' => '<path d="M4 10a.75.75 0 01.75-.75h10.5a.75.75 0 010 1.5H4.75A.75.75 0 014 10z" />', 'label' => __('No'), 'tone' => 'text-muted-foreground']);
        @endphp

        <x-ui.table variant="striped" bordered class="mt-12 min-w-[48rem] text-xs shadow-sm">
            <caption class="sr-only">{{ __('Feature comparison: :brand vs competitors', ['brand' => $yourBrand]) }}</caption>
            <colgroup>
                <col class="w-2/5">
                <col class="w-[18%]">
                @foreach ($competitors as $comp)
                    <col class="w-[18%]">
                @endforeach
            </colgroup>
            <x-ui.table.header>
                <x-ui.table.row class="bg-muted/40 hover:bg-muted/40">
                    <x-ui.table.head scope="col" class="font-semibold uppercase tracking-wide">{{ __('Feature') }}</x-ui.table.head>
                    <x-ui.table.head scope="col" align="center" class="h-auto bg-primary/5 !py-4">
                        <div class="flex flex-col items-center gap-2">
                            <span class="text-base font-bold text-foreground">{{ __($yourBrand) }}</span>
                            <x-ui.badge variant="default" size="sm">{{ __('Recommended') }}</x-ui.badge>
                        </div>
                    </x-ui.table.head>
                    @foreach ($competitors as $comp)
                        <x-ui.table.head scope="col" align="center" class="h-auto !py-4"><span class="text-base font-semibold text-muted-foreground">{{ __($comp['name']) }}</span></x-ui.table.head>
                    @endforeach
                </x-ui.table.row>
            </x-ui.table.header>
            <x-ui.table.body>
                @foreach ($rows as $row)
                    <x-ui.table.row>
                        <x-ui.table.head scope="row" class="h-auto py-2 font-medium text-foreground">{{ __($row['label']) }}</x-ui.table.head>
                        @foreach (array_merge([$row['values'][0] ?? false], array_map(fn ($ci) => $row['values'][$ci + 1] ?? false, array_keys($competitors))) as $col => $value)
                            @php $ours = $col === 0; $glyph = $mark($value, $ours ? 'text-primary' : 'text-muted-foreground'); @endphp
                            <x-ui.table.cell align="center" @class(['bg-primary/5' => $ours])>
                                @if ($glyph === null)
                                    <span @class(['font-medium text-foreground' => $ours, 'text-muted-foreground' => ! $ours])>{{ __($value) }}</span>
                                @else
                                    <svg viewBox="0 0 20 20" fill="currentColor" class="mx-auto size-5 {{ $glyph['tone'] }}" aria-hidden="true">{!! $glyph['path'] !!}</svg>
                                    <span class="sr-only">{{ $glyph['label'] }}</span>
                                @endif
                            </x-ui.table.cell>
                        @endforeach
                    </x-ui.table.row>
                @endforeach
                <x-ui.table.row class="bg-muted/10 hover:bg-muted/10">
                    <x-ui.table.cell class="!py-6"></x-ui.table.cell>
                    <x-ui.table.cell align="center" class="bg-primary/5 !py-6">
                        <x-ui.button :href="$ctaHref" variant="default" class="w-full max-w-[160px]">{{ __($ctaLabel) }}</x-ui.button>
                    </x-ui.table.cell>
                    @foreach ($competitors as $comp)
                        <x-ui.table.cell align="center" class="!py-6"><span class="text-xs text-muted-foreground">—</span></x-ui.table.cell>
                    @endforeach
                </x-ui.table.row>
            </x-ui.table.body>
        </x-ui.table>

        <p class="mt-4 text-center text-xs text-muted-foreground">{{ __('Competitor data is sourced from public pricing pages and may not reflect recent changes.') }}</p>
    </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.6
Status
Stable
License
open
Deprecation
Not deprecated
Contract
v1
Foundation
≥ 1.0.0