From e73c1f1f741b559eec9bb87a4dcb2c33fb7096c2 Mon Sep 17 00:00:00 2001 From: CodyPChristian Date: Fri, 28 Aug 2026 23:36:08 -0400 Subject: [PATCH] fix: let a chip's @press handler actually fire MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both chip renderers read only `on_change`. A chip written as registers the callback PHP-side — Element::onPress exists and NativeElementCollector binds `_press` for every element — and then nothing invokes it, because neither renderer looks for `on_press`. The chip toggles its own local state and reports a boolean instead. Nothing errors. The chip animates on tap, so it reads as working; the filter simply never changes. In the QikCMS console this silently disabled the filter row on THIRTEEN screens, People and Tickets among them. A chip with a press handler is server-driven: the handler decides what becomes selected, so it must not toggle locally, or a filter chip fights the state it is handed back and flickers off on its own tap. Without a press handler the existing self-toggling `@change` behaviour is untouched. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01RWJoCjdX5Cy1V5VhaRKuLS --- resources/android/ChipRenderer.kt | 18 +++++++++++++----- resources/ios/NativeUIChipRenderer.swift | 18 +++++++++++++----- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/resources/android/ChipRenderer.kt b/resources/android/ChipRenderer.kt index 679173e..7941316 100644 --- a/resources/android/ChipRenderer.kt +++ b/resources/android/ChipRenderer.kt @@ -31,6 +31,7 @@ object ChipRenderer { val label = p.getString("label") val iconName = p.getString("icon") val onChangeCb = p.getCallbackId("on_change") + val onPressCb = p.getCallbackId("on_press").let { if (it != 0) it else node.onPress } val disabled = p.getBool("disabled") val a11yLabel = p.getString("a11y_label") val a11yHint = p.getString("a11y_hint") @@ -68,11 +69,18 @@ object ChipRenderer { FilterChip( selected = isSelected, onClick = { - val new = !isSelected - isSelected = new - lastSentValue = new - if (onChangeCb != 0) { - NativeUIBridge.sendToggleChangeEvent(onChangeCb, node.id, new) + if (onPressCb != 0) { + // Server-driven: the press handler owns selection. Toggling + // locally would make the chip fight the state it is handed + // back, so a filter chip would flicker off on its own tap. + NativeUIBridge.sendPressEvent(onPressCb, node.id) + } else { + val new = !isSelected + isSelected = new + lastSentValue = new + if (onChangeCb != 0) { + NativeUIBridge.sendToggleChangeEvent(onChangeCb, node.id, new) + } } }, label = { Text(label, fontFamily = nuiDefaultFontFamily()) }, diff --git a/resources/ios/NativeUIChipRenderer.swift b/resources/ios/NativeUIChipRenderer.swift index 4212e1e..3884352 100644 --- a/resources/ios/NativeUIChipRenderer.swift +++ b/resources/ios/NativeUIChipRenderer.swift @@ -29,6 +29,7 @@ struct NativeUIChipRenderer: View { let label = p.getString("label") let iconName = p.getString("icon") let onChangeCb = p.getCallbackId("on_change") + let onPressCb = p.getCallbackId("on_press") != 0 ? p.getCallbackId("on_press") : node.onPress let disabled = p.getBool("disabled") let a11yLabel = p.getString("a11y_label") let a11yHint = p.getString("a11y_hint") @@ -45,11 +46,18 @@ struct NativeUIChipRenderer: View { Button(action: { guard !disabled else { return } - let new = !isSelected - isSelected = new - lastSentValue = new - if onChangeCb != 0 { - NativeElementBridge.sendToggleChangeEvent(onChangeCb, nodeId: node.id, value: new) + if onPressCb != 0 { + // Server-driven: the press handler owns selection. Toggling + // locally would make the chip fight the state it is handed + // back, so a filter chip would flicker off on its own tap. + NativeElementBridge.sendPressEvent(onPressCb, nodeId: node.id) + } else { + let new = !isSelected + isSelected = new + lastSentValue = new + if onChangeCb != 0 { + NativeElementBridge.sendToggleChangeEvent(onChangeCb, nodeId: node.id, value: new) + } } }) { HStack(spacing: 6) {