or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/npm-storybook--addon-measure

Visual measurement and box model inspection tool for Storybook development (deprecated in v9.0+)

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/@storybook/addon-measure@9.0.x

To install, run

npx @tessl/cli install tessl/npm-storybook--addon-measure@9.0.0

index.mddocs/

Storybook Addon Measure

Storybook Addon Measure is a visual measurement and box model inspection tool for Storybook that enables developers to inspect layouts and visualize CSS box models by hovering over DOM elements and pressing keyboard shortcuts.

⚠️ DEPRECATION NOTICE: This package is deprecated in Storybook 9.0+. The functionality has been moved to the core Storybook package and is now available by default without requiring separate installation.

Package Information

  • Package Name: @storybook/addon-measure
  • Package Type: npm
  • Language: TypeScript
  • Installation: npm install @storybook/addon-measure (deprecated - throws error in v9.0+)
  • Migration: Remove from dependencies - functionality included in Storybook 9.0+ core

Core Imports

Deprecated package (v9.0+):

// These imports throw migration errors in v9.0+:
// Error: Your Storybook project is referring to package @storybook/addon-measure, 
// which no longer exists in Storybook 9.0 and above.
import { withMeasure } from "@storybook/addon-measure";

Current usage (Storybook 9.0+ core):

// Functionality is now available automatically in Storybook core
// No imports needed - the measure decorator is included automatically when FEATURES.measure is enabled
// Access through Storybook's internal APIs if needed for custom implementation:
import { useGlobals } from 'storybook/manager-api';
import type { MeasureParameters } from 'storybook/internal/types';

Basic Usage

Legacy usage (pre-v9.0):

// In .storybook/main.js - NO LONGER WORKS
export default {
  addons: ['@storybook/addon-measure'], // This will cause errors in v9.0+
};

Current usage (v9.0+):

// No configuration needed - measure is included in core automatically
// Usage:
// 1. Press 'M' key to enable measurement mode (or click the ruler icon in toolbar)
// 2. Hover over any DOM element in your story
// 3. View margin, padding, border, and content dimensions with color-coded overlays

// To disable measure for specific stories:
export default {
  parameters: {
    measure: {
      disable: true, // Disable measure for this component/story
    },
  },
};

Architecture

The measure system (now part of Storybook core) consists of several key components:

  • Feature Flag System: Controlled by globalThis.FEATURES?.measure flag in Storybook core
  • Decorator System: React decorator (withMeasure) automatically included when feature is enabled
  • Canvas Overlay: HTML5 canvas element overlaying the story viewport for drawing measurements
  • Event Handling: Mouse tracking (pointermove, pointerover) and keyboard shortcut integration
  • Measurement Engine: CSS computed style analysis and box model calculation using getComputedStyle
  • Visualization System: Color-coded overlay rendering with intelligent label positioning and collision detection
  • Shadow DOM Support: Deep element traversal including web components via crawlShadows
  • Manager Integration: Toolbar button and keyboard shortcut registration through Storybook's addon system

Capabilities

Measurement Activation

Control when measurement mode is active through global state and keyboard shortcuts.

/**
 * Global state key for controlling measurement mode
 */
const PARAM_KEY = 'measureEnabled';

/**
 * Addon and tool identifiers
 */
const ADDON_ID = 'storybook/measure-addon';
const TOOL_ID = 'storybook/measure-addon/tool';

Decorator Function

React decorator that adds measurement capability to Storybook stories (automatically included in core).

/**
 * React decorator for adding measurement functionality to stories
 * Automatically registered when globalThis.FEATURES?.measure is enabled
 * @param StoryFn - The story component function
 * @param context - Storybook story context with globals and viewMode
 * @returns Story component with measurement capabilities
 */
const withMeasure: DecoratorFunction<StoryContext> = (StoryFn, context) => React.ReactElement;

interface StoryContext {
  globals: {
    measureEnabled?: boolean;
  };
  viewMode: 'story' | 'canvas' | 'docs';
  parameters: {
    measure?: MeasureParameters['measure'];
  };
}

Canvas Management

HTML5 canvas overlay system for rendering measurements.

/**
 * Initialize measurement canvas overlay
 */
function init(): void;

/**
 * Clear all drawn measurements from canvas
 */
function clear(): void;

/**
 * Execute drawing operations with automatic clear
 * @param callback - Drawing function receiving canvas context
 */
function draw(callback: (context?: CanvasRenderingContext2D) => void): void;

/**
 * Rescale canvas for viewport changes
 */
function rescale(): void;

/**
 * Remove canvas overlay and cleanup resources
 */
function destroy(): void;

Element Measurement

Core measurement analysis and DOM element inspection.

/**
 * Get DOM element at coordinates with shadow DOM support
 * Crawls through shadow DOM boundaries to find the deepest element
 * @param x - X coordinate in pixels
 * @param y - Y coordinate in pixels
 * @returns HTML element at the specified coordinates
 */
function deepElementFromPoint(x: number, y: number): HTMLElement;

/**
 * Draw box model measurements for specified element
 * @param element - HTML element to measure and visualize
 */
function drawSelectedElement(element: HTMLElement): void;

/**
 * Measure element dimensions and calculate box model values
 * @param element - HTML element to measure
 * @returns Complete measurement data including box model and positioning
 */
function measureElement(element: HTMLElement): ElementMeasurements;

/**
 * Internal function to crawl shadow DOM boundaries
 * @param node - HTML element that may contain shadow DOM
 * @returns Deepest accessible element in shadow DOM tree
 */
function crawlShadows(node: HTMLElement): HTMLElement;

Manager UI Integration

Storybook manager panel integration for measurement controls.

/**
 * Register measurement tool in Storybook manager
 * Only registers if globalThis.FEATURES?.measure is enabled
 */
function default(): void;

/**
 * React component for measurement toggle button with ruler icon
 * Uses useGlobals hook to manage measureEnabled state
 */
const Tool: React.FC = () => React.ReactElement;

/**
 * Addon registration configuration
 */
interface AddonConfig {
  type: 'TOOL';
  title: 'Measure';
  match: (args: { viewMode: string; tabId?: string }) => boolean;
  render: () => React.ReactElement;
}

/**
 * Keyboard shortcut configuration object passed to setAddonShortcut
 */
interface ShortcutConfig {
  label: 'Toggle Measure [M]';
  defaultShortcut: ['M'];
  actionName: 'measure';
  showInMenu: false;
  action: () => void;
}

/**
 * Hook for accessing and updating global measure state
 * @returns Tuple of [globals, updateGlobals] for measure control
 */
function useGlobals(): [{ measureEnabled?: boolean }, (globals: any) => void];

Configuration Interface

Parameter interface for controlling measurement behavior.

/**
 * Configuration parameters for measurement addon
 */
interface MeasureParameters {
  measure: {
    /** Remove the addon panel and disable the addon's behavior */
    disable?: boolean;
  };
}

Types

Measurement Data Types

/**
 * Margin measurements in pixels
 */
interface Margin {
  top: number;
  bottom: number;
  left: number;
  right: number;
}

/**
 * Padding measurements in pixels
 */
interface Padding {
  top: number;
  bottom: number;
  left: number;
  right: number;
}

/**
 * Border measurements in pixels
 */
interface Border {
  top: number;
  bottom: number;
  left: number;
  right: number;
}

/**
 * Complete box model dimensions
 */
interface Dimensions {
  margin: Margin;
  padding: Padding;
  border: Border;
  width: number;
  height: number;
  top: number;
  left: number;
  bottom: number;
  right: number;
}

/**
 * Element boundary coordinates
 */
interface Extremities {
  top: number;
  bottom: number;
  left: number;
  right: number;
}

/**
 * Label positioning alignment
 */
interface FloatingAlignment {
  x: 'left' | 'right';
  y: 'top' | 'bottom';
}

/**
 * Complete element measurement data
 */
interface ElementMeasurements extends Dimensions {
  extremities: Extremities;
  floatingAlignment: FloatingAlignment;
}

Label System Types

/**
 * Label type categories
 */
type LabelType = 'margin' | 'padding' | 'border' | 'content';

/**
 * Label positioning options
 */
type LabelPosition = 'top' | 'right' | 'bottom' | 'left' | 'center';

/**
 * Direction for measurements
 */
type Direction = 'top' | 'right' | 'bottom' | 'left';

/**
 * Individual measurement label
 */
interface Label {
  type: LabelType;
  text: number | string;
  position: LabelPosition;
}

/**
 * Collection of labels for rendering
 */
type LabelStack = Label[];

/**
 * Canvas drawing utilities
 */
interface RectSize {
  w: number;
  h: number;
}

interface Coordinate {
  x: number;
  y: number;
}

interface Rect extends RectSize, Coordinate {}

interface RoundedRect extends Rect {
  r: number;
}

Event System

/**
 * Addon event identifiers
 */
const EVENTS = {
  RESULT: 'storybook/measure-addon/result';
  REQUEST: 'storybook/measure-addon/request';
  CLEAR: 'storybook/measure-addon/clear';
};

/**
 * Addon identifiers
 */
const ADDON_ID = 'storybook/measure-addon';
const TOOL_ID = 'storybook/measure-addon/tool';

Visual Features

Box Model Visualization

  • Margin: Semi-transparent orange overlay (#f6b26ba8)
  • Border: Semi-transparent yellow overlay (#ffe599a8)
  • Padding: Semi-transparent green overlay (#93c47d8c)
  • Content: Semi-transparent blue overlay (#6fa8dca8)

Smart Labeling

  • Collision Detection: Labels automatically reposition to avoid overlaps using filterZeroValues
  • External Positioning: Small elements (< 30px) show labels outside the element bounds
  • Floating Labels: Content dimensions displayed as floating labels with intelligent alignment
  • Color Coding: Labels use matching colors - margin (#f6b26b), border (#ffe599), padding (#93c47d), content (#6fa8dc)
  • Rounded Label Backgrounds: Labels rendered with rounded rectangles and 6px padding

Responsive Behavior

  • Auto-scaling: Canvas automatically rescales on window resize using devicePixelRatio
  • High DPI Support: Proper scaling for high-density displays with context scaling
  • Pointer Tracking: Real-time mouse position tracking with requestAnimationFrame optimization
  • Shadow DOM: Deep traversal into Shadow DOM boundaries via recursive crawlShadows
  • Performance Optimization: Uses pointerover events rather than continuous mousemove for better performance
  • Canvas Management: Dynamic canvas creation with proper z-index (2147483647) and pointer-events disabled

Utility Functions

Additional internal utility functions used in the measurement system.

/**
 * Convert CSS pixel string to number
 * @param px - CSS pixel value (e.g., "16px")
 * @returns Numeric pixel value
 */
function pxToNumber(px: string): number;

/**
 * Round number to appropriate precision
 * @param value - Number to round
 * @returns Integer if whole number, otherwise 2 decimal places
 */
function round(value: number): number | string;

/**
 * Remove zero-value labels from label stack
 * @param labels - Array of labels to filter
 * @returns Filtered labels without zero values
 */
function filterZeroValues(labels: LabelStack): LabelStack;

/**
 * Calculate optimal floating label alignment
 * @param extremities - Element boundary coordinates
 * @returns Alignment configuration for label positioning
 */
function floatingAlignment(extremities: Extremities): FloatingAlignment;

/**
 * Get document dimensions including scroll areas
 * @returns Width and height of the full document
 */
function getDocumentWidthAndHeight(): { width: number; height: number };

Migration Guide

For projects upgrading to Storybook 9.0+:

  1. Remove the addon: Delete @storybook/addon-measure from package.json dependencies
  2. Update configuration: Remove @storybook/addon-measure from .storybook/main.js addons array
  3. Handle errors: The old package now throws descriptive migration errors when imported
  4. No code changes: Measurement functionality works identically with same keyboard shortcuts
  5. Feature flag: Ensure FEATURES.measure is enabled in your Storybook configuration (enabled by default)
  6. Keyboard shortcut: Continue using 'M' key or ruler toolbar button to toggle measurements

Migration example:

// .storybook/main.js
export default {
  addons: [
-   '@storybook/addon-measure',
    '@storybook/addon-essentials',
    // measure is now included automatically in core
  ],
};
// package.json
{
  "devDependencies": {
-   "@storybook/addon-measure": "^8.x.x",
    "@storybook/react": "^9.0.0"
  }
}

The core functionality remains unchanged - only the installation and configuration requirements have been removed. All API functions are now internal to Storybook core.