Make grain-gradient WebGL-only v2 - #16
Conversation
Optimize WebGL frame transforms
|
@codex review |
There was a problem hiding this comment.
Pull request overview
This PR upgrades grain-gradient to v2 by making the library WebGL-only, removing the prior CSS/SVG + Android/canvas fallback surface area, and replacing the old playground with a Vite/React WebGL playground. It also updates docs and tests to reflect the new v2 contract and hardens the WebGL renderer’s lifecycle and shader behavior.
Changes:
- Remove legacy CSS/SVG generation and canvas/Android fallback APIs; make the main entry export the WebGL renderer API.
- Update the WebGL shader + CPU-side motion/grain handling (seed normalization, square grain normalization, CPU trig uniforms).
- Replace the playground with a React/Vite implementation and update docs/tests/workflows accordingly.
Reviewed changes
Copilot reviewed 17 out of 19 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| vite.config.ts | Adds Vite config targeting the new playground/ root and outputs to dist-playground/. |
| tests/library.test.mjs | Rewrites tests to assert v2 exports (WebGL-only) and validates shader/perf invariants. |
| src/webgl.ts | Implements the WebGL shader renderer changes (grain shader, CPU motion uniforms, option normalization). |
| src/webgl-react.tsx | Simplifies the legacy webgl/react entry to re-export the main React component API. |
| src/react.tsx | Replaces CSS/SVG layering with a WebGL-canvas React component and improved context lifecycle handling. |
| src/internal.ts | Simplifies swirl normalization and motion normalization helpers used by WebGL. |
| src/index.ts | Re-exports WebGL API from the main entrypoint. |
| src/core.ts | Removes legacy CSS/SVG/canvas fallback types/APIs and introduces v2 option types (mesh/motion/grain). |
| README.md | Updates positioning, examples, and playground link for v2 WebGL-only contract. |
| playground/tsconfig.json | Adds TypeScript config for the new Vite/React playground. |
| playground/src/styles.css | Adds standalone CSS styling for the new playground UI. |
| playground/src/main.tsx | New React entrypoint bootstrapping the playground app. |
| playground/src/App.tsx | Implements the new playground UI and WebGL renderer lifecycle handling. |
| playground/index.html | Replaces the old large static HTML playground with a minimal Vite/React root. |
| package.json | Bumps to v2.0.0, adds Vite/React playground build scripts and dependencies. |
| package-lock.json | Updates lockfile for new dependencies (Vite React plugin, react-dom, types). |
| docs/API.md | Rewrites API reference for the WebGL-only v2 surface area and compatibility subpaths. |
| .gitignore | Ignores dist-playground/ output and an additional .slim/deepwork/ path. |
| .github/workflows/pages.yml | Updates Pages build to build and publish the Vite playground output from dist-playground/. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| @@ -5,24 +5,9 @@ export type MotionPreset = "none" | "drift" | "breathe" | "orbit"; | |||
|
|
|||
| export const normalizeSwirl = (swirl = 0) => { | |||
| const value = clamp(swirl, 0, 100); | |||
| const shift = value / 100; | |||
| return { | |||
| value, | |||
| enabled: value > 0, | |||
| scale: (1 + value * 0.004).toFixed(3), | |||
| rotate: (value * 0.12).toFixed(2), | |||
| offsetX: shift * 12, | |||
| offsetY: shift * -10, | |||
| backgroundSizeX: (100 + value * 0.55).toFixed(1), | |||
| backgroundSizeY: (100 + value * 0.4).toFixed(1), | |||
| backgroundPositionX: (50 + shift * 12).toFixed(1), | |||
| backgroundPositionY: (50 - shift * 10).toFixed(1), | |||
| }; | |||
| return { value, enabled: value > 0 }; | |||
| - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 | ||
| with: | ||
| node-version: 20 | ||
| cache: npm |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: dc945d4482
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| swirlScale = 1.0 + swirl.value * 0.004; | ||
| rotateRad = (Number(motion.rotate) * Math.PI) / 180; | ||
| zoom = motion.enabled ? Number(motion.zoom) : 1; | ||
| travel = Number(motion.travel) / 100; |
There was a problem hiding this comment.
Zero travel for static renders
When motionPreset is "none" or motion is disabled by zero speed/intensity, normalizeMotion still returns a nonzero default travel (12% at default intensity), and render() applies it as frameTravelY = travel * orbit even for the one static draw. This makes the default/static gradient render shifted vertically and can make it jump on later resize()/update() calls; travel should be set to 0 when motion.enabled is false, similar to motionAmount.
Useful? React with 👍 / 👎.
Summary
Test Plan