Kiosk shell: drop its own bar, listen for the apps' Home button

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
jtricerolph 2026-10-15 11:34:54 +00:00
parent 41a56ce128
commit c7676ace42

View file

@ -1,5 +1,5 @@
import { useCallback, useEffect, useState } from 'react'
import { Hotel, Home, LayoutGrid } from 'lucide-react'
import { Hotel, LayoutGrid } from 'lucide-react'
import { AppIcon } from '../components/AppIcon'
interface KioskApp {
@ -44,6 +44,18 @@ export function Kiosk() {
return () => window.clearInterval(t)
}, [refresh])
// Kiosk screens ask to go home with a same-origin postMessage from their own
// header's Home button — the shell has no bar of its own.
useEffect(() => {
function onMessage(e: MessageEvent) {
if (e.origin !== window.location.origin || e.data?.type !== 'hnf:kiosk-home') return
setOpen(null)
refresh()
}
window.addEventListener('message', onMessage)
return () => window.removeEventListener('message', onMessage)
}, [refresh])
async function login(e: React.FormEvent) {
e.preventDefault()
setBusy(true); setError('')
@ -98,20 +110,9 @@ export function Kiosk() {
}
if (open) {
return (
<div style={shell}>
<div style={{ display: 'flex', alignItems: 'center', gap: '0.75rem', padding: '0.35rem 0.75rem', background: 'var(--navy)', flexShrink: 0 }}>
<button onClick={() => { setOpen(null); refresh() }} aria-label="Back to home" style={{
display: 'flex', alignItems: 'center', gap: 6, background: 'var(--surface-2)', border: 'none',
color: 'var(--text)', borderRadius: 8, padding: '0.4rem 0.8rem', fontSize: '0.85rem', fontWeight: 600, cursor: 'pointer',
}}>
<Home size={15} strokeWidth={1.75} /> Home
</button>
<span style={{ fontSize: '0.85rem', color: 'var(--text-muted)' }}>{open.name}</span>
</div>
<iframe title={open.name} src={open.kiosk_path} style={{ flex: 1, border: 'none', width: '100%', background: 'var(--body-bg)' }} />
</div>
)
// The app's own kiosk header carries the Home button (it posts hnf:kiosk-home
// — see the listener above), so the shell adds no chrome of its own.
return <iframe title={open.name} src={open.kiosk_path} style={{ height: '100dvh', width: '100%', border: 'none', background: 'var(--body-bg)' }} />
}
return (