# MRT-M03: Mobile UX guidelines for widget
**Area:** Mobile-Responsive Testing
**Model:** minimax/minimax-m2.5
**Tokens:** 3,164
**Cost:** $0.0032
**Time:** 4134ms
**Timestamp:** 2026-02-16T12:17:42.790826

---

# Mobile UX Guidelines — Sunaiva Talking Widget

**Document Type:** Production Specification  
**Version:** 1.0  
**Applies To:** Mobile web implementations (iOS Safari, Android Chrome)  
**Last Updated:** January 2025

---

## Overview

These guidelines ensure the Sunaiva Talking Widget delivers a consistent, accessible, and performant experience across mobile devices. They complement the broader Sunaiva Design System and should be treated as binding for all frontend implementations.

All dimensions assume a 1x (baseline) pixel density. Apply appropriate device pixel ratio (DPR) scaling for high-density displays.

---

## 1. Touch Target Sizing

### 1.1 Minimum Dimensions

All interactive elements must meet or exceed **44×44 CSS pixels** (equivalent to 44×44 points on iOS, 44×44dp on Android). This aligns with WCAG 2.1 Level AA success criterion 2.5.5 (Target Size) and Apple HIG recommendations.

| Element | Minimum Size | Recommended Size |
|---------|--------------|------------------|
| Primary trigger (FAB) | 44×44 px | 56×56 px |
| Secondary actions (buttons) | 44×44 px | 48×48 px |
| Close / minimize button | 44×44 px | 44×44 px |
| Input field tap target | Full width × 48 px height | Full width × 52 px height |
| List items / menu options | 44×44 px | Full width × 48 px |

### 1.2 Spacing Between Targets

- Maintain **minimum 8px spacing** between adjacent touch targets to prevent accidental activation of neighboring elements.
- In list views or menu systems, use **full-width tappable rows** with a minimum touch target of 44px height per row.

### 1.3 Hit Area Extensions

For small icons without text labels (e.g., close button, microphone toggle), visually render at 24×24 px but wrap in a **44×44 px hit area** via padding or an invisible overlay element.

```css
/* Example: Icon button with expanded hit area */
.widget-close-btn {
  width: 24px;
  height: 24px;
  padding: 10px; /* Creates 44×44 effective hit area */
  box-sizing: content-box;
}
```

---

## 2. Typography for Mobile Readability

### 2.1 Base Font Scale

All font sizes below are specified in CSS pixels. Apply a base font size of **16px** on the widget container to ensure readability without forcing users to zoom.

| Element | Font Size | Line Height | Font Weight |
|---------|-----------|-------------|-------------|
| Widget title / header | 18px | 1.3 | 600 (semibold) |
| Body text / messages | 16px | 1.5 | 400 (regular) |
| Button labels | 16px | 1.0 | 600 (semibold) |
| Secondary text / timestamps | 13px | 1.4 | 400 (regular) |
| Status labels | 12px | 1.2 | 500 (medium) |
| Badge text | 11px | 1.0 | 600 (semibold) |

### 2.2 Contrast Requirements

- **Primary text:** Minimum 4.5:1 contrast ratio against the widget background.
- **Secondary text:** Minimum 3:1 contrast ratio.
- **Icon-only buttons:** Include `aria-label` for screen readers; visual contrast must meet 3:1 for the icon against its background.

### 2.3 Text Handling

- Enable font smoothing (`-webkit-font-smoothing: antialiased`) for crisp text on Retina displays.
- Set `text-rendering: optimizeLegibility` for improved glyph rendering.
- Truncate long text with ellipsis after **2 lines** for body text, **1 line** for titles. Never truncate button labels.

---

## 3. Widget Positioning on Mobile

### 3.1 Position Selection: Bottom-Center

**Use bottom-center positioning on mobile devices (viewport width ≤ 768px).**

| Reason | Detail |
|--------|--------|
| Thumb reach | Bottom-center aligns with the natural thumb zone on both portrait and landscape orientations. |
| OS gesture compatibility | Reduces conflict with iOS home indicator and Android navigation gestures that occupy the bottom-right corner. |
| Content safety | Ensures the widget does not overlap with website footers or mobile navigation bars. |
| Visual balance | Provides symmetrical placement that feels intentional rather than an afterthought. |

### 3.2 Desktop Fallback

On viewports > 768px, revert to **bottom-right** positioning with 24px margins from the viewport edges.

### 3.3 Safe Area and Margins

- Apply **minimum 16px margin** from the viewport edges on all sides.
- Account for **dynamic safe areas** on iOS devices with notches or home indicators:

```css
/* Safe area insets for iOS */
@supports (padding-bottom: env(safe-area-inset-bottom)) {
  .sunaiva-widget {
    bottom: calc(16px + env(safe-area-inset-bottom));
    right: 16px; /* or left: 16px for bottom-center on mobile */
  }
}
```

### 3.4 Collision Detection

- The widget must detect and avoid overlapping fixed-position elements on the host page (e.g., sticky footers, cookie banners, mobile nav bars).
- Implement a **12px buffer** between the widget and any detected collision zone.
- If insufficient space exists at the bottom, elevate the widget to **16px from the top** of the viewport.

### 3.5 Position Summary

| Viewport | Position | Horizontal Offset | Vertical Offset |
|----------|----------|-------------------|-----------------|
| ≤ 768px (mobile) | Bottom-center | `left: 50%; transform: translateX(-50%)` | 16px from bottom (+ safe area) |
| > 768px (desktop) | Bottom-right | 24px from right | 24px from bottom |

---

## 4. Animation Performance

### 4.1 Frame Rate Budget

Target **60 frames per second** (16.67ms per frame). Frame times exceeding 16.67ms result in jank perceptible to users.

| Animation Type | Duration | Easing |
|----------------|----------|--------|
| Micro-interactions (button press, toggle) | 150–200ms | `ease-out` |
| Widget open / close (expand/collapse) | 250–300ms | `cubic-bezier(0.4, 0.0, 0.2, 1)` (Material standard) |
| Subtle fade transitions | 200–250ms | `ease-in-out` |
| Loading spinners | Continuous | Linear rotation |

### 4.2 Performance Constraints

- **Composite-only properties:** Animate only `transform` (translate, scale, rotate) and `opacity`. These properties do not trigger layout or paint recalculations.
- **Avoid animating:** `width`, `height`, `margin`, `padding`, `top`, `left`, `font-size`. These trigger layout thrashing.
- **GPU acceleration:** Apply `will-change: transform, opacity` to elements being animated, but remove the property once animations complete to avoid memory overhead.

```css
/* Example: Optimized open animation */
.widget-panel {
  opacity: 0;
  transform: translateY(20px) scale(0.95);
  will-change: transform, opacity;
  transition: opacity 280ms cubic-bezier(0.4, 0.0, 0.2, 1),
              transform 280ms cubic-bezier(0.4, 0.0, 0.2, 1);
}

.widget-panel.is-open {
  opacity: 1;
  transform: translateY(0) scale(1);
}
```

### 4.3 Motion Sensitivity

- Respect the `prefers-reduced-motion` media query. When enabled, disable all non-essential animations and transitions:

```css
@media (prefers-reduced-motion: reduce) {
  .sunaiva-widget * {
    animation: none !important;
    transition: none !important;
  }
}
```

### 4.4 Performance Budget Targets

| Metric | Target | Threshold |
|--------|--------|-----------|
| First paint (widget visible) | < 500ms | 1000ms |
| Interaction-to-response | < 100ms | 200ms |
| Animation frame time | < 16.67ms | 33.33ms (locked to 30fps minimum) |
| Memory footprint | < 50MB | 100MB |

---

## 5. Gesture Expectations

### 5.1 Supported Gestures

| Gesture | Element | Action | Feedback |
|---------|---------|--------|----------|
| **Tap** | FAB / trigger button | Open widget panel | Scale down to 0.95, then release (press effect) |
| **Tap** | Close button | Close widget panel | Opacity fade + scale to 0.9 |
| **Tap** | Action buttons (call, message, menu) | Execute action | Ripple effect or background highlight |
| **Tap** | Input field | Focus for text entry | Border color change, keyboard appears |
| **Vertical scroll** | Message list / content area | Scroll through messages | Native scroll behavior with momentum |
| **Swipe left** | Individual message (optional) | Reveal actions (delete, copy) | Slide reveal with shadow |

### 5.2 Gesture Conflicts

- **Do not implement horizontal swipe to close.** This conflicts with browser back/forward navigation gestures on iOS and Android.
- **Do not implement pull-to-refresh** within the widget. It conflicts with the same gesture on the host page.
- If implementing swipe-to-dismiss, restrict it to **swipe down only** and require a threshold of 100px before triggering close.

### 5.3 Touch Feedback

- All tappable elements must provide visual feedback within **100ms** of touch.
- Use the `:active` CSS state or a JavaScript touch handler to apply momentary styling changes (scale, opacity, or background color shifts).

### 5.4 Gesture Detection Rules

- Distinguish between taps and scrolls by monitoring **touchmove** delta. If vertical movement exceeds 10px, treat as scroll; otherwise, treat as tap.
- Implement **touch delay bypass** (`touch-action: manipulation`) on interactive elements to eliminate the 300ms tap delay on mobile browsers:

```css
.sunaiva-widget button,
.sunaiva-widget a {
  touch-action: manipulation;
}
```

---

## Quick Reference Summary

| Guideline | Requirement |
|-----------|-------------|
| Minimum touch target | 44×44 px |
| Base font size | 16 px |
| Mobile position | Bottom-center, 16px from edge |
| Desktop position | Bottom-right, 24px from edge |
| Animation duration (open/close) | 250–300 ms |
| Animation properties | `transform`, `opacity` only |
| Frame rate target | 60 fps |
| Reduced motion | Honor `prefers-reduced-motion` |
| Gesture feedback | < 100ms visual response |
| Safe area support | Required for iOS notched devices |

---

*This document is part of the Sunaiva Talking Widget Design Specification. For component props, API references, or brand guidelines, see the main Sunaiva Design System documentation.*