diff --git a/apps/marketing/src/layouts/Layout.astro b/apps/marketing/src/layouts/Layout.astro index e60637cbfd1..edb448ee77a 100644 --- a/apps/marketing/src/layouts/Layout.astro +++ b/apps/marketing/src/layouts/Layout.astro @@ -41,12 +41,20 @@ const { target="_blank" rel="noopener noreferrer" > - GitHub - Download + Download @@ -59,11 +67,21 @@ const { @@ -99,8 +117,10 @@ const { --accent-dim: oklch(0.68 0.17 var(--accent-h) / 0.15); --ok: oklch(0.72 0.16 150); --warn: oklch(0.76 0.15 75); - --font-sans: "DM Sans", -apple-system, BlinkMacSystemFont, system-ui, sans-serif; - --font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, monospace; + --font-sans: + "DM Sans", -apple-system, BlinkMacSystemFont, system-ui, sans-serif; + --font-mono: + "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, monospace; --radius: 12px; --radius-sm: 8px; --radius-lg: 16px; @@ -191,8 +211,11 @@ const { font-size: 14px; padding: 10px 18px; border-radius: 8px; - transition: transform 0.18s ease, background 0.18s ease, - border-color 0.18s ease, color 0.18s ease; + transition: + transform 0.18s ease, + background 0.18s ease, + border-color 0.18s ease, + color 0.18s ease; white-space: nowrap; } @@ -233,7 +256,11 @@ const { position: relative; border: 1px solid var(--border); border-radius: var(--radius); - background: linear-gradient(180deg, rgba(255, 255, 255, 0.015), rgba(255, 255, 255, 0)); + background: linear-gradient( + 180deg, + rgba(255, 255, 255, 0.015), + rgba(255, 255, 255, 0) + ); overflow: hidden; } @@ -255,20 +282,31 @@ const { } @keyframes pulse { - 50% { opacity: 0.4; } + 50% { + opacity: 0.4; + } } @keyframes spin { - to { transform: rotate(360deg); } + to { + transform: rotate(360deg); + } } @keyframes floatDrift { - 0%, 100% { translate: 0 0; } - 50% { translate: 0 -10px; } + 0%, + 100% { + translate: 0 0; + } + 50% { + translate: 0 -10px; + } } @keyframes blink { - 50% { opacity: 0; } + 50% { + opacity: 0; + } } @@ -332,14 +370,17 @@ const { .nav-gh { display: inline-flex; align-items: center; - gap: 6px; - padding: 7px 12px; + gap: 8px; + padding: 10px 14px; border: 1px solid var(--border); border-radius: 8px; color: var(--fg-muted); font-family: var(--font-mono); - font-size: 12px; - transition: color 0.2s ease, background 0.2s ease, border-color 0.2s ease; + font-size: 14px; + transition: + color 0.2s ease, + background 0.2s ease, + border-color 0.2s ease; } .nav-gh:hover { diff --git a/apps/marketing/src/pages/download.astro b/apps/marketing/src/pages/download.astro index b9e0e0181e4..b8cfcdb30d0 100644 --- a/apps/marketing/src/pages/download.astro +++ b/apps/marketing/src/pages/download.astro @@ -3,68 +3,240 @@ import Layout from "../layouts/Layout.astro"; import { RELEASES_URL } from "../lib/releases"; --- - +
-

Download T3 Code

-

- Loading latest release… - -

- -
- -
-
- -

macOS

+

Download T3 Code

+

+ Loading latest release… + +

+ +
+
+

Run without installing

+

+ Spin up T3 Code straight from your terminal — no download required. +

-
- -
-
- -

Windows

-
- -
- - -
-
- -

Linux

-
- -
-
- - +
+ +
+
+ +

macOS

+
+ +
+ Or install with Homebrew +
+ $brew install --cask t3-code +
+
+
+ + +
+
+ +

Windows

+
+ +
+ Or install with winget +
+ $winget install T3Tools.T3Code +
+
+
+ + +
+
+ +

Linux

+
+ +
+ Or install from the AUR +
+ $yay -S t3code-bin +
+
+
+
+ +
@@ -73,7 +245,8 @@ import { RELEASES_URL } from "../lib/releases"; async function init() { const versionLabel = document.getElementById("version-label"); - const cards = document.querySelectorAll(".download-card"); + const cards = + document.querySelectorAll(".download-card"); try { const release = await fetchLatestRelease(); @@ -82,7 +255,9 @@ import { RELEASES_URL } from "../lib/releases"; versionLabel.textContent = `Latest (${release.tag_name})`; } - const changelogLink = document.getElementById("changelog-link") as HTMLAnchorElement | null; + const changelogLink = document.getElementById( + "changelog-link", + ) as HTMLAnchorElement | null; if (changelogLink && release.html_url) { changelogLink.href = release.html_url; changelogLink.style.display = ""; @@ -92,7 +267,9 @@ import { RELEASES_URL } from "../lib/releases"; const suffix = card.dataset.asset; if (!suffix) return; - const match = (release.assets ?? []).find((a) => a.name.endsWith(`-${suffix}`)); + const match = (release.assets ?? []).find((a) => + a.name.endsWith(`-${suffix}`), + ); if (match) { card.href = match.browser_download_url; } else { @@ -109,7 +286,51 @@ import { RELEASES_URL } from "../lib/releases"; } } + const COPY_ICON_SVG = ``; + const CHECK_ICON_SVG = ``; + + function initCopyButtons() { + document.querySelectorAll(".cmd-block").forEach((block) => { + const code = block.querySelector("code"); + if (!code) return; + + const wrap = document.createElement("div"); + wrap.className = "cmd-block-wrap"; + block.parentNode?.insertBefore(wrap, block); + wrap.appendChild(block); + + const tooltip = document.createElement("span"); + tooltip.className = "cmd-tooltip"; + tooltip.textContent = "Copy"; + wrap.appendChild(tooltip); + + const button = document.createElement("button"); + button.type = "button"; + button.className = "cmd-copy"; + button.setAttribute("aria-label", "Copy command to clipboard"); + button.innerHTML = COPY_ICON_SVG + CHECK_ICON_SVG; + block.appendChild(button); + + let resetTimer: number | undefined; + block.addEventListener("click", async () => { + try { + await navigator.clipboard.writeText(code.textContent ?? ""); + button.classList.add("is-copied"); + tooltip.textContent = "Copied"; + if (resetTimer !== undefined) window.clearTimeout(resetTimer); + resetTimer = window.setTimeout(() => { + button.classList.remove("is-copied"); + tooltip.textContent = "Copy"; + }, 1600); + } catch { + // Ignore clipboard failures (insecure context, denied permission). + } + }); + }); + } + init(); + initCopyButtons();