Hide mobile nav while typing and fix searchable select keyboard on iOS

This commit is contained in:
Kalle
2026-10-11 13:09:12 +03:00
parent 643b8744bf
commit 05b2a4c42b
7 changed files with 58 additions and 11 deletions

View File

@@ -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);

View File

@@ -69,6 +69,15 @@ describe("SendouSelect", () => {
.not.toBeInTheDocument();
});
test("focuses the search input within the opening click", async () => {
const screen = await render(<GroupedSelect search={{}} />);
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(<GroupedSelect search={{}} />);

View File

@@ -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<T extends object>({
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<T extends object>({
}
data-required={isRequired || undefined}
{...popoverTriggerProps}
onClick={onTriggerClick}
onKeyDown={onTriggerKeyDown}
>
<span

View File

@@ -670,19 +670,39 @@
place-items: center;
}
/* iOS can't pin the tab bar on top of the virtual keyboard, so it gets out of the way while typing */
@media (pointer: coarse) {
body:has(
:is(
input:is(
:not([type]),
[type="text"],
[type="search"],
[type="email"],
[type="url"],
[type="tel"],
[type="password"],
[type="number"]
),
textarea,
[contenteditable]:not([contenteditable="false"])
):not([readonly], [inputmode="none"]):focus
) {
--mobile-nav-height: 0px;
--mobile-tab-bar-display: none;
}
}
@media screen and (max-width: 599px) {
body:not(:has(.planner)) .publift-widget-sticky_footer-container {
bottom: calc(
var(--layout-nav-height) +
env(safe-area-inset-bottom)
) !important;
bottom: var(--mobile-nav-height) !important;
}
}
/* the consent dialog is drawn outside the top layer, where the tab bar would cover its buttons */
@media screen and (max-width: 599px) {
body:not(:has(.planner)) #qc-cmp2-container .qc-cmp-cleanslate {
bottom: calc(var(--layout-nav-height) + env(safe-area-inset-bottom));
bottom: var(--mobile-nav-height);
height: auto;
}
}

View File

@@ -318,6 +318,11 @@ html,
to the document scroll, for a smooth transition between sticking and un-sticking
*/
--layout-nav-height: 55px;
--mobile-nav-height: calc(
var(--layout-nav-height) +
env(safe-area-inset-bottom)
);
--mobile-tab-bar-display: flex;
--layout-sidenav-width: 250px;
--layout-fuse-bottom-height: 90px;
--layout-main-padding: var(--s-3);

View File

@@ -0,0 +1,4 @@
---
type: bug
---
Bottom navigation bar on mobile no longer floats awkwardly above the keyboard, it now hides while typing

View File

@@ -0,0 +1,4 @@
---
type: bug
---
Searchable dropdowns like the weapon picker now bring up the keyboard right away on iPhone