Skip to content

Commit 2592e90

Browse files
committed
docs: make terminal animation visibly loop
1 parent c460bb6 commit 2592e90

File tree

2 files changed

+66
-32
lines changed

2 files changed

+66
-32
lines changed

docs/assets/site.css

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,7 @@ h3 {
444444
.typed-terminal {
445445
min-height: 300px;
446446
white-space: pre-wrap;
447+
transition: opacity 220ms ease, transform 220ms ease;
447448
}
448449

449450
.typed-terminal .line {
@@ -471,6 +472,11 @@ h3 {
471472
animation: blink 1s steps(1) infinite;
472473
}
473474

475+
.typed-terminal.is-switching {
476+
opacity: 0.32;
477+
transform: translateY(6px);
478+
}
479+
474480
.telemetry {
475481
padding: 18px;
476482
border-radius: 22px;

docs/assets/site.js

Lines changed: 60 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -49,62 +49,90 @@ function delay(ms) {
4949
return new Promise((resolve) => window.setTimeout(resolve, ms));
5050
}
5151

52-
function renderStaticTerminal() {
52+
function renderSessionMarkup(session) {
53+
return session
54+
.map((frame) => `<span class="line ${frame.className}">${frame.text}</span>`)
55+
.join("");
56+
}
57+
58+
function renderStaticTerminal(sessionIndex = 0) {
5359
if (!typedTerminal) return;
60+
typedTerminal.innerHTML = `${renderSessionMarkup(sessions[sessionIndex])}<span class="cursor" aria-hidden="true"></span>`;
61+
}
5462

55-
const lines = sessions.flatMap((session, index) => {
56-
const sessionLines = session.map((frame) => `<span class="line ${frame.className}">${frame.text}</span>`);
57-
if (index < sessions.length - 1) {
58-
sessionLines.push('<span class="line comment">---</span>');
59-
}
60-
return sessionLines;
61-
});
63+
async function playReducedMotionLoop() {
64+
if (!typedTerminal) return;
65+
66+
let index = 0;
67+
renderStaticTerminal(index);
68+
69+
while (true) {
70+
await delay(2400);
71+
typedTerminal.classList.add("is-switching");
72+
await delay(220);
73+
index = (index + 1) % sessions.length;
74+
renderStaticTerminal(index);
75+
typedTerminal.classList.remove("is-switching");
76+
}
77+
}
6278

63-
typedTerminal.innerHTML = `${lines.join("")}<span class="cursor" aria-hidden="true"></span>`;
79+
async function typeLine(line, text) {
80+
for (const character of text) {
81+
line.textContent += character;
82+
await delay(16);
83+
}
84+
}
85+
86+
async function eraseLine(line) {
87+
while (line.textContent.length > 0) {
88+
line.textContent = line.textContent.slice(0, -1);
89+
await delay(8);
90+
}
6491
}
6592

6693
async function playTerminalLoop() {
6794
if (!typedTerminal) return;
6895
if (prefersReducedMotion) {
69-
renderStaticTerminal();
96+
await playReducedMotionLoop();
7097
return;
7198
}
7299

100+
const lines = [];
101+
73102
while (true) {
74103
typedTerminal.innerHTML = "";
104+
lines.length = 0;
75105

76-
for (let s = 0; s < sessions.length; s += 1) {
77-
const session = sessions[s];
78-
106+
for (const session of sessions) {
79107
for (const frame of session) {
80108
const line = document.createElement("span");
81109
line.className = `line ${frame.className}`;
82110
typedTerminal.appendChild(line);
111+
lines.push(line);
83112

84-
for (const character of frame.text) {
85-
line.textContent += character;
86-
await delay(16);
87-
}
88-
89-
await delay(180);
113+
await typeLine(line, frame.text);
114+
await delay(120);
90115
}
91116

92-
if (s < sessions.length - 1) {
93-
const spacer = document.createElement("span");
94-
spacer.className = "line comment";
95-
spacer.textContent = "---";
96-
typedTerminal.appendChild(spacer);
97-
}
117+
const cursor = document.createElement("span");
118+
cursor.className = "cursor";
119+
cursor.setAttribute("aria-hidden", "true");
120+
typedTerminal.appendChild(cursor);
98121

99-
await delay(520);
100-
}
122+
await delay(900);
123+
cursor.remove();
101124

102-
const cursor = document.createElement("span");
103-
cursor.className = "cursor";
104-
cursor.setAttribute("aria-hidden", "true");
105-
typedTerminal.appendChild(cursor);
125+
for (let i = lines.length - 1; i >= 0; i -= 1) {
126+
await eraseLine(lines[i]);
127+
lines[i].remove();
128+
lines.pop();
129+
await delay(40);
130+
}
106131

107-
await delay(1800);
132+
typedTerminal.classList.add("is-switching");
133+
await delay(140);
134+
typedTerminal.classList.remove("is-switching");
135+
}
108136
}
109137
}
110138

0 commit comments

Comments
 (0)