diff --git a/resources/boost/guidelines/core.blade.php b/resources/boost/guidelines/core.blade.php
index 35207f5..299e903 100644
--- a/resources/boost/guidelines/core.blade.php
+++ b/resources/boost/guidelines/core.blade.php
@@ -188,7 +188,7 @@
- Use `a11y-hint` sparingly, for supplementary guidance the label doesn't
cover ("Double-tap to reorder"). Never repeat the label in the hint.
- List items with a trailing icon button take `trailing-a11y-label` to label
- that button separately from the row.
+ that button separately from the row, and `on-trailing-press` for its handler.
- Text scales with the user's system font size on both platforms
automatically — don't hardcode layouts that break at larger type sizes.
@@ -197,6 +197,7 @@
+
@endverbatim
diff --git a/src/Elements/ListItem.php b/src/Elements/ListItem.php
index e4bb74d..d5b2ace 100644
--- a/src/Elements/ListItem.php
+++ b/src/Elements/ListItem.php
@@ -200,6 +200,12 @@ public function applyAttributes(array $attrs): void
$this->onTrailingChange($attrs['on-trailing-change'] ?? $attrs['onTrailingChange']);
}
+ // Trailing icon button press, same spellings as the change
+ // callbacks above.
+ if (isset($attrs['on-trailing-press']) || isset($attrs['onTrailingPress'])) {
+ $this->onTrailingPress($attrs['on-trailing-press'] ?? $attrs['onTrailingPress']);
+ }
+
// Swipe actions — new structured multi-action API. Each entry
// is `['method' => …, 'label' => …, 'icon' => …, 'tint' => …,
// 'role' => …]`. Both arrays support 1+ actions.
diff --git a/tests/ListItemTrailingPressTest.php b/tests/ListItemTrailingPressTest.php
new file mode 100644
index 0000000..8330f52
--- /dev/null
+++ b/tests/ListItemTrailingPressTest.php
@@ -0,0 +1,75 @@
+ 'Buy milk', 'trailingIconButton' => 'trash'] + $attrs);
+
+ return NativeElementCollector::collect()->toArray($registry);
+}
+
+it('registers the trailing press handler from each Blade spelling', function (string $attr) {
+ $registry = new CallbackRegistry;
+ $tree = trailingPressTree([$attr => 'deleteTodo(7)'], $registry);
+
+ expect($tree['props']['trailing_type'])->toBe('icon_button')
+ ->and($tree['props']['on_trailing_press'])->toBeInt()
+ ->and($registry->resolve($tree['props']['on_trailing_press']))
+ ->toBe(['method' => 'deleteTodo', 'args' => [7]]);
+})->with(['on-trailing-press', 'onTrailingPress']);
+
+it('compiles on-trailing-press with a bound argument from a Blade tag', function () {
+ $wasActive = NativeTagPrecompiler::setActive(true);
+
+ try {
+ $php = (new NativeTagPrecompiler)(
+ ''
+ );
+ } finally {
+ NativeTagPrecompiler::setActive($wasActive);
+ }
+
+ (function (int $id) use ($php) {
+ eval('?>'.$php);
+ })(7);
+
+ $registry = new CallbackRegistry;
+ $tree = NativeElementCollector::collect()->toArray($registry);
+
+ expect($registry->resolve($tree['props']['on_trailing_press']))
+ ->toBe(['method' => 'deleteTodo', 'args' => [7]]);
+});
+
+it('sends no trailing press callback when none is set', function () {
+ $tree = trailingPressTree([], new CallbackRegistry);
+
+ expect($tree['props'])->not->toHaveKey('on_trailing_press');
+});
+
+it('keeps the fluent onTrailingPress builder working', function () {
+ $registry = new CallbackRegistry;
+ $props = ListItem::make('Buy milk')->trailingIconButton('trash')->onTrailingPress('deleteTodo')
+ ->toArray($registry)['props'];
+
+ expect($registry->resolve($props['on_trailing_press']))->toBe(['method' => 'deleteTodo', 'args' => []]);
+});