feat: enhance CSS and components for Telegram Mini App performance

- Updated CSS to utilize viewport variables for safe area insets and stable height, improving layout consistency across devices.
- Introduced haptic feedback triggers in various components to enhance user interaction, mimicking native Telegram behavior.
- Added functionality to detect Android performance class, minimizing animations on low-performance devices for better user experience.
- Refactored components to incorporate new CSS classes for content safety and improved responsiveness.
This commit is contained in:
2026-03-04 19:19:14 +03:00
parent 13aba85e28
commit 07e22079ee
15 changed files with 129 additions and 14 deletions

View File

@@ -6,15 +6,20 @@ import {
mountMiniAppSync,
mountThemeParamsSync,
bindThemeParamsCssVars,
mountViewport,
bindViewportCssVars,
unmountViewport,
} from "@telegram-apps/sdk-react";
import { fixSurfaceContrast } from "@/hooks/use-telegram-theme";
import { applyAndroidPerformanceClass } from "@/lib/telegram-android-perf";
/**
* Wraps the app with Telegram Mini App SDK initialization.
* Calls init(acceptCustomStyles), mounts theme params (binds --tg-theme-* CSS vars),
* and mounts the mini app. Does not call ready() here — the app calls
* callMiniAppReadyOnce() from lib/telegram-ready when the first visible screen
* has finished loading, so Telegram keeps its native loading animation until then.
* mounts the mini app, then mounts viewport and binds viewport CSS vars
* (--tg-viewport-stable-height, --tg-viewport-content-safe-area-inset-*, etc.).
* Does not call ready() here — the app calls callMiniAppReadyOnce() from
* lib/telegram-ready when the first visible screen has finished loading.
* Theme is set before first paint by the inline script in layout.tsx (URL hash);
* useTelegramTheme() in the app handles ongoing theme changes.
*/
@@ -39,7 +44,26 @@ export function TelegramProvider({
mountMiniAppSync();
}
return cleanup;
applyAndroidPerformanceClass();
let unbindViewportCssVars: (() => void) | undefined;
if (mountViewport.isAvailable()) {
mountViewport()
.then(() => {
if (bindViewportCssVars.isAvailable()) {
unbindViewportCssVars = bindViewportCssVars();
}
})
.catch(() => {
// Viewport not supported (e.g. not in Mini App); ignore.
});
}
return () => {
unbindViewportCssVars?.();
unmountViewport();
cleanup();
};
}, []);
return <>{children}</>;