/* BEGIN USAGE */ // iOS.jsx — Simplified iOS 26 (Liquid Glass) device frame // Based on the iOS 26 UI Kit + Figma status bar spec. No assets, no deps. // Exports (to window): IOSDevice, IOSStatusBar, IOSList, IOSListRow, IOSKeyboard // // Usage — wrap your screen content in to get the bezel, status bar // and home indicator (props: width=402, height=874, dark, keyboard): // // // ...your screen content... // // // // smaller device size // // Safe areas — REQUIRED on every screen. The status bar (top) and home // indicator (bottom) float OVER your content; inset it or it overlaps them. // --ios-safe-top top inset (Dynamic Island + status bar) // --ios-safe-bottom bottom inset (home indicator) /* END USAGE */ // ───────────────────────────────────────────────────────────── // Status bar // ───────────────────────────────────────────────────────────── function IOSStatusBar({ dark = false, time = '9:41' }) { const c = dark ? '#fff' : '#000'; return (
{time}
); } // ───────────────────────────────────────────────────────────── // Grouped list (inset card, r:26) + row (52px) // ───────────────────────────────────────────────────────────── function IOSListRow({ title, detail, icon, chevron = true, isLast = false, dark = false }) { const text = dark ? '#fff' : '#000'; const sec = dark ? 'rgba(235,235,245,0.6)' : 'rgba(60,60,67,0.6)'; const ter = dark ? 'rgba(235,235,245,0.3)' : 'rgba(60,60,67,0.3)'; const sep = dark ? 'rgba(84,84,88,0.65)' : 'rgba(60,60,67,0.12)'; return (
{icon && (
)}
{title}
{detail && {detail}} {chevron && ( )} {!isLast && (
)}
); } function IOSList({ header, children, dark = false }) { const hc = dark ? 'rgba(235,235,245,0.6)' : 'rgba(60,60,67,0.6)'; const bg = dark ? '#1C1C1E' : '#fff'; return (
{header && (
{header}
)}
{children}
); } // ───────────────────────────────────────────────────────────── // Device frame // ───────────────────────────────────────────────────────────── function IOSDevice({ children, width = 402, height = 874, dark = false, keyboard = false, }) { return (
{/* dynamic island */}
{/* status bar (absolute) */}
{/* content */}
{children}
{keyboard && }
{/* home indicator — always on top */}
); } // ───────────────────────────────────────────────────────────── // Keyboard — iOS 26 liquid glass // ───────────────────────────────────────────────────────────── function IOSKeyboard({ dark = false }) { const glyph = dark ? 'rgba(255,255,255,0.7)' : '#595959'; const sugg = dark ? 'rgba(255,255,255,0.6)' : '#333'; const keyBg = dark ? 'rgba(255,255,255,0.22)' : 'rgba(255,255,255,0.85)'; // special-key icons const icons = { shift: , del: , ret: , }; const key = (content, { w, flex, ret, fs = 25, k } = {}) => (
{content}
); const row = (keys, pad = 0) => (
{keys.map(l => key(l, { flex: true, k: l }))}
); return (
{/* liquid glass bg — same recipe as nav pills */}
{/* autocorrect bar */}
{['"The"', 'the', 'to'].map((w, i) => ( {i > 0 &&
}
{w}
))}
{/* key layout */}
{row(['q','w','e','r','t','y','u','i','o','p'])} {row(['a','s','d','f','g','h','j','k','l'], 20)}
{key(icons.shift, { w: 45, k: 'shift' })}
{['z','x','c','v','b','n','m'].map(l => key(l, { flex: true, k: l }))}
{key(icons.del, { w: 45, k: 'del' })}
{key('ABC', { w: 92.25, fs: 18, k: 'abc' })} {key('', { flex: true, k: 'space' })} {key(icons.ret, { w: 92.25, ret: true, k: 'ret' })}
{/* bottom spacer (emoji+mic area, icons omitted) */}
); } Object.assign(window, { IOSDevice, IOSStatusBar, IOSList, IOSListRow, IOSKeyboard, });