K

Core

Callout

A soft, coloured notice box with a heading, an icon and an optional dismiss — its body from a schema or a plain string.

On this page

A coloured notice inside a form or an infolist — "this cannot be undone", "your trial ends in three days". Reach for it when the message belongs to one part of a screen and should stay there. For something that appears in response to what the user just did, and goes away again, you want a notification instead.

use NyonCode\WireCore\Foundation\Schema\Callout;

How It Works

A callout is a layout component: no value, no state path, safe to add or remove without touching data. It renders a soft, bordered box carrying role="alert", with an optional icon on the left and an optional bold heading above the body.

The body has two sources and they are not equal. Child components win:

  1. Every visible child in schema() is rendered and concatenated.
  2. Only if that produced nothing is content() used.

So a callout with both a schema and a content() string shows the schema and silently drops the string. And there is a second difference between them: children are Htmlable, so their markup is emitted as-is, while content() is escaped. A content('<strong>Careful</strong>') renders the tags as visible text. Markup in a callout goes through a child component, not through content().

The colour vocabulary is shorter than it looks. getAlertColorClasses() is a closed match over success/emerald, green, warning/amber, yellow, danger/red, black and white — and everything it does not recognise falls through to informational blue. ->color('primary') and ->color('purple') are both blue, without an error. In practice: use the four shortcuts, and treat anything else as a request that may not be honoured.

Dismissing is Alpine and is not remembered. dismissible() wraps the box in x-data="{ show: true }" and hides it with x-show, so the dismiss costs no round trip — and the callout is back on the next render, after a wire:navigate or a form round trip. A notice that must stay dismissed is application state.

Heading, icon and body are each optional and each independently omitted from the markup when absent; a callout with none of them is an empty coloured box.

Basic Usage

Callout::make()
->warning()
->icon('outline:exclamation-triangle')
->heading('Heads up')
->content('This action cannot be undone.')

title() is an alias for heading() if that reads better where you are.

Colours

Callout::make()->info(); // the default — same as ->color('info')
Callout::make()->success();
Callout::make()->warning();
Callout::make()->danger();

The four shortcuts are the whole practical vocabulary. ->color() also takes emerald, green, yellow, red, amber, black and white; every other value renders as info blue.

A Body With Markup In It

Because content() is escaped, anything richer than a sentence goes in the schema:

Callout::make()
->info()
->heading('Billing')
->schema([
Placeholder::make('plan')->content('Pro — renews 1 March'),
Placeholder::make('seats')->content('12 of 20 used'),
])

Remember that a schema, once it renders anything, replaces content() entirely.

Dismissible

Callout::make()
->danger()
->dismissible()
->heading('Payment failed')
->content('We could not charge your card.')

Extended Example

A callout at the top of a form, shown only while the account is unverified:

use Livewire\Component;
use NyonCode\WireCore\Foundation\Schema\Callout;
use NyonCode\WireCore\Foundation\Schema\Section;
use NyonCode\WireForms\Components\TextInput;
use NyonCode\WireForms\Forms\Form;
use NyonCode\WireForms\Forms\WithForms;
 
class EditProfile extends Component
{
use WithForms;
 
public ?array $data = [];
 
public function form(Form $form): Form
{
return $form
->statePath('data')
->model(User::class)
->schema([
Callout::make()
->warning()
->icon('outline:exclamation-triangle')
->heading('Your e-mail is not verified')
->content('Some features stay locked until you confirm it.')
->visible(fn (): bool => ! auth()->user()->hasVerifiedEmail()),
 
Section::make('profile')
->label('Profile')
->columns(2)
->schema([
TextInput::make('name')->required(),
TextInput::make('email')->email()->required(),
]),
]);
}
 
public function save(): void
{
$this->form->save();
}
}

visible() comes from the shared layout surface, so the callout disappears entirely — markup and all — once the condition stops holding.

Standalone Tag

The same markup is a Blade tag, for a callout outside any schema:

<x-wire::callout color="warning" heading="Heads up">
This action cannot be undone.
</x-wire::callout>

In a form, the Alert display field is the field-style alias of this component, and the modal surface uses the same palette.

Callout API

->heading(string|Closure|null $heading) // bold line above the body
->title(string|Closure|null $title) // alias of heading()
->content(string|Closure|null $content) // plain-text body, ESCAPED, ignored when a schema renders
->color(string|Color $color) // 'info' (default)|'success'|'warning'|'danger'|'emerald'|'green'|'amber'|'yellow'|'red'|'black'|'white' — anything else falls through to info blue
->info() // shortcut for color('info')
->success() // shortcut for color('success')
->warning() // shortcut for color('warning')
->danger() // shortcut for color('danger')
->icon(string|Icon|null $icon) // leading icon
->dismissible(bool $condition = true) // client-side dismiss, not remembered — default false
->getHeading(): ?string
->getContent(): ?string
->getColor(): string
->getIcon(): ?string
->isDismissible(): bool

Everything else — schema(), visible(), hidden(), columnSpan() — is the shared layout surface. See Common Layout API.

  • Schema — the vocabulary this belongs to, and the shared surface
  • Empty State — the other prime component
  • Alert — the same box as a form display field
  • Notifications — for a message that answers an action