Skip to content

hetalhouse/cathode

Repository files navigation

cathode

A retro CRT curved-screen datagrid for the web. Barrel-distorted columns, phosphor aesthetics, more data per viewport.

npm license bundle size types

cathode workspace — the curvature slider sweeping the workspace flat→fishbowl, then the shader magnifier lens chasing the cursor across the curved grid

▶ Try it live — the curve slider is the fun part. 🎬 Watch the 26-second tour (mp4) — workspace → magnifier lens → three.js candles → themes.

Stills reproduce with npm run capture:hero (see tools/capture-hero.mjs); the workspace hero lives at docs/hero.png.


Why

Flat datagrids waste peripheral vision. A curved screen — like a real CRT monitor — angles the left and right columns toward the viewer, creating a panoramic effect that lets you read more columns comfortably without horizontal eye strain. Edge columns are slightly foreshortened, fitting 10–15% more content at the same viewport width.

The effect is pure CSS 3D (perspective + rotateY per column). Text stays real DOM — selectable, copyable, accessible.


Quick start

npm install @hetalhouse/cathode

Minimal — drop a grid into a Vue 3 app:

<script setup lang="ts">
import { CathodeGrid, type ColDef } from '@hetalhouse/cathode'
import '@hetalhouse/cathode/style'

const cols: ColDef[] = [
  { field: 'ticker', headerName: 'Ticker' },
  { field: 'price',  headerName: 'Price'  },
]

const rows = [
  { ticker: 'BTC', price: 67_341.20 },
  { ticker: 'ETH', price: 2_481.05  },
]
</script>

<template>
  <CathodeGrid :column-defs="cols" :row-data="rows" theme="phosphor" />
</template>

That's it. The grid renders, the curve activates, the phosphor glow lights up.

Comprehensive example — API callback, pagination, custom styling
<script setup lang="ts">
import { CathodeGrid } from '@hetalhouse/cathode'
import '@hetalhouse/cathode/style'
import type { ColDef, GridApi } from '@hetalhouse/cathode'

const cols: ColDef[] = [
  { field: 'ticker',   headerName: 'Ticker',  width: 90 },
  { field: 'price',    headerName: 'Price',   width: 100, cellStyle: { textAlign: 'right' } },
  { field: 'pnl',      headerName: 'PnL %',   width: 80  },
]

let api: GridApi

function onGridReady(e: { api: GridApi }) {
  api = e.api
  api.setGridOption('rowData', myRows)
}
</script>

<template>
  <CathodeGrid
    :column-defs="cols"
    :row-height="28"
    theme="phosphor"
    :curvature="12"
    :scanlines="true"
    :glow="true"
    :pagination="true"
    :pagination-page-size="50"
    @grid-ready="onGridReady"
    @row-clicked="e => console.log(e.data)"
  />
</template>

Status

v0.1.x — production-ready for small-to-mid datasets. Cathode is in active use rendering live trading data in a production dashboard.

Works well for Choose something else for
100s–10ks of rows 100k+ rows (use TanStack Table — virtual scrolling is on cathode's roadmap but not yet shipped)
Vue 3 apps React (no wrapper yet — see ROADMAP.md)
Dashboards, status panels, sci-fi UIs Spreadsheet-style apps with row grouping / aggregation (not yet shipped)
Built-in CRT / phosphor aesthetic Plain Material / Tailwind look — pass theme="none" and bring your own CSS vars

See ROADMAP.md for what's coming next.


Props

Prop Type Default Description
columnDefs ColDef[] required Column definitions
rowData any[] [] Initial row data (use api.setGridOption('rowData', …) to update)
rowHeight number 28 Row height in px
defaultColDef Partial<ColDef> {} Merged into every column definition
getRowStyle (p) => CSSProperties Per-row inline style callback
pinnedBottomRowData any[] Rows pinned to the bottom of the scroll area
pagination boolean false Enable pagination bar
paginationPageSize number 50 Rows per page
theme 'none' | 'phosphor' | 'amber' | 'paper' 'none' Built-in colour theme ('none' inherits parent CSS vars)
curvature number 10 Max rotateY angle (°) for edge columns — 0 = flat
perspective number 1400 CSS perspective distance (px) — higher = subtler vanishing point
scanlines boolean true Overlay repeating scanline gradient
glow boolean true Apply text-shadow phosphor glow to cell text

Grid API

Emitted via @grid-ready. Mirrors the ag-Grid Community API surface used in typical dashboards.

api.setGridOption('rowData', rows)
api.setGridOption('pinnedBottomRowData', pinnedRows)
api.setGridOption('quickFilterText', 'BTC')

api.getColumnState()                   // → ColState[]
api.applyColumnState({ state, applyOrder })
api.setFilterModel({ status: { type: 'equals', filter: 'open' } })
api.getFilterModel()
await api.setColumnFilterModel('status', { type: 'equals', filter: 'open' })
api.onFilterChanged()                  // no-op — Vue reactivity handles it

api.refreshCells()                     // force re-evaluation (e.g. Age column)
api.exportDataAsCsv({ fileName: 'trades.csv' })
api.resetColumnState()

ColDef

interface ColDef {
  field?:          string           // row[field]
  headerName?:     string
  colId?:          string           // explicit ID; defaults to field → headerName slug
  width?:          number
  minWidth?:       number
  sortable?:       boolean
  filter?:         boolean          // shows ⌕ icon in header → popup text filter
  resizable?:      boolean
  hide?:           boolean
  sort?:           'asc' | 'desc'   // initial sort
  valueGetter?:    (p) => any
  valueFormatter?: (p) => string
  cellStyle?:      CSSProperties | ((p) => CSSProperties)
  cellRenderer?:   (p) => string    // HTML string rendered via v-html
  comparator?:     (a, b) => number
}

Themes

Theme Background Text Use for
none (default) inherits --c-bg CSS var inherits --c-tx1 Drop into an existing dashboard
phosphor #060d06 #33ff33 Classic green CRT terminal
amber #0a0700 #ffb000 Amber phosphor
paper #f6f6f6 #222 Light / Lumen-style

CSS custom properties (theme="none")

If no theme is set, the grid reads these variables from its parent — making it a natural fit alongside an existing :root / html.light token system:

--c-bg, --c-surface, --c-header, --c-tx1, --c-tx2, --c-tx4,
--c-border, --c-input

Contributing

See CONTRIBUTING.md for development setup, the Playwright regression-test suite, and the release process.


License

MIT — © Brady House

About

A curved-screen datagrid for the web. Barrel-distorted columns, CRT aesthetics, more data per viewport.

Resources

License

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors