diff --git a/playground/index.html b/playground/index.html index f4009c4..0ab566d 100644 --- a/playground/index.html +++ b/playground/index.html @@ -177,12 +177,9 @@
# contact-phase excerpt -posecode posture "Superhero Three-Point Landing" - pose start = standing - - step "Make three-point contact" 0.3s settle: +step "Make three-point contact" 0.3s settle: ground-lock: foot_right reach: knee_left floor reach: fist_left floor diff --git a/playground/src/landing.css b/playground/src/landing.css index 7678290..8e85eec 100644 --- a/playground/src/landing.css +++ b/playground/src/landing.css @@ -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; @@ -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); } diff --git a/playground/src/library-order.ts b/playground/src/library-order.ts new file mode 100644 index 0000000..b5dfc75 --- /dev/null +++ b/playground/src/library-order.ts @@ -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( + 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]; +} diff --git a/playground/src/main.ts b/playground/src/main.ts index 2e0a2f4..e4e81ab 100644 --- a/playground/src/main.ts +++ b/playground/src/main.ts @@ -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 @@ -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)), + ), ); } diff --git a/playground/test/library-order.test.ts b/playground/test/library-order.test.ts new file mode 100644 index 0000000..b6d28a9 --- /dev/null +++ b/playground/test/library-order.test.ts @@ -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); + }); +});