You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

7.7 KiB

Click-to-Component

A zero-config, high-precision component inspector and Click-to-Component developer tool for Next.js and React applications.

Hover over any UI element on your web page while holding Alt (or Option) to highlight component boundaries in real time, and click to instantly jump to the exact file, line, and column in your IDE (Antigravity IDE, VS Code, Cursor, WebStorm, Sublime Text, etc.).


Features

  • 🎯 Direct IDE Jump: Opens your active IDE and focuses the exact file and cursor position (file.tsx:line:col).
  • 🔍 Live Hover Highlighting: Holding Alt outlines the component under your mouse with dynamic bounding box tracking and smooth scroll support.
  • 🔀 Dual Hierarchy Modes:
    • Outer Component Mode (Alt): Selects the outer component or section container.
    • Inner Leaf Mode (Alt + Ctrl / Cmd): Drills down directly to the exact innermost child element (e.g. <svg>, <button>, <span>).
    • Live Dynamic Toggle: Press or release Ctrl while hovering to switch between Outer and Inner mode in real time!
  • 🏷️ Smart Component Badge: Displays the JSX tag name (e.g. <section>, <button>), short relative file path, line number, and active inspection mode pill (OUTER / INNER).
  • 📱 Mobile & Tablet Ready: Floating draggable inspector button with tap-to-inspect on touch devices.
  • 🛡️ Zero Production Overhead: Completely disabled, tree-shaken, and stripped out in production builds.

🏗️ Architecture & How It Works

The system operates across three interconnected layers:

flowchart TD
    subgraph BuildTime["1. Build-Time AST Transform"]
        A[Babel / Compiler] -->|add-data-locator.cjs| B[Injects data-locator attribute on JSX elements]
    end

    subgraph ClientSide["2. Client Runtime"]
        B --> C[DevClickToComponent]
        C -->|Alt + Hover| D[Draws Emerald Bounding Box for Outer Component]
        C -->|Alt + Ctrl + Hover| E[Draws Cyan Bounding Box for Inner Element]
        C -->|Alt + Click| F[Sends locator to API]
    end

    subgraph ServerSide["3. Local Server API"]
        F -->|POST /api/open-in-ide| G[route.ts]
        G -->|CLI Command Execution| H[antigravity-ide / code -r -g filepath:line:col]
        H --> I[IDE Opens & Focuses Line]
    end

📁 Repository Structure

click-to-component/
├── add-data-locator.cjs         # Babel AST plugin to inject data-locator attributes
├── .babelrc.example             # Babel configuration example
├── client/
│   └── dev-click-to-component.tsx  # React Client Component (Inspector UI & Listeners)
├── server/
│   └── route.ts                 # Next.js App Router API Route (/api/open-in-ide)
├── package.json                 # Standalone package metadata
└── README.md                    # Documentation

🚀 Quick Setup & Installation

Step 1: Install Babel Plugin

Copy add-data-locator.cjs to your project root.

Create or update .babelrc in your project root:

{
  "presets": ["next/babel"],
  "env": {
    "development": {
      "plugins": [
        "./add-data-locator.cjs"
      ]
    }
  }
}

Note: Scoping the plugin inside "env": { "development": ... } guarantees that no data-locator attributes will be added to your production builds.


Step 2: Add the Server API Route

Create the file app/api/open-in-ide/route.ts and copy server/route.ts into it:

import { NextResponse } from "next/server";
import { exec } from "child_process";
import os from "os";

export async function POST(req: Request) {
  if (process.env.NODE_ENV !== "development") {
    return NextResponse.json(
      { message: "Not available in production" },
      { status: 404 }
    );
  }

  try {
    const { locator } = await req.json();
    if (!locator) {
      return NextResponse.json({ message: "Locator is required" }, { status: 400 });
    }

    const isWindows = os.platform() === "win32";
    const bin = isWindows ? "antigravity-ide.cmd" : "antigravity-ide";
    const cmd = `${bin} -r -g "${locator}"`;

    return new Promise<Response>((resolve) => {
      exec(cmd, (error) => {
        if (error) {
          const fallbackBin = isWindows ? "code.cmd" : "code";
          const fallbackCmd = `${fallbackBin} -r -g "${locator}"`;

          exec(fallbackCmd, (fallbackError) => {
            if (fallbackError) {
              resolve(
                NextResponse.json(
                  { message: "Failed to open file in IDE", error: error.message },
                  { status: 500 }
                )
              );
            } else {
              resolve(NextResponse.json({ success: true, via: "code" }));
            }
          });
          return;
        }
        resolve(NextResponse.json({ success: true, via: "antigravity" }));
      });
    });
  } catch (err: unknown) {
    const message = err instanceof Error ? err.message : String(err);
    return NextResponse.json(
      { message: "Internal server error", error: message },
      { status: 500 }
    );
  }
}

Step 3: Add the Client Component

Copy client/dev-click-to-component.tsx to app/components/dev-click-to-component.tsx (or components/dev-click-to-component.tsx).

Include it in your root layout (app/layout.tsx):

import { DevClickToComponent } from "./components/dev-click-to-component";

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        {children}
        {process.env.NODE_ENV === "development" && <DevClickToComponent />}
      </body>
    </html>
  );
}

🎮 How to Use

Desktop Shortcuts

Shortcut Mode Highlight Color Target
Alt + Hover OUTER 🟩 Emerald Green (#2dd9a4) Outer Component / Section Container
Alt + Ctrl + Hover (or Alt+Cmd on Mac) INNER 🟦 Electric Cyan (#38bdf8) Innermost leaf element under mouse cursor
Alt + Click Open Flash Pulse Opens the currently highlighted element in your IDE

Mobile / Touch Devices

  • A floating draggable button appears on screens $\le 768\text{px}$.
  • Tap the button to toggle Inspect Mode.
  • Tap any element on screen to highlight it and open its source code in the IDE.

💻 Supported IDEs & Protocol Fallbacks

When the local CLI is invoked, the system opens your existing active IDE window using -r -g <filepath>:<line>:<col>:

  • Antigravity IDE (antigravity-ide -r -g)
  • VS Code / VS Code Insiders (code -r -g)
  • Cursor (cursor -r -g)

If the API route is unreachable (e.g. running inside certain sandboxed iframe environments), the client automatically falls back to browser URL protocol schemes:

  • antigravity://file/<locator>
  • cursor://file/<locator>
  • vscode://file/<locator>
  • webstorm://open?file=<locator>
  • subl://open?url=file://<locator>
  • atom://open?url=file://<locator>

🛡️ Production Safety & Performance

  1. Compiler Level: In NODE_ENV === "production", add-data-locator.cjs returns early without modifying the AST.
  2. Bundle Level: In app/layout.tsx, {process.env.NODE_ENV === "development" && <DevClickToComponent />} evaluates to false during next build, allowing bundlers to completely tree-shake the client component out of the production bundle.
  3. Runtime Level: Event listeners and rendering are guarded with process.env.NODE_ENV !== "development".
  4. Security Level: The /api/open-in-ide route returns a 404 in production environments, preventing arbitrary command execution.

📄 License

MIT