← Public packages
@kentcdodds/package-app-kit
Design tokens, PWA install/update, About/version, cache helpers, and optional realtime notes sync for Kody package apps.
src/error-display.ts
58 lines · 1.7 KB · TypeScript/**
* Error display helpers for package apps.
* Prefer a stable in-flow alert (or reserved slot) over injecting late chrome that shifts layout.
* For ephemeral failures, prefer a toast overlay (zero CLS).
*/
export type ErrorDisplayInput = {
title?: string
message: string
hint?: string
/** Optional technical detail for tip / expandable */
detail?: string
}
/** Normalize unknown thrown values into a short user-facing message. */
export function toErrorMessage(error: unknown): string {
if (error instanceof Error && error.message) return error.message
if (typeof error === 'string' && error.trim()) return error.trim()
try {
return JSON.stringify(error)
} catch {
return String(error)
}
}
/**
* HTML fragment for an inline error alert (role=alert).
* Use when the error replaces expected content in a reserved region.
*/
export function errorBannerHtml(input: ErrorDisplayInput): string {
const title = escapeHtml(input.title || 'Something went wrong')
const message = escapeHtml(input.message || 'Unknown error')
const hint = input.hint
? `<p class="pak-muted pak-error-hint">${escapeHtml(input.hint)}</p>`
: ''
const tip = input.detail ? ` data-tip="${escapeAttr(input.detail)}"` : ''
return `
<div class="pak-error" role="alert"${tip} tabindex="0">
<strong class="pak-error-title">${title}</strong>
<p class="pak-error-message">${message}</p>
${hint}
</div>
`.trim()
}
function escapeHtml(value: string) {
return value
.replaceAll('&', '&')
.replaceAll('<', '<')
.replaceAll('>', '>')
.replaceAll('"', '"')
}
function escapeAttr(value: string) {
return escapeHtml(value).replaceAll("'", ''')
}
export default errorBannerHtml