← Public packages
@kentcdodds/package-app-kit
Design tokens, PWA install/update, About/version, cache helpers, and optional realtime notes sync for Kody package apps.
import type { ReactNode } from 'react'
import { Link } from '@tanstack/react-router'
import { InstallCta } from './install-cta.tsx'
import { UpdateBanner } from './update-banner.tsx'
import { createRoutes } from '../routes.ts'
import { useAppShell } from '../router-context.ts'
export type AppShellProps = {
page: 'home' | 'about' | 'notes'
heading: string
lede?: ReactNode
children?: ReactNode
}
/**
* Tooltips (`data-tip`): tip only controls that are NOT obvious from visible
* label/text. Labeled nav and action buttons do not get tips.
*/
export function AppShell({ page, heading, lede, children }: AppShellProps) {
const { appBasePath } = useAppShell()
const routes = createRoutes(appBasePath)
return (
<div className="pak-wrap pak-stack">
<header className="pak-header">
<div className="pak-brand">
<img
className="pak-logo"
src={routes.icon192.href()}
width={28}
height={28}
alt=""
decoding="async"
tabIndex={0}
data-tip="__PACKAGE_NAME__"
aria-label="__PACKAGE_NAME__"
/>
<h1 className="pak-title">{heading}</h1>
<InstallCta appName="__APP_TITLE__" />
</div>
<nav className="pak-nav" aria-label="App">
<Link
to="/"
className="pak-btn"
aria-current={page === 'home' ? 'page' : undefined}
>
Home
</Link>
<Link
to="/notes"
className="pak-btn"
aria-current={page === 'notes' ? 'page' : undefined}
>
Notes
</Link>
<Link
to="/about"
className="pak-btn"
aria-current={page === 'about' ? 'page' : undefined}
>
About
</Link>
</nav>
{lede ? <p className="pak-muted pak-lede">{lede}</p> : null}
</header>
<UpdateBanner />
{children}
</div>
)
}