or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

animations.mdchart-runtime.mdcomponents.mdcompositions.mdcoordinates.mddata-transforms.mdencoding-scales.mdextensions.mdindex.mdinteractions.mdmarks.mdthemes.md
tile.json

components.mddocs/

Components and Legends

Chart component system including axes, legends, titles, and interactive components for enhancing visualizations.

Capabilities

Axis Components

Components for displaying scales and reference information along chart axes.

/**
 * Adds X-axis component to chart
 * @param options - X-axis configuration options
 */
component(type: "axisX", options?: AxisXOptions): Chart;

/**
 * Adds Y-axis component to chart
 * @param options - Y-axis configuration options
 */
component(type: "axisY", options?: AxisYOptions): Chart;

interface AxisXOptions {
  /** Show or hide axis title */
  title?: string | boolean;
  /** Axis title configuration */
  titleStyle?: StyleOptions;
  /** Show or hide grid lines */
  grid?: boolean;
  /** Grid line style */
  gridStyle?: StyleOptions;
  /** Show or hide tick marks */
  tick?: boolean;
  /** Tick mark configuration */
  tickStyle?: StyleOptions;
  /** Show or hide axis labels */
  label?: boolean;
  /** Label configuration */
  labelStyle?: StyleOptions;
  /** Label formatter function */
  labelFormatter?: (value: any) => string;
  /** Number of ticks */
  tickCount?: number;
  /** Specific tick values */
  tickValues?: any[];
  /** Axis line style */
  lineStyle?: StyleOptions;
}

interface AxisYOptions extends AxisXOptions {
  /** Position of Y axis: 'left' | 'right' */
  position?: "left" | "right";
}

Usage Examples:

// Basic axes
chart
  .interval()
  .data(salesData)
  .encode("x", "month")
  .encode("y", "revenue")
  .component("axisX", { title: "Month" })
  .component("axisY", { title: "Revenue ($)" });

// Customized axis with grid
chart
  .line()
  .data(timeSeriesData)
  .encode("x", "date")
  .encode("y", "price")
  .component("axisX", {
    title: "Date",
    grid: true,
    gridStyle: { stroke: "#f0f0f0", strokeWidth: 1 }
  })
  .component("axisY", {
    title: "Price",
    labelFormatter: (d) => `$${d.toFixed(2)}`,
    position: "right"
  });

Legend Components

Components for displaying color, size, and other visual encoding legends.

/**
 * Adds categorical legend for discrete color/shape mappings
 * @param options - Categorical legend options
 */
component(type: "legendCategory", options?: LegendCategoryOptions): Chart;

/**
 * Adds continuous legend for continuous color/size mappings
 * @param options - Continuous legend options
 */
component(type: "legendContinuous", options?: LegendContinuousOptions): Chart;

/**
 * Adds multiple legends with automatic layout
 */
component(type: "legends", options?: LegendsOptions): Chart;

interface LegendCategoryOptions {
  /** Legend title */
  title?: string;
  /** Legend position */
  position?: "top" | "bottom" | "left" | "right" | "top-left" | "top-right" | "bottom-left" | "bottom-right";
  /** Item layout direction */
  layout?: "horizontal" | "vertical";
  /** Number of columns (for horizontal layout) */
  cols?: number;
  /** Item spacing */
  itemSpacing?: number;
  /** Item width */
  itemWidth?: number;
  /** Item height */
  itemHeight?: number;
  /** Legend item style */
  itemStyle?: StyleOptions;
  /** Title style */
  titleStyle?: StyleOptions;
  /** Label formatter */
  labelFormatter?: (value: any) => string;
}

interface LegendContinuousOptions {
  /** Legend title */
  title?: string;
  /** Legend position */
  position?: "top" | "bottom" | "left" | "right";
  /** Legend width */
  width?: number;
  /** Legend height */
  height?: number;
  /** Number of tick marks */
  tickCount?: number;
  /** Label formatter */
  labelFormatter?: (value: any) => string;
  /** Title style */
  titleStyle?: StyleOptions;
}

Usage Examples:

// Categorical color legend
chart
  .point()
  .data(scatterData)
  .encode("x", "height")
  .encode("y", "weight")
  .encode("color", "gender")
  .component("legendCategory", {
    title: "Gender",
    position: "right",
    layout: "vertical"
  });

// Continuous color legend for heatmap
chart
  .rect()
  .data(heatmapData)
  .encode("x", "x")
  .encode("y", "y")
  .encode("color", "value")
  .component("legendContinuous", {
    title: "Temperature (°C)",
    position: "bottom",
    width: 300,
    labelFormatter: (d) => `${d}°C`
  });

// Multiple legends
chart
  .point()
  .data(bubbleData)
  .encode("x", "gdp")
  .encode("y", "lifeExpectancy")
  .encode("color", "continent")
  .encode("size", "population")
  .component("legends", {
    color: {
      title: "Continent",
      position: "right"
    },
    size: {
      title: "Population",
      position: "bottom"
    }
  });

Interactive Components

Components that provide user interaction capabilities.

/**
 * Adds horizontal data slider for filtering
 * @param options - Horizontal slider options
 */
component(type: "sliderX", options?: SliderXOptions): Chart;

/**
 * Adds vertical data slider for filtering
 * @param options - Vertical slider options
 */
component(type: "sliderY", options?: SliderYOptions): Chart;

/**
 * Adds horizontal scrollbar for panning
 * @param options - Horizontal scrollbar options
 */
component(type: "scrollbarX", options?: ScrollbarXOptions): Chart;

/**
 * Adds vertical scrollbar for panning
 * @param options - Vertical scrollbar options
 */
component(type: "scrollbarY", options?: ScrollbarYOptions): Chart;

interface SliderXOptions {
  /** Slider position */
  position?: "top" | "bottom";
  /** Initial range [start, end] as ratios (0-1) */
  range?: [number, number];
  /** Slider height */
  height?: number;
  /** Handle style */
  handleStyle?: StyleOptions;
  /** Track style */
  trackStyle?: StyleOptions;
  /** Callback for range changes */
  onChange?: (range: [number, number]) => void;
}

interface SliderYOptions {
  /** Slider position */
  position?: "left" | "right";
  /** Initial range [start, end] as ratios (0-1) */
  range?: [number, number];
  /** Slider width */
  width?: number;
  /** Handle style */
  handleStyle?: StyleOptions;
  /** Track style */
  trackStyle?: StyleOptions;
  /** Callback for range changes */
  onChange?: (range: [number, number]) => void;
}

Usage Examples:

// Time series with date range slider
chart
  .line()
  .data(timeSeriesData)
  .encode("x", "date")
  .encode("y", "value")
  .component("sliderX", {
    position: "bottom",
    range: [0.8, 1.0], // Show last 20% initially
    onChange: (range) => {
      console.log("Date range changed:", range);
    }
  });

// Large dataset with vertical range slider
chart
  .point()
  .data(largeDataset)
  .encode("x", "value1")
  .encode("y", "value2")
  .component("sliderY", {
    position: "right",
    range: [0, 0.5], // Show bottom half initially
    width: 20
  });

Title Components

Components for chart titles and annotations.

/**
 * Chart title component configuration
 */
interface TitleComponent {
  /** Title text */
  text: string;
  /** Title position */
  position?: "top" | "bottom" | "left" | "right";
  /** Title alignment */
  align?: "start" | "center" | "end";
  /** Title style */
  style?: TitleStyle;
  /** Subtitle text */
  subtitle?: string;
  /** Subtitle style */
  subtitleStyle?: StyleOptions;
}

interface TitleStyle {
  /** Font size */
  fontSize?: number;
  /** Font weight */
  fontWeight?: string | number;
  /** Font family */
  fontFamily?: string;
  /** Text color */
  fill?: string;
  /** Text alignment */
  textAlign?: "left" | "center" | "right";
  /** Margin around title */
  margin?: number | [number, number, number, number];
}

Usage Examples:

// Add title via chart specification
const chartSpec = {
  type: "view",
  children: [
    {
      type: "interval",
      data: salesData,
      encode: { x: "month", y: "revenue" }
    }
  ],
  title: {
    text: "Monthly Revenue Trends",
    subtitle: "2023 Sales Performance",
    position: "top",
    align: "center",
    style: {
      fontSize: 20,
      fontWeight: "bold",
      fill: "#333"
    }
  }
};

Component Styling

Comprehensive styling options for all component types.

interface StyleOptions {
  /** Fill color */
  fill?: string;
  /** Stroke color */
  stroke?: string;
  /** Stroke width */
  strokeWidth?: number;
  /** Opacity (0-1) */
  opacity?: number;
  /** Font family */
  fontFamily?: string;
  /** Font size */
  fontSize?: number;
  /** Font weight */
  fontWeight?: string | number;
  /** Text alignment */
  textAlign?: "left" | "center" | "right";
  /** Line dash pattern */
  lineDash?: number[];
  /** Border radius */
  radius?: number;
  /** Padding */
  padding?: number | [number, number, number, number];
  /** Margin */
  margin?: number | [number, number, number, number];
}

Component Layout

Components automatically position themselves but can be customized.

// Component positioning
interface ComponentLayout {
  /** Automatic layout (default) */
  layout?: "auto";
  /** Manual positioning */
  position?: {
    x?: number;
    y?: number;
    width?: number;
    height?: number;
  };
  /** Z-index for layering */
  zIndex?: number;
}

Layout Examples:

// Custom positioned legend
chart
  .point()
  .data(data)
  .encode("x", "x")
  .encode("y", "y")
  .encode("color", "category")
  .component("legendCategory", {
    position: { x: 50, y: 50, width: 150, height: 100 },
    title: "Categories"
  });

// Multiple components with z-index
chart
  .line()
  .data(data)
  .encode("x", "date")
  .encode("y", "value")
  .component("axisX", { zIndex: 1 })
  .component("axisY", { zIndex: 1 })
  .component("legendCategory", { zIndex: 2 });

Component Events

Components can respond to user interactions.

interface ComponentEvents {
  /** Click event */
  onClick?: (event: ComponentEvent) => void;
  /** Hover event */
  onHover?: (event: ComponentEvent) => void;
  /** Value change (for interactive components) */
  onChange?: (value: any) => void;
}

interface ComponentEvent {
  type: string;
  target: any;
  data?: any;
  x?: number;
  y?: number;
}

Event Examples:

// Interactive legend with click events
chart
  .point()
  .data(data)
  .encode("x", "x")
  .encode("y", "y")
  .encode("color", "category")
  .component("legendCategory", {
    title: "Categories",
    onClick: (event) => {
      console.log("Legend item clicked:", event.data);
      // Toggle category visibility
    }
  });

// Slider with change events
chart
  .line()
  .data(timeSeriesData)
  .encode("x", "date")
  .encode("y", "value")
  .component("sliderX", {
    onChange: (range) => {
      // Filter data based on range
      const filtered = filterDataByRange(timeSeriesData, range);
      chart.update({ data: filtered });
    }
  });