Перейти к содержанию
Innovialabs

Дизайн Telegram Mini App: тема, кнопки и нативное ощущение

Практика4 мин

Коротко

Mini App ощущается нативным, когда берёт цвета из темы Telegram, учитывает safe areas, использует MainButton и BackButton вместо своих кнопок, даёт тактильный отклик и открывается почти мгновенно.

Что делает Mini App нативным

Пользователь не должен замечать, что открыл сайт. Для этого Mini App:

  • берёт цвета из темы Telegram, а не из своего брендбука целиком;
  • учитывает размер окна и safe areas — вырезы, системные панели, кнопки Telegram;
  • использует системные кнопки — MainButton, BackButton, SettingsButton;
  • отвечает вибрацией на важные действия;
  • загружается быстро и сразу вызывает Telegram.WebApp.ready().

Всё это даёт объект window.Telegram.WebApp из официального скрипта telegram-web-app.js.

Цвета темы

Telegram передаёт в приложение themeParams — набор цветов текущей темы пользователя: bg_color, text_color, hint_color, link_color, button_color, button_text_color, secondary_bg_color и другие. Они же доступны как CSS-переменные.

body {
  background: var(--tg-theme-bg-color);
  color: var(--tg-theme-text-color);
}
.card { background: var(--tg-theme-secondary-bg-color); }
.hint { color: var(--tg-theme-hint-color); }

Практические правила:

  • Фон, текст и подсказки — только из темы. Иначе в тёмной теме будет белое пятно.
  • Бренд оставьте в акцентах: логотип, иллюстрации, одна-две фирменные плашки.
  • Подпишитесь на событие themeChanged — пользователь может сменить тему, не закрывая приложение.
  • Цвет шапки и фона окна задаются через setHeaderColor() и setBackgroundColor() — подберите их под первый экран, чтобы не было «шва».
  • Всегда задавайте запасные значения для CSS-переменных: при открытии в обычном браузере темы нет.

Viewport и safe areas

Высота окна Mini App меняется: пользователь тянет шторку, открывается клавиатура. Поэтому 100vh здесь ненадёжен.

  • --tg-viewport-height — текущая высота, меняется во время анимации.
  • --tg-viewport-stable-height — высота после завершения изменений. Используйте её для элементов, прибитых к низу.
  • expand() раскрывает окно на максимальную высоту — вызывайте, если интерфейсу тесно.

Safe areas — зоны, которые перекрывают системные элементы устройства и интерфейс Telegram. Есть два набора отступов:

  • --tg-safe-area-inset-* — от системных элементов (вырез, жестовая полоса);
  • --tg-content-safe-area-inset-* — от элементов Telegram поверх контента.
.screen {
  padding-top: calc(var(--tg-safe-area-inset-top, 0px) + var(--tg-content-safe-area-inset-top, 0px));
  padding-bottom: var(--tg-safe-area-inset-bottom, 0px);
}

Особенно важно в полноэкранном режиме: без отступов заголовок уйдёт под вырез камеры.

Кнопки: MainButton и BackButton

MainButton — большая кнопка внизу экрана в стиле Telegram. Её стоит использовать для главного действия экрана: «Оформить заказ», «Оплатить», «Далее».

const tg = window.Telegram.WebApp;
tg.MainButton.setParams({ text: "Оформить заказ", is_visible: true });
tg.MainButton.onClick(async () => {
  tg.MainButton.showProgress();
  await submitOrder();
  tg.MainButton.hideProgress();
});
  • Одно главное действие на экран. Для второстепенного есть SecondaryButton.
  • Отключайте кнопку (disable()), пока форма не заполнена, и показывайте showProgress() на время запроса.
  • BackButton в шапке вместо своей стрелки «назад». Связывайте её с роутером приложения.
  • Не дублируйте MainButton своей кнопкой в вёрстке — получится две одинаковые кнопки.
  • Снимайте обработчики через offClick() при смене экрана, иначе клик сработает несколько раз.

Тактильный отклик

HapticFeedback делает интерфейс «физическим»:

  • impactOccurred("light" | "medium" | "heavy" | "rigid" | "soft") — нажатия и перетаскивания;
  • notificationOccurred("success" | "warning" | "error") — результат действия;
  • selectionChanged() — смена выбора в списке или переключателе.

Используйте вибрацию дозированно: на подтверждения, ошибки и выбор. Вибрация на каждый тап утомляет.

Полноэкранный режим

requestFullscreen() разворачивает Mini App на весь экран — подходит для игр, медиа, карт. Учитывайте:

  • обязательны safe areas, иначе контент окажется под системными элементами;
  • слушайте fullscreenChanged и fullscreenFailed — режим поддерживается не во всех клиентах;
  • для обычных магазинов и форм полноэкранный режим чаще не нужен.

Если в приложении есть вертикальные жесты (свайпы, слайдеры), disableVerticalSwipes() не даст случайно свернуть окно.

Быстрая загрузка

Первое впечатление — это скорость. Чек-лист:

  • вызывайте ready() как можно раньше, после отрисовки первого экрана;
  • показывайте скелетон в цветах темы, а не пустой белый экран;
  • держите стартовый бандл маленьким, тяжёлые экраны грузите лениво;
  • раздавайте статику через CDN с кешированием;
  • не блокируйте первый экран запросами к API — сначала каркас, потом данные;
  • проверяйте на недорогом Android и медленной сети, а не только на своём ноутбуке.

Частые ошибки

  • Жёстко заданный белый фон и тёмный текст.
  • 100vh и фиксированные блоки, которые прыгают при открытии клавиатуры.
  • Своя кнопка «Назад» в углу вместо BackButton.
  • Отсутствие проверки версии: перед вызовом новых методов используйте isVersionAtLeast().

Частые вопросы

Нет. Базовые поверхности и текст берите из темы Telegram, а фирменный цвет используйте в акцентах, иллюстрациях и, при желании, в MainButton через setParams({ color }).

Поможем с этим

Если хотите не разбираться самим, а получить результат — этим мы занимаемся каждый день.

Обсудить проект

Читайте также

Есть идея или задача? Расскажите нам

Ответим в течение рабочего дня и предложим решение. Консультация бесплатная.