evOo-local/apps/www/src/components/GetStartedDialog.astro
cynarAI 6c7eed7580 Initial clean evOo-local from f00577b
Fresh history cut from cynarAI/evoo antigravity-handoff/project-timeline
(Voice First + project timeline). Brand docs/titles as evOo; keep @rakazo/*
packages as tech debt. Excludes node_modules, caches, secrets, voice blobs.
2026-09-20 17:15:16 +02:00

160 lines
5.5 KiB
Plaintext

---
import type { HomeCopy } from "../i18n/home";
import { GITHUB_URL } from "../site";
import Button from "./Button.astro";
import WaitlistForm from "./WaitlistForm.astro";
type Props = {
copy: HomeCopy["getStartedDialog"];
waitlist: HomeCopy["waitlist"];
};
const { copy, waitlist } = Astro.props;
---
<dialog class="get-started-dialog" data-get-started-dialog aria-labelledby="get-started-title">
<div class="get-started-dialog__panel">
<button
class="get-started-dialog__close"
type="button"
data-get-started-close
aria-label={copy.closeLabel}
>
<svg viewBox="0 0 24 24" aria-hidden="true">
<path d="m6 6 12 12M18 6 6 18"></path>
</svg>
</button>
<div data-get-started-choice>
<div class="eyebrow">{copy.eyebrow}</div>
<h2 id="get-started-title">{copy.title}</h2>
<p class="get-started-dialog__copy">{copy.copy}</p>
<div class="get-started-dialog__choices">
<button class="get-started-dialog__choice" type="button" data-get-started-selfhost>
<span class="get-started-dialog__choice-title">{copy.selfHostNow}</span>
<span class="get-started-dialog__choice-hint">{copy.selfHostHint}</span>
</button>
<button class="get-started-dialog__choice" type="button" data-get-started-cloud>
<span class="get-started-dialog__choice-title">{copy.cloudWaitlist}</span>
<span class="get-started-dialog__choice-hint">{copy.cloudHint}</span>
</button>
</div>
</div>
<div data-get-started-signup hidden>
<button class="get-started-dialog__back" type="button" data-get-started-back>{copy.back}</button>
<div class="eyebrow">{copy.cloudWaitlist}</div>
<h2 id="get-started-cloud-title">{copy.cloudWaitlist}</h2>
<p class="get-started-dialog__copy">{copy.cloudHint}</p>
<div class="get-started-dialog__form">
<WaitlistForm
emailId="get-started-email"
emailLabel={waitlist.emailLabel}
placeholder={waitlist.placeholder}
submitLabel={waitlist.submit}
joiningLabel={waitlist.joining}
successLabel={waitlist.success}
addedLabel={waitlist.added}
errorLabel={waitlist.error}
/>
</div>
</div>
<div class="get-started-dialog__success" data-get-started-success hidden>
<div class="get-started-dialog__success-mark" aria-hidden="true">
<svg viewBox="0 0 24 24">
<path d="m5 12 4 4L19 6"></path>
</svg>
</div>
<h2 id="get-started-success-title" tabindex="-1" data-get-started-success-title>{copy.successTitle}</h2>
<p class="get-started-dialog__copy">
{copy.successCopy}
</p>
<div class="get-started-dialog__actions">
<a class="button button--primary" href="#selfhost" data-get-started-close>{copy.selfHostNow}</a>
<Button href={GITHUB_URL} variant="secondary" external>{copy.viewOnGithub}</Button>
<button class="button button--secondary" type="button" data-get-started-close>{copy.done}</button>
</div>
</div>
</div>
</dialog>
<script is:inline>
(function () {
const dialog = document.querySelector("[data-get-started-dialog]");
if (!dialog) return;
const choice = dialog.querySelector("[data-get-started-choice]");
const signup = dialog.querySelector("[data-get-started-signup]");
const success = dialog.querySelector("[data-get-started-success]");
const successTitle = dialog.querySelector("[data-get-started-success-title]");
const email = dialog.querySelector("input[type='email']");
const selfHostBtn = dialog.querySelector("[data-get-started-selfhost]");
function showChoice() {
if (!choice || !signup || !success) return;
choice.hidden = false;
signup.hidden = true;
success.hidden = true;
dialog.setAttribute("aria-labelledby", "get-started-title");
}
function showCloud() {
if (!choice || !signup || !success) return;
choice.hidden = true;
signup.hidden = false;
success.hidden = true;
dialog.setAttribute("aria-labelledby", "get-started-cloud-title");
window.requestAnimationFrame(() => email?.focus());
}
document.addEventListener("click", (event) => {
const target = event.target;
if (!(target instanceof Element)) return;
if (target.closest("[data-get-started-open]")) {
if (dialog.open) return;
showChoice();
dialog.showModal();
window.requestAnimationFrame(() => selfHostBtn?.focus());
return;
}
if (target.closest("[data-get-started-close]")) {
dialog.close();
return;
}
if (target.closest("[data-get-started-selfhost]")) {
dialog.close();
document.getElementById("selfhost")?.scrollIntoView({ behavior: "smooth" });
return;
}
if (target.closest("[data-get-started-cloud]")) {
showCloud();
return;
}
if (target.closest("[data-get-started-back]")) {
showChoice();
}
});
dialog.addEventListener("click", (event) => {
if (event.target === dialog) dialog.close();
});
dialog.addEventListener("waitlist:joined", () => {
if (!choice || !signup || !success) return;
choice.hidden = true;
signup.hidden = true;
success.hidden = false;
dialog.setAttribute("aria-labelledby", "get-started-success-title");
successTitle?.focus();
});
document.documentElement.dataset.getStartedReady = "";
})();
</script>