PluginUI

Dot Matrix Display

dot-matrix-displayViewers

This is the other half of the panel from the segment display. A segment readout can show a number; this display can show C:Small Plate on the top line and Mix=99 Volume=99 on the bottom. It works like hardware: a fixed field of dots, five columns by seven or eight rows per character, with ink moving across dots that never move. The preset determines the screen type. An LED marquee makes light at each dot, so it is round, bright and haloed on black glass. A backlit character LCD lights the pane and casts the dots as shadows, so its ink is square and dark on yellow-green, with no halo; the spill comes from the backlight rather than the characters. Text wider than the panel is cut off like a real module, or scrolls on a clock derived from elapsed time so dropped frames cannot make it drift. A bitmap prop drives the dots directly for meters, waveforms and boot logos, and a blinking block cursor marks the field being edited. The unlit grid is one tiled pattern and each line of ink is one path, so a 20x2 screen uses a handful of nodes rather than 1,600.

Bone / Studio
Loading interactive preview…
Planar / Flat
Loading interactive preview…
Midnight / Minimal
Loading interactive preview…
Ember / Vintage
Loading interactive preview…
Ink / Studio
Loading interactive preview…
Mint / Flat
Loading interactive preview…

Install

Copies the source into your project. Anything it depends on comes with it.

$ pnpm dlx shadcn@latest add @pluginui/core-dot-matrix-display

Pulls in

dot-matrix-fontdisplay-chromecontrol-theme

First time? Add the registry to your components.json once:

components.json
{
  "registries": {
    "@pluginui": "https://pluginui.com/r/{name}.json"
  }
}

Usage

Connect the documented props to your application or host.

example.tsx
import { DotMatrixDisplay } from "@/components/ui/dot-matrix-display"
import { themeVars } from "maruaudio/ui/shared/theme"

// The backlit character module: dark square ink on yellow-green.
<DotMatrixDisplay
  preset="lcd-green"
  columns={16}
  rows={8}
  text={["C:Small Plate", "Mix=99 Volume=99"]}
/>

// The marquee: round lit dots on black glass, scrolling.
<DotMatrixDisplay preset="led-red" columns={12} scroll text="NOW PLAYING: SIDE TWO" />

// Straight to the dots, for anything the character generator cannot say.
<DotMatrixDisplay preset="vfd" bitmap={levels} />

// Re-skin every display in a surface from one style block.
<div style={themeVars({ displayInk: "#ff9f1a", displaySpill: "#ff9f1a" })}>
  <DotMatrixDisplay columns={12} text="MARU 128" />
</div>

Props

PropTypeDefaultDescription
textstring | string[]—A line, or one per array entry. Newlines split too.
bitmapboolean[][]—Drive the dots directly with [row][column], ignoring the font. Use this for meters, waveforms, logos or anything without a character-generator glyph.
columnsnumber—Character cells across the panel. This is its physical width and defaults to the widest line. Text past this width is cut off unless scroll is set.
rows7 | 87Dot rows per cell. Seven is the classic 5x7 module and clips descenders exactly as one does; eight draws them.
presetDisplayPresetId | DisplayPreset"led-red"Panel skin. The reflective ones (lcd-green, lcd-blue, lcd-grey) turn the screen into a backlit module: square ink, no bloom, spill from the backlight.
shape"square" | "round"—The dot itself. Defaults to square on reflective skins and round on emissive ones, which is how the two kinds of screen are actually built.
pitchnumber4Dot spacing in pixels, measured centre to centre. This sets the display's scale.
fillnumber0.74Dot size as a fraction of the pitch. Under 1 is what leaves the grid visible.
scrollbooleanfalseMarquee lines that do not fit. Stops entirely under prefers-reduced-motion; a line that already fits never moves.
speednumber18Marquee speed in dot columns per second.
cursorDotMatrixCursor—The block a module leaves where you are typing: { line?, column, style?: "block" | "underline", blink? }.
colorstring—Override the ink colour. The unlit dots are derived from it and follow.
ghostnumber—How visible the unlit dots are, 0..1. Defaults to the skin's.
bloomnumber—Halo around the lit dots, 0..1. Defaults to the skin's value, which is zero on reflective skins.
spillnumber—How far light escapes the window onto the panel, 0..1.
brightnessnumber1Overall drive on the ink.
labelstring—Silkscreen caption above the display.
Theme--uikit-display-ink / --uikit-display-spill—Not props: the two CSS custom properties (displayInk / displaySpill via themeVars) that re-skin every display under a wrapper, resolved in CSS with no re-render. Precedence is instance color, then these, then the skin.
framebooleantrueDraw the panel around the pane.

Interaction

  • Drag with pointer capture, so the gesture keeps tracking past the edge of the control.
  • Shift while dragging for a fine pass; release it mid-gesture and coarse tracking resumes.
  • Double-click resets to defaultValue.
  • Arrow keys step normally, Shift+arrow steps finely, PageUp/PageDown jump by ten, Home/End go to the extremes.
  • Proper slider and switch roles with live aria-valuetext, so a screen reader announces the formatted value rather than the raw number.
  • The scroll wheel adjusts the value while the pointer is over the control; stepped ranges move at least one declared step per notch by default.