From 1f0aed90d5736a271be4cb29ec99eb8651d4eef9 Mon Sep 17 00:00:00 2001
From: BigSimmo <87357024+BigSimmo@users.noreply.github.com>
Date: Fri, 24 Jul 2026 13:29:35 +0800
Subject: [PATCH 01/17] fix(viewport): implement mobile keyboard and touch
target audit fixes
---
package.json | 2 +-
src/app/globals.css | 3 +
src/app/layout.tsx | 6 +-
.../master-search-header.tsx | 20 ++++-
src/components/ui-primitives.tsx | 2 +-
src/components/use-mobile-keyboard.tsx | 74 +++++++++++++++++++
6 files changed, 103 insertions(+), 4 deletions(-)
create mode 100644 src/components/use-mobile-keyboard.tsx
diff --git a/package.json b/package.json
index 9335c003a..c7795924f 100644
--- a/package.json
+++ b/package.json
@@ -25,7 +25,7 @@
"lint": "node scripts/run-heavy.mjs --npm-script lint:internal",
"lint:internal": "node --max-old-space-size=8192 ./node_modules/eslint/bin/eslint.js src tests scripts worker supabase playwright eslint.config.mjs next.config.ts playwright.config.ts playwright.visual.config.ts vitest.config.mts --max-warnings 0 --no-error-on-unmatched-pattern --cache --cache-location node_modules/.cache/eslint/",
"typecheck": "node scripts/run-heavy.mjs --npm-script typecheck:internal",
- "typecheck:internal": "node ./node_modules/typescript/bin/tsc --noEmit",
+ "typecheck:internal": "npx rimraf .next/types && node ./node_modules/typescript/bin/tsc --noEmit",
"test": "node scripts/run-vitest.mjs run --reporter=dot",
"test:focused": "node scripts/test-focused.mjs",
"test:live": "node scripts/run-live-tests.mjs",
diff --git a/src/app/globals.css b/src/app/globals.css
index 7e560bc47..d0a15a55f 100644
--- a/src/app/globals.css
+++ b/src/app/globals.css
@@ -263,6 +263,7 @@
--shadow-lux: inset 0 1px 0 rgb(255 255 255 / 64%), 0 12px 34px rgb(8 16 24 / 7%);
--shadow-inset: inset 0 1px 0 rgb(255 255 255 / 58%);
--shadow-card: var(--shadow-tight);
+ --shadow-focus: 0 0 0 3px color-mix(in srgb, var(--focus) 25%, transparent), var(--shadow-soft);
/* Active left-rail marker (nav/list "current" indicator). One token so the
accent rail is a consistent 2px everywhere instead of hand-inlined at 2px/3px. */
--shadow-rail-active: inset 2px 0 0 var(--clinical-accent);
@@ -424,6 +425,7 @@
--shadow-elevated: 0 2px 8px rgb(0 0 0 / 46%), 0 12px 30px rgb(0 0 0 / 48%), 0 28px 58px rgb(0 0 0 / 50%);
--shadow-lux: inset 0 1px 0 rgb(255 255 255 / 4%), 0 18px 44px rgb(0 0 0 / 64%);
--shadow-inset: inset 0 1px 0 rgb(255 255 255 / 4%);
+ --shadow-focus: 0 0 0 3px color-mix(in srgb, var(--focus) 25%, transparent), var(--shadow-soft);
color-scheme: dark;
}
@@ -1156,6 +1158,7 @@ summary::-webkit-details-marker {
.chat-composer-shell-delta:focus-within {
border-color: var(--clinical-accent);
+ box-shadow: var(--shadow-focus);
}
.chat-composer-input {
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
index 809791d96..f755f94ab 100644
--- a/src/app/layout.tsx
+++ b/src/app/layout.tsx
@@ -7,6 +7,7 @@ import { PwaLifecycle } from "@/components/pwa-lifecycle";
import { WebVitalsReporter } from "@/components/web-vitals-reporter";
import { resolveMetadataBase } from "@/lib/metadata-base";
import { APP_THEME_COLORS, THEME_BOOTSTRAP_SCRIPT } from "@/lib/theme";
+import { MobileKeyboardProvider } from "@/components/use-mobile-keyboard";
import "./globals.css";
const geistSans = Geist({
@@ -58,6 +59,7 @@ export const viewport: Viewport = {
width: "device-width",
initialScale: 1,
viewportFit: "cover",
+ interactiveWidget: "resizes-content",
colorScheme: "light dark",
themeColor: [
{ media: "(prefers-color-scheme: light)", color: APP_THEME_COLORS.light },
@@ -108,7 +110,9 @@ export default async function RootLayout({
- {children}
+
+ {children}
+