Conversation timeline
canonMoments, phases, who speaks when and the sentiment curve of one meeting on a shared minute axis.
Owner-approved 29 Sep 2026 (docs/ZADANI-koucink.md, acrm !4201; FA215). Candidate until component + stories + usage/a11y are on main. Sentiment colours via semantic tokens --sentiment-pos / --sentiment-neg (AD 30 Sep). On main 30 Sep 2026 (acrm !4229, !4234, !4238; tokens !4225); docs from dev-be FA220.
Used in 1 file · 1 area · 1× — components/meetings
One meeting on a shared minute axis: moments (pain, interest, objection, next step, decision), the phases of the conversation, who speaks when, and the sentiment of the conversation (-1...+1). A cursor with a bubble reads any minute; a click, a moment chip or Enter asks the host to seek the player to that time. CSS apps/web/src/ds/meeting-analysis.css, React ConversationTimeline in @acrm/ui (packages/ui/src/components/ConversationTimeline.tsx); geometry helpers in packages/ui/src/lib/timeline-geometry.ts.
Legal constraint: sentiment is derived from the CONTENT of the conversation only, never from voice, and it never labels a person's emotions. It describes how the talk went, not how someone felt.
When to use
- The Analysis tab of a meeting or call detail: the one place the whole conversation is read at a glance.
- A demo on our own meetings: the host passes role names as speaker labels and
quote: nullfor the counterpart, so no quote is drawn.
When not to use
- A trend over weeks (one number against a band): use weekly-bars.
- The signed-in user's own voice (pitch, pace): use voice-trace, private to its owner.
- Talk share alone: use the speaker rows of the record rail or a meter.
- A recording of a couple of minutes: the shape says nothing, show the numbers.
Anatomy
- Legend row
.ma-legendrow(own row above the curve, extra space above it): first the note ("mood from content per 90 s"), then the positive and negative swatches; drawn only with a sentiment curve (more than one point). - Moments
.ma-mo: one button chip per moment above the chart (speaker dot, icon, kind), packed into up to 3 rows so neighbours do not overlap. A guide.ma-vlruns through every row at the moment's time and a dot.ma-dotmarks the curve. - Phases
.ma-ph: labelled blocks on--line-100. A narrow phase ends its label with an ellipsis (.ma-ph-t); the full label and time range are intitle. - Lanes
.ma-lane: one per speaker; the row label.ma-lcarries the name and the talk share as text. The colour is passed by the host (player palette--ic-*), so a person has the same colour in player, transcript and here. - Sentiment
.ma-plot: a smooth line split at the zero line, with a fill above and below zero. Only--sentiment-pos/--sentiment-neg; fills are the same tokens throughcolor-mix. - Axis
.ma-axrow: minute ticks, steps 1-2-5-10-15-30-60 min (then 240), at most six ticks. - Moment card
.ma-mocard(role="group"): opens from a chip — kind (icon + name), ▷ time (.play, plain text.play.is-staticwithout a player), description.d, speaker (dot + name).r, quoteq. Anchored to the chip (.is-start/.is-endnear the edges); below 560 px it spans the width of the track. A pinned card (.is-pinned) adds Close (.close, glyphx) after the time; touch targets 44 px. The card replaces a separate list of moments under the chart — the host does not repeat them. - Cursor
.ma-ov(slider) over phases, lanes and sentiment, with the line.ma-crossand the bubble.ma-tip: time and phase, who speaks, sentiment word, the quote of a moment within 60 s. - Text alternative: a visually hidden table (
.acrm-sr) of phases and moments with time, speaker and quote. - Empty state:
.ma-chart.is-emptywithlabels.emptywhen there is no duration or nothing to draw.
Behaviour
- Moment card: pointer hover or keyboard focus on a chip opens the card, leaving closes it after a short delay (moving into the card keeps it). On touch the first tap opens and pins the card, the next tap on ▷ seeks; Close or Escape closes it and returns focus to the chip. Mouse click and Enter/Space on a chip call
onSeek(m.t)directly. - The cursor rests at 0 until the pointer or keyboard moves it. Pointer move shows the bubble; leaving hides it. A tap or click moves the cursor, shows the bubble and calls
onSeek(sec); a chip callsonSeek(m.t); Enter or Space callsonSeekwith the cursor time. - The bubble is positioned in px from the measured chart width: right of the cursor when it fits, else left, and it is clamped inside the chart so it never overflows.
- Sentiment in the bubble and in
aria-valuetextis the nearest point within 90 s; the quote and the moment name come from the nearest moment within 60 s. - Below 560 px container width (
@container ma) the label column narrows, the legend note moves to its own line and chips show only the dot and icon; the kind stays in the accessible name. - Everything is optional except
durationSec,speakersandlanes: without phases, moments or sentiment the corresponding rows are simply not drawn and the lanes still show who spoke. - Entrance (a curtain over the sentiment, lanes growing, chips and dots popping in) plays once, when the chart is at least 35 % visible, only under
prefers-reduced-motion: no-preference.animate={false}disables it (print, static snapshot). - All text comes from
labels; the package has no language of its own.labels.speaking(name)andlabels.moodText(v)build the phrases;moodWord(v)maps -1...+1 to five words (thresholds +-0.35).
Do & Don't
- Pass every text through
labelsand the speaker colour the player uses; never invent a new one. - Leave out what is missing (no phases, moments or sentiment) and let the host add one quiet sentence why.
- Keep kind and phase labels to one or two words and quotes verbatim from the transcript; the bubble adds the quote marks.
- Place it straight into a section block; the demo switch belongs to the block header.
- Let the moment card carry the detail; do not add a list of moments under the chart.
- Colour sentiment with anything but the two tokens, or add a third neutral colour: neutral is the zero line.
- Derive sentiment from voice, or word it as a person's emotion ("angry", "stressed"); it describes the content of the conversation (AI Act art. 5(1)(f)).
- Frame the chart in a card or a tinted box.
- Animate under
prefers-reduced-motion: reduce.
Related: section-block, stat-tile, weekly-bars, voice-trace, the meeting player (speaker track). Stories: Components / Conversation timeline: Default, States, Composition (the open moment card is shown only by interaction until a static story exists).
Source: docs/meeting-analysis/conversation-timeline.usage.md · GitLab