or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

core-management.mdelement-collections.mdevent-system.mdextensions.mdgraph-algorithms.mdindex.mdlayout-system.mdstyling-system.md
tile.json

styling-system.mddocs/

Styling System

CSS-like styling system with selectors, properties, and themes. Supports dynamic styling, animations, and complex visual customization for nodes, edges, and the core canvas.

Capabilities

Stylesheet Definition

Define styles using CSS-like syntax with selectors and property blocks.

interface StylesheetJson extends Array<StyleRule> {}

interface StyleRule {
  /**
   * CSS-like selector for targeting elements
   */
  selector: string;
  
  /**
   * Style properties to apply
   */
  style: StyleProperties;
}

/**
 * Create stylesheet from array of style rules
 */
const stylesheet: StylesheetJson = [
  {
    selector: 'node',
    style: {
      'background-color': '#666',
      'label': 'data(id)'
    }
  },
  {
    selector: 'edge',
    style: {
      'width': 3,
      'line-color': '#ccc'
    }
  }
];

Core Styling Methods

Apply and manage styles on the core instance and collections.

interface Core {
  /**
   * Get or set stylesheet
   * @param stylesheet - Stylesheet to apply (optional)
   * @returns Current stylesheet or Core instance
   */
  style(stylesheet?: StylesheetJson): StylesheetJson | Core;
  
  /**
   * Get stylesheet object
   * @returns Stylesheet instance
   */
  stylesheet(): Stylesheet;
  
  /**
   * Update style calculations (call after dynamic changes)
   * @returns Core instance
   */
  updateStyle(): Core;
}

interface Collection {
  /**
   * Get or set style property
   * @param property - CSS property name
   * @param value - Property value (optional)
   * @returns Property value or Collection
   */
  style(property: string, value?: any): any | Collection;
  
  /**
   * Get or set multiple style properties
   * @param properties - Object with property-value pairs
   * @returns Collection for chaining
   */
  style(properties: StyleProperties): Collection;
  
  /**
   * Remove style properties (revert to stylesheet)
   * @param properties - Properties to remove (optional, removes all if not specified)
   * @returns Collection for chaining
   */
  removeStyle(properties?: string | string[]): Collection;
}

Selectors

Target specific elements using CSS-like selectors.

/**
 * Basic selectors
 */
"node"                    // All nodes
"edge"                    // All edges
"*"                       // All elements

/**
 * ID selectors
 */
"#mynode"                 // Element with id 'mynode'

/**
 * Class selectors
 */
".highlighted"            // Elements with class 'highlighted'
".important.active"       // Elements with both classes

/**
 * Data selectors
 */
"[weight]"               // Elements with 'weight' data property
"[weight > 10]"          // Elements where weight > 10
"[type = 'user']"        // Elements where type equals 'user'
"[name *= 'john']"       // Elements where name contains 'john'

/**
 * Compound selectors
 */
"node.active"            // Active nodes
"edge[weight > 5]"       // Heavy edges
"node#start.important"   // Important start node

/**
 * State selectors
 */
":selected"              // Selected elements
":unselected"            // Unselected elements
":locked"                // Locked elements
":unlocked"              // Unlocked elements
":grabbed"               // Currently grabbed elements
":free"                  // Not grabbed elements
":removed"               // Removed elements
":inside"                // Elements inside compound nodes
":grabbable"             // Grabbable elements
":ungrabbable"           // Ungrabbable elements

/**
 * Compound graph selectors
 */
":parent"                // Parent (compound) nodes
":childless"             // Nodes without children
":child"                 // Child nodes
":orphan"                // Nodes without parents

/**
 * Edge-specific selectors
 */
":simple"                // Simple edges (no loops, no multiple edges)
":loop"                  // Self-loops

/**
 * Combination selectors
 */
"node, edge"             // Nodes OR edges (union)
"node.active edge"       // Edges connected to active nodes

Usage Examples:

// Style all nodes
const stylesheet = [
  {
    selector: 'node',
    style: {
      'background-color': '#0074D9',
      'width': 20,
      'height': 20,
      'label': 'data(name)'
    }
  },
  
  // Style selected nodes differently
  {
    selector: 'node:selected',
    style: {
      'background-color': '#FF4136',
      'border-width': 3,
      'border-color': '#FFDC00'
    }
  },
  
  // Style edges by weight
  {
    selector: 'edge[weight > 5]',
    style: {
      'width': 4,
      'line-color': '#FF851B'
    }
  }
];

Node Style Properties

Comprehensive styling options for nodes.

interface NodeStyleProperties {
  // Dimensions
  'width'?: number | string;
  'height'?: number | string;
  'shape'?: 'ellipse' | 'triangle' | 'round-triangle' | 'rectangle' | 'round-rectangle' | 
           'bottom-round-rectangle' | 'cut-rectangle' | 'barrel' | 'rhomboid' | 'diamond' | 
           'round-diamond' | 'pentagon' | 'round-pentagon' | 'hexagon' | 'round-hexagon' | 
           'concave-hexagon' | 'heptagon' | 'round-heptagon' | 'octagon' | 'round-octagon' | 
           'star' | 'tag' | 'round-tag' | 'vee';
  
  // Background
  'background-color'?: string;
  'background-opacity'?: number;
  'background-blacken'?: number;
  'background-image'?: string | string[];
  'background-image-opacity'?: number | number[];
  'background-fit'?: 'none' | 'contain' | 'cover';
  'background-repeat'?: 'no-repeat' | 'repeat-x' | 'repeat-y' | 'repeat';
  'background-position-x'?: string | number;
  'background-position-y'?: string | number;
  'background-width'?: string | number;
  'background-height'?: string | number;
  'background-clip'?: 'none' | 'node';
  
  // Border
  'border-width'?: number;
  'border-style'?: 'solid' | 'dotted' | 'dashed' | 'double';
  'border-color'?: string;
  'border-opacity'?: number;
  
  // Outline (selection indicator)
  'outline-width'?: number;
  'outline-color'?: string;
  'outline-opacity'?: number;
  'outline-offset'?: number;
  
  // Padding (for compound nodes)
  'padding'?: string | number;
  'padding-left'?: string | number;
  'padding-right'?: string | number;
  'padding-top'?: string | number;
  'padding-bottom'?: string | number;
  
  // Compound node specific
  'compound-sizing-wrt-labels'?: 'include' | 'exclude';
  
  // Position
  'position'?: 'origin';
  
  // Visibility
  'opacity'?: number;
  'display'?: 'element' | 'none';
  'visibility'?: 'visible' | 'hidden';
  'z-index'?: number;
  'z-compound-depth'?: 'bottom' | 'orphan' | 'auto' | number;
  
  // Interactivity
  'min-zoomed-font-size'?: number;
  'overlay-color'?: string;
  'overlay-padding'?: number;
  'overlay-opacity'?: number;
  'underlay-color'?: string;
  'underlay-padding'?: number;
  'underlay-opacity'?: number;
  'underlay-shape'?: 'ellipse' | 'round-rectangle';
  
  // Ghost (dragging preview)
  'ghost'?: 'yes' | 'no';
  'ghost-offset-y'?: number;
  'ghost-offset-x'?: number;
  'ghost-opacity'?: number;
}

Edge Style Properties

Styling options for edges including arrows, curves, and labels.

interface EdgeStyleProperties {
  // Line
  'width'?: number;
  'line-color'?: string;
  'line-style'?: 'solid' | 'dotted' | 'dashed';
  'line-cap'?: 'butt' | 'round' | 'square';
  'line-opacity'?: number;
  'line-dash-pattern'?: number[];
  'line-dash-offset'?: number;
  
  // Curve
  'curve-style'?: 'straight' | 'haystack' | 'bezier' | 'unbundled-bezier' | 
                  'segments' | 'taxi' | 'round-taxi';
  'control-point-step-size'?: number;
  'control-point-distances'?: number | number[];
  'control-point-weights'?: number | number[];
  'segment-distances'?: number | number[];
  'segment-weights'?: number | number[];
  'taxi-turn'?: string;
  'taxi-turn-min-distance'?: number;
  'taxi-direction'?: 'auto' | 'up' | 'down' | 'left' | 'right' | 'downward' | 'upward' | 
                     'leftward' | 'rightward' | 'vertical' | 'horizontal';
  
  // Source arrow
  'source-arrow-color'?: string;
  'source-arrow-shape'?: 'triangle' | 'triangle-tee' | 'circle-triangle' | 'triangle-cross' | 
                         'triangle-backcurve' | 'vee' | 'tee' | 'square' | 'circle' | 
                         'diamond' | 'chevron' | 'none';
  'source-arrow-width'?: number;
  'source-arrow-height'?: number;
  
  // Target arrow
  'target-arrow-color'?: string;
  'target-arrow-shape'?: 'triangle' | 'triangle-tee' | 'circle-triangle' | 'triangle-cross' | 
                         'triangle-backcurve' | 'vee' | 'tee' | 'square' | 'circle' | 
                         'diamond' | 'chevron' | 'none';
  'target-arrow-width'?: number;
  'target-arrow-height'?: number;
  
  // Mid arrow
  'mid-source-arrow-color'?: string;
  'mid-source-arrow-shape'?: string;
  'mid-source-arrow-width'?: number;
  'mid-source-arrow-height'?: number;
  'mid-target-arrow-color'?: string;
  'mid-target-arrow-shape'?: string;
  'mid-target-arrow-width'?: number;
  'mid-target-arrow-height'?: number;
  
  // Visibility and interaction
  'opacity'?: number;
  'display'?: 'element' | 'none';
  'visibility'?: 'visible' | 'hidden';
  'z-index'?: number;
  'overlay-color'?: string;
  'overlay-padding'?: number;
  'overlay-opacity'?: number;
  'underlay-color'?: string;
  'underlay-padding'?: number;
  'underlay-opacity'?: number;
  
  // Selection
  'selection-box-color'?: string;
  'selection-box-border-color'?: string;
  'selection-box-border-width'?: number;
  'selection-box-opacity'?: number;
  
  // Loop edges
  'loop-direction'?: string;
  'loop-sweep'?: string;
  
  // Haystack edges
  'haystack-radius'?: number;
  
  // Ghost
  'ghost'?: 'yes' | 'no';
  'ghost-offset-y'?: number;
  'ghost-offset-x'?: number;
  'ghost-opacity'?: number;
}

Label Style Properties

Text labels for nodes and edges with extensive typography control.

interface LabelStyleProperties {
  // Content
  'label'?: string;
  
  // Typography
  'color'?: string;
  'font-family'?: string;
  'font-size'?: number | string;
  'font-style'?: 'normal' | 'italic' | 'oblique';
  'font-variant'?: 'normal' | 'small-caps';
  'font-weight'?: 'normal' | 'bold' | 'bolder' | 'lighter' | number;
  'text-transform'?: 'none' | 'uppercase' | 'lowercase' 'capitalize';
  
  // Alignment
  'text-halign'?: 'left' | 'center' | 'right';
  'text-valign'?: 'top' | 'center' | 'bottom';
  
  // Positioning
  'text-margin-x'?: number;
  'text-margin-y'?: number;
  'text-rotation'?: number | 'autorotate' | 'none';
  
  // Wrapping
  'text-wrap'?: 'none' | 'wrap' | 'ellipsis';
  'text-max-width'?: number | string;
  'text-overflow-wrap'?: 'whitespace' | 'anywhere';
  'text-justification'?: 'left' | 'center' | 'right' | 'auto';
  
  // Background
  'text-background-color'?: string;
  'text-background-opacity'?: number;
  'text-background-shape'?: 'rectangle' | 'round-rectangle';
  'text-background-padding'?: number;
  
  // Border
  'text-border-color'?: string;
  'text-border-width'?: number;
  'text-border-style'?: 'solid' | 'dotted' | 'dashed' | 'double';
  'text-border-opacity'?: number;
  
  // Outline
  'text-outline-color'?: string;
  'text-outline-width'?: number;
  'text-outline-opacity'?: number;
  
  // Shadow
  'text-shadow-blur'?: number;
  'text-shadow-color'?: string;
  'text-shadow-offset-x'?: number;
  'text-shadow-offset-y'?: number;
  'text-shadow-opacity'?: number;
  
  // Visibility
  'text-opacity'?: number;
  'min-zoomed-font-size'?: number;
  
  // Edge label positioning
  'source-text-offset'?: number;
  'target-text-offset'?: number;
  'source-text-rotation'?: number | 'autorotate';
  'target-text-rotation'?: number | 'autorotate';
}

Core Style Properties

Styling for the core canvas and global elements.

interface CoreStyleProperties {
  // Background
  'background-color'?: string;
  'background-opacity'?: number;
  'background-image'?: string;
  'background-fit'?: 'none' | 'contain' | 'cover';
  'background-repeat'?: 'no-repeat' | 'repeat-x' | 'repeat-y' | 'repeat';
  'background-position-x'?: string | number;
  'background-position-y'?: string | number;
  'background-width'?: string | number;
  'background-height'?: string | number;
  
  // Selection box
  'selection-box-color'?: string;
  'selection-box-border-color'?: string;
  'selection-box-border-width'?: number;
  'selection-box-opacity'?: number;
  
  // Active background (when panning/zooming)
  'active-bg-color'?: string;
  'active-bg-opacity'?: number;
  'active-bg-size'?: number;
  
  // Outside texture (for very large graphs)
  'outside-texture-bg-color'?: string;
  'outside-texture-bg-opacity'?: number;
}

Dynamic Styling

Apply styles programmatically and respond to data changes.

/**
 * Data-driven styling using mappers
 */

// Map data to style values
const stylesheet = [
  {
    selector: 'node',
    style: {
      'width': 'mapData(weight, 0, 100, 10, 50)',
      'height': 'mapData(weight, 0, 100, 10, 50)',
      'background-color': 'mapData(score, 0, 1, blue, red)'
    }
  }
];

// Conditional styling
const conditionalStyle = [
  {
    selector: 'node[type = "user"]',
    style: {
      'shape': 'round-rectangle',
      'background-color': '#3498db'
    }
  },
  {
    selector: 'node[type = "group"]',
    style: {
      'shape': 'hexagon',
      'background-color': '#e74c3c'
    }
  }
];

// Style based on degree
cy.nodes().forEach(node => {
  const degree = node.degree();
  node.style({
    'width': Math.max(20, degree * 5),
    'height': Math.max(20, degree * 5),
    'background-color': degree > 3 ? 'red' : 'blue'
  });
});

CSS Classes

Manage CSS classes for reusable styling patterns.

interface Collection {
  /**
   * Add CSS classes to elements
   * @param classes - Space-separated class names
   * @returns Collection for chaining
   */
  addClass(classes: string): Collection;
  
  /**
   * Remove CSS classes from elements
   * @param classes - Space-separated class names (optional, removes all if not specified)
   * @returns Collection for chaining
   */
  removeClass(classes?: string): Collection;
  
  /**
   * Toggle CSS classes on elements
   * @param classes - Space-separated class names
   * @param state - Force toggle state (optional)
   * @returns Collection for chaining
   */
  toggleClass(classes: string, state?: boolean): Collection;
  
  /**
   * Check if elements have CSS class
   * @param className - Class name to check
   * @returns True if all elements have the class
   */
  hasClass(className: string): boolean;
  
  /**
   * Get all classes on first element
   * @returns Array of class names
   */
  classes(): string[];
}

Usage Examples:

// Define classes in stylesheet
const stylesheet = [
  {
    selector: '.highlighted',
    style: {
      'background-color': 'yellow',
      'border-width': 3,
      'border-color': 'orange'
    }
  },
  {
    selector: '.faded',
    style: {
      'opacity': 0.3
    }
  }
];

// Apply classes dynamically
cy.nodes().addClass('highlighted');
cy.edges().addClass('faded');

// Toggle classes based on selection
cy.on('select', 'node', function(evt) {
  evt.target.addClass('selected');
});

cy.on('unselect', 'node', function(evt) {
  evt.target.removeClass('selected');
});

Animation and Transitions

Animate style changes for smooth visual transitions.

interface Collection {
  /**
   * Animate style changes
   * @param properties - Style properties to animate
   * @param options - Animation options
   * @returns Promise that resolves when animation completes
   */
  animate(properties: StyleProperties, options?: AnimationOptions): Promise<Collection>;
}

interface AnimationOptions {
  /**
   * Animation duration in milliseconds
   */
  duration?: number;
  
  /**
   * Easing function
   */
  easing?: string;
  
  /**
   * Delay before animation starts
   */
  delay?: number;
  
  /**
   * Callback when animation completes
   */
  complete?: () => void;
  
  /**
   * Callback for each animation step
   */
  step?: (now: number, tween: any) => void;
  
  /**
   * Animation queue name
   */
  queue?: string | boolean;
}

Usage Examples:

// Animate node color change
node.animate({
  'background-color': 'red',
  'width': 50,
  'height': 50
}, {
  duration: 1000,
  easing: 'ease-in-out'
});

// Chain animations
node.animate({
  'background-color': 'blue'
}, 500).then(() => {
  return node.animate({
    'background-color': 'green'
  }, 500);
});

// Animate multiple properties
cy.nodes().animate({
  'background-color': 'purple',
  'width': 'mapData(degree, 0, 10, 20, 60)'
}, {
  duration: 2000,
  complete: () => console.log('Animation finished')
});

Style Utilities

Helper functions and advanced styling techniques.

/**
 * Style utility functions
 */

// Get computed style value
const computedColor = node.style('background-color');
const computedWidth = node.style('width');

// Check if style is applied
const hasCustomColor = node.style('background-color') !== node.removeClass().style('background-color');

// Reset styles to stylesheet defaults
node.removeStyle();
node.removeStyle(['background-color', 'width']);

// Batch style operations for performance
cy.batch(() => {
  cy.nodes().style('background-color', 'blue');
  cy.edges().style('line-color', 'red');
});

// Style templates
function applyNodeTemplate(nodes, template) {
  nodes.style(template);
}

applyNodeTemplate(cy.nodes('.important'), {
  'background-color': '#ff6b6b',
  'border-width': 3,
  'border-color': '#4ecdc4'
});