/**
* Pure HTML atoms shared by the Bytefly browser pages.
*
* Each helper returns a string with every dynamic *value* escaped through
* `lib/escape.ts`. Fields documented as trusted (`css`, an `icon` glyph, an
* attribute key) are code-authored constants, never model or file text.
*/
import { escapeHtml } from "../escape.ts";
/** Options for {@link docHead}. */
export interface DocHeadOptions {
/** Page title, escaped. */
title: string;
/** Trusted CSS assembled by the page. */
css: string;
}
/**
* The shared document head: charset, viewport, colour scheme, title, the page
* CSS, and the pre-paint theme bootstrap. The body and its scripts stay with
* each page.
*/
export function docHead(options: DocHeadOptions): string {
return `
${escapeHtml(options.title)}
`;
}
/**
* The Bytefly nameplate: the two-tone half-block mark, the `bytefly` wordmark,
* and the product name. The mark mirrors the TUI header (`█▀█` / `█▀ █`), drawn
* as a 4x2 grid so the accent and warning rows stay crisp at any zoom.
*/
export function brandLockup(product: string): string {
return `bytefly${escapeHtml(product)}`;
}
/**
* The theme toggle button. Keeps the `#theme-toggle` id and `.theme-glyph`
* span the shared `THEME_TOGGLE_JS` scripts find.
*/
export function themeToggle(): string {
return ``;
}
/** A chip's tone, mapping to a `bf-chip--*` modifier. */
export type ChipTone = "accent" | "success" | "warn" | "danger";
/** Options for {@link chip}. */
export interface ChipOptions {
/** Visible text, escaped. */
label: string;
/** Optional tone modifier. */
tone?: ChipTone;
/** Trusted leading glyph or SVG. */
icon?: string;
}
/** A compact status chip. */
export function chip(options: ChipOptions): string {
const tone = options.tone ? ` bf-chip--${options.tone}` : "";
const icon = options.icon ? `${options.icon}` : "";
return `${icon}${escapeHtml(options.label)}`;
}
/** A button variant, mapping to a `bf-btn--*` modifier. */
export type ButtonVariant = "primary" | "ghost" | "icon";
/** Options for {@link button}. */
export interface ButtonOptions {
/** Visible text, escaped. */
label: string;
/** Optional variant modifier. */
variant?: ButtonVariant;
/** Element id. */
id?: string;
/** Tooltip and accessible name. */
title?: string;
/** Sets `aria-pressed` when defined. */
pressed?: boolean;
/** Extra code-authored attributes; keys and values are escaped. */
attrs?: Record;
}
/** A `type="button"` control wired to the kit classes. */
export function button(options: ButtonOptions): string {
const classes = options.variant ? `bf-btn bf-btn--${options.variant}` : "bf-btn";
const attrs: Array<[string, string]> = [];
if (options.id) attrs.push(["id", options.id]);
if (options.title) attrs.push(["title", options.title]);
if (options.pressed !== undefined) attrs.push(["aria-pressed", String(options.pressed)]);
for (const [key, value] of Object.entries(options.attrs ?? {})) attrs.push([key, value]);
const rendered = attrs.map(([key, value]) => ` ${key}="${escapeHtml(value)}"`).join("");
return ``;
}