The rule's circle reached below the wordmark's box, cutting it off in the README banner and on the login page. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
68 lines
3.6 KiB
JavaScript
68 lines
3.6 KiB
JavaScript
// The Steward logo and the login page's wordmark, drawn as inline SVG so
|
|
// they appear together with the page instead of loading afterwards.
|
|
//
|
|
// The "STEWARD" wordmark: the angular letters of Jarl's wordmark (its A
|
|
// and R are the same), drawn as paths so no font is needed. The login page
|
|
// shows it over a rule with a DHCP node; the header shows the letters
|
|
// alone. The letters use the text color and the rule the accent color.
|
|
import * as logoData from "./logo.js";
|
|
|
|
const NS = "http://www.w3.org/2000/svg";
|
|
|
|
function el(tag, attrs, ...children) {
|
|
const e = document.createElementNS(NS, tag);
|
|
for (const [k, v] of Object.entries(attrs || {})) e.setAttribute(k, v);
|
|
for (const c of children) e.append(c instanceof Node ? c : document.createTextNode(c));
|
|
return e;
|
|
}
|
|
|
|
// Letters on a 100-unit cap height; counters are cut with evenodd.
|
|
const letters = [
|
|
// S: squared, with a downward barb on the top bar and an upward one on
|
|
// the bottom bar (Jarl's L turned around)
|
|
{ x: 0, d: "M10 0 H54 L58 30 L40 16 H18 V41 H48 L58 51 V90 L48 100 H4 L0 70 L18 84 H40 V59 H10 L0 49 V10 Z" },
|
|
// T: a bar with barbed ends
|
|
{ x: 70, d: "M0 0 H70 L66 22 L52 18 H44 V100 H26 V18 H18 L4 22 Z" },
|
|
// E: the bottom arm ends in Jarl's L spike
|
|
{ x: 152, d: "M0 0 H52 L56 18 H18 V41 H44 V59 H18 V82 H40 L58 70 L54 100 H0 Z" },
|
|
// W: flat-topped middle peak
|
|
{ x: 222, d: "M0 0 H18 L28 66 L38 30 H52 L62 66 L72 0 H90 L76 100 H54 L45 66 L36 100 H14 Z" },
|
|
// A and R: Jarl's
|
|
{ x: 324, d: "M35 0 L46 10 L64 90 L70 100 H50 L44 76 L35 62 L26 76 L20 100 H0 L6 90 L24 10 Z M35 26 L41 40 L35 54 L29 40 Z" },
|
|
{ x: 406, d: "M0 0 H48 L60 12 V40 L50 50 L66 100 H46 L34 60 H18 V100 H0 Z M18 14 H41 L46 19 V35 L41 46 H18 Z" },
|
|
// D: cut corners, like R's bowl
|
|
{ x: 484, d: "M0 0 H44 L64 20 V80 L44 100 H0 Z M18 16 H38 L46 24 V76 L38 84 H18 Z" },
|
|
];
|
|
|
|
const W = 548; // the letters' width
|
|
|
|
// wordmark returns the login page's wordmark, letters over the rule.
|
|
// wordmark({ rule: false, height: 19, cls: "brand-name" }) returns just the
|
|
// letters, height pixels tall.
|
|
export function wordmark({ rule = true, height, cls = "wordmark" } = {}) {
|
|
const letterG = el("g", { fill: "currentColor", "fill-rule": "evenodd" },
|
|
...letters.map((l) => el("path", { d: l.d, transform: `translate(${l.x} 0)` })));
|
|
if (!rule) {
|
|
const attrs = { class: cls, viewBox: `-2 -2 ${W + 4} 104`, role: "img", "aria-label": "Steward" };
|
|
if (height) Object.assign(attrs, { height, width: Math.round(height * (W + 4) / 104) });
|
|
return el("svg", attrs, el("title", null, "Steward"), letterG);
|
|
}
|
|
const c = W / 2;
|
|
const ruleG = el("g", { class: "wordmark-rule", transform: "translate(0 118)" },
|
|
el("path", { d: `M2 18 L${c - 60} 15.6 V20.4 Z M${W - 2} 18 L${c + 60} 15.6 V20.4 Z`, class: "fill" }),
|
|
el("circle", { cx: c - 52, cy: 18, r: 4.6, class: "line" }),
|
|
el("path", { d: `M${c - 47.4} 18 H${c - 30} M${c + 30} 18 H${c + 47.4}`, class: "line" }),
|
|
el("circle", { cx: c, cy: 18, r: 30, class: "line" }),
|
|
el("circle", { cx: c + 52, cy: 18, r: 4.6, class: "line" }),
|
|
el("text", { x: c, y: 24.5, "text-anchor": "middle", class: "tag" }, "DHCP"));
|
|
return el("svg", { class: cls, viewBox: `-4 -4 ${W + 8} 176`, role: "img", "aria-label": "Steward" },
|
|
el("title", null, "Steward"), letterG, ruleG);
|
|
}
|
|
|
|
// logo returns the Steward logo (artwork/logo.svg, via scripts/logo.py) as
|
|
// an SVG of the given size in pixels.
|
|
export function logo(size, cls) {
|
|
return el("svg", { class: cls || "logo", width: size, height: size, viewBox: logoData.viewBox, "aria-hidden": "true", focusable: "false" },
|
|
...logoData.shapes.map(([tag, attrs]) => el(tag, attrs)));
|
|
}
|