Site: app regions with screenshots, props, downloads, English and Chinese, narrow layout; hit layer follows draw order

This commit is contained in:
ZacharyZhang-NY committed 2026-10-08 23:57:34 -04:00
1 parent 29e4e7f70f
commit 07719a1fd3
29 files changed
+1423 -97

No files matched your search

+48 -19
View File
@@ -1,38 +1,67 @@
import "./style.css";
import "./iso.css";
import { block, stage } from "./iso.ts";
import { grow } from "./beat.ts";
import { model } from "./model.ts";
import { touch } from "./touch.ts";
import { regions, reveal } from "./regions.ts";
import { said, speak, type Lang } from "./text.ts";
/** 112 BPM, the film's tempo; blocks land on sixteenths. */
const BEAT = 60 / 112;
const STEP = BEAT / 4;
const RELEASE = "https://github.com/ZacharyZhang-NY/ElyOffice/releases/download/v0.1.0";
const app = document.querySelector<HTMLElement>("#app");
if (!app) throw new Error("index.html has no #app");
const apps = model.slice(1, -1);
const parts = new Map<string, SVGGElement[]>();
const blocks: SVGGElement[] = [];
let beat = 1;
for (const part of model) {
const own = part.blocks.map((spec, i) => {
const g = block(spec);
g.style.setProperty("--land", `${(beat * BEAT + i * STEP).toFixed(3)}s`);
return g;
});
if (apps.includes(part)) parts.set(part.name, own);
blocks.push(...own);
beat += Math.ceil(part.blocks.length / 4);
}
const built = model.map((part) => part.blocks.map(block));
grow(built);
const parts = new Map(apps.map((p) => [p.name, built[model.indexOf(p)]]));
const hero = document.createElement("header");
hero.className = "hero";
const title = document.createElement("h1");
title.textContent = "Ely Office";
const host = document.createElement("div");
host.className = "model";
const svg = stage(blocks);
svg.classList.add("grow");
const svg = stage(built.flat());
svg.classList.add("grow", "seen");
svg.setAttribute("aria-hidden", "true");
host.append(svg);
app.append(title, host);
hero.append(title, said("p", "tagline"), said("p", "platforms"), host);
touch(host, svg, parts);
const sections = regions();
const footer = document.createElement("footer");
footer.id = "download";
const version = document.createElement("h2");
version.textContent = "Ely Office 0.1.0";
const list = document.createElement("ul");
for (const p of apps) {
const a = document.createElement("a");
a.href = `${RELEASE}/${p.name}-0.1.0-arm64.dmg`;
a.textContent = p.name;
const li = document.createElement("li");
li.append(a);
list.append(li);
}
const source = said("a", "source");
source.href = `${RELEASE}/ElyOffice-0.1.0-source.tar.gz`;
const li = document.createElement("li");
li.append(source);
list.append(li);
footer.append(version, said("p", "platforms"), said("p", "needs"), said("p", "unsigned"), list);
const toggle = said("button", "other");
toggle.className = "lang";
let lang: Lang = navigator.language.toLowerCase().startsWith("zh") ? "zh" : "en";
toggle.addEventListener("click", () => {
lang = lang === "en" ? "zh" : "en";
speak(lang);
});
const main = document.createElement("main");
main.append(...sections);
app.append(toggle, hero, main, footer);
speak(lang);
reveal(sections);