# Mini App Design Guideline

This document defines the design rules for the Duty Teller Mini App (Next.js frontend in `webapp-next/`). It aligns with [Telegram’s official Mini App design guidelines](https://core.telegram.org/bots/webapps#designing-mini-apps) (Color Schemes and Design Guidelines) and codifies the current implementation (calendar, duty list, admin) as the reference for new screens and components.

---

## 1. Telegram design principles

Telegram’s guidelines state:

- **Mobile-first:** All elements must be responsive and designed for mobile first.
- **Consistency:** Interactive elements should match the style, behaviour, and intent of existing Telegram UI components.
- **Performance:** Animations should be smooth, ideally 60fps.
- **Accessibility:** Inputs and images must have labels.
- **Theme:** The app must use the dynamic theme-based colors provided by the API (Day/Night and custom themes).
- **Safe areas:** The interface must respect the **safe area** and **content safe area** so content does not overlap system or Telegram UI, especially in fullscreen.
- **Android:** On Android, use the extra User-Agent data (e.g. performance class) and reduce animations and effects on low-performance devices for smooth operation.

**Color schemes:** Mini Apps receive the user’s current **theme** in real time. Use the `ThemeParams` object and the CSS variables Telegram exposes (e.g. `--tg-theme-bg-color`, `--tg-theme-text-color`) so the UI adapts when the user switches Day/Night or custom themes.

---

## 2. Theme and colors

### 2.1 Sources

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`.

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.

### 2.2 Mapping (ThemeParams → app tokens)

In `webapp-next/src/app/globals.css`, `:root` and `[data-theme="light"]` / `[data-theme="dark"]` map Telegram’s ThemeParams to internal design tokens:

| Telegram ThemeParam (CSS var)        | App token / usage |
|--------------------------------------|-------------------|
| `--tg-theme-bg-color`                | `--bg` (background) |
| `--tg-theme-secondary-bg-color`      | `--surface` (cards, panels) |
| `--tg-theme-text-color`              | `--text` (primary text) |
| `--tg-theme-hint-color`, `--tg-theme-subtitle-text-color` | `--muted` (secondary text) |
| `--tg-theme-link-color`              | `--accent` (links, secondary actions) |
| `--tg-theme-header-bg-color`          | `--header-bg` |
| `--tg-theme-section-bg-color`        | `--card` (sections) |
| `--tg-theme-section-header-text-color` | `--section-header` |
| `--tg-theme-section-separator-color` | `--border` |
| `--tg-theme-button-color`            | `--primary` |
| `--tg-theme-button-text-color`       | `--primary-foreground` |
| `--tg-theme-destructive-text-color` | `--error` |
| `--tg-theme-accent-text-color`      | `--accent-text` |

Tailwind/shadcn semantic tokens are wired to these: `--background` → `--bg`, `--foreground` → `--text`, `--primary`, `--secondary` → `--surface`, etc.

### 2.3 Domain colors

Duty-specific semantics (fixed per theme, not from ThemeParams):

- `--duty` — duty shift (e.g. green).
- `--unavailable` — unavailable (e.g. amber).
- `--vacation` — vacation (e.g. blue).
- `--today` — “today” highlight; tied to `--tg-theme-accent-text-color` / `--tg-theme-link-color`.

Use Tailwind classes such as `bg-duty`, `border-l-unavailable`, `text-today`, `bg-today`, etc.

### 2.4 Derived tokens (color-mix)

Prefer these instead of ad-hoc color mixes:

- `--surface-hover`, `--surface-hover-10` — hover states for surfaces.
- `--surface-today-tint`, `--surface-muted-tint` — subtle tints.
- `--today-hover`, `--today-border`, `--today-border-selected`, `--today-gradient-end` — today state.
- `--muted-fade`, `--shadow-card`, etc.

Defined in `globals.css`; use via `var(--surface-hover)` in classes (e.g. `hover:bg-[var(--surface-hover)]`).

### 2.5 Rule for new work

Use **only** these tokens and Tailwind/shadcn aliases (`bg-background`, `text-muted`, `bg-surface`, `text-accent`, `border-l-duty`, `bg-today`, etc.). Do not hardcode hex or RGB in new components or screens.

---

## 3. Layout and safe areas

### 3.1 Width

- **Token:** `--max-width-app: 420px` (in `@theme` in `globals.css`).
- **Usage:** Page wrapper uses `max-w-[var(--max-width-app)]` (e.g. in `page.tsx`, `CalendarPage.tsx`, `admin/page.tsx`). Content is centred with `mx-auto`.

### 3.2 Height

- **Viewport:** Prefer `min-h-[var(--tg-viewport-stable-height,100vh)]` for the main content area so the Mini App fills the visible height correctly when expanded/collapsed. Fallback `100vh` when not in Telegram.
- **Body:** In `globals.css`, `body` already has `min-height: var(--tg-viewport-stable-height, 100vh)` and `background: var(--bg)`.

### 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+).
- 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

Bottom sheets and modals that sit at the bottom of the screen must add safe area to their padding, e.g.:

`pb-[calc(24px+env(safe-area-inset-bottom,0px))]`

See `webapp-next/src/components/day-detail/DayDetail.tsx` for the Sheet content.

---

## 4. Typography and spacing

### 4.1 Font

- **Family:** `system-ui, -apple-system, sans-serif` (set in `globals.css` and Tailwind theme).

### 4.2 Patterns from the calendar and duty list

| Element | Classes / tokens |
|--------|-------------------|
| Month title | `text-[1.1rem]` / `sm:text-[1.25rem]`, `font-semibold` |
| Year (above month) | `text-xs`, `text-muted` |
| Nav buttons (prev/next month) | `size-10`, `rounded-[10px]` |
| Calendar day cell | `text-[0.85rem]`, `rounded-lg`, `p-1` |
| Duty timeline card | `px-2.5 py-2`, `rounded-lg` |

### 4.3 Page and block spacing

- Page container: `px-3 pb-6` in addition to `.content-safe`.
- Between sections: `mb-3`, `mb-4` as appropriate.
- Grids: `gap-1` for tight layouts (e.g. calendar grid), larger gaps where needed.

---

## 5. Component patterns

### 5.1 Buttons

- **Primary:** Use the default Button variant: `bg-primary text-primary-foreground` (from `webapp-next/src/components/ui/button.tsx`).
- **Secondary icon buttons** (e.g. calendar nav):  
  `bg-surface text-accent hover:bg-[var(--surface-hover)] focus-visible:outline-accent active:scale-95`  
  with `size-10` and `rounded-[10px]`.
- Keep focus visible (e.g. `focus-visible:outline-accent` or ring); do not remove outline without a visible replacement.

### 5.2 Cards

- **Background:** `bg-surface` or `bg-card` (both resolve to theme tokens).
- **Borders:** `border`, `--border` (section separator color).
- **Emphasis:** `var(--shadow-card)` for highlighted cards (e.g. current duty).
- **Left stripe by type:** `border-l-[3px]` with:
  - `border-l-duty`, `border-l-unavailable`, `border-l-vacation` for event types;
  - `border-l-today` for “current duty” (see `.border-l-today` in `globals.css`).

### 5.3 Calendar grid

- **Structure:** 7 columns × 6 rows; use `role="grid"` on the container and `role="gridcell"` on each cell.
- **Layout:** `min-h-[var(--calendar-grid-min-height)]`, cells `aspect-square` with `min-h-8`, `rounded-lg`, `gap-1`.
- **Today:** `bg-today text-[var(--bg)]`; hover `hover:bg-[var(--today-hover)]`.
- **Other month:** `opacity-40`, `pointer-events-none`, `bg-[var(--surface-muted-tint)]`.

### 5.4 Timeline list (duties)

- **Dates:** Horizontal line and vertical tick from shared CSS in `globals.css`:  
  `.duty-timeline-date`, `.duty-timeline-date--today` (with `::before` / `::after`).
- **Cards:** Same card rules as above; `border-l-[3px]` + type class; optional flip card for contacts (see `DutyTimelineCard.tsx`).

---

## 6. Motion and performance

### 6.1 Timing

- **Tokens:** `--transition-fast: 0.15s`, `--transition-normal: 0.25s`, `--ease-out: cubic-bezier(0.32, 0.72, 0, 1)`.
- Use these for transitions and short animations so behaviour is consistent and predictable.

### 6.2 Reduced motion

- **Rule:** `@media (prefers-reduced-motion: reduce)` in `globals.css` shortens animation and transition durations globally. New animations should remain optional or short so they degrade gracefully when reduced.

### 6.3 Android low-performance devices

- **Detection:** `webapp-next/src/lib/telegram-android-perf.ts` reads Telegram’s User-Agent and sets `data-perf="low"` on the document root when the device performance class is LOW.
- **CSS:** `[data-perf="low"] *` in `globals.css` minimizes animation/transition duration. Avoid adding heavy or long animations without considering this; prefer simple or no animation on low-end devices.

---

## 7. Accessibility

- **Focus:** Use `focus-visible:outline-accent` (or equivalent ring) on interactive elements; do not remove focus outline without a visible alternative.
- **Calendar:** Use `role="grid"` and `role="gridcell"`, `aria-label` on nav buttons (e.g. “Previous month”), and a composite `aria-label` on each day cell (date + event types). See `webapp-next/src/components/calendar/CalendarDay.tsx`.
- **Images and inputs:** Always provide labels (per Telegram’s guidelines and WCAG).

---

## 8. Telegram integration

- **Header and background:** On init (layout script and `use-telegram-theme.ts`), call:
  - `setBackgroundColor('bg_color')`
  - `setHeaderColor('bg_color')`
  - `setBottomBarColor('bottom_bar_bg_color')` when available (Bot API 7.10+).
- **Surface contrast:** When `--surface` equals `--bg` (e.g. some iOS OLED themes), `fixSurfaceContrast()` in `use-telegram-theme.ts` adjusts `--surface` using ThemeParams or a light color-mix so cards and panels remain visible.

---

## 9. Checklist for new screens and components

Use this for review when adding or changing UI:

- [ ] Use only design tokens from `globals.css` and Tailwind/shadcn aliases; no hardcoded colours.
- [ ] Page wrapper has `.content-safe`, `max-w-[var(--max-width-app)]`, and appropriate min-height (viewport-stable-height or `min-h-screen` with fallback).
- [ ] Buttons and cards follow the patterns above (variants, surfaces, border-l by type).
- [ ] Safe area is respected for bottom padding and for sheets/modals.
- [ ] Interactive elements and grids/lists have appropriate `aria-label`s and roles.
- [ ] New animations respect `prefers-reduced-motion` and `data-perf="low"` (short or minimal on low-end Android).
