mobile-ux-improver
npx skills add https://github.com/ramunasnognys/workflow-template --skill mobile-ux-improver
Agent 安装分布
Skill 文档
Mobile UX Improver
Purpose
Enforce mobile-first UX best practices to ensure exceptional mobile web experiences. This skill prevents common mobile UX mistakes and guides implementation of touch-friendly, responsive, performant interfaces.
When to Use
Auto-triggers when:
- Editing mobile UI components
- Working with responsive layouts
- Implementing touch interactions
- Optimizing mobile performance
- Using Tailwind responsive classes (sm:, md:, lg:)
- Handling mobile gestures
Manual trigger when:
- Reviewing mobile UX
- Implementing new mobile features
- Debugging mobile-specific issues
Quick Reference
Touch Targets
Minimum Sizes:
- â 48px à 48px (recommended)
- â ï¸ 44px à 44px (absolute minimum)
- â < 44px (too small, avoid)
Spacing:
- 8px minimum between interactive elements
- 12px+ recommended for frequently used controls
Responsive Breakpoints (Tailwind)
// Mobile-first approach
<div className="w-full md:w-1/2 lg:w-1/3">
// Breakpoints
sm: 640px // Small tablets
md: 768px // Tablets
lg: 1024px // Small desktops
xl: 1280px // Large desktops
2xl: 1536px // Extra large
Performance Targets
- First Contentful Paint: < 1.8s
- Time to Interactive: < 3.8s
- Cumulative Layout Shift: < 0.1
- Largest Contentful Paint: < 2.5s
Core Principles
1. Mobile-First Design
Always start with mobile layout:
// â
CORRECT - Mobile first, then desktop
<button className="w-full px-4 py-3 md:w-auto md:px-6">
Tap Me
</button>
// â WRONG - Desktop first
<button className="w-auto px-6 sm:w-full sm:px-4">
Tap Me
</button>
Why: Mobile constraints force better UX decisions, easier to scale up than down.
2. Touch-Friendly Targets
Minimum interactive area:
// â
CORRECT - 48px touch target
<button className="min-h-[48px] min-w-[48px] p-3">
<Icon className="w-6 h-6" />
</button>
// â WRONG - Too small
<button className="p-1">
<Icon className="w-4 h-4" />
</button>
Spacing between targets:
// â
CORRECT - Adequate spacing
<div className="flex gap-3">
<button className="p-3">A</button>
<button className="p-3">B</button>
</div>
// â WRONG - Targets too close
<div className="flex gap-1">
<button className="p-1">A</button>
<button className="p-1">B</button>
</div>
3. Responsive Typography
Use relative units for mobile:
// â
CORRECT - Scales with viewport
<h1 className="text-2xl md:text-4xl lg:text-5xl">
Heading
</h1>
// â
CORRECT - Clamp for fluid scaling
<p className="text-base leading-relaxed">
Body text
</p>
// â ï¸ AVOID - Fixed pixel sizes
<h1 style={{ fontSize: '60px' }}>
Heading
</h1>
4. Viewport Configuration
Required meta tag:
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=5">
Why maximum-scale=5: Allows zoom for accessibility while preventing excessive zoom accidents.
Touch Targets & Spacing
Target Sizing Chart
| Element Type | Minimum Size | Recommended Size | Spacing |
|---|---|---|---|
| Primary Button | 44px | 48px | 12px |
| Icon Button | 44px | 48px | 8px |
| Link in Text | 44px height | 48px height | 8px vertical |
| Checkbox/Radio | 44px | 48px | 12px |
| Slider Thumb | 44px | 48px | N/A |
Common Patterns
Primary Action Button:
<button className="w-full px-6 py-4 text-lg font-semibold rounded-lg bg-brand-blue text-white hover:bg-blue-600 active:bg-blue-700 transition-colors min-h-[48px]">
Continue
</button>
Icon Button:
<button
className="p-3 rounded-full hover:bg-gray-100 active:bg-gray-200 transition-colors min-h-[48px] min-w-[48px] flex items-center justify-center"
aria-label="Close"
>
<XIcon className="w-6 h-6" />
</button>
List of Links:
<nav className="space-y-2">
{links.map(link => (
<a
key={link.id}
href={link.url}
className="block px-4 py-3 text-base hover:bg-gray-50 active:bg-gray-100 rounded-lg min-h-[48px]"
>
{link.label}
</a>
))}
</nav>
ð Complete Guide: resources/touch-targets-guide.md
Responsive Design
Mobile-First Approach
Start with mobile, enhance for larger screens:
// Layout structure
<div className="
flex flex-col gap-4 /* Mobile: stack vertically */
md:flex-row md:gap-6 /* Tablet: horizontal */
lg:gap-8 /* Desktop: more spacing */
">
<aside className="w-full md:w-64 lg:w-80">
Sidebar
</aside>
<main className="flex-1">
Content
</main>
</div>
Container Patterns
Responsive containers:
// Full-width on mobile, constrained on desktop
<div className="
w-full px-4 /* Mobile: full width, padding */
md:px-6 /* Tablet: more padding */
lg:max-w-7xl lg:mx-auto lg:px-8 /* Desktop: centered, max width */
">
{children}
</div>
Grid Layouts
Responsive grid:
<div className="
grid grid-cols-1 gap-4 /* Mobile: 1 column */
sm:grid-cols-2 sm:gap-6 /* Small tablet: 2 columns */
lg:grid-cols-3 lg:gap-8 /* Desktop: 3 columns */
">
{items.map(item => (
<Card key={item.id} {...item} />
))}
</div>
Hiding/Showing Elements
Conditional visibility:
// Mobile menu vs desktop nav
<>
{/* Mobile menu button */}
<button className="md:hidden p-3">
<MenuIcon />
</button>
{/* Desktop navigation */}
<nav className="hidden md:flex gap-6">
<NavLink href="/about">About</NavLink>
<NavLink href="/contact">Contact</NavLink>
</nav>
</>
ð Complete Guide: resources/responsive-patterns.md
Mobile Gestures
Horizontal Scrolling
Swipeable container:
<div className="
flex gap-4 overflow-x-auto snap-x snap-mandatory
scrollbar-hide /* Hide scrollbar on mobile */
pb-4 /* Padding for scroll indicator */
-mx-4 px-4 /* Edge-to-edge on mobile */
md:mx-0 md:px-0 /* Contained on desktop */
">
{items.map(item => (
<div
key={item.id}
className="flex-shrink-0 w-72 snap-center"
>
<Card {...item} />
</div>
))}
</div>
Pull-to-Refresh
Implement with overscroll-behavior:
<main className="
overscroll-contain /* Prevent chain scrolling */
overflow-y-auto
h-screen
">
{content}
</main>
Scroll Behavior
Smooth scrolling:
// Global CSS or Tailwind
<html className="scroll-smooth">
// Component-level
<div className="overflow-y-auto scroll-smooth">
{longContent}
</div>
ð Complete Guide: resources/mobile-gestures.md
Performance Optimization
Image Optimization
Responsive images:
<img
src="/hero-mobile.jpg"
srcSet="
/hero-mobile.jpg 640w,
/hero-tablet.jpg 1024w,
/hero-desktop.jpg 1920w
"
sizes="
(max-width: 640px) 100vw,
(max-width: 1024px) 50vw,
33vw
"
alt="Hero image"
loading="lazy"
className="w-full h-auto"
/>
Lazy Loading
Component lazy loading:
import { lazy, Suspense } from 'react';
const HeavyComponent = lazy(() => import('./HeavyComponent'));
function Page() {
return (
<Suspense fallback={<LoadingSpinner />}>
<HeavyComponent />
</Suspense>
);
}
Font Loading
Optimize web fonts:
<link
rel="preload"
href="/fonts/custom-font.woff2"
as="font"
type="font/woff2"
crossorigin
/>
ð Complete Guide: resources/mobile-performance.md
Accessibility for Mobile
Screen Reader Support
Proper labeling:
<button
aria-label="Close dialog"
className="p-3"
>
<XIcon className="w-6 h-6" />
</button>
Focus Management
Keyboard + touch support:
<button className="
p-3 rounded-lg
focus:outline-none focus:ring-2 focus:ring-brand-blue focus:ring-offset-2
active:bg-gray-100
">
Action
</button>
Color Contrast
WCAG AA minimum:
- Normal text: 4.5:1
- Large text: 3:1
- Interactive elements: 3:1
Common Anti-Patterns to Avoid
â Don’t: Hover-Only Interactions
// â WRONG - No hover on touch devices
<div className="hover:visible">
Hidden content
</div>
// â
CORRECT - Click/tap to reveal
<button onClick={() => setVisible(true)}>
Show content
</button>
â Don’t: Fixed Positioning That Blocks Content
// â WRONG - Header blocks content
<header className="fixed top-0 w-full h-16 bg-white">
<main className="pt-0"> /* Content hidden behind header */
// â
CORRECT - Account for header
<header className="fixed top-0 w-full h-16 bg-white z-10">
<main className="pt-16"> /* Content starts below header */
â Don’t: Tiny Text
// â WRONG - Unreadable on mobile
<p className="text-xs">
Important information
</p>
// â
CORRECT - Readable base size
<p className="text-base md:text-sm">
Important information
</p>
â Don’t: Disable Zoom
<!-- â WRONG - Prevents accessibility -->
<meta name="viewport" content="user-scalable=no, maximum-scale=1">
<!-- â
CORRECT - Allow zoom for accessibility -->
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=5">
Example: Mobile-Optimized Component
Complete touch-friendly card:
import React from 'react';
interface ProductCardProps {
title: string;
price: number;
image: string;
onAddToCart: () => void;
}
export const ProductCard: React.FC<ProductCardProps> = ({
title,
price,
image,
onAddToCart
}) => {
return (
<div className="
bg-white rounded-lg shadow-sm overflow-hidden
hover:shadow-md transition-shadow
w-full /* Mobile: full width */
sm:w-64 /* Tablet: fixed width */
">
<img
src={image}
alt={title}
loading="lazy"
className="w-full h-48 object-cover"
/>
<div className="p-4">
<h3 className="text-lg font-semibold mb-2 line-clamp-2">
{title}
</h3>
<p className="text-2xl font-bold text-brand-blue mb-4">
${price.toFixed(2)}
</p>
<button
onClick={onAddToCart}
className="
w-full px-6 py-3 rounded-lg
bg-brand-blue text-white font-semibold
hover:bg-blue-600 active:bg-blue-700
transition-colors
min-h-[48px] /* Touch-friendly height */
focus:outline-none focus:ring-2 focus:ring-brand-blue focus:ring-offset-2
"
aria-label={`Add ${title} to cart`}
>
Add to Cart
</button>
</div>
</div>
);
};
export default ProductCard;
Testing Mobile UX
Manual Testing Checklist
- Test on real mobile devices (iOS, Android)
- Verify touch targets are 44px+ minimum
- Check text is readable without zoom
- Test horizontal scrolling with touch
- Verify forms work with mobile keyboards
- Test landscape + portrait orientations
- Check performance on slow connections
- Verify hover states have touch alternatives
- Test with screen reader (VoiceOver, TalkBack)
- Check color contrast meets WCAG AA
Browser DevTools
Chrome DevTools Mobile Emulation:
- Open DevTools (F12)
- Toggle device toolbar (Cmd+Shift+M / Ctrl+Shift+M)
- Select device or custom dimensions
- Enable touch emulation
- Test throttling (3G, 4G networks)
Reference Existing Components
Good examples in your codebase:
FilterPill.tsx– Touch-friendly pill buttons with proper spacingTeamCard.tsx– Responsive card layout with touch interactionsFab.tsx– Floating action button with proper touch target
Related Skills
- frontend-dev-guidelines: React/TypeScript best practices
- seo-specialist: Mobile SEO optimization
- error-tracking: Performance monitoring
Skill Status: Active guardrail – Enforces mobile UX quality Line Count: < 500 (following 500-line rule) â Progressive Disclosure: Reference files for detailed guides â