From fe730e7baac908c5153666c6ee7c3a4aa8673d7d Mon Sep 17 00:00:00 2001 From: Sakti Kumar Chourasia Date: Sat, 18 Apr 2026 20:02:08 -0700 Subject: [PATCH] feat: inspectorbubble --- README.md | 287 ++++++++ demo/main.tsx | 506 +++++++++++++- llms.txt | 68 +- src/InspectorBubble.tsx | 932 +++++++++++++++++++++++++ src/__tests__/InspectorBubble.test.tsx | 249 +++++++ src/index.ts | 2 + 6 files changed, 2036 insertions(+), 8 deletions(-) create mode 100644 src/InspectorBubble.tsx create mode 100644 src/__tests__/InspectorBubble.test.tsx diff --git a/README.md b/README.md index 5bb88d1..055a9f2 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,7 @@ Building a chat widget, floating toolbar, debug panel, or side dock? You want th | [``](#snapdock) | An edge-pinned dock that slides along any side of the viewport and flips orientation automatically between horizontal and vertical. | | [``](#draggablesheet) | A pull-up / pull-down sheet pinned to an edge with named snap points (`peek`, `half`, `full`) or arbitrary pixel / percentage stops. | | [``](#resizablesplitter) | An N-pane resizable split layout with draggable handles, min/max constraints, and localStorage-persisted ratios. | +| [``](#inspectorbubble) | A Chrome-DevTools-style element picker overlay for design QA — hover to see tag, selector, dimensions, font, colors + WCAG contrast, box model, ARIA role, and accessible name. | ## Installation @@ -585,6 +586,288 @@ interface ResizableSplitPaneProps { --- +## InspectorBubble + +A Chrome-DevTools-style element picker overlay for design QA. Turn it on, hover any DOM element, and the picker draws a highlight plus an info bubble showing tag, short CSS selector, dimensions, typography (including the actual rendered font), effective colors with WCAG contrast, padding/margin, ARIA role, computed accessible name, and a11y state flags. Click to select; Escape or a hotkey to exit. + +### Features + +- **DevTools-style box model** — 4-layer margin / border / padding / content overlay, or a single outline +- **Rich info bubble** — tag, selector, dimensions, font + rendered family, fg/bg colors with WCAG contrast, spacing, ARIA role (explicit or implicit), computed accessible name, and a11y state flags +- **Fully configurable** — each bubble field is its own toggle; disable the bubble entirely for a pure highlight +- **Custom render** — take over the bubble with `bubble.render` and use the full `ElementInfo` however you want +- **Hotkey toggle** — `cmd/meta`, `ctrl`, `shift`, `alt/option` + key +- **Ignore rules** — skip elements matching `behavior.ignoreSelector`; overlays self-skip via `[data-inspector-bubble-ignore]` so the picker never highlights its own chrome +- **Controlled & uncontrolled** — omit `active` for uncontrolled, pass it for parent-driven activation +- **Portal + max z-index** — overlays always render above your app content + +### Examples + +#### Basic + +```tsx +import { useState } from 'react'; +import { InspectorBubble } from 'react-driftkit'; + +function App() { + const [active, setActive] = useState(false); + + return ( + <> + + + console.log('selected', el, info), + }} + /> + + ); +} +``` + +#### Minimal — single outline, no info bubble + +```tsx + +``` + +#### Granular bubble fields + +```tsx + +``` + +#### Custom bubble content + +```tsx + ( + + ), + }} +/> +``` + +#### A11y audit workflow + +```tsx + + console.log(info.selector, { + role: info.a11y.role, + name: info.a11y.accessibleName, + contrast: info.contrastRatio, + }), + }} +/> +``` + +### Props + +| Prop | Type | Default | Description | +|------|------|---------|-------------| +| `active` | `boolean` | — | Controlled active state. Omit for uncontrolled. | +| `defaultActive` | `boolean` | `false` | Uncontrolled initial active state. | +| `on` | `InspectorBubbleEvents` | — | Event handlers — `activeChange`, `select`, `hover`. | +| `behavior` | `InspectorBubbleBehavior` | — | Hotkey, ignore rule, and exit rules. | +| `highlight` | `InspectorBubbleHighlight` | — | Box-model vs. outline, and overlay colors. | +| `bubble` | `InspectorBubbleBubble` | — | Info bubble — `enabled`, `fields`, `render`. | +| `zIndex` | `number` | `2147483647` | z-index for overlay and bubble. | +| `className` | `string` | `''` | CSS class on the default bubble wrapper. | +| `style` | `CSSProperties` | `{}` | Inline styles merged with the default bubble wrapper. | + +#### `on` + +| Key | Signature | Fires when | +|-----|-----------|------------| +| `activeChange` | `(active: boolean) => void` | Active toggles via click-select, Escape, or the hotkey. | +| `select` | `(el: Element, info: ElementInfo) => void` | User clicks an element while the picker is active. | +| `hover` | `(el: Element \| null, info: ElementInfo \| null) => void` | The hovered element changes. `null` when no valid target (e.g. over ignored nodes). | + +#### `behavior` + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| `hotkey` | `string` | — | Toggle shortcut, e.g. `'cmd+shift+c'`. Supports `cmd/meta`, `ctrl`, `shift`, `alt/option` + key. | +| `ignoreSelector` | `string` | — | CSS selector for elements the picker should skip entirely. | +| `exitOnSelect` | `boolean` | `true` | Deactivate after a successful click-select. | +| `exitOnEscape` | `boolean` | `true` | Deactivate when Escape is pressed. | + +#### `highlight` + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| `boxModel` | `boolean` | `true` | Render the 4-layer DevTools box model (margin / border / padding / content). | +| `outline` | `boolean` | `!boxModel` | Render a single outline around the element instead of the box model. | +| `colors` | `InspectorBubbleColors` | DevTools-like | Override overlay colors — `margin`, `border`, `padding`, `content`, `outline`. | + +#### `bubble` + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| `enabled` | `boolean` | `true` | Render the info bubble. Set `false` to show only the highlight. | +| `fields` | `InspectorBubbleFields` | all `true` | Per-field toggles for the default bubble. | +| `render` | `(info: ElementInfo) => ReactNode` | — | Full escape hatch — replaces the default bubble content. Receives the live `ElementInfo`. | + +#### `bubble.fields` + +Every key defaults to `true`. Pass `false` to hide that row. + +| Key | Description | +|-----|-------------| +| `tag` | Lowercase tag name. | +| `selector` | Short CSS selector — `tag#id`, `tag[data-testid="…"]`, or `tag.class1.class2`. | +| `dimensions` | Rendered `width × height`. | +| `font` | Font size, rendered family (first loaded font from the declared list), and weight. | +| `colors` | Foreground + effective background swatches and WCAG contrast ratio. | +| `spacing` | Padding and margin values (T R B L). | +| `role` | ARIA role — explicit or implicit from the tag. | +| `accessibleName` | Computed accessible name (aria-labelledby → aria-label → alt → `