Beta FeatureThis feature is currently in beta, and needs to be imported from @servicetitan/anvil2/beta.While we hope to minimize breaking changes, they may occur due to feedback we receive or other improvements. These will always be documented in the changelog and communicated in Slack.Please reach out in the #ask-designsystem channel with any questions or feedback!
A React hook for detecting whether to use mobile or desktop UI patterns based on device characteristics.
Overview
useAdaptiveView determines the optimal UI pattern (e.g., Dialog vs Popover) by combining two factors:
- Screen size: Viewport width relative to the
md breakpoint (768px)
- Pointer precision: Whether the device has a coarse (touch) or fine (mouse/trackpad) primary pointer
A device is considered “mobile” only when it has both a small screen (below 768px) and a coarse pointer (touch input). This approach correctly distinguishes between:
| Device Type | Screen Size | Pointer | Result |
|---|
| Mobile phones | Small | Coarse (touch) | Mobile view |
| iPads/tablets | Large | Coarse (touch) | Desktop view |
| Touch laptops | Large | Fine (trackpad) | Desktop view |
| Desktop | Large | Fine (mouse) | Desktop view |
Import
import { useAdaptiveView } from "@servicetitan/anvil2/beta";
Return Value
The hook returns an object with the following properties:
| Property | Type | Description |
|---|
view | "mobile" | "desktop" | The current adaptive view type |
isMobile | boolean | true when the device should use mobile-optimized UI |
isDesktop | boolean | true when the device should use desktop-optimized UI |
Basic Usage
Use useAdaptiveView to conditionally render different UI components based on the device:
import { useAdaptiveView } from "@servicetitan/anvil2/beta";
import { Dialog, Popover, Button } from "@servicetitan/anvil2";
function AdaptiveMenu({ children }) {
const { isMobile } = useAdaptiveView();
return isMobile ? (
<Dialog>
<Dialog.Trigger>
<Button>Open Menu</Button>
</Dialog.Trigger>
<Dialog.Content>{children}</Dialog.Content>
</Dialog>
) : (
<Popover>
<Popover.Trigger>
<Button>Open Menu</Button>
</Popover.Trigger>
<Popover.Content>{children}</Popover.Content>
</Popover>
);
}
Use Cases
Adaptive Selection Components
Components like SelectField use this hook internally to render a full-screen dialog on mobile devices and a popover dropdown on desktop:
const { isMobile } = useAdaptiveView();
// On mobile: render a tray-style Dialog for easier touch interaction
// On desktop: render a Popover positioned below the trigger
Adjust form interactions based on device capabilities:
function AdaptiveForm() {
const { isMobile } = useAdaptiveView();
return (
<Form>
{isMobile ? (
// Full-screen form with larger touch targets
<MobileFormLayout />
) : (
// Standard form layout
<DesktopFormLayout />
)}
</Form>
);
}
Technical Details
Detection Method
The hook uses two browser APIs to detect device characteristics:
useBreakpoint: Monitors viewport width against Anvil2 breakpoint tokens
- CSS Media Query: Uses
(pointer: coarse) to detect touch-primary devices
Dynamic Updates
The hook automatically updates when:
- The viewport is resized (e.g., browser window resized, device rotation)
- The pointer capability changes (e.g., connecting/disconnecting a mouse on a touch device)
SSR Compatibility
During server-side rendering, the hook defaults to desktop view since browser APIs are unavailable. The correct view is determined on the client after hydration.Last modified on January 23, 2026