X-Ray Scan

A glowing scanner bar sweeps across a device and reveals its white-line internals, with one part marked in red

Installation
$ pnpm dlx shadcn@latest add @remocn/x-ray-scan

Usage

XRayScan is a full-frame scene. It starts on the outside of a device. A thin glowing bar sweeps across it, and behind the bar the shell is gone: the device shows as white linework on a dark plate, with one part highlighted in the accent color. A freshly exposed band just behind the bar glows brighter and fades as the bar moves on.

tsx
import { XRayScan } from "@/components/remocn/x-ray-scan";
 
export const Inside = () => <XRayScan />;

Without outside and inside it draws the back of a phone and its internals: the camera array, the logic board with the SoC in the accent color, the battery with a wireless charging coil, and the speaker grille. direction picks a left-to-right or a top-to-bottom sweep.

Your own layers

Pass outside and inside to scan your own product. Both are full-frame layers stacked on each other, so draw them in the same coordinates, for example as two aligned images.

tsx
import { AbsoluteFill, Img, staticFile } from "remotion";
import { XRayScan } from "@/components/remocn/x-ray-scan";
 
export const Watch = () => (
  <XRayScan
    direction="vertical"
    outside={
      <AbsoluteFill style={{ alignItems: "center", justifyContent: "center" }}>
        <Img src={staticFile("watch-front.png")} style={{ height: 560 }} />
      </AbsoluteFill>
    }
    inside={
      <AbsoluteFill style={{ alignItems: "center", justifyContent: "center" }}>
        <Img src={staticFile("watch-xray.png")} style={{ height: 560 }} />
      </AbsoluteFill>
    }
  />
);

The sweep is sized to the default device, a centered box 80% of the frame height tall and about 39% of the height wide. The bar starts 12% of the frame width before that box and stops 12% past it, or 10% of the frame height for a vertical sweep. Content outside that span never changes: before the start it shows the inside layer from the first frame, and past the end it keeps the outside layer. Keep custom products centered and about that size.

Timing

At 30 fps and speed={1}:

FramesMotion
0–5The outside of the device holds
5–32The bar sweeps across on an ease-in-out, revealing the inside
32+The bar is gone and the inside holds

xRayScanLength is 32. speed scales the sweep.

Notes

The inside layer renders twice: once as the revealed view and once under a glow filter for the bright band behind the bar. Heavy custom inside content costs twice.

Props9

PropTypeDefault
outside
React.ReactNode—

Full-frame exterior shown ahead of the bar. Defaults to the back of a phone

inside
React.ReactNode—

Full-frame interior revealed behind the bar. Defaults to white-line phone internals

direction
"horizontal" | "vertical""horizontal"

Horizontal sweeps left to right, vertical sweeps top to bottom

shell
string"#E5322D"

Shell of the default device. Overrides colors.shell when set

accent
string"#E5322D"

Highlighted part inside the default device. Overrides colors.accent when set

line
string"#FFFFFF"

Interior linework and the scan bar. Overrides colors.line when set

background
string"#111111"

Frame background. Overrides colors.background when set

colors
{ background?, shell?, detail?, xray?, line?, accent?: string }{ background: "#111111", shell: "#E5322D", detail: "#111111", xray: "#07080A", line: "#FFFFFF", accent: "#E5322D" }

All colors as one object: frame background, default shell and its camera bump, x-ray plate, linework and scan bar, highlighted part. The flat props above take precedence, missing keys keep their defaults; shell, detail, xray and accent only affect the default device

speed
number1

Playback multiplier

  • outsideReact.ReactNode

    Full-frame exterior shown ahead of the bar. Defaults to the back of a phone

  • insideReact.ReactNode

    Full-frame interior revealed behind the bar. Defaults to white-line phone internals

  • direction"horizontal" | "vertical"

    Horizontal sweeps left to right, vertical sweeps top to bottom

    Default"horizontal"

  • shellstring

    Shell of the default device. Overrides colors.shell when set

    Default"#E5322D"

  • accentstring

    Highlighted part inside the default device. Overrides colors.accent when set

    Default"#E5322D"

  • linestring

    Interior linework and the scan bar. Overrides colors.line when set

    Default"#FFFFFF"

  • backgroundstring

    Frame background. Overrides colors.background when set

    Default"#111111"

  • colors{ background?, shell?, detail?, xray?, line?, accent?: string }

    All colors as one object: frame background, default shell and its camera bump, x-ray plate, linework and scan bar, highlighted part. The flat props above take precedence, missing keys keep their defaults; shell, detail, xray and accent only affect the default device

    Default{ background: "#111111", shell: "#E5322D", detail: "#111111", xray: "#07080A", line: "#FFFFFF", accent: "#E5322D" }

  • speednumber

    Playback multiplier

    Default1