Skip to content
Brok UI

Loading…

No results

Rich Text

Open source

Long-form prose sections — an article, policy or terms body with headings, lists and a pull-quote.

Preview

resources/views/blocks/rich-text-with-toc.blade.php Blade
@props([
    'eyebrow'  => 'Published, June 2026',
    'title'    => 'Building products people actually trust',
    'lead'     => 'Great software is not just functional — it is legible, honest, and built with the people who use it in mind. A long-form look at the principles that guide our decisions.',
    'tags'     => null,
    'sections' => null,
])

@php
    $tags ??= ['Product', 'Design', 'Engineering'];
    $sections ??= [
        ['id' => 'start-with-why', 'title' => 'Start with why, not what', 'paragraphs' => ['Every feature begins as a hypothesis. Before a single line of code is written, we ask: who is this for, and what changes for them when it exists? Answering that honestly is one of the hardest things a team can do.', 'The teams that skip this step ship quickly and revisit slowly. Refactoring a feature whose purpose was never agreed on is far more expensive than the brief discomfort of alignment work upfront.'], 'list' => null, 'quote' => null],
        ['id' => 'design-for-the-edge', 'title' => 'Design for the edge, not the average', 'paragraphs' => ['Average-case thinking produces interfaces that work well for nobody in particular. Real users arrive in contexts you did not predict — low bandwidth, assistive tech, RTL scripts, bright sunlight.'], 'list' => ['Colour contrast is the floor, not the ceiling.', 'Every interactive element must be operable without a pointer.', 'Logical CSS properties give you RTL support for free.', 'Reduced-motion queries are table stakes.'], 'quote' => 'Accessibility is not a feature. It is a quality of the whole.'],
        ['id' => 'shipping-is-the-start', 'title' => 'Shipping is the start, not the finish', 'paragraphs' => ['Launch day is when you begin to learn. Everything before that is theory. The metrics you instrument and the support conversations you read are the real product research.', 'This does not mean rushing. It means releasing intentionally, with the observability to understand what is happening and the process to act on it.'], 'list' => null, 'quote' => null],
        ['id' => 'maintenance-is-craft', 'title' => 'Maintenance is craft', 'paragraphs' => ['The industry romanticises building new things. Fewer people write about the craft of keeping existing systems healthy — upgrading dependencies, retiring features, writing the boring migration.'], 'list' => ['Dependency hygiene is a security practice, not a chore.', 'Dead code is a liability that hides real behaviour.', 'Changelog entries for breaking changes are an act of respect.', 'Automated tests make confident refactoring possible.'], 'quote' => null],
    ];
@endphp

<x-ui.section space="xl" {{ $attributes }}>
    <div class="mx-auto max-w-5xl px-4">
        <div class="lg:grid lg:grid-cols-[220px_1fr] lg:gap-10">
            <aside class="mb-10 lg:mb-0">
                <nav aria-label="{{ __('On this page') }}" class="lg:sticky lg:top-24">
                    <p class="mb-4 text-sm font-semibold uppercase tracking-widest text-muted-foreground">{{ __('On this page') }}</p>
                    <ul class="space-y-2" role="list">
                        @foreach ($sections as $i => $section)
                            <li>
                                <a href="#{{ $section['id'] }}" @class(['block text-sm leading-relaxed transition-colors', 'border-s-2 border-primary ps-4 font-medium text-link' => $i === 0, 'ps-4 text-muted-foreground hover:text-foreground' => $i !== 0])>{{ __($section['title']) }}</a>
                            </li>
                        @endforeach
                    </ul>
                </nav>
            </aside>

            <article>
                @if (! empty($tags))
                    <div class="mb-4 flex flex-wrap gap-2">
                        @foreach ($tags as $tag)<x-ui.badge variant="secondary">{{ __($tag) }}</x-ui.badge>@endforeach
                    </div>
                @endif
                @if ($eyebrow)<p class="mb-4 text-sm text-muted-foreground">{{ __($eyebrow) }}</p>@endif
                <h1 class="mb-4 text-balance text-3xl font-bold tracking-tight sm:text-4xl">{{ __($title) }}</h1>
                <p class="mb-8 text-pretty text-xl leading-relaxed text-muted-foreground">{{ __($lead) }}</p>

                <x-ui.separator class="mb-10" />

                <div class="space-y-12">
                    @foreach ($sections as $section)
                        <section id="{{ $section['id'] }}">
                            <h2 class="mb-4 text-xl font-semibold text-foreground sm:text-2xl">{{ __($section['title']) }}</h2>
                            <div class="space-y-4">
                                @foreach ($section['paragraphs'] as $para)
                                    <p class="text-pretty leading-relaxed text-muted-foreground">{{ __($para) }}</p>
                                @endforeach
                                @if (! empty($section['list']))
                                    <ul class="ms-6 list-disc space-y-2 text-muted-foreground" role="list">
                                        @foreach ($section['list'] as $item)<li class="text-pretty leading-relaxed">{{ __($item) }}</li>@endforeach
                                    </ul>
                                @endif
                                @if (! empty($section['quote']))
                                    <blockquote class="border-s-2 border-primary ps-4 italic text-foreground">{{ __($section['quote']) }}</blockquote>
                                @endif
                            </div>
                            @unless ($loop->last)<x-ui.separator class="mt-10" />@endunless
                        </section>
                    @endforeach
                </div>
            </article>
        </div>
    </div>
</x-ui.section>

Installation

terminal
php artisan ui:add blocks/rich-text-with-toc

Installs these dependencies automatically:

Registry contract

Install confidence

php artisan ui:add blocks/rich-text-with-toc 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/rich-text-with-toc.blade.php

Registry dependencies

badge section separator

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.

rich-text-with-toc.md
# Brok UI block: Rich Text TOC (`rich-text-with-toc`)

A long-form article with a sticky on-this-page table of contents beside the prose, headings, lists and pull-quotes.

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/rich-text-with-toc
```

## Render it

```blade
<x-blocks.rich-text-with-toc />
```

## Props

- `eyebrow` (string, default `Published, June 2026`) — Small label above the title, typically a publish date.
- `title` (string, default `Building products people actually trust`) — Article title.
- `lead` (string, default `Great software is not just functional — it is legible, honest, and built with the people who use it in mind. A long-form look at the principles that guide our decisions.`) — Supporting lead paragraph under the heading.
- `tags` (mixed|null, default `null`) — Topic badges shown under the title; null falls back to a default sample set.
- `sections` (mixed|null, default `null`) — Ordered list of {id, title, paragraphs, list, quote} sections that also drive the sticky table of contents; null falls back to sample copy.

## Use when

- Publishing a long-form article or guide that benefits from a sticky on-this-page table of contents beside the prose.
- Needing sections with headings, paragraphs, lists and pull-quotes that a reader may want to jump between.

## Avoid when

- Publishing a shorter legal document without navigation needs; use rich-text-article instead.

## Rules

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

  • Publishing a long-form article or guide that benefits from a sticky on-this-page table of contents beside the prose.
  • Needing sections with headings, paragraphs, lists and pull-quotes that a reader may want to jump between.

Avoid when

  • Publishing a shorter legal document without navigation needs; use rich-text-article instead.

Anti-patterns

  • Do not replace semantic props with conflicting utility classes.
  • Do not remove labels, focus styles, or state attributes.

Usage

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

resources/views/welcome.blade.php Blade
<x-blocks.rich-text-with-toc />

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/rich-text-with-toc.blade.php Blade
@props([
    'eyebrow'  => 'Published, June 2026',
    'title'    => 'Building products people actually trust',
    'lead'     => 'Great software is not just functional — it is legible, honest, and built with the people who use it in mind. A long-form look at the principles that guide our decisions.',
    'tags'     => null,
    'sections' => null,
])

@php
    $tags ??= ['Product', 'Design', 'Engineering'];
    $sections ??= [
        ['id' => 'start-with-why', 'title' => 'Start with why, not what', 'paragraphs' => ['Every feature begins as a hypothesis. Before a single line of code is written, we ask: who is this for, and what changes for them when it exists? Answering that honestly is one of the hardest things a team can do.', 'The teams that skip this step ship quickly and revisit slowly. Refactoring a feature whose purpose was never agreed on is far more expensive than the brief discomfort of alignment work upfront.'], 'list' => null, 'quote' => null],
        ['id' => 'design-for-the-edge', 'title' => 'Design for the edge, not the average', 'paragraphs' => ['Average-case thinking produces interfaces that work well for nobody in particular. Real users arrive in contexts you did not predict — low bandwidth, assistive tech, RTL scripts, bright sunlight.'], 'list' => ['Colour contrast is the floor, not the ceiling.', 'Every interactive element must be operable without a pointer.', 'Logical CSS properties give you RTL support for free.', 'Reduced-motion queries are table stakes.'], 'quote' => 'Accessibility is not a feature. It is a quality of the whole.'],
        ['id' => 'shipping-is-the-start', 'title' => 'Shipping is the start, not the finish', 'paragraphs' => ['Launch day is when you begin to learn. Everything before that is theory. The metrics you instrument and the support conversations you read are the real product research.', 'This does not mean rushing. It means releasing intentionally, with the observability to understand what is happening and the process to act on it.'], 'list' => null, 'quote' => null],
        ['id' => 'maintenance-is-craft', 'title' => 'Maintenance is craft', 'paragraphs' => ['The industry romanticises building new things. Fewer people write about the craft of keeping existing systems healthy — upgrading dependencies, retiring features, writing the boring migration.'], 'list' => ['Dependency hygiene is a security practice, not a chore.', 'Dead code is a liability that hides real behaviour.', 'Changelog entries for breaking changes are an act of respect.', 'Automated tests make confident refactoring possible.'], 'quote' => null],
    ];
@endphp

<x-ui.section space="xl" {{ $attributes }}>
    <div class="mx-auto max-w-5xl px-4">
        <div class="lg:grid lg:grid-cols-[220px_1fr] lg:gap-10">
            <aside class="mb-10 lg:mb-0">
                <nav aria-label="{{ __('On this page') }}" class="lg:sticky lg:top-24">
                    <p class="mb-4 text-sm font-semibold uppercase tracking-widest text-muted-foreground">{{ __('On this page') }}</p>
                    <ul class="space-y-2" role="list">
                        @foreach ($sections as $i => $section)
                            <li>
                                <a href="#{{ $section['id'] }}" @class(['block text-sm leading-relaxed transition-colors', 'border-s-2 border-primary ps-4 font-medium text-link' => $i === 0, 'ps-4 text-muted-foreground hover:text-foreground' => $i !== 0])>{{ __($section['title']) }}</a>
                            </li>
                        @endforeach
                    </ul>
                </nav>
            </aside>

            <article>
                @if (! empty($tags))
                    <div class="mb-4 flex flex-wrap gap-2">
                        @foreach ($tags as $tag)<x-ui.badge variant="secondary">{{ __($tag) }}</x-ui.badge>@endforeach
                    </div>
                @endif
                @if ($eyebrow)<p class="mb-4 text-sm text-muted-foreground">{{ __($eyebrow) }}</p>@endif
                <h1 class="mb-4 text-balance text-3xl font-bold tracking-tight sm:text-4xl">{{ __($title) }}</h1>
                <p class="mb-8 text-pretty text-xl leading-relaxed text-muted-foreground">{{ __($lead) }}</p>

                <x-ui.separator class="mb-10" />

                <div class="space-y-12">
                    @foreach ($sections as $section)
                        <section id="{{ $section['id'] }}">
                            <h2 class="mb-4 text-xl font-semibold text-foreground sm:text-2xl">{{ __($section['title']) }}</h2>
                            <div class="space-y-4">
                                @foreach ($section['paragraphs'] as $para)
                                    <p class="text-pretty leading-relaxed text-muted-foreground">{{ __($para) }}</p>
                                @endforeach
                                @if (! empty($section['list']))
                                    <ul class="ms-6 list-disc space-y-2 text-muted-foreground" role="list">
                                        @foreach ($section['list'] as $item)<li class="text-pretty leading-relaxed">{{ __($item) }}</li>@endforeach
                                    </ul>
                                @endif
                                @if (! empty($section['quote']))
                                    <blockquote class="border-s-2 border-primary ps-4 italic text-foreground">{{ __($section['quote']) }}</blockquote>
                                @endif
                            </div>
                            @unless ($loop->last)<x-ui.separator class="mt-10" />@endunless
                        </section>
                    @endforeach
                </div>
            </article>
        </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