Walk a chip set with the arrow keys

M3's chip keyboard table makes a set one tab stop that the arrows move
through; ten filter chips cost ten Tab presses today. The set now keeps a
roving tabindex — re-applied whenever a Livewire morph rewrites the chips
— and walks left, right, Home and End, following the writing direction.
The input chip's remove button also grows to a full 48x48 target, where
it was 34px wide.

Plan step 20, findings IN-13 and IN-14.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
This commit is contained in:
Andreas Reinhold / reini
2026-09-14 06:05:41 +02:00
co-authored by Claude Fable 5.1
parent 47ed4603d0
commit dd3d8afdb9
5 changed files with 100 additions and 14 deletions
@@ -11,7 +11,11 @@
`scroll` keeps the chips on one line that scrolls sideways, as M3 lays chips out on a narrow
screen: the edge it can still scroll towards fades (resources/js/chips.js), and a chip reached
with Tab scrolls clear of the fade. Removing a focused input chip moves focus within the set. --}}
with Tab scrolls clear of the fade. Removing a focused input chip moves focus within the set.
The set is one tab stop and the arrow keys move between the chips inside it, with Home and End
at the ends M3's chip keyboard table. Backspace and Delete still remove a focused input
chip. --}}
@props([
'label' => null,
@@ -42,13 +46,15 @@
<div
data-chip-set
x-data="materialChipSet"
x-on:keydown="key($event)"
x-on:focusin="rove($event.target)"
wire:ignore.self
class="-mx-1.5 -my-2 flex scroll-px-6 gap-2 overflow-x-auto px-1.5 py-2 [scrollbar-width:none] [--chip-fade-end:0px] [--chip-fade-start:0px] data-scroll-end:[--chip-fade-end:1.5rem] data-scroll-start:[--chip-fade-start:1.5rem] [mask-image:linear-gradient(to_right,transparent,#000_var(--chip-fade-start),#000_calc(100%_-_var(--chip-fade-end)),transparent)] rtl:[mask-image:linear-gradient(to_left,transparent,#000_var(--chip-fade-start),#000_calc(100%_-_var(--chip-fade-end)),transparent)]"
>
{{ $slot }}
</div>
@else
<div data-chip-set class="flex flex-wrap gap-2">
<div data-chip-set x-data="materialChipSet" x-on:keydown="key($event)" x-on:focusin="rove($event.target)" class="flex flex-wrap gap-2">
{{ $slot }}
</div>
@endif