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
7 changes: 2 additions & 5 deletions playground/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -177,12 +177,9 @@ <h1 class="headline">
<div class="studio-hud"><span id="hero-phase">Drop into the landing</span></div>
</div>

<!-- Contact-phase excerpt, kept below the viewer so it never hides the motion. -->
<!-- Compact contact-phase excerpt, pinned above the motion on wide screens. -->
<pre class="code-chip" aria-hidden="true"># contact-phase excerpt
<span class="t-kw">posecode</span> <span class="t-kind">posture</span> <span class="t-str">"Superhero Three-Point Landing"</span>
<span class="t-kw">pose</span> start <span class="t-punct">=</span> <span class="t-atom">standing</span>

<span class="t-kw">step</span> <span class="t-str">"Make three-point contact"</span> <span class="t-num">0.3s</span> <span class="t-atom">settle</span><span class="t-punct">:</span>
<span class="t-kw">step</span> <span class="t-str">"Make three-point contact"</span> <span class="t-num">0.3s</span> <span class="t-atom">settle</span><span class="t-punct">:</span>
<span class="t-kw">ground-lock</span><span class="t-punct">:</span> <span class="t-atom">foot_right</span>
<span class="t-kw">reach</span><span class="t-punct">:</span> <span class="t-atom">knee_left floor</span>
<span class="t-kw">reach</span><span class="t-punct">:</span> <span class="t-atom">fist_left floor</span>
Expand Down
24 changes: 20 additions & 4 deletions playground/src/landing.css
Original file line number Diff line number Diff line change
Expand Up @@ -775,12 +775,20 @@ a.dev-card:hover {
.studio-bar { background: #0d0f10; }
.studio-bar .dots { display: none; }
.code-chip {
position: static;
position: absolute;
z-index: 2;
top: 44px;
right: -28px;
bottom: auto;
width: max-content;
max-width: 100%;
max-width: calc(100% - 48px);
box-sizing: border-box;
margin: 14px 0 0 auto;
overflow-x: auto;
margin: 0;
overflow: hidden;
pointer-events: none;
padding: 12px 14px;
font-size: 10.5px;
line-height: 1.6;
border-radius: 2px;
background: #0b0d0e;
backdrop-filter: none;
Expand Down Expand Up @@ -847,6 +855,14 @@ a.dev-card:hover {
@media (max-width: 920px) {
.hero { grid-template-columns: 1fr; min-height: auto; }
.headline { max-width: 12ch; }
.code-chip {
position: static;
width: max-content;
max-width: 100%;
margin: 14px 0 0 auto;
overflow-x: auto;
pointer-events: auto;
}
.prop:nth-child(2) { border-left: 1px solid var(--border); }
.example-card:nth-child(3n + 1) { border-left: 0; }
.example-card:nth-child(2n + 1) { border-left: 1px solid var(--border); }
Expand Down
14 changes: 14 additions & 0 deletions playground/src/library-order.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/** Movement promoted to the first visible library group when it matches. */
export const FEATURED_LIBRARY_MOVEMENT_ID = "jumping-jacks";

/** Keep filtering stable while promoting the featured launch movement. */
export function prioritizeFeaturedMovement<T extends { id: string }>(
movements: readonly T[],
): T[] {
const featured: T[] = [];
const remaining: T[] = [];
for (const movement of movements) {
(movement.id === FEATURED_LIBRARY_MOVEMENT_ID ? featured : remaining).push(movement);
}
return [...featured, ...remaining];
}
17 changes: 10 additions & 7 deletions playground/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
} from "./nice-share.js";
import type { PosecodeEditor } from "./editor.js";
import { ANIMATION_PROGRESS_MESSAGE, PRESETS } from "./presets.js";
import { prioritizeFeaturedMovement } from "./library-order.js";
import { SHOWCASE_CLIPS } from "./clips.js";

// Open on a deterministic, fully procedural movement. Mocap-backed or
Expand Down Expand Up @@ -363,13 +364,15 @@ function fold(s: string): string {

function libraryMatches(): typeof PRESETS {
const q = fold(libQuery.trim());
return PRESETS.filter(
(p) =>
(!libDomain || p.domain === libDomain) &&
(!libLevel || p.difficulty === libLevel) &&
(!libStatus || p.status === libStatus) &&
(!q ||
fold(`${p.label} ${p.target} ${p.domain} ${p.bodyPart} ${p.equipment}`).includes(q)),
return prioritizeFeaturedMovement(
PRESETS.filter(
(p) =>
(!libDomain || p.domain === libDomain) &&
(!libLevel || p.difficulty === libLevel) &&
(!libStatus || p.status === libStatus) &&
(!q ||
fold(`${p.label} ${p.target} ${p.domain} ${p.bodyPart} ${p.equipment}`).includes(q)),
),
);
}

Expand Down
32 changes: 32 additions & 0 deletions playground/test/library-order.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { describe, expect, it } from "vitest";
import {
FEATURED_LIBRARY_MOVEMENT_ID,
prioritizeFeaturedMovement,
} from "../src/library-order.js";

describe("movement library ordering", () => {
it("promotes Jumping jacks ahead of otherwise stable results", () => {
const movements = [
{ id: "squat" },
{ id: FEATURED_LIBRARY_MOVEMENT_ID },
{ id: "deadlift" },
];

expect(prioritizeFeaturedMovement(movements).map((movement) => movement.id)).toEqual([
"jumping-jacks",
"squat",
"deadlift",
]);
expect(movements.map((movement) => movement.id)).toEqual([
"squat",
"jumping-jacks",
"deadlift",
]);
});

it("preserves result order when Jumping jacks does not match the filters", () => {
const movements = [{ id: "squat" }, { id: "deadlift" }];

expect(prioritizeFeaturedMovement(movements)).toEqual(movements);
});
});