Button
Displays a button or link with variants, sizes, a pill shape, static or Livewire-targeted loading state, leading/trailing icon slots, an accessibility-safe icon-only mode and an optional animated arrow.
Preview
<x-ui.button>{{ __('Button') }}</x-ui.button>
Variant options
Size options
Shape options
Installation
php artisan ui:add button
Registry contract
php artisan ui:add button
writes only the files below. The CLI validates each file hash before writing and asks before it replaces a local change, unless you pass --force.
-
resources/views/components/ui/button.blade.php
- Registry dependencies
- None — installs on its own.
- Packages
-
composer: jml/brok:^0.2
Use with AI
A brief for your coding agent: install command, usage, props, guidance and the rules. Copy it, or open a prompt about this component in an assistant.
# Brok UI: Button (`button`)
Displays a button or link with variants, sizes, a pill shape, static or Livewire-targeted loading state, leading/trailing icon slots, an accessibility-safe icon-only mode and an optional animated arrow.
Brok UI is a Laravel Blade component registry. Installed components are plain Blade files the app owns.
## Install
```bash
php artisan ui:add button
```
## Usage
```blade
<x-ui.button>{{ __('Button') }}</x-ui.button>
```
## Props
- `variant` (default|primary|destructive|danger|outline|secondary|ghost|link, default `default`) — Semantic emphasis or intent. Primary aliases default; danger aliases destructive.
- `size` (sm|md|lg|icon|icon-sm|icon-lg, default `md`) — Control height and horizontal padding.
- `shape` (default|pill, default `default`) — Legacy silhouette override.
- `type` (button|submit|reset, default `button`) — Native button type when rendering a button element.
- `disabled` (bool, default `false`) — Prevents interaction while preserving disabled semantics.
- `loading` (bool, default `false`) — Disables interaction and exposes a busy loading state.
- `wireTarget` (string, default `null`) — Livewire action or property to watch. While that request is in flight the control is disabled and a delayed status message is announced.
- `wireLoadingLabel` (string, default `Working…`) — Screen-reader text announced while the wireTarget request is in flight.
- `withArrow` (bool, default `false`) — Legacy animated-arrow shortcut.
- `arrowClass` (string, default ``) — Legacy classes for the shortcut arrow.
- `href` (string|null, default `null`) — Renders an anchor when navigation semantics are required.
- `as` (button|a|null, default `null`) — Explicitly renders one of the supported native elements.
- `iconLabel` (string|null, default `null`) — Enables icon-only mode, supplies the accessible name, and maps sm/md/lg to square icon sizes.
- `wrap` (bool, default `false`) — Allows the label to wrap; labels truncate by default to protect constrained layouts.
- `shortcut` (string|null, default `null`) — A keyboard shortcut hint such as "e", "shift+j", "ctrl+enter" or "mod+enter", drawn as kbd keys after the label on every variant and exposed as aria-keyshortcuts (Shift+J, Control+Enter). mod is the platform command key, as in the hotkeys store: ⌘ and Meta+Enter for a request from macOS or iOS (Sec-CH-UA-Platform, else the User-Agent), Ctrl and Control+Enter elsewhere; a page in a shared full-page cache must vary on the platform or name the key. The visible hint is hidden on a touch screen (pointer: coarse). A hint only: bind the key with x-hotkey or the hotkeys store. Icon-only buttons keep aria-keyshortcuts without the visible hint.
## Use when
- Use for explicit actions and commits; keep one action visually primary when several sit together.
- Triggering an immediate action such as saving, submitting, or opening a surface.
- Presenting a prominent call to action with a consistent variant and size.
## Avoid when
- Do not use button treatment for navigation-only view changes when links, tabs, or radios describe state more clearly.
- Navigating to another URL without button semantics; render the component as a link or use a normal link.
- Representing a persistent on/off value; use switch or checkbox.
## Anti-patterns
- Using a button for navigation-only state changes
- Presenting multiple equally dominant primary actions
## Rules
- Use the `<brok:button>` tag (or `<x-ui.button>`) in Blade; do not rewrite the component.
- Prefer the documented props and variants over utility-class overrides; when a utility must win, use the `!` important modifier.
- Use semantic design tokens (`bg-primary`, `text-muted-foreground`), never raw colour utilities.
- Keep the `data-slot` attributes; they are the styling and test hooks.
## Links
- Docs: https://brokui.dev/docs/components/button
- Registry JSON (files, props, contract): https://brokui.dev/r/open/button.json
Working in Claude Code, Cursor or Codex? Give the agent the whole registry through the MCP server or the Brok UI skill.
Examples
<div class="mx-auto flex max-w-xs flex-col gap-3">
<x-ui.button class="w-full">{{ __('Sign in') }}</x-ui.button>
<x-ui.button class="w-full" variant="outline">{{ __('Create account') }}</x-ui.button>
</div>
<div class="flex flex-wrap items-center gap-3">
<x-ui.button :disabled="true">{{ __('Default') }}</x-ui.button>
<x-ui.button :disabled="true" variant="secondary">{{ __('Secondary') }}</x-ui.button>
<x-ui.button :disabled="true" variant="outline">{{ __('Outline') }}</x-ui.button>
<x-ui.button :disabled="true" variant="ghost">{{ __('Ghost') }}</x-ui.button>
</div>
<div class="flex flex-wrap items-center gap-3">
{{-- Leading icon --}}
<brok:button>
<x-slot:icon>
<svg class="size-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M12 5v14M5 12h14" />
</svg>
</x-slot:icon>
{{ __('New project') }}
</brok:button>
{{-- Trailing icon --}}
<brok:button variant="outline">
{{ __('Continue') }}
<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">
<path d="M5 12h14M13 6l6 6-6 6" />
</svg>
</x-slot:iconTrailing>
</brok:button>
{{-- Icon-only --}}
<brok:button icon-label="Settings" variant="ghost">
<svg class="size-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<circle cx="12" cy="12" r="3" />
<path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z" />
</svg>
</brok:button>
</div>
<x-ui.button :loading="true">{{ __('Saving…') }}</x-ui.button>
Long Content
<div class="w-64 max-w-full">
<x-ui.button class="w-full">{{ __('Save changes for an exceptionally long translated workspace name') }}</x-ui.button>
</div>
<div class="flex flex-wrap items-center gap-3">
<x-ui.button shape="pill">{{ __('Pill') }}</x-ui.button>
<x-ui.button shape="pill" variant="secondary">{{ __('Secondary') }}</x-ui.button>
<x-ui.button shape="pill" variant="outline">{{ __('Outline') }}</x-ui.button>
<x-ui.button shape="pill" size="icon" variant="outline" aria-label="{{ __('Add') }}">
<svg class="size-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M12 5v14M5 12h14" />
</svg>
</x-ui.button>
</div>
{{-- A shortcut hint on every variant. The hint is decorative; the button
carries aria-keyshortcuts, and x-hotkey or the hotkeys store binds the key. --}}
<div class="flex flex-wrap items-center gap-2">
<x-ui.button shortcut="e">{{ __('Archive') }}</x-ui.button>
<x-ui.button variant="secondary" shortcut="shift+j">{{ __('Select below') }}</x-ui.button>
<x-ui.button variant="outline" shortcut="ctrl+enter">{{ __('Send') }}</x-ui.button>
<x-ui.button variant="ghost" shortcut="s">{{ __('Snooze') }}</x-ui.button>
<x-ui.button variant="link" shortcut="o">{{ __('Open original') }}</x-ui.button>
<x-ui.button variant="destructive" shortcut="#">{{ __('Delete') }}</x-ui.button>
<x-ui.button size="sm" variant="outline" shortcut="esc">{{ __('Close') }}</x-ui.button>
</div>
@php
// Icon-only sizes render an icon, never a text label — a glyph stays centred
// in the square while a word would overflow the small box.
$sizeIcon = <<<'SVG'
<svg class="size-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M12 5v14M5 12h14" />
</svg>
SVG;
@endphp
<div class="flex flex-col gap-4">
<div class="flex flex-wrap items-center gap-3">
<x-ui.button size="sm">{{ __('Small') }}</x-ui.button>
<x-ui.button size="md">{{ __('Medium') }}</x-ui.button>
<x-ui.button size="lg">{{ __('Large') }}</x-ui.button>
</div>
<div class="flex flex-wrap items-center gap-3">
<x-ui.button size="icon-sm" variant="outline" aria-label="{{ __('Add (small)') }}">{!! $sizeIcon !!}</x-ui.button>
<x-ui.button size="icon" variant="outline" aria-label="{{ __('Add') }}">{!! $sizeIcon !!}</x-ui.button>
<x-ui.button size="icon-lg" variant="outline" aria-label="{{ __('Add (large)') }}">{!! $sizeIcon !!}</x-ui.button>
</div>
</div>
<div class="flex flex-wrap items-center gap-3">
<x-ui.button variant="default">{{ __('Default') }}</x-ui.button>
<x-ui.button variant="secondary">{{ __('Secondary') }}</x-ui.button>
<x-ui.button variant="outline">{{ __('Outline') }}</x-ui.button>
<x-ui.button variant="ghost">{{ __('Ghost') }}</x-ui.button>
<x-ui.button variant="link">{{ __('Link') }}</x-ui.button>
<x-ui.button variant="destructive">{{ __('Destructive') }}</x-ui.button>
<x-ui.button :with-arrow="true">{{ __('With arrow') }}</x-ui.button>
</div>
API
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| variant | default | primary | destructive | danger | outline | secondary | ghost | link | default | Semantic emphasis or intent. Primary aliases default; danger aliases destructive. |
| size | sm | md | lg | icon | icon-sm | icon-lg | md | Control height and horizontal padding. |
| shape | default | pill | default | Legacy silhouette override. |
| type | button | submit | reset | button | Native button type when rendering a button element. |
| disabled | bool | false | Prevents interaction while preserving disabled semantics. |
| loading | bool | false | Disables interaction and exposes a busy loading state. |
| wireTarget | string | null | Livewire action or property to watch. While that request is in flight the control is disabled and a delayed status message is announced. |
| wireLoadingLabel | string | Working… | Screen-reader text announced while the wireTarget request is in flight. |
| withArrow | bool | false | Legacy animated-arrow shortcut. |
| arrowClass | string | Legacy classes for the shortcut arrow. | |
| href | string | null | null | Renders an anchor when navigation semantics are required. |
| as | button | a | null | null | Explicitly renders one of the supported native elements. |
| iconLabel | string | null | null | Enables icon-only mode, supplies the accessible name, and maps sm/md/lg to square icon sizes. |
| wrap | bool | false | Allows the label to wrap; labels truncate by default to protect constrained layouts. |
| shortcut | string | null | null | A keyboard shortcut hint such as "e", "shift+j", "ctrl+enter" or "mod+enter", drawn as kbd keys after the label on every variant and exposed as aria-keyshortcuts (Shift+J, Control+Enter). mod is the platform command key, as in the hotkeys store: ⌘ and Meta+Enter for a request from macOS or iOS (Sec-CH-UA-Platform, else the User-Agent), Ctrl and Control+Enter elsewhere; a page in a shared full-page cache must vary on the platform or name the key. The visible hint is hidden on a touch screen (pointer: coarse). A hint only: bind the key with x-hotkey or the hotkeys store. Icon-only buttons keep aria-keyshortcuts without the visible hint. |
Slots
default— Button label and inline content.iconLeading— Leading decorative icon.icon— Legacy alias for iconLeading.iconTrailing— Trailing decorative icon or affordance.
Renders as button, a.
Data slots
Stable hooks for CSS overrides and browser tests.
Behavior
- Native buttons activate with Enter and Space; link mode preserves anchor semantics.
- The loading state prevents repeat activation and announces busy state.
- Icon-only mode keeps its label in screen-reader text and treats the icon as decorative.
- Shortcut hint (shortcut="e"): the keys render after the label as decorative kbd elements (data-slot="button-shortcut") in the label colour with a faint current-colour edge, so they read on filled, outline, ghost, link and destructive buttons alike; the button gets aria-keyshortcuts with the ARIA key names. Modifiers ctrl, cmd/meta, alt/option and shift and the keys enter, esc, space, tab, backspace, delete and the arrows get their usual labels; other keys show upper-cased.
- Renders a native button by default and an anchor when href is provided.
- For disabled anchors, href is removed and aria-disabled/tabindex are applied.
- Declares registry capability flags: a11y, responsive, rtl, darkMode, localized.
Guidance
Commit an explicit user action.
Use when
- Use for explicit actions and commits; keep one action visually primary when several sit together.
- Triggering an immediate action such as saving, submitting, or opening a surface.
- Presenting a prominent call to action with a consistent variant and size.
Avoid when
- Do not use button treatment for navigation-only view changes when links, tabs, or radios describe state more clearly.
- Navigating to another URL without button semantics; render the component as a link or use a normal link.
- Representing a persistent on/off value; use switch or checkbox.
Use instead
- Link for navigation
- Tabs or radios for view changes
Anti-patterns
- Using a button for navigation-only state changes
- Presenting multiple equally dominant primary actions
- Anatomy
- Theming hooks
Accessibility
- Keyboard
- Enter Space
- Focus
native
- Use iconLabel for icon-only buttons so the accessible name cannot be omitted by accident.
- Use destructive only for actions with destructive consequences.
- Semantic HTML and a stable
data-slotattribute for styling and scripting hooks. - Focus-visible rings use the
ringtoken, so keyboard focus is always visible. - Disabled and invalid states are conveyed to assistive tech, not by color alone.
- Targets WCAG 2.2 AA; verify contrast in light, dark, admin and customer surfaces in the preview.
- Labels go through
__()and layout uses logical properties (ms-*,text-start), so it mirrors underdir="rtl"— flip the preview to RTL to confirm. - Dark mode uses the same semantic tokens under the
darkclass; high contrast follows forced-color system tokens.
Livewire
Livewire can update this component through forwarded wire:* attributes.
Source
The exact, editable file ui:add writes
into your app. Previews render this same code; there are no preview-only components.
@props([
'variant' => 'default',
'size' => 'md',
'shape' => 'default',
'type' => 'button',
'disabled' => false,
'loading' => false,
// Optional Livewire action/property target. When present, Livewire disables
// the control during the matching request and exposes a delayed spinner.
'wireTarget' => null,
'wireLoadingLabel' => 'Working…',
'withArrow' => false,
'arrowClass' => '',
'href' => null,
'as' => null,
// Accessible icon-only mode. A non-empty label supplies the screen-reader
// name and maps the normal size vocabulary onto the matching square size.
'iconLabel' => null,
// Buttons are single-line and overflow-safe by default. Opt into wrapping
// for prose-like actions whose full label must remain visible.
'wrap' => false,
// A keyboard shortcut hint such as "e", "shift+j" or "mod+enter": drawn
// as <kbd> keys after the label on every variant and exposed as
// aria-keyshortcuts. `mod` is the platform's command key, as in the
// hotkeys store: ⌘ (Meta) for a request from macOS or iOS, else Ctrl
// (Control). It is a hint only; bind the key with x-hotkey or the hotkeys
// store. Icon-only buttons keep the attribute without the visible hint,
// and the hint is hidden on a touch screen (pointer: coarse).
'shortcut' => null,
])
@php
$styles = require base_path(config('ui.component_path', 'resources/views/components/ui').'/_styles.php');
$variant = $styles['normalizeVariant']($variant);
$button = $styles['button'];
$variantAliases = ['primary' => 'default', 'danger' => 'destructive'];
$resolvedVariant = $variantAliases[$variant] ?? $variant;
$isIconOnly = filled($iconLabel);
$iconSizeAliases = ['sm' => 'icon-sm', 'md' => 'icon', 'lg' => 'icon-lg'];
$resolvedSize = $isIconOnly ? ($iconSizeAliases[$size] ?? $size) : $size;
// The link variant is text-only: drop the fixed control height/padding so it
// sits inline like an anchor while still honouring the sm/lg type scale.
$sizeClass = $resolvedVariant === 'link'
? ($button['linkSizes'][$resolvedSize] ?? $button['linkSizes']['md'])
: ($button['sizes'][$resolvedSize] ?? $button['sizes']['md']);
// Shape overrides only the corner radius. The base radius is removed rather
// than out-competed: Tailwind orders `rounded-full` before `rounded-md`, so
// appending the pill class alone would leave the base rounding in charge.
$shapeClass = $shape === 'pill' ? ($button['shapes']['pill'] ?? '') : '';
$baseClass = $shapeClass === ''
? $button['base']
: trim((string) preg_replace('/(?<!\S)rounded(?:-(?:none|xs|sm|md|lg|xl|\dxl|full))?(?!\S)/', '', $button['base']));
$classes = trim($baseClass.' '.($button['variants'][$resolvedVariant] ?? $button['variants']['default']).' '.$sizeClass.' '.$shapeClass);
$isDisabled = $disabled || $loading;
$shortcutKeys = [];
$shortcutAria = null;
if (filled($shortcut)) {
$keyNames = [
'ctrl' => ['Ctrl', 'Control'], 'control' => ['Ctrl', 'Control'], 'cmd' => ['⌘', 'Meta'], 'meta' => ['⌘', 'Meta'],
'alt' => ['Alt', 'Alt'], 'option' => ['⌥', 'Alt'], 'shift' => ['Shift', 'Shift'], 'enter' => ['Enter', 'Enter'],
'escape' => ['Esc', 'Escape'], 'esc' => ['Esc', 'Escape'], 'space' => ['Space', 'Space'], 'tab' => ['Tab', 'Tab'],
'backspace' => ['Backspace', 'Backspace'], 'delete' => ['Delete', 'Delete'],
'up' => ['↑', 'ArrowUp'], 'down' => ['↓', 'ArrowDown'], 'left' => ['←', 'ArrowLeft'], 'right' => ['→', 'ArrowRight'],
];
$shortcutParts = array_filter(explode('+', trim((string) $shortcut)), 'strlen');
if (in_array('mod', array_map('mb_strtolower', $shortcutParts), true)) {
// The server picks the label for `mod`: Sec-CH-UA-Platform first
// (Chromium), then the User-Agent (Safari and Firefox). A page in a
// shared full-page cache must vary on it, or name the key itself.
$platformHint = trim((string) request()->header('Sec-CH-UA-Platform'), "\" ");
$isApplePlatform = $platformHint !== ''
? in_array(mb_strtolower($platformHint), ['macos', 'ios'], true)
: preg_match('/Macintosh|Mac OS X|iPhone|iPad|iPod/i', (string) request()->userAgent()) === 1;
$keyNames['mod'] = $isApplePlatform ? ['⌘', 'Meta'] : ['Ctrl', 'Control'];
}
$ariaParts = [];
foreach ($shortcutParts as $part) {
[$label, $aria] = $keyNames[mb_strtolower($part)] ?? [mb_strtoupper($part), mb_strtoupper($part)];
$shortcutKeys[] = $label;
$ariaParts[] = $aria;
}
$shortcutAria = $ariaParts === [] ? null : implode('+', $ariaParts);
}
$allowedTags = ['button', 'a'];
$tag = $as !== null && in_array($as, $allowedTags, true)
? $as
: ($href !== null ? 'a' : 'button');
@endphp
<{{ $tag }}
@if ($tag === 'button')
type="{{ $type }}"
@disabled($isDisabled)
@else
href="{{ $isDisabled ? null : $href }}"
@if ($isDisabled) aria-disabled="true" tabindex="-1" @endif
@endif
@if ($loading) aria-busy="true" @endif
@if (filled($wireTarget))
wire:target="{{ $wireTarget }}"
@if ($tag === 'button')
wire:loading.attr="disabled"
@else
wire:loading.attr="aria-disabled"
wire:loading.class="pointer-events-none"
@endif
@endif
@if ($shortcutAria) aria-keyshortcuts="{{ $shortcutAria }}" @endif
data-slot="button"
data-variant="{{ $resolvedVariant }}"
data-size="{{ $resolvedSize }}"
@if ($isIconOnly) data-icon-only="true" @endif
{{ $attributes->merge(['class' => $classes]) }}
>
@if ($loading)
<svg class="size-4 shrink-0 animate-spin motion-reduce:animate-none" viewBox="0 0 24 24" fill="none" aria-hidden="true">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v4a4 4 0 00-4 4H4z"></path>
</svg>
@else
@if (filled($wireTarget))
<svg
wire:loading.delay.shorter
wire:target="{{ $wireTarget }}"
class="size-4 shrink-0 animate-spin motion-reduce:animate-none"
viewBox="0 0 24 24"
fill="none"
aria-hidden="true"
>
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v4a4 4 0 00-4 4H4z"></path>
</svg>
@endif
@if (isset($iconLeading) || isset($icon))
<span
class="contents shrink-0"
data-slot="button-icon-leading"
aria-hidden="true"
@if (filled($wireTarget)) wire:loading.remove wire:target="{{ $wireTarget }}" @endif
>{{ $iconLeading ?? $icon }}</span>
@elseif ($isIconOnly)
<span
class="contents shrink-0"
data-slot="button-icon-leading"
aria-hidden="true"
@if (filled($wireTarget)) wire:loading.remove wire:target="{{ $wireTarget }}" @endif
>{{ $slot }}</span>
@endif
@endif
@if ($isIconOnly)
<span data-slot="button-label" class="sr-only">{{ __($iconLabel) }}</span>
@else
<span
data-slot="button-label"
@if (filled($wireTarget)) wire:loading.remove wire:target="{{ $wireTarget }}" @endif
{{-- An <svg> written straight into the slot (instead of the icon slot)
is block-level under Preflight and would wrap onto its own line:
keep it inline, sized and vertically centred beside the text.
:where() keeps these defaults at zero specificity, so an svg's
own size class (an icon tile's size-5) still wins. --}}
@class([
'min-w-0 [:where(&)_svg]:inline-block [:where(&)_svg]:size-4 [:where(&)_svg]:shrink-0 [:where(&)_svg]:align-[-0.125em]',
'whitespace-normal break-words text-wrap' => $wrap,
'truncate' => ! $wrap,
])
>{{ $slot }}</span>
@if (filled($wireTarget))
<span
data-slot="button-loading-label"
wire:loading
wire:target="{{ $wireTarget }}"
class="min-w-0 truncate"
role="status"
>{{ __($wireLoadingLabel) }}</span>
@endif
@endif
@if (filled($wireTarget) && $isIconOnly)
<span wire:loading.delay.shorter wire:target="{{ $wireTarget }}" class="sr-only" role="status">
{{ __($wireLoadingLabel) }}
</span>
@endif
@if ($shortcutKeys !== [] && ! $isIconOnly)
<span
data-slot="button-shortcut"
dir="ltr"
aria-hidden="true"
class="{{ $button['shortcut'] ?? 'inline-flex shrink-0 items-center gap-1 pointer-coarse:hidden' }}"
@if (filled($wireTarget)) wire:loading.remove wire:target="{{ $wireTarget }}" @endif
>@foreach ($shortcutKeys as $key)<kbd class="{{ $button['shortcutKey'] ?? 'inline-flex h-5 min-w-5 items-center justify-center rounded-sm border border-current/25 px-1 font-body text-xs font-medium leading-none' }}">{{ $key }}</kbd>@endforeach</span>
@endif
@isset($iconTrailing)
<span
class="contents shrink-0"
data-slot="button-icon-trailing"
aria-hidden="true"
@if (filled($wireTarget)) wire:loading.remove wire:target="{{ $wireTarget }}" @endif
>{{ $iconTrailing }}</span>
@endisset
@if ($withArrow)
<svg
class="{{ $button['arrow'] }} {{ $arrowClass }}"
@if (filled($wireTarget)) wire:loading.remove wire:target="{{ $wireTarget }}" @endif
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>
@endif
</{{ $tag }}>
Ownership & lifecycle
Owner, release state, review evidence and adoption for this item.
- Owner
- Platform UI (@JoshJML)
- Current version
-
1.10.1 - Status
- Stable
- License
-
open - Accessibility reviewed
- No review date recorded
- Last breaking change
- No date recorded
- Deprecation
- Not deprecated
- Contract
-
v6 - Foundation
-
≥ 1.0.0
Migration history
-
1.7.1 → 1.8.0— Replace legacy button shape and arrow shortcuts with consumer classes and the iconTrailing slot.