Files
time/typy/public/index.html
T
2026-10-24 23:37:52 +00:00

157 lines
13 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">
<meta name="theme-color" content="#f5f3ec">
<!--OG-->
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
<link rel="stylesheet" href="/style.css">
<script type="module" src="/app.js"></script>
</head>
<body>
<div class="shell">
<header class="masthead">
<a class="brand" href="/" aria-label="typy home">typy<span class="brand-dot" aria-hidden="true"></span></a>
<span class="brand-note">a little more in the moment.</span>
<nav class="top-nav" aria-label="Main">
<a href="/daily" id="daily-link"><span class="sun" aria-hidden="true">✳</span> the daily</a>
<button class="icon-button" id="settings-open" aria-label="Typing settings" title="Typing settings">
<svg width="21" height="21" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true"><path d="M4 7h16M4 17h16"/><circle cx="9" cy="7" r="3" fill="var(--paper)"/><circle cx="15" cy="17" r="3" fill="var(--paper)"/></svg>
</button>
<button class="icon-button help-button" id="help-open" aria-label="How to play">?</button>
</nav>
</header>
<main id="main">
<section class="toolbar" aria-label="Run options">
<div class="mode-switch" id="mode-switch" aria-label="Run length">
<button data-mode="30" aria-pressed="true">30s</button>
<button data-mode="60" aria-pressed="false">60s</button>
<button data-mode="50" aria-pressed="false">50 words</button>
<button data-mode="endless" aria-pressed="false" aria-label="Endless">∞</button>
<span class="mode-divider" aria-hidden="true"></span>
<button data-mode="tempo" class="tempo-option" aria-pressed="false"><span class="tempo-icon" aria-hidden="true"><i></i><i></i><i></i></span>tempo</button>
</div>
<button class="source-button" id="source-open"><span id="source-label">common words</span><span aria-hidden="true">↗</span></button>
</section>
<section id="load-panel" class="load-panel" hidden aria-live="polite">
<div class="spinner" id="loading-spinner" aria-hidden="true"></div>
<p class="eyebrow" id="load-kicker">one moment</p>
<h1 id="load-title">finding the words…</h1>
<p id="load-description"></p>
<div class="button-row" id="load-actions" hidden><button class="button primary" id="load-retry">try again</button><button class="button" id="load-common">use common words</button></div>
</section>
<section id="play-panel" class="play-panel" aria-label="Typing stage">
<div class="run-strip">
<div class="run-status"><span class="status-dot" id="status-dot"></span><span id="run-status">a fresh start</span></div>
<div id="best-score" class="best-score"></div>
</div>
<div class="metrics" aria-label="Live score">
<div><span class="metric-label">pace</span><span class="metric-value" id="live-wpm">0</span><span class="metric-unit">wpm</span></div>
<div><span class="metric-label">accuracy</span><span class="metric-value" id="live-accuracy">100</span><span class="metric-unit">%</span></div>
<div class="time-metric"><span class="metric-label" id="time-label">remaining</span><span class="metric-value" id="live-time">30</span><span class="metric-unit" id="time-unit">s</span></div>
</div>
<div id="ghost-race" class="ghost-race" hidden aria-live="off"><span>you <b id="race-you">0</b></span><span class="race-separator">/</span><span class="ghost-label">ghost <b id="race-them">0</b></span><span id="race-delta"></span></div>
<div class="stage" id="stage">
<span class="word-number" id="word-number" aria-hidden="true">001</span>
<div class="word-wrap">
<div class="word-pair" id="word-pair">
<div class="word" id="word" aria-live="off" aria-label="Word to type"></div>
<div class="upcoming" id="upcoming" aria-hidden="true"><b id="next-word"></b></div>
</div>
</div>
</div>
<div id="tempo-track" class="tempo-track" hidden><div class="tempo-rail"><div id="tempo-progress"></div></div><div class="tempo-caption"><span id="tempo-caption">find the beat</span><span id="tempo-lives" aria-label="Three beats remaining"><i></i><i></i><i></i></span></div></div>
<div class="input-row" id="input-row">
<input id="typing-input" class="typing-input" type="text" inputmode="text" enterkeyhint="next" autocomplete="off" autocapitalize="off" autocorrect="off" spellcheck="false" maxlength="64" aria-label="Type the word shown above" placeholder="tap here to type">
<p class="run-hint" id="run-hint"><span class="hint-start">type the word to begin</span><span class="hint-separator">·</span><span id="advance-hint"><kbd>space</kbd> next word</span></p>
<button id="finish-run" class="text-button" hidden>finish run ↵</button>
</div>
<section id="replay-controls" class="replay-controls" hidden aria-label="Replay controls">
<button class="button small" id="replay-play">pause</button>
<input type="range" id="replay-scrubber" min="0" max="1000" step="10" value="0" aria-label="Replay position">
<span class="replay-time" id="replay-time">0:00 / 0:30</span>
<button class="text-button" id="replay-back">back to result ↗</button>
</section>
</section>
<section id="result-panel" class="result-panel" hidden aria-labelledby="result-title">
<div class="result-heading"><p class="eyebrow" id="result-kicker">30 seconds, well spent</p><span class="new-best" id="new-best" hidden>personal best ↗</span></div>
<h1 id="result-title">there’s your rhythm.</h1>
<div class="result-grid">
<div class="result-main"><span id="result-wpm">0</span><span>words per minute</span></div>
<dl class="result-detail">
<div><dt>accuracy</dt><dd id="result-accuracy">100%</dd></div>
<div><dt>best clean streak</dt><dd id="result-streak">0 words</dd></div>
<div><dt>words completed</dt><dd id="result-words">0</dd></div>
</dl>
</div>
<div class="rhythm-chart"><div class="chart-label"><span>your rhythm</span><span>each word, in wpm</span></div><svg id="speed-chart" viewBox="0 0 900 95" role="img" aria-label="Speed for each completed word"></svg></div>
<div class="slow-words"><span>room to grow</span><div id="slow-words"></div></div>
<div class="result-actions">
<button class="button primary" id="again-button">go again <span aria-hidden="true">↵</span></button>
<button class="button" id="replay-button">replay <span aria-hidden="true">▷</span></button>
<button class="button" id="share-button">share result <span aria-hidden="true">↗</span></button>
<button class="text-button" id="race-button">race this →</button>
</div>
<div class="result-note" id="result-note"></div>
<button class="text-button daily-board-button" id="board-open" hidden>today’s board ↗</button>
</section>
</main>
<footer class="footer"><span>one word. then the next.</span><div><button class="text-button" id="footer-board" hidden>today’s board ↗</button><span id="restart-tip"><kbd>esc</kbd> restart</span><a href="https://teahub.xyz/teahubxyz/time/issues/254" target="_blank" rel="noopener" aria-label="About typy on Teahub">a small experiment ↗</a></div></footer>
</div>
<dialog id="settings-dialog" class="dialog">
<form method="dialog"><button class="dialog-close" aria-label="Close settings">×</button></form>
<p class="eyebrow">make yourself comfortable</p><h2>your rhythm, your rules.</h2>
<label class="setting-row"><span><b>Next word</b><small>Choose what moves you forward.</small></span><select id="advance-setting"><option value="space">press space</option><option value="letter">last letter</option></select></label>
<label class="setting-row"><span><b>A little look ahead</b><small>Show the upcoming word.</small></span><input class="switch" id="preview-setting" type="checkbox" checked></label>
<p class="dialog-note">Changes start a fresh run. Your best scores stay on this device.</p>
<button class="button primary full" id="settings-done">all set</button>
</dialog>
<dialog id="source-dialog" class="dialog wide">
<form method="dialog"><button class="dialog-close" aria-label="Close text sources">×</button></form>
<p class="eyebrow">words worth spending time with</p><h2>what’s on your mind?</h2>
<div class="source-tabs" role="tablist" aria-label="Text source"><button id="tab-topic" role="tab" aria-selected="true" aria-controls="source-topic">a topic</button><button id="tab-paste" role="tab" aria-selected="false" aria-controls="source-paste">your own text</button><button id="tab-common" role="tab" aria-selected="false" aria-controls="source-common">common words</button></div>
<form id="source-topic" class="source-pane" role="tabpanel" aria-labelledby="tab-topic">
<label for="topic-input">Turn something you’re curious about into a passage.</label>
<div class="field-with-button"><input id="topic-input" name="topic" type="text" placeholder="e.g. why leaves change color" maxlength="64" required autocomplete="off"><button class="button primary" type="submit" aria-label="Create topic passage">↗</button></div>
<div class="topic-chips"><button type="button" data-topic="react-hooks">react hooks</button><button type="button" data-topic="fano-plane">the fano plane</button><button type="button" data-topic="deep-sea">the deep sea</button></div>
<p class="dialog-note">A short, AI-written passage. The topic becomes the URL, so you can send it to a friend.</p>
</form>
<form id="source-paste" class="source-pane" role="tabpanel" aria-labelledby="tab-paste" hidden>
<label for="paste-input">A paragraph, a poem, something you want to remember.</label><textarea id="paste-input" rows="6" maxlength="18000" placeholder="Your words go here…" required></textarea>
<div class="paste-footer"><span id="paste-count">up to 300 words</span><button class="button primary" type="submit">use these words ↗</button></div>
<p class="dialog-note">Pasted text stays on this device until you choose to share a result.</p>
</form>
<div id="source-common" class="source-pane" role="tabpanel" aria-labelledby="tab-common" hidden><p>Familiar words, picked by frequency. Nothing to think about except the next one.</p><button class="button primary full" id="common-start">find your flow ↗</button></div>
</dialog>
<dialog id="share-dialog" class="dialog">
<form method="dialog"><button class="dialog-close" aria-label="Close sharing">×</button></form>
<p class="eyebrow" id="share-kicker">a good rhythm is worth sharing</p><h2 id="share-title">leave a little ghost.</h2>
<div id="share-create"><label for="share-name">Your name <span class="optional">(optional)</span></label><input id="share-name" type="text" maxlength="24" placeholder="anonymous" autocomplete="nickname"><p class="dialog-note">The link makes this passage, score, and replay public. Your mistyped characters are never saved.</p><button class="button primary full" id="save-result">create share link ↗</button></div>
<div id="share-ready" hidden><label for="share-url" id="share-url-label">Your result link</label><div class="field-with-button"><input id="share-url" type="url" readonly><button class="button primary" id="copy-link">copy</button></div><p class="dialog-note" id="share-ready-note">Anyone with this link can watch your replay or race your ghost.</p></div>
<p class="inline-error" id="share-error" role="alert" hidden></p>
</dialog>
<dialog id="board-dialog" class="dialog wide">
<form method="dialog"><button class="dialog-close" aria-label="Close daily board">×</button></form>
<p class="eyebrow" id="board-date">same words. a different rhythm.</p><h2>the daily board.</h2><p class="dialog-note">One passage. Sixty seconds. A fresh start at midnight UTC.</p><div id="board-content" aria-live="polite"></div><button class="text-button" id="board-refresh">refresh ↻</button>
</dialog>
<dialog id="help-dialog" class="dialog">
<form method="dialog"><button class="dialog-close" aria-label="Close help">×</button></form>
<p class="eyebrow">less looking. more doing.</p><h2>one word at a time.</h2>
<div class="help-steps"><p><span>01</span>Type the word in the middle. Your first letter starts the clock.</p><p><span>02</span>Use Backspace to fix a mistake, then Space for the next word. Switch to “last letter” in settings for automatic advances.</p><p><span>03</span>Try tempo: finish each word before the beat. Keep up and it gets faster. Three missed beats end the run.</p></div>
<p class="dialog-note">WPM counts five correct output characters as one word. Accuracy measures correct key attempts. Your best scores and settings stay on this device.</p><button class="button primary full" id="help-done">let’s type ↗</button>
</dialog>
<div id="toast" class="toast" role="status" hidden></div>
</body>
</html>