apple: keep textarea borderless + e2e fixes (semantics refresh, autofocus edge, hoisted toolbar id) - #52
Merged
Conversation
c90fe35 applied .roundedBorder to every non-search text control, which puts a ~1px outlined box around multi-line textareas that used to sit bare on their host card (e.g. chat composer-input). Textareas keep the default borderless style; single-line fields keep the native chrome.
Contributor
|
I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".
|
Lands the deferred Flutter parity for bd0c92c — the generated schema gained _NodeKind.menuTrigger but the backend never handled it, so the exhaustive switch in _buildNode failed to compile (surfaced by the chat Android e2e build). - menuTrigger() renders a MenuAnchor with a TextButton label (icon + text, accessibility label, enabled, foreground) - dropdown-menu children may be menu-trigger (nested submenus); menu-trigger accepts only a dropdown-menu child - text/enabled/foreground/icon/accessibility-label allowed on the kind; toolbar children and _canContainChildren include it
with_press on a column previously emitted nothing on any platform: the OCaml property/event matrices (and each backend's mirror) rejected press-enabled for containers, so container-level taps were silently dropped. Admit column so apps can wire container tap actions (e.g. tap-to-focus). - OCaml: property_supported PressEnabled + event_supported Press - Apple: supports gate, performPress guard, LUIColumnView tap gesture - Flutter: _supports, performAction pressable, column GestureDetector - Qt: schema property/event arms, performPress, LuiColumn tap layer - WinUI: CommonPropertySupported/EventSupported, PerformAction pressable
A detached RenderObject's markNeedsSemanticsUpdate is a no-op (!attached early-returns), so removing a modal route leaves its semantics node linked under a parent that is never re-dirtied and the platform a11y tree freezes on the last emit — which still contains the sheet — hiding the new screen from assistive tech (observed as android e2e button.sidebar assert failing while the UI is visibly on the chat screen). Refresh by marking every render object in the tree dirty across two consecutive frames, covering both the removeRoute path and detaches that land a frame later; also refresh when the route was already inactive.
onChange previously only focused on false->true edges, so a second focus request while the flag already read true (field unfocused) produced no edge and never refocused. Any transition now requests focus, which pairs with producers pulsing the flag to force an edge.
The autofocus prop only reached TextField at build time, so later transitions never moved focus. Pass the node handle's FocusNode into _LUITextInput and requestFocus on any autofocus change, matching the edge-triggered focus-request semantics.
A placement-hoisted toolbar renders through a zero-size Color.clear carrier, so its accessibility identifier never reached the a11y tree — iOS e2e's toolbar.outliner.editor assert failed while every toolbar button was present. Apply the identifier to the first emitted ToolbarItem's content (the fused capsule, or the first bare item).
Two frames is not enough — a sheet's exit animation detaches its overlay entries ~15 frames after removal is scheduled, so marks made that early flush while the sheet is still attached and the a11y tree freezes again at detach. Mark every frame for ~750ms.
…area-borderless # Conflicts: # platform/apple/Sources/LUIAppleBackend/LUISwiftUIRoot.swift # platform/flutter/lib/lui_flutter_backend.dart
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes driving chat's composer/sidebar-restore PR (logseq/chat#24), plus root-cause fixes for both chat e2e failures that were failing on main.
c90fe35added.roundedBorderto all non-search text controls, which put an unintended gray ring around the composer textarea. Textareas now keep the borderless design; buttons get explicit 44x44 sizing in the app (the iOS 44pt default-height removal was intentional).with_press/press-enabledwas silently dropped forcolumn— the protocol never allowed it, so the composer's tap-to-focus was a no-op. AddsPressEnabled+PressEventto the column matrix and implements press handling on all four hosts (SwiftUIonTapGesture, FlutterGestureDetector, QtTapHandler, WinUITapped).button.sidebar):markNeedsSemanticsUpdateearly-returns on detached RenderObjects, so removing a modal route's overlay entries never re-dirtied any semantics ancestor — the platform a11y tree stayed frozen on the stale sheet._refreshSemanticsAfterModalRemovalnow marks the whole render tree dirty across two frames, and_scheduleRouteRemovalrefreshes even on the!route.isActiveearly-return path.FocusComposertoggles a flag, so a press while autofocus is already true produces a true→false→true edge. Hosts now treat any transition as a focus request instead of onlyfalse→true.toolbar.outliner.editor): aplacement-hoisted toolbar renders via a zero-sizeColor.clearcarrier, so itsaccessibility_identifiernever reached the a11y tree (allbutton.outliner.editor.*buttons were present, the container id was not). The identifier is now carried on the first emittedToolbarItem's content.Link to Devin session: https://app.devin.ai/sessions/eab2eca00a5649d09fcf48626d9f09ef
Open in Devin Desktop: https://app.devin.ai/desktop/session/eab2eca00a5649d09fcf48626d9f09ef?variant=devin
Requested by: @tiensonqin