Skip to content
← Public packages

@kentcdodds/package-app-kit

Design tokens, PWA install/update, About/version, cache helpers, and optional realtime notes sync for Kody package apps.

FollowFork

starter-tanstack/app/ui/layout.tsx

69 lines · 1.7 KB · TypeScript
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>
	)
}