Overview
LoopString is designed to work well on phones and tablets. The dashboard adapts its layout for small screens, replacing the desktop sidebar with a bottom navigation bar and adding touch gestures that make common tasks reachable with one hand. All mobile features work in the browser and in the installed PWA.
Bottom Navigation Bar
On small screens (below the sm breakpoint, roughly 640 px wide) the app renders a fixed bottom navigation bar in place of any top-level sidebar. It contains six destinations:
- Devices — device list and per-device dashboard
- Configurator — Node-RED flow designer
- Analytics — historical signal charts
- Journal — device notes and observations
- Fleet — multi-device fleet overview
- Settings — account and device settings
The Alerts bell is also embedded in the bottom bar on mobile. On desktop the bell floats in the top-right corner instead (hidden sm:block).
The active destination is highlighted in the primary theme color. A screen-reader-only badge announces the count of active alerts when any are firing.
Swipe Navigation Between Rooms
When the dashboard is in tabs view mode and a device has two or more rooms, you can swipe left or right across the card grid to move between rooms.
The gesture is handled by the useSwipeGesture hook, which uses native touch events (onTouchStart, onTouchMove, onTouchEnd). A swipe only fires if:
- The horizontal travel is at least 50 px
- The swipe velocity is at least 0.3 px/ms (to distinguish an intentional swipe from a slow drag)
- The vertical drift stays within 60 px (to avoid triggering while the user scrolls vertically)
Swipe left to advance to the next room. Swipe right to go back to the previous room. The room tab bar at the top of the dashboard updates to show the active room as you swipe.
If the dashboard is in all rooms view mode, swipe gestures are ignored — the full list of rooms is always visible and there is nothing to navigate between.
Pull-to-Refresh
Pulling down from the top of the dashboard content area triggers a refresh when the page is already scrolled to the top. This re-subscribes the device's RTDB data stream and invalidates the React Query cache for devices, alert configs, dashboard layout, room config, and sparkline history — the equivalent of a full reload without leaving the page.
The gesture uses rubber-band physics: the content area follows your finger with increasing resistance as you pull further down. Release after pulling at least 80 px to trigger the refresh. The content snaps back with a brief spinner visible while the refresh runs.
Pull-to-refresh works in both the browser and in PWA standalone mode. If the page is already scrolled below the top, the gesture is ignored so normal vertical scrolling is not interrupted.
Long-Press Quick Actions
Long-pressing any sensor or actuator card (hold for about 500 ms without moving your finger) opens a Quick Action Sheet — a bottom sheet that slides up from the bottom of the screen with actions relevant to that card type.
For sensor cards the quick actions are:
- View History — navigates to the Analytics page for the device
- Set Alert Threshold — scrolls the card into view so the threshold editor is accessible
- Hide Card — removes the card from the visible layout (marked destructive in red)
For actuator cards the quick actions are:
- Turn On / Turn Off — toggles the actuator immediately via RTDB command
- View Duty Cycle — navigates to the Analytics page
- Hide Card — removes the card from the layout
The long-press triggers haptic feedback (a 50 ms vibration pulse via navigator.vibrate) on devices that support it. The browser's native context menu is suppressed when a long-press fires so it does not appear on top of the sheet.
Tapping anywhere on the backdrop or pressing Escape dismisses the sheet without taking an action.
Floating Action Button (FAB)
A floating action button appears at the bottom-right corner of the dashboard, above the bottom navigation bar. It gives quick access to three dashboard management actions without scrolling to find a button:
- Add Room — scrolls the page to the Create Room button and focuses it
- Add Spacer — inserts a blank spacer card into the active room
- Deploy Flow — opens the flow deploy dialog
The FAB shows a + icon when collapsed. Tapping it expands a small menu of labeled action chips that fan out upward. Tapping the + again (which rotates to ×) or tapping outside the FAB closes the menu.
The FAB hides automatically while scrolling down and reappears when scrolling stops or when you scroll back up. This keeps the button out of the way when reading through a long list of cards.
Responsive Layout Differences
Below the sm breakpoint (roughly 640 px wide), the following layout differences apply compared to desktop:
- The bottom navigation bar replaces any persistent sidebar or top-level nav links.
- The notification bell moves from the floating top-right corner into the bottom bar.
- Content gets extra bottom padding (
pb-14) to ensure cards are not obscured by the bottom bar. - The QuickActionSheet renders as a full-width bottom sheet with a drag-handle indicator. On desktop the same component falls back to a popover anchored to the card.
The dashboard card grid is a responsive CSS grid that reduces to fewer columns on narrow screens. Individual cards can be expanded to span two columns using the resize option in the three-dot card menu, which is useful on tablets in landscape orientation.
PWA Installation
LoopString can be installed as a Progressive Web App, giving it a home screen icon and a full-screen standalone window without browser chrome. This is especially useful on mobile because:
- Pull-to-refresh works correctly in standalone mode (the hook explicitly supports it).
- The bottom navigation bar extends to the safe-area inset on notched phones so it does not overlap the home indicator.
- The app loads from a service worker cache, so the dashboard is usable even when the connection is poor.
See the Installing the PWA documentation for installation steps on iOS and Android.
Troubleshooting
Swipe gestures are not changing rooms. Check that the dashboard is in tabs view mode. In all-rooms view mode, swipe gestures are intentionally disabled. You can switch view modes from the room tab bar at the top of the dashboard. Also confirm the device has at least two rooms — there is nothing to swipe between with a single room.
Long-press opens the browser context menu instead of the quick actions sheet. This can happen on some Android browsers when the page detects a long press before the app does. Try holding slightly more firmly and keeping your finger still. If the issue persists, installing the app as a PWA removes the browser context menu interference because the app runs in standalone mode without browser gesture overrides.