Phase 4: component library

The approved element rules and ornament kit as Astro components in
packages/ui: buttons, pills, chips, filters, kickers, notices, fields and
cards; star paths, the header divider, tick scales and rings, seals and
edge seals, gilt corners, dust and placeholder art; the site header,
footer and page shell. Brand fonts are self-hosted. A gallery page shows
everything, and astro check now runs with the root typecheck.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012aSbo2D1qP8cMFQCykf7kx
This commit is contained in:
Claude
2026-10-11 20:44:16 +00:00
parent 32cf13a5cb
commit 807528a613
159 changed files with 6270 additions and 87 deletions
+44
View File
@@ -0,0 +1,44 @@
---
/**
* Rule V. A labelled field: input, select or text area in the 10px box, with
* the filament drawn across its base on focus.
*/
import type { HTMLAttributes } from "astro/types";
type Props = {
label: string;
name: string;
as?: "input" | "select" | "textarea";
hint?: string;
error?: string;
options?: (string | { value: string; label: string })[];
/** Rows for a text area. */
rows?: number;
class?: string;
} & HTMLAttributes<"input">;
const { label, name, as = "input", hint, error, options = [], rows, class: className, id = `f-${name}`, ...rest } = Astro.props;
const describedBy = [hint && `${id}-hint`, error && `${id}-error`].filter(Boolean).join(" ") || undefined;
const common = { id, name, class: "gk-field", "aria-describedby": describedBy, "aria-invalid": error ? ("true" as const) : undefined };
---
<div class:list={["gk-label", className]}>
<label class="gk-label-text" for={id}>{label}</label>
{as === "select" ? (
<select {...common} {...(rest as object)}>
{options.map((o) => (typeof o === "string" ? <option>{o}</option> : <option value={o.value}>{o.label}</option>))}
</select>
) : as === "textarea" ? (
<textarea {...common} rows={rows} {...(rest as object)} />
) : (
<input {...common} {...rest} />
)}
{hint && <span class="gk-hint" id={`${id}-hint`}>{hint}</span>}
{error && <span class="error" id={`${id}-error`}>{error}</span>}
</div>
<style>
.error {
font-size: 12px;
color: #f0857a;
}
</style>