Stage 17 (contour round 3): Telegram Mini Apps polish, board scroll, keyboard overlay
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 8s
CI / integration (pull_request) Successful in 10s
CI / ui (pull_request) Successful in 27s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 54s

- Telegram (lib/telegram.ts): chrome colours (setHeaderColor/setBackgroundColor/setBottomBarColor) match Telegram's header/bg/bottom bar to the app; native BackButton on sub-screens (app chevron hidden in TG); HapticFeedback on tile place/commit/error; enableClosingConfirmation while a game is open; disableVerticalSwipes so swipe-to-minimise doesn't fight tile drag / board scroll
- #9 board-only vertical scroll: Screen 'column' mode lets the board area scroll while score/status/rack/tab bar stay fixed (zoom keeps its own scroll)
- #10 check-word dialog opens in Modal keyboard-overlay mode (top-anchored, keyboard overlays the empty area) — no resize/relayout jank; other modals stay keyboard-aware
- docs: UI_DESIGN Telegram integration + vertical fit/keyboard; PLAN round 2-3 follow-ups
This commit is contained in:
Ilia Denisov
2026-06-06 12:55:46 +02:00
parent 645a503532
commit f6bffd1f57
9 changed files with 204 additions and 18 deletions
+12 -2
View File
@@ -4,18 +4,21 @@
let {
title = '',
onclose,
overlayKeyboard = false,
children,
}: { title?: string; onclose?: () => void; children?: Snippet } = $props();
}: { title?: string; onclose?: () => void; overlayKeyboard?: boolean; children?: Snippet } = $props();
// Track the visual viewport so the backdrop covers only the area above an open
// mobile keyboard: dvh alone shrinks the sheet but the fixed, layout-viewport
// backdrop still centres it behind the keyboard. Sizing the backdrop to
// visualViewport keeps the sheet (and the start of a chat) fully on screen.
// overlayKeyboard opts out: the sheet is small and top-anchored, so the keyboard
// simply overlays the empty lower area — no resize, no relayout jank (e.g. check word).
let vh = $state(0);
let top = $state(0);
$effect(() => {
const vv = typeof window !== 'undefined' ? window.visualViewport : null;
if (!vv) return;
if (!vv || overlayKeyboard) return;
const update = () => {
vh = vv.height;
top = vv.offsetTop;
@@ -34,6 +37,7 @@
<!-- svelte-ignore a11y_no_static_element_interactions -->
<div
class="backdrop"
class:overlay={overlayKeyboard}
style:height={vh ? `${vh}px` : null}
style:top={vh ? `${top}px` : null}
onclick={() => onclose?.()}
@@ -61,6 +65,12 @@
padding: 16px;
z-index: 40;
}
/* Overlay mode: top-anchor the (small) sheet and don't track the keyboard, so the
soft keyboard overlays the empty lower area without resizing/relaying out. */
.backdrop.overlay {
align-items: flex-start;
padding-top: 12vh;
}
.sheet {
background: var(--surface);
color: var(--text);