@elsahafy/ux-mcp-server 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,353 @@
1
+ {
2
+ "name": "React Component Patterns",
3
+ "description": "Advanced React patterns for component composition, state management, and performance",
4
+ "composition_patterns": {
5
+ "compound_components": {
6
+ "description": "Components that work together to form a cohesive UI",
7
+ "use_when": "Building flexible, customizable components (tabs, select, accordion)",
8
+ "example": "<Tabs>\n <TabList>\n <Tab>Tab 1</Tab>\n <Tab>Tab 2</Tab>\n </TabList>\n <TabPanels>\n <TabPanel>Panel 1</TabPanel>\n <TabPanel>Panel 2</TabPanel>\n </TabPanels>\n</Tabs>",
9
+ "implementation": "Use React.Children or Context to share state",
10
+ "benefits": [
11
+ "Flexible API",
12
+ "Clear component relationships",
13
+ "Easier to customize"
14
+ ],
15
+ "libraries": ["Radix UI", "Reach UI", "Headless UI"]
16
+ },
17
+ "render_props": {
18
+ "description": "Pass function as children/prop to share logic",
19
+ "use_when": "Need to share behavior with different rendering",
20
+ "example": "<Mouse>\n {({ x, y }) => (\n <div>Mouse position: {x}, {y}</div>\n )}\n</Mouse>",
21
+ "modern_alternative": "Custom hooks (usually preferred now)",
22
+ "still_useful": "When component needs to own the DOM structure"
23
+ },
24
+ "higher_order_components": {
25
+ "description": "Function that takes component, returns enhanced component",
26
+ "use_when": "Legacy codebases, some library patterns",
27
+ "example": "const EnhancedComponent = withAuth(MyComponent);",
28
+ "modern_alternative": "Hooks (strongly preferred)",
29
+ "drawbacks": [
30
+ "Wrapper hell",
31
+ "Props collision",
32
+ "Hard to follow in DevTools"
33
+ ],
34
+ "legacy": "Mostly replaced by hooks, but still used in some libraries"
35
+ },
36
+ "custom_hooks": {
37
+ "description": "Extract and reuse stateful logic",
38
+ "use_when": "Share logic between components",
39
+ "naming": "Always start with 'use' prefix",
40
+ "examples": {
41
+ "data_fetching": "function useFetch(url) {\n const [data, setData] = useState(null);\n const [loading, setLoading] = useState(true);\n \n useEffect(() => {\n fetch(url)\n .then(res => res.json())\n .then(setData)\n .finally(() => setLoading(false));\n }, [url]);\n \n return { data, loading };\n}",
42
+ "local_storage": "function useLocalStorage(key, initial) {\n const [value, setValue] = useState(() => {\n const stored = localStorage.getItem(key);\n return stored ? JSON.parse(stored) : initial;\n });\n \n useEffect(() => {\n localStorage.setItem(key, JSON.stringify(value));\n }, [key, value]);\n \n return [value, setValue];\n}"
43
+ },
44
+ "best_practices": [
45
+ "Return values consistently (tuple or object)",
46
+ "Handle cleanup in useEffect",
47
+ "Memoize expensive computations",
48
+ "Follow hooks rules (top level, React functions only)"
49
+ ]
50
+ },
51
+ "slots_pattern": {
52
+ "description": "Named placeholders for content injection",
53
+ "implementation": "Props for different content areas",
54
+ "example": "<Card\n header={<CardHeader title='Title' />}\n footer={<CardFooter>Actions</CardFooter>}\n>\n Card content\n</Card>",
55
+ "benefits": [
56
+ "Clear API",
57
+ "Type-safe with TypeScript",
58
+ "Better than many boolean props"
59
+ ]
60
+ },
61
+ "provider_pattern": {
62
+ "description": "Context API for sharing state down tree",
63
+ "use_when": "Data needed by many nested components (theme, auth, etc.)",
64
+ "example": "const ThemeContext = createContext();\n\nfunction ThemeProvider({ children }) {\n const [theme, setTheme] = useState('light');\n return (\n <ThemeContext.Provider value={{ theme, setTheme }}>\n {children}\n </ThemeContext.Provider>\n );\n}\n\nfunction useTheme() {\n const context = useContext(ThemeContext);\n if (!context) throw new Error('useTheme must be used within ThemeProvider');\n return context;\n}",
65
+ "best_practices": [
66
+ "Split contexts by update frequency",
67
+ "Provide custom hook for consuming",
68
+ "Validate context exists",
69
+ "Memoize context value if expensive"
70
+ ],
71
+ "optimization": "Use useMemo for context value to prevent re-renders"
72
+ }
73
+ },
74
+ "state_management": {
75
+ "local_state": {
76
+ "use_when": "State only needed in component/small tree",
77
+ "tools": ["useState", "useReducer"],
78
+ "example": "const [count, setCount] = useState(0);",
79
+ "prefer": "Keep state as local as possible"
80
+ },
81
+ "lifted_state": {
82
+ "description": "State shared between siblings via common parent",
83
+ "use_when": "Multiple components need same state",
84
+ "pattern": "Lift state to nearest common ancestor"
85
+ },
86
+ "url_state": {
87
+ "description": "State stored in URL (query params, hash)",
88
+ "use_when": "Need shareable/bookmarkable state (filters, search, pagination)",
89
+ "benefits": [
90
+ "Shareable links",
91
+ "Back button works",
92
+ "No re-fetch on refresh"
93
+ ],
94
+ "libraries": ["React Router", "Next.js router", "TanStack Router"]
95
+ },
96
+ "global_state": {
97
+ "context": {
98
+ "use_when": "Shared state, low update frequency",
99
+ "pros": ["Built-in", "No extra library"],
100
+ "cons": ["Can cause unnecessary re-renders"]
101
+ },
102
+ "zustand": {
103
+ "use_when": "Simple global state",
104
+ "pros": ["Minimal API", "No providers", "Good DevTools"],
105
+ "cons": ["Less ecosystem than Redux"]
106
+ },
107
+ "redux": {
108
+ "use_when": "Complex state, time-travel debugging needed",
109
+ "pros": ["Mature ecosystem", "Excellent DevTools", "Predictable"],
110
+ "cons": ["Boilerplate", "Learning curve"]
111
+ },
112
+ "jotai": {
113
+ "use_when": "Atomic state management",
114
+ "pros": ["Minimal boilerplate", "TypeScript-first"],
115
+ "cons": ["Smaller ecosystem"]
116
+ },
117
+ "recommendation": "Start with Context/useState, add library when needed"
118
+ },
119
+ "server_state": {
120
+ "description": "Data from server (different from client state)",
121
+ "tools": {
122
+ "react_query": {
123
+ "use": "Data fetching, caching, synchronization",
124
+ "features": ["Auto refetch", "Caching", "Optimistic updates", "Infinite scroll"],
125
+ "recommended": "Yes - industry standard"
126
+ },
127
+ "swr": {
128
+ "use": "Similar to React Query, lighter weight",
129
+ "features": ["Stale-while-revalidate", "Focus refetch", "Offline support"]
130
+ },
131
+ "rtk_query": {
132
+ "use": "Redux Toolkit's data fetching (if already using Redux)",
133
+ "integration": "Tight Redux integration"
134
+ }
135
+ },
136
+ "best_practice": "Separate server state from client state"
137
+ }
138
+ },
139
+ "performance_patterns": {
140
+ "memoization": {
141
+ "react_memo": {
142
+ "use": "Prevent re-render if props haven't changed",
143
+ "example": "const MemoizedComponent = React.memo(MyComponent);",
144
+ "when": "Expensive render or frequent parent re-renders",
145
+ "note": "Shallow comparison by default, can provide custom compare"
146
+ },
147
+ "use_memo": {
148
+ "use": "Memoize expensive computations",
149
+ "example": "const sortedList = useMemo(() => list.sort(compareFn), [list]);",
150
+ "when": "Expensive calculations, derived data",
151
+ "avoid": "Don't memoize everything (overhead exists)"
152
+ },
153
+ "use_callback": {
154
+ "use": "Memoize function reference",
155
+ "example": "const handleClick = useCallback(() => doSomething(), []);",
156
+ "when": "Passing callback to memoized child or useEffect dependency",
157
+ "note": "Only needed if child is memoized or in dependency array"
158
+ }
159
+ },
160
+ "code_splitting": {
161
+ "lazy_loading": {
162
+ "use": "Load components on demand",
163
+ "example": "const HeavyComponent = React.lazy(() => import('./HeavyComponent'));\n\nfunction App() {\n return (\n <Suspense fallback={<Loading />}>\n <HeavyComponent />\n </Suspense>\n );\n}",
164
+ "benefits": [
165
+ "Smaller initial bundle",
166
+ "Faster first load",
167
+ "Better Core Web Vitals"
168
+ ],
169
+ "use_for": [
170
+ "Route-based splitting",
171
+ "Modal/dialog content",
172
+ "Tabs not initially visible",
173
+ "Below-fold features"
174
+ ]
175
+ },
176
+ "dynamic_import": {
177
+ "use": "Load code only when needed",
178
+ "example": "const handleExport = async () => {\n const { exportToPDF } = await import('./export');\n exportToPDF(data);\n};"
179
+ }
180
+ },
181
+ "virtualization": {
182
+ "description": "Render only visible items in long lists",
183
+ "use_when": "Lists with 100+ items",
184
+ "libraries": [
185
+ "react-window (recommended, lightweight)",
186
+ "react-virtualized (feature-rich, larger)",
187
+ "TanStack Virtual (framework agnostic)"
188
+ ],
189
+ "benefit": "Massive performance improvement for long lists",
190
+ "example": "<FixedSizeList\n height={600}\n itemCount={1000}\n itemSize={35}\n>\n {({ index, style }) => <div style={style}>Row {index}</div>}\n</FixedSizeList>"
191
+ },
192
+ "debounce_throttle": {
193
+ "debounce": {
194
+ "use": "Wait for user to stop typing before action",
195
+ "example": "Search input - wait 300ms after last keystroke",
196
+ "implementation": "useDeferredValue or custom hook with setTimeout"
197
+ },
198
+ "throttle": {
199
+ "use": "Limit frequency of function calls",
200
+ "example": "Scroll/resize handlers - max once per 100ms",
201
+ "implementation": "Custom hook or library (lodash)"
202
+ }
203
+ },
204
+ "suspense": {
205
+ "description": "Declarative loading states",
206
+ "use": "With React.lazy and data fetching (future)",
207
+ "example": "<Suspense fallback={<Skeleton />}>\n <AsyncComponent />\n</Suspense>",
208
+ "benefits": [
209
+ "Declarative loading",
210
+ "Better UX with skeletons",
211
+ "Coordinates multiple async components"
212
+ ]
213
+ },
214
+ "transitions": {
215
+ "use_transition": {
216
+ "use": "Mark updates as non-urgent",
217
+ "example": "const [isPending, startTransition] = useTransition();\n\nstartTransition(() => {\n setSearchResults(heavyFilter(query));\n});",
218
+ "benefit": "Keep UI responsive during heavy updates"
219
+ },
220
+ "use_deferred_value": {
221
+ "use": "Defer updating a value",
222
+ "example": "const deferredQuery = useDeferredValue(query);",
223
+ "benefit": "Similar to useTransition, for values instead of updates"
224
+ }
225
+ }
226
+ },
227
+ "data_fetching_patterns": {
228
+ "fetch_on_render": {
229
+ "description": "Fetch data in useEffect",
230
+ "example": "useEffect(() => {\n fetch('/api/data').then(r => r.json()).then(setData);\n}, []);",
231
+ "issues": [
232
+ "Waterfall requests",
233
+ "No caching",
234
+ "Manual loading/error states"
235
+ ],
236
+ "better": "Use React Query or SWR"
237
+ },
238
+ "fetch_then_render": {
239
+ "description": "Fetch before rendering component",
240
+ "use": "Server-side rendering, route loaders",
241
+ "example": "Next.js getServerSideProps, Remix loaders"
242
+ },
243
+ "render_as_fetch": {
244
+ "description": "Start fetching when component renders (Suspense)",
245
+ "future": "React Server Components",
246
+ "benefit": "Parallel data fetching"
247
+ },
248
+ "prefetching": {
249
+ "description": "Load data before it's needed",
250
+ "use_when": "Predictable user paths (hover link, pagination)",
251
+ "example": "const queryClient = useQueryClient();\nqueryClient.prefetchQuery({ queryKey: ['post', id] });"
252
+ },
253
+ "optimistic_updates": {
254
+ "description": "Update UI before server confirms",
255
+ "use_when": "Good network, recoverable actions (like, vote)",
256
+ "example": "mutation.mutate(newData, {\n onMutate: async (newData) => {\n await queryClient.cancelQueries(['posts']);\n const prev = queryClient.getQueryData(['posts']);\n queryClient.setQueryData(['posts'], old => [...old, newData]);\n return { prev };\n },\n onError: (err, newData, context) => {\n queryClient.setQueryData(['posts'], context.prev);\n }\n});",
257
+ "benefit": "Instant feedback, better UX"
258
+ }
259
+ },
260
+ "error_handling": {
261
+ "error_boundary": {
262
+ "description": "Catch React errors in component tree",
263
+ "example": "class ErrorBoundary extends React.Component {\n state = { hasError: false };\n \n static getDerivedStateFromError(error) {\n return { hasError: true };\n }\n \n componentDidCatch(error, info) {\n console.error('Error:', error, info);\n }\n \n render() {\n if (this.state.hasError) {\n return <ErrorFallback />;\n }\n return this.props.children;\n }\n}",
264
+ "use": "Wrap app sections to prevent full app crash",
265
+ "note": "Only catches render errors, not async or event handlers",
266
+ "libraries": ["react-error-boundary (recommended)"]
267
+ },
268
+ "async_error_handling": {
269
+ "try_catch": "Wrap async calls in try-catch",
270
+ "react_query": "Built-in error handling",
271
+ "example": "const { data, error, isError } = useQuery({\n queryKey: ['posts'],\n queryFn: fetchPosts,\n retry: 3\n});\n\nif (isError) return <ErrorMessage error={error} />;"
272
+ }
273
+ },
274
+ "accessibility_patterns": {
275
+ "focus_management": {
276
+ "use_ref": "Get reference to DOM elements",
277
+ "focus_trap": "Keep focus inside modal",
278
+ "restore_focus": "Return focus after closing modal",
279
+ "example": "const previousFocus = useRef();\n\nuseEffect(() => {\n if (isOpen) {\n previousFocus.current = document.activeElement;\n modalRef.current?.focus();\n return () => previousFocus.current?.focus();\n }\n}, [isOpen]);"
280
+ },
281
+ "keyboard_navigation": {
282
+ "arrow_keys": "Handle in onKeyDown",
283
+ "escape": "Close modals, clear search",
284
+ "enter_space": "Activate buttons/links",
285
+ "example": "const handleKeyDown = (e) => {\n if (e.key === 'Escape') close();\n if (e.key === 'ArrowDown') focusNext();\n};"
286
+ },
287
+ "aria_attributes": {
288
+ "live_regions": "Announce dynamic content",
289
+ "example": "<div role='status' aria-live='polite'>{message}</div>",
290
+ "labels": "aria-label, aria-labelledby for context",
291
+ "states": "aria-expanded, aria-selected, aria-checked"
292
+ }
293
+ },
294
+ "testing_patterns": {
295
+ "component_testing": {
296
+ "library": "React Testing Library (recommended)",
297
+ "principle": "Test behavior, not implementation",
298
+ "example": "import { render, screen } from '@testing-library/react';\n\ntest('shows error message on failed login', async () => {\n render(<LoginForm />);\n await userEvent.click(screen.getByRole('button', { name: 'Login' }));\n expect(screen.getByText(/invalid credentials/i)).toBeInTheDocument();\n});",
299
+ "query_priority": [
300
+ "getByRole (most accessible)",
301
+ "getByLabelText (forms)",
302
+ "getByPlaceholderText",
303
+ "getByText",
304
+ "getByTestId (last resort)"
305
+ ]
306
+ },
307
+ "mocking": {
308
+ "api_calls": "Mock fetch with MSW (Mock Service Worker)",
309
+ "example": "import { rest } from 'msw';\n\nconst handlers = [\n rest.get('/api/user', (req, res, ctx) => {\n return res(ctx.json({ name: 'John' }));\n })\n];"
310
+ }
311
+ },
312
+ "file_organization": {
313
+ "by_feature": {
314
+ "structure": "features/auth/\n components/\n hooks/\n utils/\n index.ts",
315
+ "recommended": "Yes - scales well"
316
+ },
317
+ "by_type": {
318
+ "structure": "components/\nhooks/\nutils/",
319
+ "use": "Small apps only"
320
+ },
321
+ "colocation": {
322
+ "principle": "Keep related files together",
323
+ "example": "Button/\n Button.tsx\n Button.test.tsx\n Button.module.css\n index.ts",
324
+ "benefit": "Easy to find everything for a component"
325
+ }
326
+ },
327
+ "best_practices": [
328
+ "Keep components small and focused (Single Responsibility)",
329
+ "Prefer composition over prop drilling",
330
+ "Use TypeScript for type safety",
331
+ "Memoize only when profiling shows benefit",
332
+ "Use proper semantic HTML and ARIA",
333
+ "Handle loading and error states",
334
+ "Test user behavior, not implementation details",
335
+ "Use keys properly in lists (stable, unique, not index)",
336
+ "Avoid prop drilling with Context for deeply nested state",
337
+ "Split large components into smaller ones",
338
+ "Use custom hooks to extract logic",
339
+ "Follow consistent naming conventions"
340
+ ],
341
+ "anti_patterns": [
342
+ "Huge components (> 300 lines)",
343
+ "Prop drilling 5+ levels deep",
344
+ "Overusing Context (causes re-renders)",
345
+ "Premature optimization (memoize everything)",
346
+ "Using index as key in dynamic lists",
347
+ "Mutating state directly",
348
+ "Side effects in render",
349
+ "Not handling errors",
350
+ "Missing loading states",
351
+ "Ignoring accessibility"
352
+ ]
353
+ }
@@ -0,0 +1,258 @@
1
+ {
2
+ "name": "Responsive Design Best Practices",
3
+ "description": "Mobile-first design principles, breakpoints, and responsive patterns",
4
+ "principles": {
5
+ "mobile_first": {
6
+ "description": "Design for mobile devices first, then progressively enhance for larger screens",
7
+ "rationale": [
8
+ "Forces focus on core content and features",
9
+ "Easier to scale up than down",
10
+ "Better performance on mobile devices",
11
+ "Mobile traffic often exceeds desktop"
12
+ ],
13
+ "implementation": {
14
+ "css_approach": "Base styles for mobile, media queries for desktop",
15
+ "example": "/* Mobile first (no media query) */\n.container { padding: 1rem; }\n\n/* Tablet and up */\n@media (min-width: 768px) {\n .container { padding: 2rem; }\n}\n\n/* Desktop and up */\n@media (min-width: 1024px) {\n .container { padding: 3rem; }\n}"
16
+ }
17
+ },
18
+ "breakpoints": {
19
+ "description": "Common device breakpoints for responsive layouts",
20
+ "standard_breakpoints": {
21
+ "mobile": "0px - 639px",
22
+ "tablet": "640px - 1023px",
23
+ "desktop": "1024px - 1279px",
24
+ "wide": "1280px+"
25
+ },
26
+ "tailwind_breakpoints": {
27
+ "sm": "640px",
28
+ "md": "768px",
29
+ "lg": "1024px",
30
+ "xl": "1280px",
31
+ "2xl": "1536px"
32
+ },
33
+ "bootstrap_breakpoints": {
34
+ "xs": "< 576px",
35
+ "sm": "576px",
36
+ "md": "768px",
37
+ "lg": "992px",
38
+ "xl": "1200px",
39
+ "xxl": "1400px"
40
+ },
41
+ "best_practices": [
42
+ "Design for content, not specific devices",
43
+ "Use 3-4 breakpoints maximum",
44
+ "Test actual devices, not just browser resize",
45
+ "Consider landscape orientations",
46
+ "Use relative units (rem, em) over px"
47
+ ]
48
+ },
49
+ "viewport_meta": {
50
+ "description": "Essential viewport configuration for mobile",
51
+ "required": "<meta name='viewport' content='width=device-width, initial-scale=1'>",
52
+ "explanation": {
53
+ "width=device-width": "Match screen width (prevents zoom out)",
54
+ "initial-scale=1": "No zoom on page load"
55
+ },
56
+ "avoid": {
57
+ "user-scalable=no": "Prevents pinch zoom (accessibility issue)",
58
+ "maximum-scale=1": "Prevents zoom (accessibility issue)"
59
+ }
60
+ },
61
+ "touch_targets": {
62
+ "description": "Minimum sizes for touch interactions",
63
+ "requirements": {
64
+ "minimum": "44x44px (Apple) or 48x48px (Android)",
65
+ "recommended": "48x48px minimum for all platforms",
66
+ "spacing": "8px minimum between targets"
67
+ },
68
+ "implementation": [
69
+ "Add padding to increase touch area",
70
+ "Use ::before/::after for larger hitbox",
71
+ "Avoid placing small targets near edges",
72
+ "Consider thumb zones on mobile"
73
+ ]
74
+ }
75
+ },
76
+ "responsive_patterns": {
77
+ "navigation": {
78
+ "mobile": {
79
+ "hamburger_menu": {
80
+ "when_to_use": "5+ navigation items",
81
+ "structure": "Hamburger icon → Full-screen or slide-in menu",
82
+ "best_practices": [
83
+ "Icon should be 44x44px minimum",
84
+ "Clearly labeled (aria-label='Menu')",
85
+ "Show/hide with smooth transition",
86
+ "Close button or overlay dismiss",
87
+ "Prevent body scroll when open"
88
+ ]
89
+ },
90
+ "bottom_navigation": {
91
+ "when_to_use": "Mobile apps, 3-5 primary destinations",
92
+ "structure": "Fixed bottom bar with icons + labels",
93
+ "best_practices": [
94
+ "Icons with text labels",
95
+ "Current page highlighted",
96
+ "56-72px height recommended",
97
+ "3-5 items only"
98
+ ]
99
+ }
100
+ },
101
+ "tablet_desktop": {
102
+ "horizontal_nav": "Traditional header navigation",
103
+ "sidebar": "Persistent side navigation for apps"
104
+ }
105
+ },
106
+ "layout": {
107
+ "single_column": {
108
+ "mobile": "All content stacks vertically",
109
+ "implementation": "Default layout, no grid needed"
110
+ },
111
+ "multi_column": {
112
+ "tablet": "2-column layouts",
113
+ "desktop": "3-4 column layouts",
114
+ "implementation": "CSS Grid or Flexbox with media queries"
115
+ },
116
+ "grid_examples": {
117
+ "responsive_grid": "/* Mobile: 1 column */\n.grid {\n display: grid;\n gap: 1rem;\n}\n\n/* Tablet: 2 columns */\n@media (min-width: 768px) {\n .grid {\n grid-template-columns: repeat(2, 1fr);\n }\n}\n\n/* Desktop: 3+ columns */\n@media (min-width: 1024px) {\n .grid {\n grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));\n }\n}"
118
+ }
119
+ },
120
+ "typography": {
121
+ "fluid_typography": {
122
+ "description": "Font sizes that scale with viewport",
123
+ "implementation": "clamp(min, preferred, max)",
124
+ "example": "font-size: clamp(1rem, 2.5vw, 2rem);",
125
+ "benefits": [
126
+ "Smooth scaling between breakpoints",
127
+ "No need for multiple media queries",
128
+ "Better readability across devices"
129
+ ]
130
+ },
131
+ "responsive_scale": {
132
+ "mobile": "Base size 16px, scale 1.2",
133
+ "desktop": "Base size 18px, scale 1.25",
134
+ "implementation": "Adjust root font-size at breakpoints"
135
+ }
136
+ },
137
+ "images": {
138
+ "responsive_images": {
139
+ "srcset": {
140
+ "description": "Provide multiple image sizes",
141
+ "example": "<img\n src='image-800.jpg'\n srcset='image-400.jpg 400w,\n image-800.jpg 800w,\n image-1200.jpg 1200w'\n sizes='(max-width: 768px) 100vw,\n (max-width: 1024px) 50vw,\n 800px'\n alt='Description'\n/>"
142
+ },
143
+ "picture": {
144
+ "description": "Art direction or format switching",
145
+ "example": "<picture>\n <source media='(max-width: 768px)' srcset='mobile.jpg'>\n <source media='(max-width: 1024px)' srcset='tablet.jpg'>\n <img src='desktop.jpg' alt='Description'>\n</picture>"
146
+ },
147
+ "css_background": {
148
+ "example": ".hero {\n background-image: url('mobile.jpg');\n}\n\n@media (min-width: 768px) {\n .hero {\n background-image: url('desktop.jpg');\n }\n}"
149
+ }
150
+ },
151
+ "lazy_loading": {
152
+ "native": "<img src='image.jpg' loading='lazy' alt='Description'>",
153
+ "best_for": "Below-the-fold images",
154
+ "avoid": "Above-the-fold or LCP images"
155
+ }
156
+ },
157
+ "forms": {
158
+ "mobile_optimization": [
159
+ "Large input fields (min 44px height)",
160
+ "Appropriate input types (tel, email, number)",
161
+ "Reduce form fields to minimum",
162
+ "Use autocomplete attributes",
163
+ "Large, tappable submit buttons",
164
+ "Inline validation",
165
+ "Auto-advance for OTP/PIN inputs"
166
+ ],
167
+ "input_types": {
168
+ "tel": "Numeric keyboard with tel symbols",
169
+ "email": "Keyboard with @ and .",
170
+ "number": "Numeric keypad",
171
+ "url": "Keyboard with / and .com",
172
+ "search": "Shows search action in keyboard",
173
+ "date": "Native date picker"
174
+ }
175
+ },
176
+ "tables": {
177
+ "responsive_strategies": [
178
+ {
179
+ "name": "Horizontal Scroll",
180
+ "when": "Few columns with important data",
181
+ "implementation": "overflow-x: auto on container"
182
+ },
183
+ {
184
+ "name": "Stack Columns",
185
+ "when": "2-3 columns",
186
+ "implementation": "Convert to vertical layout on mobile"
187
+ },
188
+ {
189
+ "name": "Card View",
190
+ "when": "Many columns",
191
+ "implementation": "Display each row as a card"
192
+ },
193
+ {
194
+ "name": "Hide Columns",
195
+ "when": "Non-critical columns",
196
+ "implementation": "Show only essential columns on mobile"
197
+ }
198
+ ],
199
+ "card_transform_example": "/* Desktop table */\ntable { display: table; }\n\n/* Mobile cards */\n@media (max-width: 768px) {\n table, thead, tbody, tr, th, td {\n display: block;\n }\n \n tr {\n margin-bottom: 1rem;\n border: 1px solid #e5e7eb;\n border-radius: 0.5rem;\n }\n \n td::before {\n content: attr(data-label);\n font-weight: bold;\n }\n}"
200
+ }
201
+ },
202
+ "testing_checklist": [
203
+ "Test on real devices (iOS, Android)",
204
+ "Check all breakpoints",
205
+ "Test portrait and landscape",
206
+ "Verify touch targets (44x44px min)",
207
+ "Test forms with mobile keyboard",
208
+ "Check image loading and sizes",
209
+ "Verify navigation works on mobile",
210
+ "Test with slow 3G network",
211
+ "Check accessibility on mobile screen readers",
212
+ "Verify no horizontal scroll",
213
+ "Test with large font sizes (accessibility)",
214
+ "Check dark mode if supported"
215
+ ],
216
+ "common_mistakes": [
217
+ {
218
+ "mistake": "Desktop-first CSS",
219
+ "problem": "Requires overriding styles for mobile",
220
+ "solution": "Start with mobile base styles"
221
+ },
222
+ {
223
+ "mistake": "Disabling zoom (user-scalable=no)",
224
+ "problem": "Accessibility violation (WCAG)",
225
+ "solution": "Never disable zoom"
226
+ },
227
+ {
228
+ "mistake": "Small touch targets",
229
+ "problem": "Hard to tap accurately",
230
+ "solution": "Minimum 44x44px"
231
+ },
232
+ {
233
+ "mistake": "Horizontal scroll",
234
+ "problem": "Poor mobile UX",
235
+ "solution": "Use overflow-x: hidden on body, design within viewport"
236
+ },
237
+ {
238
+ "mistake": "Tiny text on mobile",
239
+ "problem": "Unreadable",
240
+ "solution": "Minimum 16px font size"
241
+ },
242
+ {
243
+ "mistake": "Loading full desktop images on mobile",
244
+ "problem": "Slow, wastes data",
245
+ "solution": "Use srcset or picture element"
246
+ }
247
+ ],
248
+ "performance_tips": [
249
+ "Lazy load below-the-fold images",
250
+ "Use modern image formats (WebP, AVIF)",
251
+ "Minimize CSS and JavaScript",
252
+ "Avoid render-blocking resources",
253
+ "Use system fonts when possible",
254
+ "Implement critical CSS",
255
+ "Reduce network requests",
256
+ "Use CSS instead of JavaScript animations"
257
+ ]
258
+ }