Table Minimap
v...Tired of explaining to your boss why having too many columns in a table isn't a good idea? Give him Table-Minimap so he'll leave you alone. A framework-agnostic minimap for navigating large HTML tables. Like VS Code's minimap - but for tables.
Weekly npm downloads: Loading...
Columns Mode
Top / Bottom PositionSimple column-based visualization. Toggle between top and bottom position.
Scroll Position
0%
Mode
Columns
Fixed Position
Floating OverlayMinimap floats in a configurable corner over the table. Double-click the minimap to move it to the next corner.
Scroll Position
0%
Compact Fixed Position
Hideable DotA smaller floating minimap that collapses into a translucent dot in a configurable corner. Click it to expand, or double-click it to move it to the next corner.
Scroll Position
0%
Mode
Compact
Canvas Mode
Real Text + Zoom Mobile SupportRenders actual table content! Scroll wheel to zoom. Click to select one column, Shift+Click to select a range, Cmd/Ctrl+Click to add or remove individual columns. Right-click a selected column to apply menu actions to the selection. Full mobile support: pinch-to-zoom and double-tap for context menu.
Scroll Position
0%
Zoom Level
1.0x
Installation
# npm
npm install table-minimap
# yarn
yarn add table-minimap
# pnpm
pnpm add table-minimap
Works with any HTML table – no framework required.
Basic Usage
import { TableMinimap } from 'table-minimap';
import 'table-minimap/style.css';
// Initialize with selector
const minimap = new TableMinimap('#my-table', {
mode: 'columns',
height: 40,
position: 'bottom'
});
// Or with DOM element
const tableEl = document.getElementById('my-table');
const minimap2 = new TableMinimap(tableEl, {
mode: 'canvas',
height: 80,
zoomable: true,
maxZoom: 12
});
Dynamic Tables
let minimap = null;
// Initialize after table is loaded
function initTable(data) {
// Destroy existing minimap
minimap?.destroy();
// Populate your table...
renderTable(data);
// Create new minimap
minimap = new TableMinimap('#data-table', {
mode: 'canvas',
height: 60,
zoomable: true
});
}
// Call refresh() when table content changes
function updateCell(row, col, value) {
// Update cell...
minimap?.refresh();
}
Complete HTML Example
<!-- HTML -->
<div id="table-container">
<div class="table-wrapper" style="overflow-x: auto;">
<table id="my-table">
<thead>
<tr>
<th>Column 1</th>
<th>Column 2</th>
<!-- ... more columns -->
</tr>
</thead>
<tbody>
<!-- Table rows -->
</tbody>
</table>
</div>
</div>
<!-- JavaScript -->
<script type="module">
import { TableMinimap } from 'table-minimap';
import 'table-minimap/style.css';
const minimap = new TableMinimap('#my-table', {
mode: 'canvas',
height: 60,
zoomable: true
});
</script>
Use a custom hook for clean integration with React's lifecycle.
useTableMinimap Hook
// hooks/useTableMinimap.ts
import { useEffect, useRef, RefObject } from 'react';
import { TableMinimap, TableMinimapOptions } from 'table-minimap';
import 'table-minimap/style.css';
export function useTableMinimap<T extends HTMLElement>(
options: TableMinimapOptions = {}
): {
tableRef: RefObject<T>;
minimapRef: RefObject<TableMinimap | null>;
refresh: () => void;
resetZoom: () => void;
} {
const tableRef = useRef<T>(null);
const minimapRef = useRef<TableMinimap | null>(null);
useEffect(() => {
if (!tableRef.current) return;
minimapRef.current = new TableMinimap(tableRef.current, options);
return () => {
minimapRef.current?.destroy();
minimapRef.current = null;
};
}, []);
const refresh = () => minimapRef.current?.refresh();
const resetZoom = () => minimapRef.current?.resetZoom();
return { tableRef, minimapRef, refresh, resetZoom };
}
Usage in Component
// components/DataTable.tsx
import { useTableMinimap } from '../hooks/useTableMinimap';
interface DataTableProps {
data: Array<{ id: string; [key: string]: any }>;
columns: string[];
}
export function DataTable({ data, columns }: DataTableProps) {
const { tableRef, refresh, resetZoom } = useTableMinimap<HTMLDivElement>({
mode: 'canvas',
height: 80,
zoomable: true,
maxZoom: 12
});
return (
<div className="space-y-4">
<div className="flex gap-2">
<button onClick={refresh}>Refresh</button>
<button onClick={resetZoom}>Reset Zoom</button>
</div>
<div ref={tableRef} className="overflow-x-auto">
<table className="min-w-full">
<thead>
<tr>
{columns.map(col => (
<th key={col}>{col}</th>
))}
</tr>
</thead>
<tbody>
{data.map(row => (
<tr key={row.id}>
{columns.map(col => (
<td key={col}>{row[col]}</td>
))}
</tr>
))}
</tbody>
</table>
</div>
</div>
);
}
With Dynamic Data
// When data changes, refresh the minimap
import { useEffect } from 'react';
import { useTableMinimap } from '../hooks/useTableMinimap';
export function DynamicTable({ data }) {
const { tableRef, refresh } = useTableMinimap({
mode: 'canvas',
height: 60
});
// Refresh minimap when data changes
useEffect(() => {
refresh();
}, [data]);
return (
<div ref={tableRef}>
<table>{/* ... */}</table>
</div>
);
}
Clean integration using Vue 3's Composition API with composables.
useTableMinimap Composable
// composables/useTableMinimap.ts
import { ref, onMounted, onBeforeUnmount, Ref } from 'vue';
import { TableMinimap, TableMinimapOptions } from 'table-minimap';
import 'table-minimap/style.css';
export function useTableMinimap(options: TableMinimapOptions = {}) {
const tableRef = ref<HTMLElement | null>(null);
let minimap: TableMinimap | null = null;
onMounted(() => {
if (tableRef.value) {
minimap = new TableMinimap(tableRef.value, options);
}
});
onBeforeUnmount(() => {
minimap?.destroy();
minimap = null;
});
const refresh = () => minimap?.refresh();
const resetZoom = () => minimap?.resetZoom();
const getZoomState = () => minimap?.getZoomState();
return {
tableRef,
refresh,
resetZoom,
getZoomState
};
}
Usage in Component
<!-- components/DataTable.vue -->
<script setup lang="ts">
import { watch } from 'vue';
import { useTableMinimap } from '@/composables/useTableMinimap';
const props = defineProps<{
data: Array<Record<string, any>>;
columns: string[];
}>();
const { tableRef, refresh, resetZoom } = useTableMinimap({
mode: 'canvas',
height: 80,
zoomable: true,
maxZoom: 12
});
// Refresh when data changes
watch(() => props.data, () => {
refresh();
}, { deep: true });
</script>
<template>
<div class="space-y-4">
<div class="flex gap-2">
<button @click="refresh">Refresh</button>
<button @click="resetZoom">Reset Zoom</button>
</div>
<div ref="tableRef" class="overflow-x-auto">
<table class="min-w-full">
<thead>
<tr>
<th v-for="col in columns" :key="col">{{ col }}</th>
</tr>
</thead>
<tbody>
<tr v-for="row in data" :key="row.id">
<td v-for="col in columns" :key="col">{{ row[col] }}</td>
</tr>
</tbody>
</table>
</div>
</div>
</template>
Options API Alternative
<!-- For Vue Options API users -->
<script>
import { TableMinimap } from 'table-minimap';
import 'table-minimap/style.css';
export default {
data() {
return {
minimap: null
};
},
mounted() {
this.minimap = new TableMinimap(this.$refs.tableWrapper, {
mode: 'canvas',
height: 60,
zoomable: true
});
},
beforeUnmount() {
this.minimap?.destroy();
},
methods: {
refreshMinimap() {
this.minimap?.refresh();
}
}
};
</script>
<template>
<div ref="tableWrapper">
<table><!-- ... --></table>
</div>
</template>
Options
| Option | Type | Default | Description |
|---|---|---|---|
| Core Options | |||
mode
|
'columns' | 'canvas' | 'columns' | Rendering mode |
height
|
number | 40 | Height in pixels |
position
|
'top' | 'bottom' | 'fixed' | 'bottom' | Position: top/bottom of table, or fixed overlay |
draggable
|
boolean | true | Enable drag navigation on viewport |
showViewport
|
boolean | true | Show the viewport indicator |
| Fixed Position Options | |||
fixedWidth
|
number | 300 | Width when position is 'fixed' |
fixedPosition
|
'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' | 'bottom-right' | Corner when position is 'fixed'; double-click to cycle |
compact
|
boolean | false | Collapse into dot handle, expand on hover/click |
| Zoom Options (Canvas Mode) | |||
zoomable
|
boolean | false | Enable scroll wheel / pinch-to-zoom |
minZoom
|
number | 1 | Minimum zoom level (1 = full overview) |
maxZoom
|
number | 10 | Maximum zoom level |
zoomSpeed
|
number | 0.1 | Zoom speed multiplier |
| Canvas Context Menu | |||
canvasClipboard
|
boolean | false | Enable "Copy column to clipboard" context menu |
canvasClipboardLabel
|
string | 'Copy column to clipboard' | i18n label for clipboard action |
canvasColumnMarking
|
boolean | false | Enable mark/unmark column in context menu |
canvasMarkColumnLabel
|
string | 'Mark column' | i18n label for mark action |
canvasUnmarkColumnLabel
|
string | 'Unmark column' | i18n label for unmark action |
canvasUnmarkAllColumnsLabel
|
string | 'Unmark all columns' | i18n label for unmark-all action |
canvasColumnHiding
|
boolean | false | Enable collapse/expand column in context menu |
canvasColumnSelection
|
boolean | false | Enable click, Shift+Click and Cmd/Ctrl+Click column selection |
canvasHideColumnLabel
|
string | 'Collapse column' | i18n label for collapse action |
canvasShowColumnLabel
|
string | 'Expand column' | i18n label for expand action |
canvasShowAllColumnsLabel
|
string | 'Expand all columns' | i18n label for expand-all action |
collapsedColumnWidth
|
number | 10 | Width in pixels for collapsed columns |
| State & Callbacks | |||
markedColumns
|
number[] | [] | Initially marked column indices |
hiddenColumns
|
number[] | [] | Initially collapsed column indices |
onMarkedColumnsChange
|
(details) => void | - | Callback when marked columns change |
onHiddenColumnsChange
|
(details) => void | - | Callback when collapsed columns change |
selectedColumns
|
number[] | [] | Initially selected column indices |
onSelectedColumnsChange
|
(details) => void | - | Callback when selected columns change |
API Methods
| Method | Description |
|---|---|
| Core Methods | |
destroy()
|
Remove minimap and cleanup all event listeners |
refresh()
|
Force re-render after table content changes |
scrollToColumn(index)
|
Scroll table to bring specific column into view |
| Zoom Methods (Canvas Mode) | |
getZoomState()
|
Get current zoom level and state info |
setZoom(level, panX?)
|
Set zoom level programmatically with optional pan position |
resetZoom()
|
Reset to full table overview (zoom 1x) |
zoomToColumns(start, end)
|
Zoom to show a specific column range |
| Column Marking Methods | |
getMarkedColumns()
|
Get array of marked column indices |
setMarkedColumns(indices)
|
Replace all marked columns programmatically |
clearMarkedColumns()
|
Clear all marked columns |
| Column Collapsing Methods | |
getHiddenColumns()
|
Get array of collapsed column indices |
setHiddenColumns(indices)
|
Replace all collapsed columns with dark overlay |
clearHiddenColumns()
|
Expand all collapsed columns |
| Column Selection Methods | |
getSelectedColumns()
|
Get array of selected column indices |
setSelectedColumns(indices)
|
Replace all selected columns programmatically |
clearSelectedColumns()
|
Clear all selected columns |