Saved Views
A named view switcher with a menu mode for many views and a tab-strip mode for few, distinguishing system, owned, and shared views.
Preview
<x-ui.saved-views
:views="[
['key' => 'all', 'label' => __('All orders'), 'href' => '?view=all', 'active' => true, 'system' => true],
['key' => 'unpaid', 'label' => __('Awaiting payment'), 'href' => '?view=unpaid', 'count' => 12, 'tone' => 'attention', 'system' => true],
['key' => 'shipped', 'label' => __('Shipped'), 'href' => '?view=shipped', 'count' => 48, 'system' => true],
[
'key' => 'my-wholesale',
'label' => __('Wholesale, this week'),
'href' => '?view=my-wholesale',
'owned' => true,
'renameUrl' => '#',
'deleteUrl' => '#',
],
[
'key' => 'team-backorders',
'label' => __('Team backorders'),
'href' => '?view=team-backorders',
'owned' => false,
'shared' => true,
'owner' => 'Priya',
],
]"
save-url="#"
/>
Installation
php artisan ui:add saved-views
Note
This component ships an Alpine behavior module at
resources/js/ui/saved-views.js. Import it once from your bundle so it registers on alpine:init:
import './saved-views.js';
Registry contract
php artisan ui:add saved-views
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/saved-views.blade.php
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: Saved Views (`saved-views`)
A named view switcher with a menu mode for many views and a tab-strip mode for few, distinguishing system, owned, and shared views.
Brok UI is a Laravel Blade component registry. Installed components are plain Blade files the app owns.
## Install
```bash
php artisan ui:add saved-views
```
## Usage
```blade
<x-ui.saved-views
:views="[
['key' => 'all', 'label' => __('All orders'), 'href' => '?view=all', 'active' => true, 'system' => true],
['key' => 'unpaid', 'label' => __('Awaiting payment'), 'href' => '?view=unpaid', 'count' => 12, 'tone' => 'attention', 'system' => true],
['key' => 'shipped', 'label' => __('Shipped'), 'href' => '?view=shipped', 'count' => 48, 'system' => true],
[
'key' => 'my-wholesale',
'label' => __('Wholesale, this week'),
'href' => '?view=my-wholesale',
'owned' => true,
'renameUrl' => '#',
'deleteUrl' => '#',
],
[
'key' => 'team-backorders',
'label' => __('Team backorders'),
'href' => '?view=team-backorders',
'owned' => false,
'shared' => true,
'owner' => 'Priya',
],
]"
save-url="#"
/>
```
## Props
- `views` (array, default `[]`) — Views to render: each entry is ['key','label','href','event','payload','count','tone','active','system','owned','shared','owner','renameUrl','deleteUrl']. href must carry the view's full state (filters, sort, tab); pass event (+ optional payload) instead to dispatch rather than navigate, for a list that owns its own state. An entry with neither is inert. Renaming, deleting and saving stay server-only (renameUrl/deleteUrl/saveUrl).
- `mode` (menu|tabs, default `menu`) — menu opens a dropdown split into Standard/Saved sections with rename, delete, and save-current; tabs renders a flat, always-visible strip with no editing.
- `heading` (string|null, default `null`) — Accessible name for the switcher. Defaults to a localized "Views".
- `saveUrl` (string|null, default `null`) — POST target that saves the list's current state as a new view. The save-current form is hidden without it.
- `saveLabel` (string|null, default `null`) — Label for the save-current submit button. Defaults to a localized "Save view".
- `anchored` (bool, default `true`) — Forwards to the menu-mode dropdown's anchored/teleported placement so a clipping toolbar ancestor never cuts the panel off.
## Use when
- Use to orient users and help them move across pages, sections, or commands.
- A list's filters, sort, and tab together form named, revisitable states worth switching between.
- The list has enough saved/system views that a fixed tab strip would wrap or crowd the toolbar (use mode="menu"); a handful of system views fit as a strip instead (mode="tabs").
## Avoid when
- Do not hide primary wayfinding in novelty interactions or deep nested structures if straightforward navigation would be clearer.
- There is only one way to look at the list — a saved-views switcher with a single entry is a control with nothing to switch to.
- Picking or editing filter VALUES — use <x-ui.filters>; this switches between whole saved combinations.
## Anti-patterns
- Hiding primary wayfinding in novelty interactions
## Rules
- Use the `<brok:saved-views>` tag (or `<x-ui.saved-views>`) 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/saved-views
- Registry JSON (files, props, contract): https://brokui.dev/r/open/saved-views.json
Working in Claude Code, Cursor or Codex? Give the agent the whole registry through the MCP server or the Brok UI skill.
Examples
{{-- Each view decides for itself: a system view can still navigate while a
personal view (in a list that owns its own state) dispatches instead —
mixed in the same menu. Rename/delete/save stay server-only. --}}
<div
x-data="{ last: null }"
x-on:orders:select-view="last = JSON.stringify($event.detail)"
class="flex flex-col gap-3"
>
<x-ui.saved-views
:views="[
['key' => 'all', 'label' => __('All orders'), 'count' => 128, 'system' => true, 'active' => true, 'href' => '?view=all'],
['key' => 'unpaid', 'label' => __('Awaiting payment'), 'count' => 12, 'tone' => 'attention', 'system' => true, 'href' => '?view=unpaid'],
[
'key' => 'mine',
'label' => __('My queue'),
'owned' => true,
'event' => 'orders:select-view',
'payload' => ['key' => 'mine'],
],
]"
/>
<p class="text-xs text-muted-foreground">
{{ __('Host received:') }}
<span data-slot="preview-event-log" class="font-mono text-foreground" x-text="last ?? '—'"></span>
</p>
</div>
Long Content
<div class="max-w-xs">
<x-ui.saved-views
:views="[
[
'key' => 'my-view',
'label' => __('A deliberately long saved-view name that verifies truncation instead of layout overflow'),
'href' => '?view=my-view',
'active' => true,
'owned' => true,
'renameUrl' => '#',
'deleteUrl' => '#',
],
['key' => 'all', 'label' => __('All records'), 'href' => '?view=all', 'system' => true],
]"
save-url="#"
/>
</div>
API
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| views | array | [] | Views to render: each entry is ['key','label','href','event','payload','count','tone','active','system','owned','shared','owner','renameUrl','deleteUrl']. href must carry the view's full state (filters, sort, tab); pass event (+ optional payload) instead to dispatch rather than navigate, for a list that owns its own state. An entry with neither is inert. Renaming, deleting and saving stay server-only (renameUrl/deleteUrl/saveUrl). |
| mode | menu | tabs | menu | menu opens a dropdown split into Standard/Saved sections with rename, delete, and save-current; tabs renders a flat, always-visible strip with no editing. |
| heading | string | null | null | Accessible name for the switcher. Defaults to a localized "Views". |
| saveUrl | string | null | null | POST target that saves the list's current state as a new view. The save-current form is hidden without it. |
| saveLabel | string | null | null | Label for the save-current submit button. Defaults to a localized "Save view". |
| anchored | bool | true | Forwards to the menu-mode dropdown's anchored/teleported placement so a clipping toolbar ancestor never cuts the panel off. |
Slots
Default Blade slot only.
Data slots
Stable hooks for CSS overrides and browser tests.
Behavior
- Each view decides for itself: href renders a plain link, so applying it survives a middle-click, a shared address, and a page with no JavaScript; event dispatches instead (payload defaults to the whole entry) for a list that owns its own state; neither renders the view inert (listed, not switchable).
- Rename and delete post real forms to each view's own renameUrl/deleteUrl; there is no client-side persistence for either, or for save.
- Rename and delete are only offered on a view whose owned field is not false; system views are fixed.
- In tabs mode there is no rename, delete, or save-current — that mode is for a handful of fixed views only.
- A dispatched event fires from the component's own root (found by id), not from the click site, so it still reaches a host listener when menu mode teleports its content to <body>.
- Installs a JavaScript behavior module when the registry item includes resources/js/ui files.
- Declares registry capability flags: a11y, interactive, authoredStateFixtures, responsive, rtl, darkMode, localized.
Guidance
Orient users and move between destinations.
Use when
- Use to orient users and help them move across pages, sections, or commands.
- A list's filters, sort, and tab together form named, revisitable states worth switching between.
- The list has enough saved/system views that a fixed tab strip would wrap or crowd the toolbar (use mode="menu"); a handful of system views fit as a strip instead (mode="tabs").
Avoid when
- Do not hide primary wayfinding in novelty interactions or deep nested structures if straightforward navigation would be clearer.
- There is only one way to look at the list — a saved-views switcher with a single entry is a control with nothing to switch to.
- Picking or editing filter VALUES — use <x-ui.filters>; this switches between whole saved combinations.
Use instead
- Visible links and local navigation
Anti-patterns
- Hiding primary wayfinding in novelty interactions
- Anatomy
- Theming hooks
Accessibility
- Keyboard
- Escape
- Focus
managed
- Meet the WCAG 2.2 AA target declared in meta.a11y.
- The active tab exposes aria-current="page"; the menu trigger names the current view rather than a bare chevron.
- 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
Add a stable wire:key when Livewire can reorder this interactive component.
<div wire:key="saved-views-{{ $record->id }}">
<x-ui.saved-views
:views="[
['key' => 'all', 'label' => __('All orders'), 'href' => '?view=all', 'active' => true, 'system' => true],
['key' => 'unpaid', 'label' => __('Awaiting payment'), 'href' => '?view=unpaid', 'count' => 12, 'tone' => 'attention', 'system' => true],
['key' => 'shipped', 'label' => __('Shipped'), 'href' => '?view=shipped', 'count' => 48, 'system' => true],
[
'key' => 'my-wholesale',
'label' => __('Wholesale, this week'),
'href' => '?view=my-wholesale',
'owned' => true,
'renameUrl' => '#',
'deleteUrl' => '#',
],
[
'key' => 'team-backorders',
'label' => __('Team backorders'),
'href' => '?view=team-backorders',
'owned' => false,
'shared' => true,
'owner' => 'Priya',
],
]"
save-url="#"
/>
</div>
Source
The exact, editable file ui:add writes
into your app. Previews render this same code; there are no preview-only components.
{{--
Saved Views — a named view switcher over a list's own state.
A view is a bookmark for everything the URL would restore: filters, sort,
tab. Storing only a label would make it a bookmark that lies about where
it goes, so `views[].href` is expected to carry the full query state — or,
for a list that owns its own state, `views[].event` (+ optional
`payload`) dispatches instead of navigating. Each view decides for
itself, so a menu may legitimately mix system views that navigate with a
personal view that doesn't. A view with neither is inert: listed, but not
a thing you can switch to.
Two modes for two shapes of the same idea:
`menu` — a trigger naming the current view, opening a menu split into
system-shipped "Standard" views (fixed, uncounted-editable)
and personal/shared "Saved" views (rename, delete, save
current). Use this once there are enough views that a fixed
strip would wrap or force the operator to hunt.
`tabs` — a flat, always-visible strip of links (no rename/delete/save):
the right shape for a handful of system views, one always
active.
Names are never truncated: the point of naming a view is defeated by
cutting the name to fit the control, so the menu is sized for names
rather than names cut to fit the menu.
A view's `owned`/`shared`/`owner` fields distinguish a personal view (which
only its owner can rename/delete) from one shared by a colleague (whose
byline says so, because changing it affects them too) from a system view
(fixed, carries a live `count`). Renaming, deleting and saving stay
server-only (`renameUrl`/`deleteUrl`/`saveUrl`) — only *switching* views
gained a client-dispatch alternative; a list that needs the edit
affordances too still wires them to real endpoints.
A dispatched event fires from this component's own root, not from
`$el` at the click site: menu mode's content panel teleports to <body>
(`anchored`, see dropdown's own docs), so a plain `$dispatch` from inside
it would bubble through <body> and never reach a host listening around
where this component was placed. Firing from the root — found by `id`,
real or generated — reaches that host in both modes identically.
Generalised from `orders/saved-views.blade.php` and `files/views.blade.php`
(~19 admin modules use one of the two shapes). Renaming/deleting/saving
post real forms to per-view `renameUrl`/`deleteUrl` and the top-level
`saveUrl` — no fetch layer is assumed, so this works identically under
Livewire or a plain controller. The client's own `v2-orders-saved-views.js`
anchor math is replaced by dropdown's built-in `anchored` teleport mode.
--}}
@props([
// [['key','label','href','event'=>null,'payload'=>null,'count'=>null,
// 'tone'=>null,'active'=>false,'system'=>false,'owned'=>true,
// 'shared'=>false,'owner'=>null,'renameUrl'=>null,'deleteUrl'=>null]]
// href XOR event pick how switching to that view behaves; neither makes
// it inert. event's payload defaults to the whole view entry.
'views' => [],
// menu (default, for many views) | tabs (a flat strip, for few).
'mode' => 'menu',
'heading' => null,
// POST target that saves the list's current state as a new view.
'saveUrl' => null,
'saveLabel' => null,
'anchored' => true,
])
@php
$views = array_values(array_filter((array) $views, 'is_array'));
$mode = in_array($mode, ['menu', 'tabs'], true) ? $mode : 'menu';
$heading ??= __('Views');
$saveLabel ??= __('Save view');
$current = collect($views)->firstWhere('active', true);
$standard = array_values(array_filter($views, static fn (array $v): bool => (bool) ($v['system'] ?? false)));
$saved = array_values(array_filter($views, static fn (array $v): bool => ! ($v['system'] ?? false)));
// A stable id to dispatch from (see the header note on teleported
// content) — the caller's own id when given, so two instances never
// collide, otherwise one generated once per render.
$instanceId = (string) ($attributes->get('id') ?: 'saved-views-'.\Illuminate\Support\Str::random(8));
// The payload is encoded with Js::from, never string-interpolated.
$dispatchExpr = static function (string $event, $payload) use ($instanceId): string {
return 'document.getElementById('.\Illuminate\Support\Js::from($instanceId).')'
.'?.dispatchEvent(new CustomEvent('.\Illuminate\Support\Js::from($event).', '
.'{ detail: '.\Illuminate\Support\Js::from($payload).', bubbles: true }))';
};
// Precomputed per view, because Blade's component-tag parser reads a tag
// with a regex: a directive written between its attributes is not seen,
// so each mode has to arrive as a bound attribute that is null when
// unused — a null-valued bound attribute is dropped from the tag rather
// than rendered empty.
$viewTag = static fn (array $view): string => match (true) {
! empty($view['href']) => 'a',
! empty($view['event']) => 'button',
default => 'span',
};
$viewHref = static fn (array $view): ?string => $view['href'] ?? null;
$viewHandler = static fn (array $view): ?string => (empty($view['href']) && ! empty($view['event']))
? $dispatchExpr((string) $view['event'], $view['payload'] ?? $view)
: null;
// menu mode already gets an Alpine root from <x-ui.dropdown>; tabs mode
// does not, so it only grows one (and the id it dispatches from) when a
// view actually needs to dispatch.
$needsDispatch = collect($views)->contains(
static fn (array $view): bool => empty($view['href']) && ! empty($view['event'])
);
// Icon-button recipe shared by the row actions (rename, delete, save, cancel).
$actionClass = 'inline-flex size-7 shrink-0 items-center justify-center rounded-sm text-muted-foreground transition-colors hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-[length:var(--ring-width)] focus-visible:ring-ring motion-reduce:transition-none';
$countTone = static function (array $view): string {
$count = $view['count'] ?? null;
return ($view['tone'] ?? null) === 'attention' && (int) $count > 0 ? 'soft-warning' : 'soft-neutral';
};
@endphp
@if ($mode === 'tabs')
<nav
data-slot="saved-views"
aria-label="{{ $heading }}"
@if ($needsDispatch) x-data="{}" @endif
{{ $attributes->merge(array_filter(['class' => 'flex flex-wrap items-center gap-2', 'id' => $needsDispatch ? $instanceId : null])) }}
>
@foreach ($views as $view)
@php $active = (bool) ($view['active'] ?? false); @endphp
<{{ $viewTag($view) }}
@if ($viewHref($view))
href="{{ $viewHref($view) }}"
@elseif ($viewHandler($view))
type="button"
x-on:click="{{ $viewHandler($view) }}"
@else
aria-disabled="true"
tabindex="-1"
@endif
@if ($active) aria-current="page" @endif
@class([
'inline-flex h-9 items-center gap-2 rounded-md px-2 text-sm transition-colors focus-visible:outline-none focus-visible:ring-[length:var(--ring-width)] focus-visible:ring-ring',
'bg-secondary font-medium text-foreground' => $active,
'text-muted-foreground hover:bg-secondary/60 hover:text-foreground' => ! $active,
])
>
<span class="min-w-0 truncate">{{ $view['label'] ?? '' }}</span>
@if (($view['count'] ?? null) !== null)
<x-ui.badge :variant="$countTone($view)" size="sm" class="tabular-nums">
{{ $view['count'] }}
</x-ui.badge>
@endif
</{{ $viewTag($view) }}>
@endforeach
</nav>
@else
<x-ui.dropdown data-slot="saved-views" :id="$needsDispatch ? $instanceId : null" :anchored="$anchored" {{ $attributes->except('data-slot') }}>
<x-ui.dropdown.trigger class="inline-flex h-9 max-w-[19rem] items-center gap-2 rounded-md border border-border px-2 text-sm transition-colors hover:bg-secondary focus-visible:outline-none focus-visible:ring-[length:var(--ring-width)] focus-visible:ring-ring">
<span class="min-w-0 truncate font-medium">{{ $current['label'] ?? __('All') }}</span>
@if (($current['count'] ?? null) !== null)
<x-ui.badge :variant="$countTone($current)" size="sm" class="shrink-0 tabular-nums">
{{ $current['count'] }}
</x-ui.badge>
@endif
<svg aria-hidden="true" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.75" class="size-3 shrink-0 text-muted-foreground">
<path d="m4 6 4 4 4-4" stroke-linecap="round" stroke-linejoin="round" />
</svg>
</x-ui.dropdown.trigger>
<x-ui.dropdown.content align="start" class="w-96">
@if ($standard !== [])
<x-ui.dropdown.label>{{ __('Standard') }}</x-ui.dropdown.label>
<x-ui.dropdown.group>
@foreach ($standard as $view)
<x-ui.dropdown.item :href="$viewHref($view)" :x-on:click="$viewHandler($view)">
<span class="min-w-0 flex-1 truncate">{{ $view['label'] ?? '' }}</span>
@if (($view['count'] ?? null) !== null)
<x-ui.badge :variant="$countTone($view)" size="sm" class="tabular-nums">
{{ $view['count'] }}
</x-ui.badge>
@endif
</x-ui.dropdown.item>
@endforeach
</x-ui.dropdown.group>
@endif
@if ($saved !== [])
@if ($standard !== [])
<x-ui.dropdown.separator />
@endif
<x-ui.dropdown.label>{{ __('Saved') }}</x-ui.dropdown.label>
<x-ui.dropdown.group>
@foreach ($saved as $view)
@php $owned = (bool) ($view['owned'] ?? true); @endphp
<div
x-data="{ editing: false, draft: {{ Illuminate\Support\Js::from($view['label'] ?? '') }} }"
data-slot="saved-views-item"
class="group/view flex min-h-9 items-center gap-2 rounded-sm px-2 py-1 hover:bg-accent"
>
<template x-if="!editing">
<{{ $viewTag($view) }}
@if ($viewHref($view))
href="{{ $viewHref($view) }}"
@elseif ($viewHandler($view))
type="button"
x-on:click="{{ $viewHandler($view) }}"
@else
aria-disabled="true"
tabindex="-1"
@endif
role="menuitem"
class="min-w-0 flex-1 text-start text-sm text-popover-foreground outline-none"
>
<span class="block truncate">{{ $view['label'] ?? '' }}</span>
@if (! empty($view['shared']) && ! empty($view['owner']))
<span class="mt-0.5 block truncate text-xs text-muted-foreground">
{{ __('Shared by :owner', ['owner' => $view['owner']]) }}
</span>
@endif
</{{ $viewTag($view) }}>
</template>
@if ($owned && ! empty($view['renameUrl']))
<template x-if="editing">
<form method="POST" action="{{ $view['renameUrl'] }}" class="flex min-w-0 flex-1 items-center gap-1">
@csrf
<input
type="text"
name="label"
x-model="draft"
x-on:keydown.escape="editing = false"
aria-label="{{ __('Rename :label', ['label' => $view['label'] ?? '']) }}"
class="me-1 h-8 w-full min-w-0 rounded-md border border-input bg-background px-2 text-sm focus-visible:outline-none focus-visible:ring-[length:var(--ring-width)] focus-visible:ring-ring"
/>
<button type="submit" aria-label="{{ __('Save name') }}" title="{{ __('Save') }}" class="{{ $actionClass }} text-foreground">
<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="m5 12 5 5L20 7" /></svg>
</button>
<button type="button" x-on:click="editing = false" aria-label="{{ __('Cancel') }}" title="{{ __('Cancel') }}" class="{{ $actionClass }}">
<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="M18 6 6 18M6 6l12 12" /></svg>
</button>
</form>
</template>
@endif
@if ($owned)
{{-- Row actions: icon buttons that surface on hover/focus (always on touch). --}}
<div class="flex shrink-0 items-center gap-1 opacity-0 transition-opacity group-hover/view:opacity-100 group-focus-within/view:opacity-100 [@media(hover:none)]:opacity-100 motion-reduce:transition-none" x-show="!editing">
@if (! empty($view['renameUrl']))
<button type="button" x-on:click.stop="editing = true; $nextTick(() => $root.querySelector('input[name=label]')?.select())" aria-label="{{ __('Rename :label', ['label' => $view['label'] ?? '']) }}" title="{{ __('Rename') }}" class="{{ $actionClass }}">
<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 20h9" /><path d="M16.5 3.5a2.1 2.1 0 0 1 3 3L7 19l-4 1 1-4Z" /></svg>
</button>
@endif
@if (! empty($view['deleteUrl']))
<form method="POST" action="{{ $view['deleteUrl'] }}" class="contents">
@csrf
@method('DELETE')
<button type="submit" aria-label="{{ __('Delete :label', ['label' => $view['label'] ?? '']) }}" title="{{ __('Delete') }}" class="{{ $actionClass }} hover:text-destructive-text">
<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="M3 6h18" /><path d="M8 6V4h8v2" /><path d="M19 6l-1 14H6L5 6" /><path d="M10 11v6M14 11v6" /></svg>
</button>
</form>
@endif
</div>
@endif
</div>
@endforeach
</x-ui.dropdown.group>
@endif
@if ($saveUrl)
<x-ui.dropdown.separator />
<form method="POST" action="{{ $saveUrl }}" class="p-2">
@csrf
<label for="saved-views-new-name" class="block text-xs text-muted-foreground">
{{ __('Save current as a view') }}
</label>
<div class="mt-2 flex items-center gap-2">
<input
id="saved-views-new-name"
type="text"
name="label"
required
placeholder="{{ __('View name') }}"
class="h-9 w-full min-w-0 rounded-md border border-input bg-background px-2 text-sm focus-visible:outline-none focus-visible:ring-[length:var(--ring-width)] focus-visible:ring-ring"
/>
<x-ui.button type="submit" size="sm" class="shrink-0">{{ $saveLabel }}</x-ui.button>
</div>
</form>
@endif
</x-ui.dropdown.content>
</x-ui.dropdown>
@endif
Ownership & lifecycle
Owner, release state, review evidence and adoption for this item.
- Owner
- Platform UI (@JoshJML)
- Current version
-
1.2.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