fix(ui): mesh/web5/apps layout, modal, and search UX fixes

- Mesh: fix 920-1280px bottom margin (phantom mobile-nav reservation
  leaking into the desktop-sidebar range), let the mesh view scale to
  full width on wide screens instead of capping at 1600px, and make the
  Device panel collapsible on desktop (previously mobile-only)
- Search/controller-nav: a global gamepad/keyboard-nav feature was
  auto-clicking "the next button in the DOM" on Enter in any text input,
  which cleared the mesh peer search and popped the sideload modal from
  the App Store/My Apps search boxes. Opt out via data-controller-no-submit
  on all filter inputs; bump the mesh clear button's touch target
- Modals: several (sideload, credential, Lightning channel open, identity
  create) used ad-hoc blue buttons and non-fullscreen backdrops that only
  covered the main content area, not the sidebar. Teleport them to body,
  unify backdrop/button theming to the dark+orange convention, fix the
  sideload modal's square bottom corners on desktop, and standardize
  close buttons to the ghost-icon style
- Web5: remove the redundant/dead "Messages" tab from Connected Nodes
  (its deep-link was unreachable dead code); fix the "view message" toast
  to actually open the Archipelago channel instead of silently failing to
  match a LoRa peer; make identity rows responsive via a container query
  (viewport-based breakpoints don't work in the page's 2-column grid) and
  right-justify their action icons; collapse DID/DHT/Wallet/Nostr/Connected
  Nodes by default on mobile
- Apps/App Store: match the search bar and sideload button's height,
  padding, and background to the mode-switcher tabs beside them
- Mesh chat: keep the compose input focused after sending

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
archipelago
2026-07-01 18:04:31 -04:00
co-authored by Claude Sonnet 5
parent 469b0203b7
commit 8256fde1a6
18 changed files with 242 additions and 169 deletions
+11 -2
View File
@@ -236,8 +236,17 @@ export function useControllerNav(containerRef?: { value: HTMLElement | null }) {
// ── TEXT INPUT HANDLING ──────────────────────────────────
if (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA') {
if (e.key === 'Enter' && target.tagName === 'INPUT' && (target as HTMLInputElement).type !== 'submit') {
// Enter in input: click next button (submit pattern)
if (
e.key === 'Enter' &&
target.tagName === 'INPUT' &&
(target as HTMLInputElement).type !== 'submit' &&
!target.hasAttribute('data-controller-no-submit')
) {
// Enter in input: click next button (submit pattern). Live-filter
// search boxes opt out via data-controller-no-submit — the "next
// focusable element" after a search field is often an unrelated
// button (a clear icon, a sideload/upload action) that just happens
// to sit next to it in the DOM, not a submit action for the query.
e.preventDefault()
const all = getFocusableElements(containerRef?.value ?? document)
const idx = all.indexOf(target)