Skip to main content

Touch Mode

Touch mode provides larger, touch-friendly targets for form fields on mobile and tablet devices. It ensures a comfortable tap experience and prevents iOS zoom-on-focus by enforcing proper input sizing.

Features

  • Auto-detection — Automatically activates on viewports ≤979px
  • Manual control — Programmatically enable/disable via props or ref methods
  • Override support — User can toggle touch mode and override auto-detection
  • iOS zoom prevention — 16px minimum font size on inputs prevents unwanted zoom

Quick Start

import { EsheetRenderer } from '@esheet/renderer';

// Auto-detect based on viewport
<EsheetRenderer formDataInput={formDef} touchMode="auto" />

// Always enable
<EsheetRenderer formDataInput={formDef} touchMode={true} />

// Rely on CSS media query only (default)
<EsheetRenderer formDataInput={formDef} />

Props

PropTypeDefaultDescription
touchModeboolean | 'auto'undefinedControl touch mode activation
onTouchModeChange(enabled: boolean) => voidCallback when touch mode changes

touchMode Options

ValueBehavior
trueAlways enable touch mode
falseNever enable via JS (CSS media query still applies)
'auto'Enable based on viewport width (≤979px). Responds to resize.
undefinedRely on CSS media query only (default)

Ref Methods

Access these via a ref to EsheetRenderer:

const rendererRef = useRef<EsheetRendererHandle>(null);

// Check if touch mode is enabled
const isEnabled = rendererRef.current?.isTouchModeEnabled();

// Toggle touch mode (only works with touchMode="auto" or undefined)
rendererRef.current?.setTouchMode(true); // Enable
rendererRef.current?.setTouchMode(false); // Disable

// Reset to auto-detection (only works with touchMode="auto")
rendererRef.current?.resetTouchMode();
MethodReturnsDescription
isTouchModeEnabled()booleanCurrent touch mode state
setTouchMode(enabled)voidManually enable/disable. Overrides auto-detection.
resetTouchMode()voidClear manual override, return to auto-detection

Example: Custom Toggle Button

import { useRef, useState } from 'react';
import { EsheetRenderer, type EsheetRendererHandle } from '@esheet/renderer';

function FormWithTouchToggle({ formDef }) {
const rendererRef = useRef<EsheetRendererHandle>(null);
const [touchEnabled, setTouchEnabled] = useState(false);

return (
<div>
<button
onClick={() => rendererRef.current?.setTouchMode(!touchEnabled)}
className={touchEnabled ? 'bg-primary' : 'bg-gray-200'}
>
{touchEnabled ? '📱 Touch Mode ON' : '🖥️ Touch Mode OFF'}
</button>

<EsheetRenderer
ref={rendererRef}
formDataInput={formDef}
touchMode="auto"
onTouchModeChange={setTouchEnabled}
/>
</div>
);
}

Behavior Matrix

touchModeViewportManual OverrideResult
trueAnyN/ATouch mode ON
false≤979pxN/ACSS applies touch styles
false>979pxN/ANormal styling
'auto'≤979pxNoTouch mode ON
'auto'>979pxNoTouch mode OFF
'auto'AnyEnabledTouch mode ON (ignores viewport)
'auto'AnyDisabledTouch mode OFF (blocks CSS media query)

What Touch Mode Changes

ElementNormalTouch Mode
Inputs/textareasDefault height48px min-height, 16px font
Radio/checkboxDefault size1.75× scale
LabelsDefault size44px min-height, flex-aligned
ButtonsDefault size44px min-height

CSS Classes

The renderer applies these classes to its root element:

ClassWhen Applied
.esheet-renderer-rootAlways
.esheet-touch-activeWhen touch mode is enabled via JS
.touch-mode-disabledWhen user manually disables in auto mode

You can use these classes for custom styling if needed.

Best Practices

  1. Use touchMode="auto" for most cases — It provides the best experience across devices
  2. Sync external UI — Use onTouchModeChange to keep toggle buttons in sync
  3. Test on real devices — Touch targets should be tested on actual mobile devices
  4. Don't force touch mode on desktop — Let users control it if they prefer larger targets