PluginUI

Segment Display

segment-displayViewers

A segment display is not a font. It uses 7, 14 or 16 bars in fixed positions. The unlit bars make it unmistakable: a cell showing 1 still shows the ghost of 8, dark red on darker glass. A typeface can draw only the lit state, so this component draws the geometry, including mitred bars generated from a thickness and gutter and thinner diagonals like real glass. The bars shear around the baseline because every module in a rack is italic by a few degrees. The display also recreates a panel's physical details: a pane recessed under the bezel's overhang, a bloom extending past each lit bar, and light spilling onto the panel in proportion to how much is lit. For example, 88:88 washes the bezel while 1 barely does. Show a plain value in a window of digits, or several captioned fields behind one piece of glass, as a multi-tap delay might show DELAY / 4X 60MS / L+R instead of opening a menu. Decimal points ride the cell before them, so 120.5 is four digits wide. Overflow is truncated from the end the text is not aligned to; a tempo drops leading digits and keeps the ones that move.

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-segment-display

Pulls in

segment-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 { SegmentDisplay } from "@/components/ui/segment-display"
import { themeVars } from "maruaudio/ui/shared/theme"

// A tempo readout: seven segments, right-aligned, the point riding a cell.
<SegmentDisplay type="seven" value="128.5" digits={4} align="right" />

// A whole front panel: three captioned windows behind one piece of glass.
<SegmentDisplay
  size={30}
  fields={[
    { label: "mode", text: "DELAY", digits: 5 },
    { label: "parameter 1", text: "4X 60MS", digits: 7 },
    { label: "parameter 2", text: "L+R", digits: 5 },
  ]}
/>

// No character generator: a bar graph out of the bars themselves.
<SegmentDisplay masks={levels.map((on) => (on ? 0x00ff : 0x00c0))} digits={8} />

// Another decade's panel: the skin is the whole colour surface.
<SegmentDisplay preset="vfd" value="PROGRAM 07" digits={10} />

// Every display under one wrapper, without touching a component.
// Instance color still wins; anything deeper takes a whole preset object.
<div style={themeVars({ displayInk: "#ff9f1a", displaySpill: "#ff9f1a" })}>
  <SegmentDisplay value="PATCH 12" digits={8} />
</div>

Props

PropTypeDefaultDescription
valuestring | number—The readout is shown as written. Format it before passing it in; the display does not choose decimal places.
digitsnumber—Cells in the window. Omit to fit the value. Text longer than the window is truncated from the end it is not aligned to.
align"left" | "right""left"Which end the text sits at, and therefore which end an overflow eats. Numbers default to right.
fieldsSegmentField[]—Several windows behind one pane, each with a silkscreen caption above it: { label?, text, digits?, align? }. The captions are laid out from the same widths the windows are, so they stay over their own field at any size.
masksnumber[]—Drive the bars directly, one mask per cell, bit 0 being segment A (SEGMENT_NAMES names the bits). Ignores value, and is the counterpart of the dot screen's bitmap: a bar graph out of the middle bars, a rotating busy segment, the annunciators a real panel has. Also available per field.
type"seven" | "fourteen" | "sixteen""fourteen"Seven bars for numbers, fourteen for words, sixteen for the starburst with its split top and bottom bars.
presetDisplayPresetId | DisplayPreset"led-red"Panel skin: led-red, led-amber, led-green, led-blue, vfd, plasma, lcd-green, lcd-blue, lcd-grey. A whole preset object re-skins one instance completely.
colorstring—Override the lit colour. Ghosts derive their colour from it, so they follow along. An amber display with red ghosts is not a hardware look.
sizenumber26Cell height in pixels. Everything else is proportional to it.
weightnumber0.095Bar thickness as a fraction of the cell height.
slantnumber6Italic lean in degrees, sheared about the baseline. Zero is upright, which reads as a web page rather than a module.
ghostnumber—How visible the unlit bars are, 0..1. Defaults to the skin's. Zero switches them off, which is exactly what a display does not look like.
bloomnumber—Halo around the lit bars, 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. Scaled by how much of the display is lit.
brightnessnumber1Overall drive on the lit bars, for a dimmed panel, fade or idle state.
labelstring—Silkscreen caption above the whole display.
Theme--uikit-display-ink / --uikit-display-spill—These are not props. They are the two CSS custom properties (displayInk / displaySpill via themeVars) that re-skin every display under a wrapper. CSS resolves them without a re-render. Precedence is instance colour, then these properties, then the skin. To change anything beyond the light, such as glass, bezel, bloom or ghost level, pass a whole DisplayPreset object instead of adding tokens.
framebooleantrueDraw the panel around the pane. Off leaves the bare recessed window to drop into your own.
blinkboolean | numberfalseBlink the lit bars. Pass true for a 500 ms period, or pass a period in milliseconds. The ghosts stay put as they do on hardware.

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.