Skip to content

Commit 9fe8d43

Browse files
committed
bump to 1.6.1 and smooth board layout transitions
1 parent 078db52 commit 9fe8d43

File tree

7 files changed

+104
-6
lines changed

7 files changed

+104
-6
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "torus-tauri",
33
"private": true,
4-
"version": "1.3.0",
4+
"version": "1.6.1",
55
"type": "module",
66
"scripts": {
77
"dev": "vite",

src-tauri/Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src-tauri/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "torus-app"
3-
version = "1.3.0"
3+
version = "1.6.1"
44
description = "Torus game desktop app"
55
authors = ["u-keunsong"]
66
edition = "2021"

src-tauri/tauri.conf.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"$schema": "https://schema.tauri.app/config/2",
33
"productName": "Torus",
4-
"version": "1.3.0",
4+
"version": "1.6.1",
55
"identifier": "com.u-keunsong.Torus",
66
"build": {
77
"beforeDevCommand": "npm run dev",

src/main.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1058,6 +1058,7 @@ function toggleKeyCard(): void {
10581058
keyCardVisible = true;
10591059
dom.keyCardEl.classList.remove("hidden");
10601060
dom.sideColumnEl.classList.remove("key-hidden");
1061+
renderer.refreshLayout();
10611062
return;
10621063
}
10631064

@@ -1070,6 +1071,7 @@ function toggleKeyCard(): void {
10701071
keyCardVisible = false;
10711072
dom.keyCardEl.classList.add("hidden");
10721073
dom.sideColumnEl.classList.add("key-hidden");
1074+
renderer.refreshLayout();
10731075
}
10741076

10751077
function setKeyGuidePage(

src/styles.css

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,21 @@ button:active {
441441
gap: 14px;
442442
align-items: start;
443443
min-height: 0;
444+
transition: grid-template-columns var(--motion-4xl) ease, gap var(--motion-4xl) ease;
445+
}
446+
447+
.arena.score-hidden {
448+
grid-template-columns: minmax(0, 1fr) minmax(220px, 256px);
449+
}
450+
451+
.arena.side-hidden {
452+
grid-template-columns: minmax(0, 1fr) 0;
453+
gap: 0;
454+
}
455+
456+
.arena.side-hidden .side-column {
457+
opacity: 0;
458+
pointer-events: none;
444459
}
445460

446461
.board-card,
@@ -455,7 +470,15 @@ button:active {
455470
row-gap: clamp(8px, 1vh, 12px);
456471
min-height: 0;
457472
overflow: hidden;
458-
transition: grid-template-rows var(--motion-2xl) ease, row-gap var(--motion-2xl) ease;
473+
transition:
474+
grid-template-rows var(--motion-4xl) ease,
475+
row-gap var(--motion-4xl) ease,
476+
opacity var(--motion-4xl) ease;
477+
}
478+
479+
.side-column.score-hidden {
480+
grid-template-rows: minmax(0, 0fr) minmax(0, 1fr);
481+
row-gap: 0;
459482
}
460483

461484
.side-column.key-hidden {
@@ -638,7 +661,7 @@ button:active {
638661
}
639662

640663
.score-card {
641-
transition: opacity var(--motion-md) ease, transform var(--motion-md) ease;
664+
transition: opacity var(--motion-4xl) ease, transform var(--motion-4xl) ease;
642665
display: grid;
643666
grid-template-rows: auto minmax(0, 1fr);
644667
min-height: 0;
@@ -1659,6 +1682,12 @@ button:active {
16591682
grid-template-columns: 1fr;
16601683
}
16611684

1685+
.arena.score-hidden,
1686+
.arena.side-hidden {
1687+
grid-template-columns: 1fr;
1688+
gap: 14px;
1689+
}
1690+
16621691
.side-column {
16631692
grid-template-rows: auto auto;
16641693
height: auto;

src/ui/renderer.ts

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ export class TorusRenderer {
2525
private status: GameStatus = "Paused";
2626
private scoreVisible = true;
2727
private expandedScoreIndex: number | null = null;
28+
private lastPoleHeight: number | null = null;
29+
private poleResizeTimer: number | null = null;
2830

2931
constructor(private readonly dom: TorusDom) {}
3032

@@ -53,6 +55,7 @@ export class TorusRenderer {
5355
}
5456

5557
public refreshLayout(): void {
58+
this.syncSideColumnLayout();
5659
this.syncPanelHeights();
5760
}
5861

@@ -63,6 +66,8 @@ export class TorusRenderer {
6366
public setScoreboardVisible(visible: boolean): void {
6467
this.scoreVisible = visible;
6568
this.dom.scoreCardEl.classList.toggle("hidden", !visible);
69+
this.syncSideColumnLayout();
70+
this.syncPanelHeights();
6671
}
6772

6873
public renderScoreboard(
@@ -269,6 +274,10 @@ export class TorusRenderer {
269274
}
270275

271276
private renderPole(snapshot: GameSnapshot): void {
277+
const poleStageEl = this.getPoleStageElement();
278+
const previousHeight = poleStageEl?.getBoundingClientRect().height ?? 0;
279+
const shouldAnimateHeight = this.lastPoleHeight !== null && this.lastPoleHeight !== snapshot.poleHeight;
280+
272281
this.dom.poleGridEl.style.gridTemplateColumns = `repeat(${snapshot.numCols}, var(--ascii-cell-width))`;
273282

274283
const cells: string[] = [];
@@ -288,6 +297,10 @@ export class TorusRenderer {
288297
}
289298

290299
this.dom.poleGridEl.innerHTML = cells.join("");
300+
this.lastPoleHeight = snapshot.poleHeight;
301+
if (shouldAnimateHeight) {
302+
this.animatePoleStageResize(previousHeight);
303+
}
291304
}
292305

293306
private renderPoleCell(entry: PoleEntry, difficulty: Difficulty): string {
@@ -302,6 +315,45 @@ export class TorusRenderer {
302315
return this.renderStaticBoxCell(entry, difficulty);
303316
}
304317

318+
private getPoleStageElement(): HTMLDivElement | null {
319+
const parent = this.dom.poleGridEl.parentElement;
320+
if (!(parent instanceof HTMLDivElement)) {
321+
return null;
322+
}
323+
return parent;
324+
}
325+
326+
private animatePoleStageResize(previousHeight: number): void {
327+
const poleStageEl = this.getPoleStageElement();
328+
if (!poleStageEl || previousHeight <= 0) {
329+
return;
330+
}
331+
if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
332+
return;
333+
}
334+
335+
const nextHeight = poleStageEl.getBoundingClientRect().height;
336+
if (!Number.isFinite(nextHeight) || Math.abs(nextHeight - previousHeight) < 1) {
337+
return;
338+
}
339+
340+
if (this.poleResizeTimer !== null) {
341+
window.clearTimeout(this.poleResizeTimer);
342+
this.poleResizeTimer = null;
343+
}
344+
345+
poleStageEl.style.height = `${previousHeight}px`;
346+
poleStageEl.style.transition = "height 280ms cubic-bezier(0.22, 1, 0.36, 1)";
347+
void poleStageEl.offsetWidth;
348+
poleStageEl.style.height = `${nextHeight}px`;
349+
350+
this.poleResizeTimer = window.setTimeout(() => {
351+
poleStageEl.style.height = "";
352+
poleStageEl.style.transition = "";
353+
this.poleResizeTimer = null;
354+
}, 320);
355+
}
356+
305357
private syncPanelHeights(): void {
306358
const board = this.dom.boardStageCardEl;
307359
const side = this.dom.sideColumnEl;
@@ -324,6 +376,21 @@ export class TorusRenderer {
324376

325377
side.style.height = `${clamped}px`;
326378
}
379+
380+
private syncSideColumnLayout(): void {
381+
const arena = this.dom.boardStageCardEl.parentElement;
382+
if (!(arena instanceof HTMLElement)) {
383+
return;
384+
}
385+
386+
const scoreHidden = !this.scoreVisible;
387+
const keyVisible = !this.dom.keyCardEl.classList.contains("hidden");
388+
const sideHidden = scoreHidden && !keyVisible;
389+
390+
this.dom.sideColumnEl.classList.toggle("score-hidden", scoreHidden);
391+
arena.classList.toggle("score-hidden", scoreHidden && keyVisible);
392+
arena.classList.toggle("side-hidden", sideHidden);
393+
}
327394
}
328395

329396
function renderAsciiCell(

0 commit comments

Comments
 (0)