agentsclimarketplace

D3 interactive table

Skill cxcscmu/SkillLearnBench/skills/b1-one-shot-claude-sonnet-4-6/stock-data-visualization/d3-interactive-table

Build a sortable, highlightable HTML data table linked to a D3 chart so clicking a chart element highlights the matching table row and vice versa.From its SKILL.md

Install
npx -y skills add cxcscmu/SkillLearnBench --skill d3-interactive-table

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

SKILL.md

3.2 KB, 840 tokens by cl100k_base, as published. Nobody here has run it

D3 v6 Interactive Table with Chart Cross-Linking

Overview

A pure-HTML table built alongside a D3 chart where selections are synchronized: clicking a bubble highlights a table row, clicking a table row highlights the bubble.

Table Construction Pattern

function buildTable(data, containerId) {
    const container = d3.select(containerId);
    const table = container.append('table').attr('class', 'data-table');

    // Header
    const thead = table.append('thead');
    thead.append('tr').selectAll('th')
        .data(['Ticker', 'Full Name', 'Sector', 'Market Cap'])
        .join('th')
        .text(d => d);

    // Body
    const tbody = table.append('tbody');
    const rows = tbody.selectAll('tr')
        .data(data)
        .join('tr')
        .attr('data-ticker', d => d.ticker)  // stable identifier
        .on('click', function(event, d) {
            selectItem(d.ticker);
        });

    rows.selectAll('td')
        .data(d => [d.ticker, d.name, d.sector, formatMarketCap(d.marketCap)])
        .join('td')
        .text(v => v);
}

Cross-Linking Pattern

Use a shared selectItem(ticker) function that updates both the chart and table:

let selectedTicker = null;

function selectItem(ticker) {
    selectedTicker = ticker;

    // Update table rows
    d3.selectAll('tr[data-ticker]')
        .classed('selected', d => d.ticker === ticker);

    // Update chart circles
    d3.selectAll('circle.bubble')
        .classed('selected', d => d.ticker === ticker);

    // Scroll to highlighted row
    const row = document.querySelector(`tr[data-ticker="${ticker}"]`);
    if (row) row.scrollIntoView({ block: 'nearest', behavior: 'smooth' });
}

CSS for Highlighted State

/* Table row highlight */
tr[data-ticker]:hover {
    background: #f0f4ff;
    cursor: pointer;
}
tr[data-ticker].selected {
    background: #dce8ff;
    font-weight: 600;
}

/* Bubble highlight */
circle.bubble.selected {
    stroke: #1a1a2e;
    stroke-width: 3px;
    filter: drop-shadow(0 0 4px rgba(0,0,0,0.5));
}

Market Cap Formatting

function formatMarketCap(val) {
    if (!val || isNaN(+val)) return '—';
    const v = +val;
    if (v >= 1e12) return (v / 1e12).toFixed(2) + 'T';
    if (v >= 1e9)  return (v / 1e9).toFixed(2) + 'B';
    if (v >= 1e6)  return (v / 1e6).toFixed(2) + 'M';
    return v.toFixed(0);
}

Scrollable Table Container

For large datasets, constrain table height and enable overflow scrolling:

.table-container {
    max-height: 600px;
    overflow-y: auto;
    border: 1px solid #ddd;
    border-radius: 6px;
}

/* Sticky header */
thead th {
    position: sticky;
    top: 0;
    background: #f8f9fa;
    z-index: 10;
}

Click Toggle (Deselect on Second Click)

.on('click', function(event, d) {
    if (selectedTicker === d.ticker) {
        clearSelection();
    } else {
        selectItem(d.ticker);
    }
})

function clearSelection() {
    selectedTicker = null;
    d3.selectAll('.selected').classed('selected', false);
}

What ships with it

Read from the repository

Just SKILL.md. No reference files, no scripts.

Keep looking

Skills are one crate of 325,949. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.