/* ============================================================ exemple-mobile-saisie-doc.jsx — partie 2 Doc panneau droit (catalogue commenté avec visuels) + ROOT. ============================================================ */ const { useState: uDS, useEffect: eDS } = React; /* ============================================================ VISUALS ============================================================ */ /* Mini-clavier virtuel selon le type */ function KeyboardVisual({ kind }) { const wrap = (cells) => (
{cells.map((c, i) => {c})}
); const row = (keys, big) => (
{keys.map((k, i) => ( {k} ))}
); if (kind === 'text') return wrap([row(['q','w','e','r','t','y','u','i','o','p']), row(['a','s','d','f','g','h','j','k','l']), row(['z','x','c','v','b','n','m','⌫']), row(['123','espace','↵'], true)]); if (kind === 'numeric') return wrap([row(['1','2','3'], true), row(['4','5','6'], true), row(['7','8','9'], true), row(['','0','⌫'], true)]); if (kind === 'decimal') return wrap([row(['1','2','3'], true), row(['4','5','6'], true), row(['7','8','9'], true), row([',','0','⌫'], true)]); if (kind === 'tel') return wrap([row(['1','2 ABC','3 DEF'], true), row(['4 GHI','5 JKL','6 MNO'], true), row(['7 PQRS','8 TUV','9 WXYZ'], true), row(['+ * #','0 +','⌫'], true)]); if (kind === 'email') return wrap([row(['q','w','e','r','t','y','u','i','o','p']), row(['a','s','d','f','g','h','j','k','l']), row(['z','x','c','v','b','n','m','⌫']), row(['123','@','espace','.','↵'], true)]); if (kind === 'url') return wrap([row(['q','w','e','r','t','y','u','i','o','p']), row(['a','s','d','f','g','h','j','k','l']), row(['z','x','c','v','b','n','m','⌫']), row(['123','.','/','.com','Aller'], true)]); if (kind === 'search') return wrap([row(['q','w','e','r','t','y','u','i','o','p']), row(['a','s','d','f','g','h','j','k','l']), row(['z','x','c','v','b','n','m','⌫']), row(['123','espace','Rechercher'], true)]); if (kind === 'none') return (
(aucun clavier — picker custom)
); return null; } /* Mini SVG phone pour montrer les écrans */ function ScreenVisual({ type }) { const phone = (inner) => ( {inner} ); if (type === 'login') return phone( OU ); if (type === 'profile') return phone( Profil ); if (type === 'form') return phone( ); if (type === 'swipe') return phone( Boîte Lu Pin ); return phone(null); } /* ============================================================ DOC PANEL ============================================================ */ function NamedItem({ name, desc, location, preview }) { return (
<{name}/> {location && 📍 {location}}
{desc}
{preview && (
{preview}
)}
); } function ScreenCard({ type, name, when, why, gestures, example }) { return (
Écran {name}
Quand{when}
Pourquoi{why}
{gestures &&
Gestes{gestures}
}
Tester{example}
); } function Doc() { return (
{/* INTRO */}

Saisie & formulaires mobile

Suite logique de la variante mobile : écrans de connexion, profil, formulaire complet, liste swipeable. Tous les composants sont nommés et le clavier virtuel se configure précisément (8 types, autocomplete système, touche Entrée personnalisable).

{/* ÉCRANS */}

4 écrans modèles

Chaque écran combine plusieurs composants. Bascule entre eux via les onglets en bas du smartphone.

{/* COMPOSANTS */}

Composants de saisie

Tous ont une API homogène : value / onChange / label / hint / error. Les inputs supportent en plus le contrôle clavier virtuel.

{}} keyboard="email" icon="bell" />} /> {}} mode="date" />} /> {}} placeholder="Choisir…" options={['Option A', 'Option B', 'Option C']} />} /> {}} label="J'accepte les conditions" description="En cochant tu acceptes notre politique." />} /> {}} options={[ { value: 'a', label: 'Option A', description: 'Première option' }, { value: 'b', label: 'Option B', description: 'Deuxième option' }, ]} />} /> {}} />} /> } />
} />
← swipe-moi dans un sens ou l'autre →
} /> {/* CLAVIER VIRTUEL */}

Clavier virtuel

Sur mobile, le clavier qui s'affiche dépend de la prop keyboard (attribut HTML inputmode). Choisis le BON type pour faire gagner du temps à l'utilisateur — exemple : keyboard="numeric" pour un code OTP fait apparaître directement le pavé numérique au lieu du clavier complet.

{KEYBOARD_CATALOG.map((k) => (
{k.name}
{k.desc}
Usage : {k.usage}
))}
{/* AUTOCOMPLETE */}

Aide à la saisie (autocomplete)

L'attribut autocomplete dit au système ce que représente le champ. Sur iOS/Android, ça déclenche : remplissage automatique (nom, email, adresse), proposition du mot de passe enregistré, génération d'un nouveau mot de passe, lecture auto du code SMS reçu.

{AUTOCOMPLETE_CATALOG.map((a) => (
{a.name} {a.usage}
))}
{/* ENTER KEY HINT */}

Touche Entrée — enterKeyHint

La touche en bas à droite du clavier peut afficher un mot différent selon le contexte (au lieu du standard "Entrée").

{ENTER_HINT_CATALOG.map((e) => (
{e.name}
{e.usage}
))}
{/* CHEAT SHEET */}

Antisèche · combinaisons utiles

Email keyboard="email" + autocomplete="email" + autocapitalize="off"
Mot de passe type="password" + autocomplete="current-password" (ou "new-password" en inscription)
Code OTP SMS keyboard="numeric" + autocomplete="one-time-code" + maxLength=6
Téléphone keyboard="tel" + autocomplete="tel"
Recherche keyboard="search" + enterHint="search"
Prix / mesure keyboard="decimal"
Adresse autocomplete="address-line1", puis postal-code, country
Texte libre autocapitalize="sentences" + spellCheck=true
); } /* ============================================================ APP ROOT ============================================================ */ function PhoneAppSaisie({ theme }) { const [tab, setTab] = uDS('login'); const [toast, setToast] = uDS(null); const [sheet, setSheet] = uDS(false); const showToast = (msg) => setToast(msg); return (
{tab === 'login' && setTab('profile')} showToast={showToast} />} {tab === 'profile' && setSheet(true)} />} {tab === 'form' && } {tab === 'swipe' && }
setSheet(false)} title="Paramètres rapides"> {}} /> {}} />} /> {}} />} /> { setSheet(false); setTab('login'); }} /> setToast(null)} message={toast} variant="ok" />
); } function App() { const [theme, setTheme] = uDS('dark'); const [device, setDevice] = uDS('ios'); eDS(() => { document.documentElement.dataset.theme = theme; }, [theme]); return (

Exemple mobile · saisie login · profil · form · swipe · clavier virtuel

exemple mobile
{device === 'ios' &&
}
↑ teste les écrans, swipe les lignes, joue avec les formulaires
); } const root = ReactDOM.createRoot(document.getElementById('root')); root.render();