Tracks whether the viewport is below the mobile breakpoint (768px) and updates when the media query changes.
Usage
import { useIsMobile } from '@kuzenbo/hooks';
function Demo() {
const isMobile = useIsMobile();
return (
<div>
{isMobile ? 'Mobile View' : 'Desktop View'}
</div>
);
}
Function Signature
function useIsMobile(): boolean
Parameters
This hook takes no parameters.
Return Value
true if the viewport width is less than 768px, otherwise false. Initially false until mounted.
Examples
Conditional Navigation
import { useIsMobile } from '@kuzenbo/hooks';
function Navigation() {
const isMobile = useIsMobile();
return (
<nav>
{isMobile ? <MobileMenu /> : <DesktopMenu />}
</nav>
);
}
Responsive Table
import { useIsMobile } from '@kuzenbo/hooks';
function DataTable({ data }) {
const isMobile = useIsMobile();
if (isMobile) {
return (
<div>
{data.map((item) => (
<div key={item.id} style={{ marginBottom: '16px' }}>
<div><strong>Name:</strong> {item.name}</div>
<div><strong>Email:</strong> {item.email}</div>
<div><strong>Role:</strong> {item.role}</div>
</div>
))}
</div>
);
}
return (
<table>
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>Role</th>
</tr>
</thead>
<tbody>
{data.map((item) => (
<tr key={item.id}>
<td>{item.name}</td>
<td>{item.email}</td>
<td>{item.role}</td>
</tr>
))}
</tbody>
</table>
);
}
Mobile-Specific Features
import { useIsMobile } from '@kuzenbo/hooks';
function ContactForm() {
const isMobile = useIsMobile();
return (
<form>
<input
type="tel"
placeholder="Phone"
// Auto-focus on desktop only
autoFocus={!isMobile}
/>
{isMobile && (
<button type="button">
📞 Call Us
</button>
)}
<button type="submit">Submit</button>
</form>
);
}
Adaptive Grid Layout
import { useIsMobile } from '@kuzenbo/hooks';
function ProductGrid({ products }) {
const isMobile = useIsMobile();
return (
<div
style={{
display: 'grid',
gridTemplateColumns: isMobile ? '1fr' : 'repeat(3, 1fr)',
gap: isMobile ? '12px' : '24px',
}}
>
{products.map((product) => (
<ProductCard key={product.id} product={product} />
))}
</div>
);
}
Conditional Modal Behavior
import { useIsMobile } from '@kuzenbo/hooks';
function Modal({ isOpen, onClose, children }) {
const isMobile = useIsMobile();
if (!isOpen) return null;
return (
<div
style={{
position: 'fixed',
inset: 0,
display: 'flex',
alignItems: isMobile ? 'flex-end' : 'center',
justifyContent: 'center',
}}
>
<div
style={{
background: 'white',
borderRadius: isMobile ? '16px 16px 0 0' : '8px',
width: isMobile ? '100%' : 'auto',
maxWidth: isMobile ? '100%' : '600px',
padding: isMobile ? '16px' : '24px',
}}
>
{children}
</div>
</div>
);
}
import { useIsMobile } from '@kuzenbo/hooks';
function ActionButton({ children, onClick }) {
const isMobile = useIsMobile();
return (
<button
onClick={onClick}
style={{
padding: isMobile ? '12px 24px' : '8px 16px',
fontSize: isMobile ? '16px' : '14px',
minHeight: isMobile ? '44px' : 'auto', // Touch target size
}}
>
{children}
</button>
);
}
Responsive Image Gallery
import { useIsMobile } from '@kuzenbo/hooks';
function ImageGallery({ images }) {
const isMobile = useIsMobile();
return (
<div
style={{
display: 'flex',
flexDirection: isMobile ? 'column' : 'row',
gap: '16px',
}}
>
{images.map((image) => (
<img
key={image.id}
src={isMobile ? image.thumbnail : image.full}
alt={image.alt}
style={{
width: isMobile ? '100%' : '200px',
height: 'auto',
}}
/>
))}
</div>
);
}
import { useIsMobile } from '@kuzenbo/hooks';
import { useState } from 'react';
function Layout({ children }) {
const isMobile = useIsMobile();
const [isSidebarOpen, setIsSidebarOpen] = useState(false);
return (
<div style={{ display: 'flex' }}>
{isMobile ? (
// Mobile: Overlay sidebar
<>
<button onClick={() => setIsSidebarOpen(true)}>☰ Menu</button>
{isSidebarOpen && (
<div
style={{
position: 'fixed',
inset: 0,
background: 'white',
zIndex: 1000,
}}
>
<button onClick={() => setIsSidebarOpen(false)}>✕ Close</button>
<Sidebar />
</div>
)}
</>
) : (
// Desktop: Always visible sidebar
<aside style={{ width: '250px' }}>
<Sidebar />
</aside>
)}
<main style={{ flex: 1 }}>{children}</main>
</div>
);
}
Mobile Breakpoint
The hook uses a fixed breakpoint of 768px:
- Viewport width < 768px →
isMobile = true
- Viewport width ≥ 768px →
isMobile = false
This matches common CSS frameworks like Tailwind (md: breakpoint).
Notes
- The hook uses
window.matchMedia with max-width: 767px query
- Initial value is
undefined until mounted, then becomes boolean
- Updates automatically when viewport is resized
- SSR-safe: value is determined after mount
- The breakpoint is fixed at 768px and cannot be customized
- For custom breakpoints, use
useMediaQuery instead