0
# Platform Detection
1
2
Browser and device identification utilities for conditional behavior and platform-specific features. All functions use caching for performance and return boolean values.
3
4
## Capabilities
5
6
### Apple Platform Detection
7
8
Utilities for detecting Apple devices and macOS platforms.
9
10
```typescript { .api }
11
/**
12
* Detects macOS platform
13
* @returns true if running on macOS
14
*/
15
function isMac(): boolean;
16
17
/**
18
* Detects iPhone devices
19
* @returns true if running on iPhone
20
*/
21
function isIPhone(): boolean;
22
23
/**
24
* Detects iPad devices (handles iPadOS 13+ detection)
25
* @returns true if running on iPad, including iPadOS 13+ devices
26
*/
27
function isIPad(): boolean;
28
29
/**
30
* Detects iOS devices (iPhone or iPad)
31
* @returns true if running on any iOS device
32
*/
33
function isIOS(): boolean;
34
35
/**
36
* Detects any Apple device (Mac or iOS)
37
* @returns true if running on any Apple device
38
*/
39
function isAppleDevice(): boolean;
40
```
41
42
**Usage Examples:**
43
44
```typescript
45
import { isMac, isIOS, isIPad } from "@react-aria/utils";
46
47
function PlatformSpecificComponent() {
48
const shortcutKey = isMac() ? "⌘" : "Ctrl";
49
const hasHover = !isIOS(); // iOS devices don't have true hover
50
51
return (
52
<div>
53
<p>Press {shortcutKey}+K to open search</p>
54
{hasHover && <button className="hover-effects">Hover me</button>}
55
{isIPad() && <p>iPad-specific feature available!</p>}
56
</div>
57
);
58
}
59
60
// Keyboard shortcut handling
61
function useKeyboardShortcuts() {
62
useEffect(() => {
63
const handleKeyDown = (e) => {
64
const cmdOrCtrl = isMac() ? e.metaKey : e.ctrlKey;
65
66
if (cmdOrCtrl && e.key === 'k') {
67
e.preventDefault();
68
openSearch();
69
}
70
};
71
72
window.addEventListener('keydown', handleKeyDown);
73
return () => window.removeEventListener('keydown', handleKeyDown);
74
}, []);
75
}
76
```
77
78
### Browser Detection
79
80
Utilities for detecting specific browsers and browser engines.
81
82
```typescript { .api }
83
/**
84
* Detects WebKit browsers (Safari, excluding Chrome)
85
* @returns true if running on WebKit-based browser (not Chrome)
86
*/
87
function isWebKit(): boolean;
88
89
/**
90
* Detects Chrome browser
91
* @returns true if running on Chrome browser
92
*/
93
function isChrome(): boolean;
94
95
/**
96
* Detects Firefox browser
97
* @returns true if running on Firefox browser
98
*/
99
function isFirefox(): boolean;
100
```
101
102
**Usage Examples:**
103
104
```typescript
105
import { isWebKit, isChrome, isFirefox } from "@react-aria/utils";
106
107
function BrowserSpecificBehavior() {
108
useEffect(() => {
109
// WebKit has different scrolling behavior
110
if (isWebKit()) {
111
document.body.style.webkitOverflowScrolling = 'touch';
112
}
113
114
// Chrome-specific optimizations
115
if (isChrome()) {
116
// Enable hardware acceleration for Chrome
117
document.body.style.transform = 'translateZ(0)';
118
}
119
120
// Firefox-specific handling
121
if (isFirefox()) {
122
// Firefox handles some CSS properties differently
123
document.documentElement.style.scrollBehavior = 'smooth';
124
}
125
}, []);
126
127
return <div>Browser-optimized content</div>;
128
}
129
130
// CSS-in-JS with browser detection
131
function getButtonStyles() {
132
return {
133
padding: '8px 16px',
134
borderRadius: isWebKit() ? '8px' : '4px', // Different radius for Safari
135
boxShadow: isChrome()
136
? '0 2px 4px rgba(0,0,0,0.1)'
137
: '0 1px 3px rgba(0,0,0,0.1)'
138
};
139
}
140
```
141
142
### Mobile Platform Detection
143
144
Utilities for detecting mobile platforms and devices.
145
146
```typescript { .api }
147
/**
148
* Detects Android devices
149
* @returns true if running on Android device
150
*/
151
function isAndroid(): boolean;
152
```
153
154
**Usage Examples:**
155
156
```typescript
157
import { isAndroid, isIOS } from "@react-aria/utils";
158
159
function MobileOptimizedComponent() {
160
const isMobile = isIOS() || isAndroid();
161
const touchOptimized = isMobile;
162
163
return (
164
<button
165
style={{
166
minHeight: touchOptimized ? '44px' : '32px', // Larger touch targets
167
fontSize: isAndroid() ? '16px' : '14px' // Prevent zoom on Android
168
}}
169
>
170
{isMobile ? 'Tap me' : 'Click me'}
171
</button>
172
);
173
}
174
175
// Platform-specific input handling
176
function useInputBehavior() {
177
const [inputMode, setInputMode] = useState('none');
178
179
useEffect(() => {
180
if (isIOS()) {
181
setInputMode('decimal'); // Better numeric input on iOS
182
} else if (isAndroid()) {
183
setInputMode('numeric'); // Android prefers numeric mode
184
} else {
185
setInputMode('none'); // Desktop doesn't need input mode
186
}
187
}, []);
188
189
return inputMode;
190
}
191
```
192
193
### Combined Platform Logic
194
195
Real-world examples combining multiple platform checks:
196
197
```typescript
198
import { isMac, isIOS, isAndroid, isWebKit, isChrome } from "@react-aria/utils";
199
200
function PlatformAwareComponent() {
201
// Determine if device supports true hover
202
const hasHover = !isIOS() && !isAndroid();
203
204
// Determine optimal scroll behavior
205
const scrollBehavior = useMemo(() => {
206
if (isIOS()) return 'momentum'; // iOS has native momentum scrolling
207
if (isAndroid()) return 'smooth'; // Android prefers smooth scrolling
208
return 'auto'; // Desktop default
209
}, []);
210
211
// Platform-specific event handling
212
const handleClick = useCallback((e) => {
213
// Prevent double-tap zoom on mobile
214
if (isIOS() || isAndroid()) {
215
e.preventDefault();
216
}
217
218
// Handle platform-specific actions
219
if (isMac()) {
220
// Mac-specific behavior
221
}
222
}, []);
223
224
return (
225
<div
226
onClick={handleClick}
227
style={{
228
cursor: hasHover ? 'pointer' : 'default',
229
WebkitOverflowScrolling: isIOS() ? 'touch' : undefined,
230
scrollBehavior: scrollBehavior
231
}}
232
>
233
Content optimized for {
234
isIOS() ? 'iOS' :
235
isAndroid() ? 'Android' :
236
isMac() ? 'macOS' :
237
'Desktop'
238
}
239
</div>
240
);
241
}
242
243
// Feature detection based on platform
244
function useFeatureSupport() {
245
return useMemo(() => ({
246
supportsHover: !isIOS() && !isAndroid(),
247
supportsTouch: isIOS() || isAndroid(),
248
prefersMomentumScrolling: isIOS(),
249
needsLargerTouchTargets: isIOS() || isAndroid(),
250
supportsBackdropFilter: isWebKit() || isChrome(),
251
usesCmdKey: isMac(),
252
supportsPassiveEvents: !isAndroid() // Some Android versions have issues
253
}), []);
254
}
255
```
256
257
## Performance Notes
258
259
All platform detection functions use caching internally, so multiple calls to the same function within a render cycle are optimized. The detection is performed once and cached for subsequent calls:
260
261
```typescript
262
// These calls are optimized - detection only happens once
263
const isMacPlatform = isMac();
264
const isIOSPlatform = isIOS();
265
const isMacAgain = isMac(); // Returns cached result
266
```