Add Timeline & Distributions tabs to continuous Question Groups (Consumer View)#4977
Add Timeline & Distributions tabs to continuous Question Groups (Consumer View)#4977aseckin wants to merge 12 commits into
Conversation
Consumer-view continuous Question Groups (Numeric, Discrete, Date) now offer a Timeline / Distributions toggle in the chart area, reusing the binary Timeline/Histogram tab pattern. In Distributions mode one subquestion row is always selected (click to change; the row gains an emphasized active state on top of hover), and its community distribution renders in place of the timeline in the row's color — display-only, never the user's own prediction. A PDF/CDF toggle (styled like the timeframe buttons, with the explanatory tooltip) replaces the timeframe selector. Hovering the curve shows the usual cursor point without the value text underneath. On mobile a new Distributions tab stacks every subquestion's distribution vertically with a PDF/CDF sub-tab, and the mobile Timeline tab now exposes the timeframe selector. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- ContinuousAreaChart: CDF area now fills the full width like the PDF; quartile dashed lines and the hover cursor circle honor colorOverride; the stray asymmetric bound line no longer renders without a global scale. - Active subquestion row: 2px border + 4px outer glow (25% of the row color). - Closed subquestions render their distribution in gray. - Date groups: show the list/chart divider and align the tabs like other question types. - Fan-graph panel: single tab set (Timeline / Fan Chart / Distributions) instead of two overlapping sets; in distribution mode the left time-series bins are selectable and the active bin is highlighted in the row color. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
When hovering a group distribution near a quartile line (25/median/75), show a value chip snapped to that quartile at the top of the chart and suppress the cursor circle, reusing the timeline cursor chip styling with the subquestion color as the background. Gated behind a new cursorQuartileTooltip prop so prediction inputs are unaffected. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…and) - Auto-expand the subquestion list when the auto-selected distribution row is hidden behind the "N others" fold, so the active row is visible. - Quartile hover chip now anchors at the curve/quartile intersection (where the circle would be) instead of floating at a fixed top position. - The hovered quartile line becomes solid and doubles its thickness. - CDF now fills the width consistently with the PDF by passing alignChartTabs (matching the prediction input behavior). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Clicking a fan-graph bin (or a subquestion row in any distribution-capable group) now switches into Distributions mode and activates that bin/row, instead of only working once already in Distributions. - Fan-graph panel derives its timeline/distributions state from the shared view mode, so a bin click flips it out of the fan/timeline view. - The list re-expands on every switch into a distribution whose row is hidden behind the fold (not just the first time), while still respecting a manual collapse when nothing changed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Warning Review limit reached
Next review available in: 45 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThis PR adds a consumer “Distributions” view for eligible grouped questions, with PDF/PMF and CDF charts, shared selection state, chart and forecast-row interactions, quartile tooltips, question-page navigation, and localized labels. ChangesDistributions Feature
Estimated code review effort: 4 (Complex) | ~60 minutes Possibly related PRs
Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
🚀 Preview EnvironmentYour preview environment is ready!
Details
ℹ️ Preview Environment InfoIsolation:
Limitations:
Cleanup:
|
There was a problem hiding this comment.
Actionable comments posted: 8
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
front_end/src/components/consumer_post_card/time_series_chart/index.tsx (1)
270-294: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winRestrict click selection to the plotted chart area.
onClickis attached to the outer wrapper, so clicks on the bottom padding or theUpcomingCPfooter still runclosestIndexFromEvent()and select the nearest datum. That can switch views even though no bar was clicked. Move the handler to the chart surface or guard the Y bounds before callingonBarClick.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@front_end/src/components/consumer_post_card/time_series_chart/index.tsx` around lines 270 - 294, The click handler on TimeSeriesChart is bound to the outer wrapper, so clicks outside the plotted area can still select a datum via closestIndexFromEvent(). Update handleClick/onClick so selection only happens within the chart surface used for bars, or add a Y-bounds guard before calling onBarClick; use the existing TimeSeriesChart, handleClick, and closestIndexFromEvent symbols to keep the fix localized.
🧹 Nitpick comments (1)
front_end/src/app/(main)/questions/[id]/components/question_view/consumer_question_view/group_distribution_utils.ts (1)
52-56: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low valueMinor: redundant recomputation for existence check.
hasSubquestionDistributionbuilds the full distribution object (includingcdfToPmf) just to check.length > 0. SincegetSubquestionDistributionDatareturns either[]or a single-element array based purely onisUnsuccessfullyResolved/isForecastActivechecks (lines 25-33), a lighter-weight eligibility check without thecdfToPmfcall would avoid the extra work when this is invoked across many subquestions (e.g.,selectableIdsfiltering inGroupDistributionsView).🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@front_end/src/app/`(main)/questions/[id]/components/question_view/consumer_question_view/group_distribution_utils.ts around lines 52 - 56, hasSubquestionDistribution is doing unnecessary work by calling getSubquestionDistributionData just to test whether any distribution exists. Update hasSubquestionDistribution to perform the same eligibility checks directly using the existing question state checks from getSubquestionDistributionData, and avoid constructing the full distribution data or calling cdfToPmf unless the data is actually needed. Keep the logic aligned with the current behavior in group_distribution_utils.ts so GroupDistributionsView and similar callers still get the same true/false result.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@front_end/src/app/`(main)/questions/[id]/components/question_page_shell/tab_bar.tsx:
- Around line 9-17: The Distributions tab visibility is currently based only on
the post type, so `DistributionsTab` can still be shown even when it will render
`null` because no subquestion distribution exists. Update the tab gating in
`tab_bar.tsx` to use the same renderability check as `DistributionsTab`
(including `hasSubquestionDistribution()`), so empty or new continuous groups do
not expose a blank selectable tab. Keep the logic aligned with
`isContinuousGroupPost`, `useQuestionLayout`, and the existing tab-rendering
conditions.
In
`@front_end/src/app/`(main)/questions/[id]/components/question_view/consumer_question_view/consumer_date_group_chart.tsx:
- Around line 10-12: The date-group switcher in consumer_date_group_chart.tsx
should only show Distributions when there is at least one subquestion with
distribution data. Add a canShowDistributions predicate derived from
post.group_of_questions.questions, and use it to gate both the early return and
the GroupChartViewTabs rendering in consumer_date_group_chart. Keep the fallback
behavior aligned with GroupDistributionsView so empty/new date groups do not
expose a blank Distributions state.
In
`@front_end/src/app/`(main)/questions/[id]/components/question_view/consumer_question_view/consumer_group_chart.tsx:
- Around line 56-67: Prevent switching into distributions mode when no visible
question can render a distribution. In consumer_group_chart.tsx, add a shared
hasSubquestionDistribution(...) check over visibleQuestions ??
post.group_of_questions.questions and use it to gate both the
GroupDistributionsView branch and the GroupChartViewTabs toggle logic in
consumer_question_view/consumer_group_chart.tsx so viewMode only enters
"distributions" when at least one row is eligible.
In
`@front_end/src/app/`(main)/questions/[id]/components/question_view/consumer_question_view/group_distributions_view.tsx:
- Around line 77-93: The distributions view can enter a blank state when no
visible subquestion passes hasSubquestionDistribution because defaultSelectedId
stays null. Add the same zero-selectable guard used by DistributionsTab in
group_distributions_view before rendering the desktop/fan-chart distributions
mode, and fall back out of distributions mode (or return null) when
selectableIds is empty so the component does not render only the header and
empty chart area.
In
`@front_end/src/app/`(main)/questions/[id]/components/question_view/consumer_question_view/pdf_cdf_tabs.tsx:
- Around line 62-67: The tooltip text in PdfCdfTabs is hardcoded English, so it
should be moved to i18n strings and fetched via useTranslations like the
existing button labels. Update the tooltipContent logic in
consumer_question_view/pdf_cdf_tabs.tsx to use translation keys instead of
inline PMF/PDF/CDF sentences, preserving the questionType-specific wording
through translated variants. Keep the change localized to the PdfCdfTabs
component and reference the existing t usage as the pattern for the new tooltip
strings.
In `@front_end/src/components/charts/continuous_area_chart.tsx`:
- Around line 572-574: The edge-hover cursor in continuous_area_chart.tsx is
still using the old hardcoded orange/olive color mapping even though the main
series now respects colorOverride. Update the cursorEdge-related
LineCursorPoints logic so it uses the same colorOverride-driven color selection
as the series, especially in distributions mode. Make the fix in the cursor
rendering branches that create the left/right edge markers and ensure the
selected row color is preserved instead of falling back to the default palette.
In
`@front_end/src/components/consumer_post_card/group_forecast_card/forecast_choice_bar.tsx`:
- Around line 78-91: The click target in forecast_choice_bar is still rendered
as a plain div even when onClick is present, so it lacks button semantics and
keyboard activation. Update the wrapper in ForecastChoiceBar to use a button
element when it acts as an action, or add the equivalent role, tabIndex, and
Enter/Space key handling alongside the existing
onClick/onMouseEnter/onMouseLeave behavior. Keep the current styling and
activeGlowStyle logic intact while ensuring the interactive row is accessible.
In `@front_end/src/components/consumer_post_card/time_series_chart/index.tsx`:
- Around line 146-161: The selected highlight color is computed independently
from the bar fill logic, so resolved bars can highlight with the wrong color.
Update the selection path in time_series_chart to reuse the same color-selection
helper used by the bar renderer (the logic that decides the fill for each datum,
including resolved/purple cases), and apply it when computing selectedBarColor
from selectedDatum/selectedIndex so both paths stay in sync.
---
Outside diff comments:
In `@front_end/src/components/consumer_post_card/time_series_chart/index.tsx`:
- Around line 270-294: The click handler on TimeSeriesChart is bound to the
outer wrapper, so clicks outside the plotted area can still select a datum via
closestIndexFromEvent(). Update handleClick/onClick so selection only happens
within the chart surface used for bars, or add a Y-bounds guard before calling
onBarClick; use the existing TimeSeriesChart, handleClick, and
closestIndexFromEvent symbols to keep the fix localized.
---
Nitpick comments:
In
`@front_end/src/app/`(main)/questions/[id]/components/question_view/consumer_question_view/group_distribution_utils.ts:
- Around line 52-56: hasSubquestionDistribution is doing unnecessary work by
calling getSubquestionDistributionData just to test whether any distribution
exists. Update hasSubquestionDistribution to perform the same eligibility checks
directly using the existing question state checks from
getSubquestionDistributionData, and avoid constructing the full distribution
data or calling cdfToPmf unless the data is actually needed. Keep the logic
aligned with the current behavior in group_distribution_utils.ts so
GroupDistributionsView and similar callers still get the same true/false result.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 1db09ec9-6064-48e4-b011-73b1aded4a4d
📒 Files selected for processing (28)
front_end/messages/cs.jsonfront_end/messages/en.jsonfront_end/messages/es.jsonfront_end/messages/pt.jsonfront_end/messages/zh-TW.jsonfront_end/messages/zh.jsonfront_end/src/app/(main)/questions/[id]/components/group_timeline.tsxfront_end/src/app/(main)/questions/[id]/components/multiple_choices_chart_view/index.tsxfront_end/src/app/(main)/questions/[id]/components/question_page_shell/index.tsxfront_end/src/app/(main)/questions/[id]/components/question_page_shell/tab_bar.tsxfront_end/src/app/(main)/questions/[id]/components/question_page_shell/tabs.tsxfront_end/src/app/(main)/questions/[id]/components/question_page_shell/tabs/distributions.tsxfront_end/src/app/(main)/questions/[id]/components/question_page_shell/tabs/timeline.tsxfront_end/src/app/(main)/questions/[id]/components/question_view/consumer_question_view/consumer_date_group_chart.tsxfront_end/src/app/(main)/questions/[id]/components/question_view/consumer_question_view/consumer_group_chart.tsxfront_end/src/app/(main)/questions/[id]/components/question_view/consumer_question_view/consumer_list_chart_shell.tsxfront_end/src/app/(main)/questions/[id]/components/question_view/consumer_question_view/consumer_time_series_pane.tsxfront_end/src/app/(main)/questions/[id]/components/question_view/consumer_question_view/fan_graph_chart_panel.tsxfront_end/src/app/(main)/questions/[id]/components/question_view/consumer_question_view/group_chart_view_tabs.tsxfront_end/src/app/(main)/questions/[id]/components/question_view/consumer_question_view/group_distribution_utils.tsfront_end/src/app/(main)/questions/[id]/components/question_view/consumer_question_view/group_distributions_view.tsxfront_end/src/app/(main)/questions/[id]/components/question_view/consumer_question_view/pdf_cdf_tabs.tsxfront_end/src/components/charts/continuous_area_chart.tsxfront_end/src/components/charts/primitives/chart_container.tsxfront_end/src/components/charts/primitives/line_cursor_points.tsxfront_end/src/components/consumer_post_card/group_forecast_card/forecast_choice_bar.tsxfront_end/src/components/consumer_post_card/group_forecast_card/numeric_forecast_card.tsxfront_end/src/components/consumer_post_card/time_series_chart/index.tsx
…ew fixes - Only expose Distributions for continuous groups (Numeric/Discrete/Date) that have distribution data, via a new hasGroupDistributions() helper. Fixes binary fan-graph groups (e.g. #39796) that wrongly showed a blank Distributions view, and empty/new groups showing a blank tab/state (code-review CR1-CR4). getSubquestionDistributionData now short-circuits for non-continuous subquestions so the gating is safe on binary groups. - Quartile hover chips now show a one-word explainer above the value chip (25TH % / MEDIAN / 75TH %) in a 50%-black rounded pill, in the subquestion color. - The distribution x-axis baseline is always grayscale (no longer tied to subquestion color/state). - Code review: PdfCdfTabs tooltip moved to i18n (CR5); edge-hover cursor now honors colorOverride (CR6); clickable rows get button role/tabindex/keyboard activation (CR7); time-series selected-bar highlight color reuses the bar fill logic so resolved/closed bars match (CR8). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Drop the 50%-black rounded container behind the quartile explainer labels (MEDIAN / 25TH % / 75TH %) and render them as plain gray-700 text (gray-700-dark in dark mode). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…istributions # Conflicts: # front_end/src/app/(main)/questions/[id]/components/question_page_shell/index.tsx # front_end/src/app/(main)/questions/[id]/components/question_view/consumer_question_view/consumer_group_chart.tsx # front_end/src/app/(main)/questions/[id]/components/question_view/consumer_question_view/fan_graph_chart_panel.tsx # front_end/src/components/charts/primitives/chart_container.tsx
These files (.claude/launch.json, .design-sync/*, design-prompt-mobile-consumer.md, lightweight-accounts-spec.md) and the .gitignore edits were accidentally swept into 858d221 by a git add -A; they are unrelated to the Distributions feature. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…DF tooltips, unclip fan tooltip - Hide the 'Forecast Timeline' chart title whenever a tab switcher is present (fan-panel overlay or inline Timeline/Distributions), in both consumer and forecaster mode, via a threaded hideChartTitle flag. - Show the MC-style predictions tooltip on the group timeline hover by dropping hideTooltip in ConsumerGroupChart. - Add a right-aligned question-mark PDF/CDF explainer tooltip to the mobile Distributions tab, reusing the desktop pattern. - Clamp the fan-chart tooltip within #fan-graph-container so an edge-aligned tooltip isn't cut off by the section's overflow-x-clip. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
🧹 Nitpick comments (1)
front_end/src/app/(main)/questions/[id]/components/multiple_choices_chart_view/index.tsx (1)
312-324: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
headerLeftis silently dropped in the binary and MC branches whenwithLegendis false.The non-MC branch (Line 374) correctly passes through the
headerLeftprop whenwithLegendis false, but the binary branch (Line 324) and MC branch (Line 344) both fall back toundefined. SinceGroupTimelineforwardsheaderLeftunconditionally, the prop is silently ignored for MC/binary question types withwithLegend={false}.This doesn't affect the current feature (continuous groups only hit the non-MC branch), but it's a latent inconsistency that could cause confusion if
headerLeftis later used with MC or binary charts.♻️ Proposed fix: pass through `headerLeft` in all branches
// Binary branch (lines 323-324) - ) : undefined + ) : ( + headerLeft + ) } forceShowLinePoints={!embedMode} /> // MC branch (lines 344-345) - ) : undefined + ) : ( + headerLeft + ) } />Also applies to: 333-345
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@front_end/src/app/`(main)/questions/[id]/components/multiple_choices_chart_view/index.tsx around lines 312 - 324, Update the binary and multiple-choice branches in the chart component so their headerLeft expressions preserve and forward the incoming headerLeft prop when withLegend is false, matching the existing non-MC branch behavior. Keep the CompactLegendBar rendering unchanged when withLegend is true.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In
`@front_end/src/app/`(main)/questions/[id]/components/multiple_choices_chart_view/index.tsx:
- Around line 312-324: Update the binary and multiple-choice branches in the
chart component so their headerLeft expressions preserve and forward the
incoming headerLeft prop when withLegend is false, matching the existing non-MC
branch behavior. Keep the CompactLegendBar rendering unchanged when withLegend
is true.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: bf4ab4b9-b440-481a-b662-05a79487b9b6
📒 Files selected for processing (5)
front_end/src/app/(main)/questions/[id]/components/group_timeline.tsxfront_end/src/app/(main)/questions/[id]/components/multiple_choices_chart_view/index.tsxfront_end/src/app/(main)/questions/[id]/components/question_page_shell/tabs/distributions.tsxfront_end/src/app/(main)/questions/[id]/components/question_view/consumer_question_view/consumer_group_chart.tsxfront_end/src/components/charts/primitives/chart_fan_tooltip.tsx
🚧 Files skipped from review as they are similar to previous changes (3)
- front_end/src/app/(main)/questions/[id]/components/group_timeline.tsx
- front_end/src/app/(main)/questions/[id]/components/question_view/consumer_question_view/consumer_group_chart.tsx
- front_end/src/app/(main)/questions/[id]/components/question_page_shell/tabs/distributions.tsx
…end is false Makes the three MultiChoicesChartView chart branches symmetric with the non-MC branch, which already forwards the incoming headerLeft. No behavior change today (those branches only run for MC-typed questions, which never receive a headerLeft), but future-proofs against a switcher being routed into an MC group timeline. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>


Closes #4765
What & why
On Consumer View question pages, continuous Question Group posts (Numeric, Discrete, Date) previously showed only the aggregated time-series of medians — there was no way to see an individual subquestion's full probability distribution.
This PR adds a Timeline / Distributions toggle (mirroring the Binary Timeline/Histogram pattern). In Distributions mode one subquestion is always selected and its community distribution renders in the chart area, in that row's color, display-only (no user prediction), with a PDF/CDF toggle. On mobile it's a dedicated Distributions tab; the mobile Timeline tab also gains the timeframe selector it was missing.
Demo
dist.mp4
Behavior
Desktop
?tooltip) replaces the timeframe selector in this mode.Mobile
md).Hidden CP: when the community prediction is hidden / not yet revealed, the switcher and distributions are suppressed and the existing Reveal-CP behavior is kept.
Implementation notes
viewMode,selectedQuestionId,graphType) lives in the existingListChartExpandedContextshared between the left list and the right chart.ContinuousAreaChartfor rendering. New, opt-in props keep other call-sites (prediction inputs, feed tiles) unchanged:colorOverride— render the curve/line/quartiles/cursor in an arbitrary color.cursorQuartileTooltip— the quartile value-chip-on-hover behavior.alignChartTabs(already existed) is now passed here so PDF and CDF stay aligned, matching the prediction input.ContinuousAreaChartthat also benefit prediction inputs: CDF area now extends to the full plot width like the PDF, and the stray asymmetric bound line no longer renders without a global scale.group_distributions_view.tsx,group_chart_view_tabs.tsx,pdf_cdf_tabs.tsx,consumer_date_group_chart.tsx,group_distribution_utils.ts, and the mobiletabs/distributions.tsx.distributionskey to all six message files.Scope / follow-ups
distributionswas added toen/es/cs/pt/zh/zh-TW.Testing
bun run lint(types + JS) andbun run formatclean on all changed files;bun run buildpasses.react-hooks/refslint error insrc/hooks/use_previous.tsonmain, untouched here.)Summary by CodeRabbit
New Features
Bug Fixes
Documentation