A PerfectPixel-style design overlay as a React component. It renders a semi-transparent design image (e.g. an exported Figma artboard) on top of your live page so you can verify a pixel-perfect implementation — without a browser extension, checked into the project so the whole team and CI screenshots get the same tool.
Framework-agnostic within React: no styling-library dependency (plain CSS modules), rendered through a portal on document.body, SSR-safe.
- Overlay images — pass a list of
sources(or point the bundled Vite plugin at an image folder) and pick one from a dropdown in the panel; or drop / paste any PNG, JPG or SVG onto the page at runtime - Opacity — slider, or keys 1–9 (10–90 %) and 0 (100 %)
- Blend modes — normal, difference (identical pixels go black, deviations light up), multiply, overlay — plus color invert
- Pixel-level positioning — drag the image, or nudge with arrow keys (Shift = 10 px), plus numeric X/Y/scale inputs
- Click-through lock — locked, the overlay ignores the mouse so you can use and inspect the page beneath; unlocked, you can drag it
- Persistence — all settings and the dropped image survive reloads via
localStorage, namespaced perstorageKey - Collapsible control panel
npm install @artcom/react-pixel-overlay --save-dev(Or as a file:/git dependency while unpublished.)
import { PixelOverlay } from "@artcom/react-pixel-overlay"
import "@artcom/react-pixel-overlay/styles.css"
// QA tooling only — mount in dev builds, or anywhere via `?overlay` in the URL.
const overlayEnabled =
import.meta.env.DEV || new URLSearchParams(window.location.search).has("overlay")
function App() {
return (
<>
<YourApp />
{overlayEnabled && <PixelOverlay src="/design-overlay.png" />}
</>
)
}The image is rendered at its natural size from the top-left corner of the page, so export your design at the exact target resolution (e.g. a 3840×2160 artboard for a 4K screen) and use the scale input only as a fallback.
A browser can't list a server directory, so the package ships a tiny Vite plugin that scans an image folder inside public/ at dev/build time and exposes the file list as a virtual module (in dev, adding/removing images reloads automatically):
// vite.config.js
import { pixelOverlaySources } from "@artcom/react-pixel-overlay/vite"
export default defineConfig({
plugins: [react(), pixelOverlaySources("design-overlays")], // public/design-overlays/
})import overlaySources from "virtual:pixel-overlay-sources"
<PixelOverlay sources={overlaySources} />Every image in the folder shows up in the panel's dropdown, labeled by filename. Not using Vite? Pass any string[] (or { label, src }[]) to sources instead — e.g. from a hand-written manifest. TypeScript users can type the virtual module by referencing @artcom/react-pixel-overlay/virtual.
| Prop | Type | Default | Description |
|---|---|---|---|
sources |
Array<string | { label, src }> |
[] |
Overlay images, selectable from a dropdown. String entries are labeled by filename. |
src |
string |
– | Shorthand for a single image; prepended to sources. |
storageKey |
string |
"pixel-overlay" |
localStorage key for settings; the dropped image is stored under <storageKey>:image. Use distinct keys for apps sharing an origin. |
zIndex |
number |
2147482000 |
z-index of the image; the panel uses zIndex + 1. |
A dropped/pasted image appears in the dropdown as "Dropped image" and is selected automatically. The selection is persisted; if the selected file disappears, the first entry is used.
Active while no form field is focused:
| Key | Action |
|---|---|
| O | Show / hide overlay |
| L | Toggle click-through lock / movable |
| B | Cycle blend mode |
| I | Invert colors |
| ↑ ↓ ← → | Move by 1 px (Shift: 10 px) |
| 1–9, 0 | Opacity 10–90 %, 100 % |
- Dropped images are persisted as data URLs; very large images can exceed the ~5 MB
localStoragequota — the overlay still works, it just won't survive a reload (a warning is logged). - Don't ship it to production users: gate the mount as in the example above.
npm install
npm run dev # demo playground with a sample "design"
npm run build # builds dist/ (ESM + CJS + style.css, exported as "@artcom/react-pixel-overlay/styles.css")