Components › Records & data › Meeting analysis › Conversation timeline

Conversation timeline

canon

Moments, 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: null for 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-vl runs through every row at the moment's time and a dot .ma-dot marks 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 in title.
  • Lanes .ma-lane: one per speaker; the row label .ma-l carries 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 through color-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-static without a player), description .d, speaker (dot + name) .r, quote q. Anchored to the chip (.is-start / .is-end near the edges); below 560 px it spans the width of the track. A pinned card (.is-pinned) adds Close (.close, glyph x) 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-cross and 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-empty with labels.empty when 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 calls onSeek(m.t); Enter or Space calls onSeek with 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-valuetext is 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, speakers and lanes: 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) and labels.moodText(v) build the phrases; moodWord(v) maps -1...+1 to five words (thresholds +-0.35).

Do & Don't

Do
  • Pass every text through labels and 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.
Don’t
  • 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