Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion vortex-web/.storybook/preview.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: Copyright the Vortex contributors

import { createElement } from 'react';
import type { Preview } from '@storybook/react-vite';
import { ThemeContext } from '../src/contexts/ThemeContext';
import '../src/index.css';

const preview: Preview = {
Expand All @@ -27,7 +29,13 @@ const preview: Preview = {
const theme = context.globals.theme || 'light';
document.documentElement.classList.toggle('dark', theme === 'dark');
document.documentElement.classList.toggle('light', theme === 'light');
return Story();
// Supply the theme context so components using useTheme render in stories,
// following the Storybook theme toolbar rather than persisted preferences.
return createElement(
ThemeContext.Provider,
{ value: { theme, setTheme: () => {} } },
Story(),
);
},
],
parameters: {
Expand Down
36 changes: 31 additions & 5 deletions vortex-web/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,32 @@

A web UI for exploring Vortex data files, built with React, TypeScript, Tailwind CSS, and Rust/WASM.

## Treemap Explorer

The detail panel's **Treemap** tab renders the file's physical blocks all the
way down to the leaves: layouts nest, flat layouts subdivide into their
array-encoding buffers, and every block is sized by its byte footprint and
coloured by dtype to match the swimlane. Each layout's name sits locally on the
block — in a container's header band (which its children never occupy, so labels
never collide) or in a leaf's body. Single-click a block to select it — it is
highlighted and the tree panel scrolls to it; double-click to zoom in (re-root
the map there), with an "↑" control to zoom back out. Selecting a node in the
tree panel drives the zoom too — the map re-roots at it.

![Treemap explorer overview](docs/img/treemap-explorer-overview.png)

Hovering a block shows its physical statistics — data and metadata bytes,
percentage of the file, encoded bytes-per-row density, rows, and segment/buffer
counts — in a floating tooltip; the sidebar and data sample track the selected
block, and selection stays in sync with the tree panel.

![Hovering a tile shows physical statistics](docs/img/treemap-explorer-hover.png)

Files with many chunks expose every chunk as its own byte-sized tile, making
skew and per-chunk size distribution obvious at a glance:

![Many chunks rendered as byte-sized tiles](docs/img/treemap-explorer-chunks-dark.png)

## Prerequisites

- Node.js 22+
Expand Down Expand Up @@ -34,7 +60,7 @@ This starts a dev server at http://localhost:6006.
## Scripts

| Command | Description |
|---------------------------|--------------------------------------------|
| ------------------------- | ------------------------------------------ |
| `npm run dev` | Build WASM (debug) + start Vite dev server |
| `npm run build` | Production build (WASM release + Vite) |
| `npm run storybook` | Start Storybook dev server on port 6006 |
Expand All @@ -49,18 +75,18 @@ This starts a dev server at http://localhost:6006.
Add story files alongside your components as `*.stories.tsx`:

```tsx
import type {Meta, StoryObj} from '@storybook/react-vite';
import {MyComponent} from './MyComponent';
import type { Meta, StoryObj } from '@storybook/react-vite';
import { MyComponent } from './MyComponent';

const meta: Meta<typeof MyComponent> = {
component: MyComponent,
component: MyComponent,
};
export default meta;

type Story = StoryObj<typeof MyComponent>;

export const Default: Story = {
args: {},
args: {},
};
```

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added vortex-web/docs/img/treemap-explorer-hover.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added vortex-web/docs/img/treemap-explorer-overview.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 7 additions & 3 deletions vortex-web/src/components/detail/DetailPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { SummaryPane } from './SummaryPane';
import { ArraySummaryPane } from './ArraySummaryPane';
import { EncodingPane } from './EncodingPane';
import { SegmentsPane } from './SegmentsPane';
import { TreemapPane } from './TreemapPane';
import { BlockTreemap } from '../explorer/BlockTreemap';
import { BuffersPane } from './BuffersPane';

type TabId = 'encoding' | 'segments' | 'treemap' | 'buffers';
Expand Down Expand Up @@ -155,11 +155,15 @@ export function DetailPanel() {
<SegmentsPane node={selection.selectedNode} segments={file.segments} />
)}
{currentTab === 'treemap' && selection.selectedNode && (
<TreemapPane
node={selection.selectedNode}
<BlockTreemap
root={file.layoutTree}
segments={file.segments}
fileSize={file.fileSize}
selectedNodeId={selection.selectedNodeId}
hoveredNodeId={selection.hoveredNodeId}
onSelectNode={selectNode}
onHoverNode={hoverNode}
onExpand={file.expandArrayTree}
/>
)}
{currentTab === 'buffers' && selection.selectedNode && (
Expand Down
52 changes: 0 additions & 52 deletions vortex-web/src/components/detail/TreemapPane.stories.tsx

This file was deleted.

Loading
Loading