# Dashboard components

> What a dashboard component is: the catalog of kinds, the addresses they bind, how a reading is drawn, and the property sections every kind shares.

A **component** is one item on a dashboard: a rectangle of grid cells that draws
something. Most components read the live address space and present it, a few write to
it, and a few only draw. You place one from the **Add** area of the
[dashboard editor](view-editor)'s tool rail, by dragging it onto a precise cell or
clicking it to take the first free one, and it opens in Properties for you to configure.

Every kind has a reference page of its own, listed under [The catalog](#the-catalog) and
in this group's own list. This page holds what they all have in common: the addresses
they bind, how a reading is drawn, and the property sections that repeat on every kind.
Which role may press a control, and the lock mark a component wears when the signed-in
role may not, are on [View and dashboards](home).

## The catalog {#the-catalog}

The Add palette groups the catalog by category, and the categories say what a family
does. **Display** is everything that reports: the plain readouts and tables, the lamps,
and the charts that follow points over time or compare them side by side. **Control** is
the family dedicated to writing: every one of its components exists to put a value on a
point. It is not the only surface an operator presses, though. **Alarm** brings the
pending registry onto a screen, and its banner is acknowledged from there, per row and
for the lot; the Procedure cards listed below are pressed too. **Media** places pictures, library marks and industrial
artwork. **Layout** groups a region behind the rest of the screen.

| Category | Components |
|---|---|
| Display | [Label](component-label) · [Value](component-value) · [Point table](component-point-table) · [Status LED](component-status-led) · [Line chart](component-line-chart) · [Bar chart](component-bar-chart) · [Pie chart](component-pie-chart) · [Gauge](component-gauge) · [KPI card](component-kpi-card) · [Progress](component-progress) |
| Control | [Toggle](component-toggle) · [Input](component-input) · [Button](component-button) · [Selector](component-selector) · [Setpoint slider](component-setpoint-slider) · [Step keys](component-step-keys) |
| Alarm | [Alarm banner](component-alarm-banner) |
| Media | [Image](component-image) · [Icon](component-icon) · [Symbol](component-symbol) |
| Layout | [Frame](component-frame) |

Beyond the palette, the generated unit panels carry the Procedure cards, placed by the
Process workspace and not offered in Add: [Interlock](component-interlock),
[Procedure picker](component-procedure-picker),
[Occurrence list](component-occurrence-list) and
[Comment timeline](component-comment-timeline).

The pictures, marks and artwork the Media kinds draw come from the station's own library
on the Logic page: [The asset library](logic-assets) holds the images, icons and colors,
and [Symbols](assets-symbols) the catalog a [Symbol](component-symbol) is picked from,
with the terminals its connections are drawn between.

## Addresses and live readings {#addresses-and-live-readings}

Live components bind to **addresses**: rooted names into the station's live address
space, the same space Logic reads (see the [Logic page](logic)). An address names one
point, wherever it lives:

| Address shape | What it names |
|---|---|
| `Connector.<Driver>.<Device>.<Tag>` | A Connector tag's engineering value, with the device's folders between the driver and the device when it is filed in any (see the [Connector page](connector)) |
| `Variables.<name>` | A Logic variable (memory or computed) |
| `Alarms.<name>` | An alarm's active state |
| `Assets.Icons.<name>` | A mark of the icon library |
| `Process.<Model>.<Unit>.…` | A unit's run points: readings, `Commands.*`, `Next.<field>`, `Commands.Comment` |

Address fields are free text with suggestions: the list is drawn from the live point
list, capped at 50 rows, narrowed to the value category the field consumes (a gauge
suggests numbers, a toggle leads with Bool points, a write control lists only what can
be written), and every row is marked with its type. You may always type an address the
list does not offer, including one that does not exist yet. Once a field names a
point, the editor shows **what that point reads right now** under the field: the
confirmation a component drawing no number of its own cannot give. On a screen defined
on a Process model, the model's abstract channels lead every list; picking one binds
the channel and leaves the unit to be answered when a unit opens the screen.

The canvas refreshes its components from the address space every 150 ms on the
station's own window and every 400 ms on a remote browser, over the values the logic
sweep publishes. Two rules hold for every live component:

- **Never a stale value.** A point that stops reading drops to that component's own
  placeholder (the gap dash, a hollow lamp, a chart gap), never the last number.
- **One bad-reading mark.** A component whose bound point *fails to read* (the address
  resolves to nothing, or the point answers with bad quality) wears one shared mark:
  a dashed caution outline around the cell and a small circled `!` badge in its top
  right corner. Every kind wears the same mark, so it is learned once. A resolved
  point answering good quality with *no value* is not a failure (a bench between
  runs, a counter outside a cycle), so the component keeps its quiet placeholder and
  the mark stays dark. An **unbound** address is nobody's fault: a screen still being
  assembled never reads as a screen of warnings.

## Value display {#value-display}

How big a reading is drawn is governed by one contract, shared by every text surface
on the canvas (readouts, captions, key faces, state words):

- Every surface is either **automatic** (the cell decides the size, bounded by the
  width the surface's declarations reserve: digits, decimals, unit, or the authored
  words) or **stated**, a size in points you give (9 to 144). A stated size is
  literal: it renders at that size in any cell and is never reduced to make content
  fit. Nothing about the size ever follows the value that happens to arrive, so a
  number ticking between four and six characters never moves the type.
- **A number is never drawn cut.** Where it cannot be shown whole (more digits than
  the field declares, or a stated size wider than the cell) the surface draws `####`,
  the spreadsheet's and the DCS's mark for a field too narrow for its value, with the
  whole reading in the tooltip.
- **Free text truncates with an ellipsis**, whole text in the tooltip. Words never
  wear the number's mark.
- A point that is **not reading** is a different fact again: the gap dash, plus
  the shared bad-reading mark where the silence is real failure. Absence of a reading
  and absence of room never borrow each other's mark.
- Numbers rest on the right of their field, in tabular figures, so columns of
  readings align with themselves.

The 11 px readability floor holds everywhere, and the shared **Content scale** knob
multiplies the resolved size: down always shows (still floored), up grows only as far
as the line still fits uncut.

## The shared property sections {#the-shared-property-sections}

Selecting a component opens its properties. The sections named for the component's own
kind come first (its content, its data, its format) and are documented on that
component's page. Around them, every component shares the same sections. The panel that
draws them, the live reading under every address field, and the controls that repeat
across kinds (display size, Reads as, the Scale bands, the chart toolbox) are described
on [The dashboard editor](view-editor).

**Identification** names the component for whoever edits the screen: the name heads
the property panel, labels the row in the Components list and answers its search.
Nothing draws it on the operator's screen; that is the Appearance title.

**Appearance** is the component's box:

| Field | What it does | Values | Default |
|---|---|---|---|
| Show frame | Draws the component's own outline. | on / off | off |
| Frame thickness (px) | How heavy that outline is. One px is a card's edge; a heavier stroke tells a group from its surroundings without a second color. | 1 to 4 | 1 |
| Show background | Fills the component's rectangle with the color pair, making it a card. Off, the grid shows through. | on / off | off |
| Background color | The fill as a pair, one half per theme, both halves edited at once, because the running theme decides which half is on screen. | `#RRGGBB` each | `#FFFFFF` light · `#2B2B2B` dark |
| Title (corner) | The component's own corner label, what the card *is*, above whatever the kind renders. Blank means no caption row. | Free text | empty |
| Title size (px) | Blank lets each card size its own title from its cell; a stated size is literal and is what makes the titles of a whole screen agree. What no longer fits ellipsizes, whole title in the tooltip. | 11 to 96, or blank | blank (automatic) |
| Title color | The title's ink pair. Untouched, the title follows the theme's own quiet tone. | `#RRGGBB` each | `#6B6B6B` light · `#A0A0A0` dark |
| Content scale | How much of its box the content takes: the cell you drew already sizes the content, and this dials it inside the cell without redrawing the grid. Artwork answers it geometrically, a readout typographically. | 0.25 to 3 | 1 |

**Position and layer** holds the numeric X / Y / W / H, the layer (Z) and the
**Bring to front** / **Send to back** pair. **Advanced** appears only on the kinds
that have infrequent extras. **Actions** duplicates or removes the component.

Hold **Ctrl** to select several components and edit what they share: the Appearance
fields fan out across the whole selection (a field where members disagree says
"Mixed"), the layer commands keep the batch's relative order, and Duplicate/Remove act
on all of them. Per-kind fields need a single component.
