Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion benchmarking.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -488,7 +488,17 @@ async function main(navigator) {
}),
...(("fx" in plot || "fy" in plot) && { grid: true }),
color: { type: "ordinal", legend: true },
width: 1280,
/* Fit the plot to its container so a phone gets a readable chart
instead of a page that scrolls sideways. Falls back to the fixed
1280 wherever there is no laid-out container to measure (no DOM,
or a container reporting 0 width). */
width: (() => {
const avail =
typeof document === "undefined"
? 0
: document.querySelector("#plot")?.clientWidth ?? 0;
return avail > 0 ? Math.min(1280, avail) : 1280;
})(),
title: plot?.title,
subtitle: plot?.subtitle,
caption: plot?.caption,
Expand Down
117 changes: 98 additions & 19 deletions demos/interactive_demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@
height: 100%;
cursor: crosshair;
display: block;
/* Claim drag gestures for the simulation instead of letting the
browser scroll/zoom the page with them. */
touch-action: none;
}

#controls {
Expand All @@ -38,10 +41,20 @@
border-radius: 12px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.6);
z-index: 10;
min-width: 180px;
}

.panel-body {
display: flex;
flex-direction: column;
gap: 10px;
min-width: 180px;
}

/* Disclosure control: hidden entirely on large screens, where the
panel is always open. */
.panel-trigger,
.panel-toggle {
display: none;
}

.control-group {
Expand Down Expand Up @@ -188,17 +201,68 @@
box-shadow: 0 4px 16px rgba(0,0,0,0.5);
}

.mode-btn {
border: 1px solid rgba(255, 255, 255, 0.25);
border-radius: 6px;
animation: none;
font-size: 13px;
padding: 10px;
min-height: 44px;
}

.mode-btn[aria-pressed="true"] {
border-color: #764ba2;
background: rgba(118, 75, 162, 0.25);
}

/* Small screens: collapse the panel to a single button instead of
shrinking the controls. The open panel previously ate roughly a
quarter of a phone screen; folding it away costs nothing, whereas
shrinking tap targets below ~44px trades a mis-tap for a few
reclaimed pixels - and each of these buttons launches a slow GPU
operation. */
@media (height < 600px) or (width < 600px) {
#controls {
gap: 5px;
top: 10px;
right: 10px;
padding: 8px;
min-width: 0;
}

.button-group {
gap: 0px;
.panel-toggle {
display: flex;
align-items: center;
justify-content: center;
width: 44px;
height: 44px;
color: #fff;
cursor: pointer;
border-radius: 8px;
}

.panel-body {
display: none;
}

.panel-trigger:checked ~ .panel-body {
display: flex;
padding-top: 8px;
min-width: 200px;
max-height: calc(100dvh - 80px);
overflow-y: auto;
}

.button-group {
flex-direction: row;
gap: 8px;
margin-top: 4px;
}

button {
padding: 5px;
}
}
.button-group button {
flex: 1;
padding: 12px 4px;
/* Explicit floor rather than relying on font metrics. */
min-height: 44px;
}
}
</style>
Expand All @@ -208,19 +272,34 @@
<div id="errorDisplay"></div>

<div id="controls">
<div class="control-group">
<label>Particles</label>
<input type="range" id="starSlider" min="1000" max="100000" step="1000" value="10000">
<div id="starCount">10K</div>
</div>
<!-- CSS-only disclosure: the panel collapses to a single button on
small screens. Deliberately not JS - interactive_demo.mjs aborts
early when WebGPU is missing, and the panel should still fold
away on the error screen. -->
<input type="checkbox" id="panel-trigger" class="panel-trigger">
<label for="panel-trigger" class="panel-toggle" aria-label="Toggle controls" title="Toggle controls">
<svg viewBox="0 0 18 15" width="18" height="15" aria-hidden="true">
<path fill="currentColor" d="M18,1.484c0,0.82-0.665,1.484-1.484,1.484H1.484C0.665,2.969,0,2.304,0,1.484l0,0C0,0.665,0.665,0,1.484,0h15.032C17.335,0,18,0.665,18,1.484L18,1.484z M18,7.516C18,8.335,17.335,9,16.516,9H1.484C0.665,9,0,8.335,0,7.516l0,0c0-0.82,0.665-1.484,1.484-1.484h15.032C17.335,6.031,18,6.696,18,7.516L18,7.516z M18,13.484C18,14.304,17.335,14.969,16.516,14.969H1.484C0.665,14.969,0,14.304,0,13.484l0,0C0,12.665,0.665,12,1.484,12h15.032C17.335,12,18,12.665,18,13.484L18,13.484z" />
</svg>
</label>

<div class="button-group">
<button id="sortBtn">Sort</button>
<button id="scanBtn">Scan</button>
<button id="reduceBtn">Reduce</button>
</div>
<div class="panel-body">
<div class="control-group">
<label>Particles</label>
<input type="range" id="starSlider" min="1000" max="100000" step="1000" value="10000">
<div id="starCount">10K</div>
</div>

<div class="info-text">Click: attract • Shift: repel</div>
<div class="button-group">
<button id="sortBtn">Sort</button>
<button id="scanBtn">Scan</button>
<button id="reduceBtn">Reduce</button>
</div>

<button id="modeBtn" class="mode-btn" aria-pressed="false">Mode: Attract</button>

<div class="info-text">Drag to move particles • Mode or Shift flips pull/push</div>
</div>
</div>

<script type="module" src="interactive_demo.mjs"></script>
Expand Down
Loading
Loading