feat: enhance theme handling and layout components for Telegram Mini App
- Updated theme resolution logic to utilize a shared inline script for consistent theme application across routes. - Introduced `AppShell` and `ReadyGate` components to manage app readiness and theme synchronization, improving user experience. - Enhanced `GlobalError` and `NotFound` pages with a unified full-screen layout for better accessibility and visual consistency. - Refactored CSS to implement safe area insets for sticky headers and content safety, ensuring proper layout on various devices. - Added unit tests for new functionality and improved existing tests for better coverage and reliability.
This commit is contained in:
@@ -26,10 +26,10 @@ Telegram’s guidelines state:
|
||||
|
||||
Theme is resolved in this order:
|
||||
|
||||
1. Hash parameters: `tgWebAppColorScheme`, `tgWebAppThemeParams` (parsed in the inline script in `webapp-next/src/app/layout.tsx`).
|
||||
2. At runtime: `Telegram.WebApp.colorScheme` and `Telegram.WebApp.themeParams` via `use-telegram-theme.ts` and `TelegramProvider`.
|
||||
1. Hash parameters: `tgWebAppColorScheme`, `tgWebAppThemeParams` (parsed in the shared inline script from `webapp-next/src/lib/theme-bootstrap-script.ts`, used in layout and global-error).
|
||||
2. At runtime: `Telegram.WebApp.colorScheme` and `Telegram.WebApp.themeParams` via **TelegramProvider** (theme sync is provider-owned in `ThemeSync` / `useTelegramTheme`), so every route (/, /admin, not-found, error) receives live theme updates.
|
||||
|
||||
The inline script in the layout maps all Telegram theme keys to `--tg-theme-*` CSS variables on the document root. The hook sets `data-theme` (`light` / `dark`) and applies Mini App background/header colors.
|
||||
The inline script maps all Telegram theme keys to `--tg-theme-*` CSS variables on the document root. The provider sets `data-theme` (`light` / `dark`) and applies Mini App background/header colors.
|
||||
|
||||
### 2.2 Mapping (ThemeParams → app tokens)
|
||||
|
||||
@@ -95,10 +95,9 @@ Use **only** these tokens and Tailwind/shadcn aliases (`bg-background`, `text-mu
|
||||
|
||||
### 3.3 Safe area and content safe area
|
||||
|
||||
- **Class `.content-safe`** (in `globals.css`): Applies:
|
||||
- `padding-top: var(--tg-viewport-content-safe-area-inset-top, env(safe-area-inset-top, 0))`
|
||||
- `padding-bottom: var(--tg-viewport-content-safe-area-inset-bottom, env(safe-area-inset-bottom, 0))`
|
||||
- Use `.content-safe` on the **root container of each page** so content is not covered by the Telegram header or bottom bar (Bot API 8.0+).
|
||||
- **CSS custom properties** (in `globals.css`): `--app-safe-top`, `--app-safe-bottom`, `--app-safe-left`, `--app-safe-right` use Telegram viewport content-safe-area insets with `env(safe-area-inset-*)` fallbacks. Use these for sticky positioning and padding so layout works on notched and landscape devices.
|
||||
- **Class `.content-safe`**: Applies padding on all four sides using the above tokens so content does not sit under Telegram header, bottom bar, or side chrome (Bot API 8.0+). Use `.content-safe` on the **root container of each page** and on full-screen fallback screens (not-found, error, access denied).
|
||||
- **Sticky headers:** Use `top-[var(--app-safe-top)]` (not `top-0`) for sticky elements (e.g. calendar header, admin header) so they sit below the Telegram UI instead of overlapping it.
|
||||
- Lists that extend to the bottom should also account for bottom inset (e.g. `padding-bottom: var(--tg-viewport-content-safe-area-inset-bottom, 12px)` in `.container-app`).
|
||||
|
||||
### 3.4 Sheets and modals
|
||||
@@ -197,7 +196,8 @@ See `webapp-next/src/components/day-detail/DayDetail.tsx` for the Sheet content.
|
||||
|
||||
## 8. Telegram integration
|
||||
|
||||
- **Header and background:** On init (layout script and `use-telegram-theme.ts`), call:
|
||||
- **Ready gate:** `callMiniAppReadyOnce()` (in `lib/telegram-ready.ts`) is invoked by the layout’s `ReadyGate` when `appContentReady` becomes true. Any route (/, /admin, not-found, in-app error) that sets `appContentReady` will trigger it so Telegram hides its loader; no route-specific logic is required.
|
||||
- **Header and background:** On init (layout script and provider’s theme sync), call:
|
||||
- `setBackgroundColor('bg_color')`
|
||||
- `setHeaderColor('bg_color')`
|
||||
- `setBottomBarColor('bottom_bar_bg_color')` when available (Bot API 7.10+).
|
||||
|
||||
Reference in New Issue
Block a user