PRIZM 4.0DSTA
Viewing C3 design language
RC3 · Components

Video tile

A single sensor feed — FPV camera, gimbal, IR, EO. RC3 ships the frame; the consumer plugs the stream player into the children slot.

Live

Three feed states. Toggle recording and reticle to see the optional overlays. The frame renders a stylised placeholder where the consumer's real video element would sit.

Live

Healthy feed with full telemetry burn-in. Ember dot marks the source as the active RC3 feed; status reads on the label.

FPV · UGV-04LIVE
01°20'58"N 103°49'13"EEOBRG 048°RNG 1.2 kmZOOM 2×
Degraded

Bandwidth-degraded link. Only the sensor mode is in scope — bearing and range are stale and deliberately omitted.

GIMBAL · UAV-09DEGRADED
IRZOOM 4×
Live

Minimal default. No telemetry passed; the tile stays sparse. Pass props only when the consumer has signal to surface.

WIDE · UGV-05LIVE
Lost

Signal lost. The overlay blanks the frame so a stale image cannot be misread as live; telemetry suppressed.

No signal
IR · UGV-07NO SIGNAL

Anatomy

Frame + five overlay layers. Everything outside the consumer's video element is RC3 chrome — restrained, never competing with the feed for attention. The source dot carries the Ember signature (identity); status reads in the label colour (semantic).

Source + status

Top-left chip. Ember identity dot + mono source identifier + semantic status label. Always visible.

Telemetry strip

Bottom-left mono row, single line. Surfaces only the cells the consumer passes — coordinates, sensor mode, bearing, range, zoom. Suppressed when feed is lost.

Recording indicator

Top-right chip. Small danger dot + REC. Optional; surfaces only when the consumer marks the feed as recording.

Reticle

Centre crosshair + outer ring for operator aim. Optional. Hidden when the feed is lost — meaning is undefined.

No-signal overlay

Replaces the frame on status="lost". Backdrop-blurred bg-bg with danger dot + NO SIGNAL caption. The frozen frame is never shown alone.

Ember signature

The source dot. Marks this surface as RC3-managed regardless of feed state. Distinct from semantic status — operators read identity and state independently.

Props

PropTypeDefaultDescription
sourcestringOperator-visible identifier — e.g. "FPV · UGV-04". Rendered in the top-left corner in mono.
status"live" | "degraded" | "lost"Feed status. Drives the corner state label and the no-signal overlay. Honours invariant 5: a lost feed surfaces as an unambiguous overlay, not a frozen frame.
recordingbooleanfalseSurfaces a danger-toned REC indicator in the top-right. The consumer drives recording state from their pipeline.
aspectRatio"16:9" | "4:3" | "9:16" | "1:1" | "auto""16:9"Aspect ratio constraint. auto releases the constraint so the consumer's video element sizes the tile naturally.
reticlebooleanfalseOptional centre crosshair + outer ring overlay for aim. Hidden when the feed is lost.
coordinatesstringConsumer-formatted look-point coordinates — e.g. 01°20'58"N 103°49'13"E. Surfaces in the telemetry strip when present.
bearingnumberCamera bearing in degrees (0–359). Formatted as BRG ###°.
rangenumberRange to look-point in metres. Formatted as RNG N m below 1 km, N.N km above.
zoomnumberZoom multiplier — e.g. 4 for 4×.
sensor"EO" | "IR" | "LL"Sensor mode badge — electro-optical, infra-red, low-light.
childrenReactNodeThe consumer-rendered video element, canvas, or stream player. Sized to fill the frame; RC3 does not ship the player.
classNamestringForwarded to the root container.

Types

FeedStatus

Feed status classifier. Your application owns the classification — typically derived from link metrics + frame rate + last-frame timestamp on the consumer side.

ts
type FeedStatus = "live" | "degraded" | "lost";
SensorMode

Sensor mode tag. EO (electro-optical, daylight), IR (infra-red), LL (low-light). Drives the sensor badge in the telemetry strip.

ts
type SensorMode = "EO" | "IR" | "LL";

Wiring

Read-only — the tile renders whatever you pass into children. Video transport varies hugely across platforms (RTSP / H.264, WebRTC, MJPEG, HLS, raw frames over WebSocket); RC3 stays out of the protocol business and lets you bring your own player.

tsx
// WebRTC / HLS — with telemetry burn-in
<VideoTile
  source="FPV · UGV-04"
  status={feed.status}
  recording={feed.recording}
  coordinates={lookAt.geo}
  bearing={camera.bearing}
  range={camera.rangeMetres}
  zoom={camera.zoom}
  sensor={camera.mode}
>
  <video
    ref={feed.videoRef}
    autoPlay
    muted
    playsInline
    className="h-full w-full object-cover"
  />
</VideoTile>
tsx
// RTSP via your JS player — minimal
<VideoTile source="GIMBAL · UAV-09" status={feed.status}>
  <YourRtspPlayer
    url={feed.rtspUrl}
    className="h-full w-full"
  />
</VideoTile>

Behavioural rule

Invariant Five

Telemetry never silently stale

A stale frame masquerading as a live feed is the worst-case failure — operators act on imagery that is no longer true. When the feed is lost, the tile blanks with an explicit NO SIGNAL overlay rather than holding the last frame.

Read invariant

Accessibility

Figure roleThe tile carries `role="figure"` with an `aria-label` of the form `{source}, {status}` so screen readers can announce the active feed and its state in one breath.
Decorative chromeSource label backdrop, status dot, reticle, and recording chip background are all `aria-hidden`. The accessible label on the figure root carries the meaning.
Recording stateThe recording chip carries `role="status"` with `aria-label="Recording"` so a screen reader can announce the start of recording.
Colour and meaningStatus colour is never the only signal — every state carries an explicit text label (LIVE / DEGRADED / NO SIGNAL). Operators with colour-vision differences still read state.
Consumer responsibilityThe video element inside `children` is the consumer's surface — captions, audio descriptions, and player controls are the consumer's accessibility responsibility.

JavaFX

Ships in the PRIZM JavaFX library for thick-client C3 apps as Rc3VideoTile (extends StackPane). Run the gallery to see it natively.

java
import design.prizm.fx.rc3.Rc3VideoTile;

Rc3VideoTile()
Rc3VideoTile(String source, FeedStatus status)
MemberTypeDefaultDescription
FeedStatusenumLIVE / DEGRADED / LOST — corner label + no-signal overlay.
AspectRatioenumR16_9R16_9 / R4_3 / R9_16 / R1_1 / AUTO — height derives from width.
SensorModeenumEO / IR / LL — sensor badge cell.
setContent(Node) → voidThe consumer's video / canvas / player; fills the tile.
setSource / setStatus(String) / (FeedStatus) → voidSource label + feed status.
setRecording / setReticle(boolean) → voidREC chip + centre reticle overlays.
setCoordinates / setBearing / setRange / setZoom / setSensor→ voidTelemetry burn-in cells (suppressed when lost).

Ships the surface; the consumer plugs the feed. Honours invariant 5 — a lost feed reads NO SIGNAL, never a frozen frame. The source dot is Ember. JavaFX has no backdrop-blur, so overlay pills use a solid fill. Mirrors components/rc3/video-tile.tsx.

Usage

A single tile renders one feed. Multi-feed surfaces (FPV + gimbal + IR side-by-side, picture-in-picture) are template-level compositions — drop several VideoTile instances into a grid and let your application decide which is primary. The status prop must reflect actual feed health on the consumer side — never default to "live" while you wait for the first frame; show "degraded" or "lost" until the stream is verified.