Skip to content

app/ui.ts

39 lines · 3.0 KB · TypeScript
Raw
// Shared look: vector-arcade font, colors, and the button style used by SOUND / MUSIC.
export const COLORS = { bg: '#05070d', ink: '#e8f1ff', glow: '#7fb4ff' }

export const baseCss = `*{box-sizing:border-box}
html,body{margin:0;background:${COLORS.bg};color:${COLORS.ink};font:600 14px/1.5 ui-monospace,SFMono-Regular,Menlo,monospace}
.btn{font:inherit;font-size:11px;line-height:1;letter-spacing:.08em;color:${COLORS.ink};background:#ffffff0a;border:1px solid #e8f1ff55;border-radius:6px;padding:5px 8px;min-width:11ch;cursor:pointer;text-decoration:none;display:inline-flex;align-items:center;justify-content:center;white-space:nowrap}
.btn:hover{background:#ffffff1a;border-color:#e8f1ffaa}.btn:focus-visible{outline:2px solid ${COLORS.glow};outline-offset:2px}
.btn[aria-pressed=false]{opacity:.55}.btn[hidden]{display:none}
.btn.hot{border-color:${COLORS.glow};box-shadow:0 0 10px ${COLORS.glow}66}
#toast{position:fixed;left:50%;bottom:max(84px,calc(env(safe-area-inset-bottom) + 84px));transform:translateX(-50%);display:flex;gap:10px;align-items:center;padding:10px 12px;background:${COLORS.bg}ee;border:1px solid ${COLORS.glow};border-radius:8px;box-shadow:0 0 18px ${COLORS.glow}55;letter-spacing:.12em;font-size:12px;z-index:10}
#toast[hidden]{display:none}`

export const esc = (s: string) => s.replace(/[&<>"']/g, (c) => `&#${c.charCodeAt(0)};`)

export type PageCtx = { origin: string; appBase: string; assetBase: string }

export function headTags(ctx: PageCtx, title: string) {
	const abs = (p: string) => esc(`${ctx.origin}${p}`)
	const desc = 'Classic vector Asteroids with synthesized chiptune sound. Play with keyboard or touch, install it, and play offline.'
	return `<meta name="theme-color" content="${COLORS.bg}">
<meta name="description" content="${esc(desc)}">
<meta property="og:type" content="website">
<meta property="og:title" content="${esc(title)}">
<meta property="og:description" content="${esc(desc)}">
<meta property="og:url" content="${abs(`${ctx.appBase}/`)}">
<meta property="og:image" content="${abs(`${ctx.assetBase}/og.jpg`)}">
<meta property="og:image:width" content="1200"><meta property="og:image:height" content="630">
<meta property="og:image:alt" content="ASTEROIDS: a glowing vector ship firing at outlined asteroids on a starfield">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="${esc(title)}">
<meta name="twitter:description" content="${esc(desc)}">
<meta name="twitter:image" content="${abs(`${ctx.assetBase}/og.jpg`)}">
<link rel="icon" href="${esc(ctx.assetBase)}/icons/favicon.svg" type="image/svg+xml">
<link rel="icon" href="${esc(ctx.assetBase)}/icons/favicon-32.png" sizes="32x32" type="image/png">
<link rel="apple-touch-icon" href="${esc(ctx.assetBase)}/icons/apple-touch-icon.png">
<link rel="manifest" href="${esc(ctx.appBase)}/manifest.webmanifest">
<meta name="apple-mobile-web-app-capable" content="yes"><meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">`
}