Touch & Mobile
Viewport and pointer
Components adapt to two independent things: the viewport width decides the layout (a sheet from the bottom instead of a panel at the side), the pointer decides the interaction (tap areas, long presses, no hover). A tablet is wide but has no hover; a narrow desktop window still has a mouse.
| Device | Viewport | Pointer | Result |
|---|---|---|---|
| Desktop | Wide | Fine, can hover | Desktop layout and interactions |
| Narrow desktop window | Narrow | Fine, can hover | Mobile layout, hover stays |
| Tablet | Wide | Coarse, no hover | Desktop layout, touch interactions |
| Phone | Narrow | Coarse, no hover | Mobile layout and touch interactions |
Hover
Hover styles only apply on devices that can hover, so they don’t stick after a tap. Use @include fusioncss.hover instead of :hover; stylelint rejects plain :hover. Nothing may only be reachable on hover — reveal it with for-hover("none") on touch screens.
.row {@include fusioncss.hover {background: fusioncss.get-color("neutral-50");}}.rowActions {opacity: 0;.row:focus-within &,.row:hover & {opacity: 1;}// No hover on touch screens: always show the actions@include fusioncss.for-hover("none") {opacity: 1;}}
Tap targets
Every interactive element covers at least 24 by 24 pixels on touch screens (WCAG 2.5.8). The target-size mixin of fusion-css grows the tap area with an invisible pseudo element, without changing the look. The dashed outline below shows the area of the small label.
.chipRemove {@include fusioncss.target-size; // only for coarse pointers, needs position: relative}
Mind the productive theme: its 14px root font shrinks rem sizes, so --size--150 is 21px there. --size--target-min is in pixels for that reason.
Components on touch screens
- Text fields use at least 16px on touch screens, otherwise iOS zooms in on focus.
- Tooltip opens on a long press instead of a tap. Info and hover Popovers open on tap.
- ContextMenu opens on a long press, at the position of the finger. Long presses are hard to discover, so offer the same actions through a visible button too.
- CommandMenu looks the same as on desktop and closes with a tap outside of it, as there is no Escape key.
- Sheet rises from the bottom edge on phones and fills the screen up to a small strip. AccountMenu opens as a bottom sheet on touch screens.
- Drag and drop starts after resting the finger for a moment, so swiping still scrolls.
Hooks
Breakpoint and pointer are available as hooks, e.g. for layouts of your own.
import {useCanHover, useCoarsePointer, useIsMobile, useLongPress} from "@brynlabs/fusion-ui";const isMobile = useIsMobile(); // viewport of the xs size and belowconst isTouch = useCoarsePointer(); // finger as primary pointerconst canHover = useCanHover();const longPress = useLongPress({onLongPress: ({clientX, clientY}) => openMenu(clientX, clientY)});<div {...longPress}>…</div>;
All of them return undefined during server rendering and hydration.
Safe areas
Set viewport-fit=cover in the viewport meta tag, so sheets, snackbars and the command menu can keep clear of the notch and the home indicator via env(safe-area-inset-*). Use 100dvh after a 100vh fallback for full height overlays.

