From 05b2a4c42b7737da0d64aa5873bf82f81c4d34ea Mon Sep 17 00:00:00 2001
From: Kalle <38327916+Sendouc@users.noreply.github.com>
Date: Sun, 11 Oct 2026 13:09:12 +0300
Subject: [PATCH] Hide mobile nav while typing and fix searchable select
keyboard on iOS
---
app/components/MobileNav.module.css | 7 +----
.../elements/Select.browser.test.tsx | 9 ++++++
app/components/elements/Select.tsx | 10 +++++++
app/styles/common.css | 30 +++++++++++++++----
app/styles/vars.css | 5 ++++
...026-10-11-mobile-nav-hides-while-typing.md | 4 +++
.../2026-10-11-searchable-select-keyboard.md | 4 +++
7 files changed, 58 insertions(+), 11 deletions(-)
create mode 100644 changelog/2026-10-11-mobile-nav-hides-while-typing.md
create mode 100644 changelog/2026-10-11-searchable-select-keyboard.md
diff --git a/app/components/MobileNav.module.css b/app/components/MobileNav.module.css
index dceb4d3b1..873433d75 100644
--- a/app/components/MobileNav.module.css
+++ b/app/components/MobileNav.module.css
@@ -11,11 +11,6 @@
background: none;
color: inherit;
z-index: 19;
-
- --mobile-nav-height: calc(
- var(--layout-nav-height) +
- env(safe-area-inset-bottom)
- );
}
@media screen and (min-width: 600px) {
@@ -25,7 +20,7 @@
}
.tabBar {
- display: flex;
+ display: var(--mobile-tab-bar-display);
justify-content: space-around;
align-items: center;
height: var(--mobile-nav-height);
diff --git a/app/components/elements/Select.browser.test.tsx b/app/components/elements/Select.browser.test.tsx
index 5efe7baf5..56ec98e73 100644
--- a/app/components/elements/Select.browser.test.tsx
+++ b/app/components/elements/Select.browser.test.tsx
@@ -69,6 +69,15 @@ describe("SendouSelect", () => {
.not.toBeInTheDocument();
});
+ test("focuses the search input within the opening click", async () => {
+ const screen = await render();
+ const trigger = screen.getByRole("button").element() as HTMLButtonElement;
+
+ trigger.click();
+
+ expect(document.activeElement).toBe(screen.getByRole("combobox").element());
+ });
+
test("shows the empty state when nothing matches the search", async () => {
const screen = await render();
diff --git a/app/components/elements/Select.tsx b/app/components/elements/Select.tsx
index b29fcaf18..2229a64db 100644
--- a/app/components/elements/Select.tsx
+++ b/app/components/elements/Select.tsx
@@ -1,6 +1,7 @@
import clsx from "clsx";
import { ChevronsUpDown, Search, X } from "lucide-react";
import * as React from "react";
+import { flushSync } from "react-dom";
import { useTranslation } from "react-i18next";
import { SendouBottomTexts } from "~/components/elements/BottomTexts";
import { SendouButton } from "~/components/elements/Button";
@@ -299,6 +300,14 @@ export function SendouSelect({
scrollIntoView(targetKey);
};
+ // iOS only brings up the keyboard for a focus inside the tap itself, but the native
+ // open is redone a frame later (useShowPopoverOnOpen), so a searchable select opens here
+ const onTriggerClick = (event: React.MouseEvent) => {
+ if (!search || open) return;
+ event.preventDefault();
+ flushSync(() => setOpen(true));
+ };
+
const onTriggerKeyDown = (event: React.KeyboardEvent) => {
if (event.key === "ArrowDown" || event.key === "ArrowUp") {
event.preventDefault();
@@ -535,6 +544,7 @@ export function SendouSelect({
}
data-required={isRequired || undefined}
{...popoverTriggerProps}
+ onClick={onTriggerClick}
onKeyDown={onTriggerKeyDown}
>