CngxTimelineConnector
projects/common/timeline/connector.component.ts
Import#
import { CngxTimelineConnector } from '@cngx/common/timeline'
Description#
The rail segment between two markers.
Decorative and aria-hidden: it repeats a sequence the DOM order
already carries, so announcing it would only add noise. It is
status-capable all the same, because the visual run of a history is
where a rejected step or a not-yet-reached tail reads fastest - a
dashed segment for upcoming and a danger-toned one for rejected,
so the distinction survives without colour.
Drawn with border-inline-start and clipped with block-direction
margins - logical properties throughout, so the rail lands on the
correct side under dir="rtl" with no override.
Between two items
<cngx-timeline-connector status="done" />Last item in the run
<cngx-timeline-connector position="last" />Metadata#
Host#
Relationships
Index#
HostBindings
Inputs#
TimelineConnectorPositionPosition in the run. 'first' clips the head back to the marker
centre, 'last' clips the tail, 'only' hides the segment
entirely. Defaults to 'middle' - a full-height segment.
'middle'Status of the segment. upcoming renders dashed, rejected in the
danger tone, done and active solid in their own tones. Left unset
the rail paints in the neutral border colour.
HostBindings#
| Binding | Expression |
|---|---|
[attr.data-status] | status() |
[attr.data-position] | position() |
The --cngx-timeline-* custom-property family, shared by every
artifact in @cngx/common/timeline and re-used by the <cngx-timeline>
organism in @cngx/ui/timeline. A pure token surface - registrations
plus :root chains, no structural rules and no @scope.
It lives with the atoms rather than with the organism on purpose: a
<cngx-timeline-item> dropped into a hand-rolled layout has to render
complete and density-correct on its own. A token family that only
resolved under a Level-4 host would make the molecule a fragment
instead of a terminal unit.
Where the spacing tokens are, and why not here
This file carries no -gap / -padding registration. A spacing token
is registered in the same stylesheet that SETs it from --cngx-space-*,
at that component's own host:
--cngx-timeline-gap,--cngx-timeline-row-gap,--cngx-timeline-content-padding-timeline-item.component.css--cngx-timeline-group-gap- the organism's stylesheet
Registering them here and SETting them there would put a registration
one file away from its derivation, where the two can drift silently: a
registered initial-value defeats every use-site var(token, fallback), so a token that loses its SET rule freezes at the literal
and a nested [data-density] never reaches it. Keeping the pair
together makes that failure impossible to introduce by accident, and is
what the repo's density guard checks per file.
The sizes that remain here are affordances, not compactness, and are
deliberately outside the density scale. --cngx-timeline-rail-inset in
particular derives from --cngx-timeline-marker-size: the rail has to
meet the marker's centre, and a density swap that moved one without the
other would detach the rail from the dot. That derivation is applied at
the row host (timeline-item.component.css), the nearest common ancestor
of the marker and the connector - custom properties inherit downwards
only, so deriving it on either sibling would never reach the other.
Colour and dark mode
Every colour chains to a --cngx-color-* foundation token, which
already carries its own light and dark values. Dark mode therefore
needs no per-token redefinition here - overriding
--cngx-color-primary or the active colour scheme re-themes the
timeline for free. The literal in each chain's tail is the leaf
default for consumers running without the foundation stylesheet.
--cngx-timeline-connector-color->--cngx-color-border--cngx-timeline-surface->--cngx-color-surface--cngx-timeline-text-color->--cngx-color-text--cngx-timeline-muted-color->--cngx-color-text-muted--cngx-timeline-done-color->--cngx-color-success--cngx-timeline-active-color->--cngx-color-primary--cngx-timeline-rejected-color->--cngx-color-danger--cngx-timeline-upcoming-color->--cngx-color-text-muted
Default visuals for CngxTimelineConnector - the vertical rail between
two markers.
Geometry
The rail is the element's own border-inline-start, which puts it on
the left in LTR and on the right in RTL with no override and no
physical property anywhere in this file. justify-self: center inside
the item's marker column lines it up with the dot above it.
Position modifiers
[data-position] clips the segment back to the adjacent marker's
centre using --cngx-timeline-rail-inset:
middle(default) - full heightfirst- head clipped, so the rail starts at the first markerlast- tail clipped, so the rail stops at the last markeronly- not rendered; a single-item timeline has no rail
Status modifiers
[data-status] recolours the border, and upcoming also switches it
to dashed so the state does not rest on colour alone.
Orientation
[data-orientation='horizontal'] on any ancestor swaps the rail onto the
other axis: the border moves from border-inline-start to
border-block-start, the position clips move from margin-block-* to
margin-inline-*, and the status recolours follow. Still no physical
property anywhere - in horizontal the run's main axis is the inline
axis, so RTL reverses the whole timeline for free, exactly as the block
axis carries it in vertical.
Index#
Layout
Typography
Variant / Done
Variant / Active
Variant / Upcoming
Variant / Rejected
Layout
<length>6pxDistance the rail is pulled back from the edge of the marker cell so
it meets the marker's centre. Affordance geometry, deliberately
outside the density scale - it tracks --cngx-timeline-marker-size
instead, and a density swap that moved it would detach the rail from
the dot.
<percentage>60%Size of a bare svg glyph projected into the marker, as a share of the
marker box. A percentage rather than a length so it tracks
--cngx-timeline-marker-size on its own: em would resolve against the
marker's pinned font-size, which is not the dot's size.
Photos are not covered by this - an img or picture fills the dot
edge to edge, because a cropped portrait wants no inset and a glyph does.
<length>192pxWidth of one row on the horizontal axis. Ignored in the vertical default, where a row takes the container's width.
An affordance, not compactness, so it is deliberately outside the density scale. It exists because a horizontal run has no sensible content-derived width: flex would size every card to its longest word and the axis would read as a ragged queue. Override per instance for denser or wider cards.
<length>3pxWidth of the halo ring drawn around a marker in the active status.
Surface
<color>oklch(0.88 0.005 250)Colour of the connector rail in its default (unstated) status.
See: [[--cngx-color-border]]
<color>oklch(1 0 0)Background the marker is punched out of, so a coloured rail passing behind the dot does not show through it.
See: [[--cngx-color-surface]]
Typography
<color>oklch(1 0 0)Foreground colour of a glyph projected into the marker.
*0.8125remFont size for secondary text across the family - timestamps, inline errors, date headers, the refreshing tail. Registered here rather than with either consumer, because the row and the organism both read it and a registration in one is out of scope for the other.
<color>oklch(0.2 0.01 250)Primary text colour inside an item.
See: [[--cngx-color-text]]
<color>oklch(0.5 0.01 250)Secondary text colour - timestamps, group headers, the refreshing tail.
See: [[--cngx-color-text-muted]]
Variant / Done
<color>oklch(0.6 0.15 145)Marker and rail colour for the done status.
See: [[--cngx-color-success]]
Variant / Active
<color>oklch(0.66 0.19 50)Marker and rail colour for the active status.
See: [[--cngx-color-primary]]
Variant / Upcoming
<color>oklch(0.5 0.01 250)Marker and rail colour for the upcoming status. Pairs with a dashed
rail, so the state survives a colour-blind reader.
See: [[--cngx-color-text-muted]]
Variant / Rejected
<color>oklch(0.6 0.18 25)Marker and rail colour for the rejected status, and for an item
whose own [state] failed.
See: [[--cngx-color-danger]]
Motion
<time>1.6sPeriod of the busy pulse on a marker. Set to 0s to stop it without
touching the rest of the family.