Skip to content

Embeds: show continuous chart side-by-side with CP value#4388

Open
ncarazon wants to merge 1 commit intomainfrom
feat/embeds-continuous-chart-update
Open

Embeds: show continuous chart side-by-side with CP value#4388
ncarazon wants to merge 1 commit intomainfrom
feat/embeds-continuous-chart-update

Conversation

@ncarazon
Copy link
Contributor

@ncarazon ncarazon commented Feb 18, 2026

This PR updates the embed view for continuous questions to display the minified chart side-by-side with the community prediction value, instead of using an overlay layout.

Before:

image

After:

image

Summary by CodeRabbit

  • Bug Fixes

    • Fixed CPStatus component visibility for continuous question types
  • Improvements

    • Enhanced responsive design for embedded questions across varying screen widths
    • Optimized chart heights and typography sizing for embedded displays
    • Improved spacing and layout consistency in embedded question views

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 18, 2026

Warning

Rate limit exceeded

@ncarazon has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 15 minutes and 58 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📝 Walkthrough

Walkthrough

This PR enhances embed mode responsiveness across multiple question and chart components by introducing width-aware logic. It adds detection for "wide" embeds (≥500px), conditionally adjusts responsive styling and chart heights based on embed width thresholds, and refines conditional rendering for continuous question headers in embed contexts.

Changes

Cohort / File(s) Summary
Embed Question Header
front_end/src/app/(embed)/questions/components/embed_question_header.tsx
Modifies conditional rendering to skip QuestionHeaderCPStatus component for continuous question types in embed mode.
Forecaster Question View Headers
front_end/src/app/(main)/questions/[id]/components/question_view/forecaster_question_view/question_header/question_header_continuous_resolution_chip.tsx, ...question_header_cp_status.tsx
Introduces embed width detection (useEmbedContainerWidth) and adds responsive styling/height logic based on embed width thresholds (376px, 500px). Adjusts chart heights and max-width constraints for embedded layouts.
Chart and Card Components
front_end/src/components/detailed_question_card/detailed_question_card/continuous_chart_card.tsx, front_end/src/components/post_card/question_tile/continuous_cp_bar.tsx
Updates OverlayableTimeline internal structure with separate overlay and timeline containers; adds isEmbedWide logic to determine unit display and interval label typography in embed mode.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • elisescu
  • lsabor
  • hlbmtc
  • cemreinanc

Poem

🐰 Embeds grow wise with responsive care,
Width thresholds detected here and there,
At 376 and 500 pixels wide,
Charts adjust with thoughtful pride—
Flexible layouts hop with grace! 🌿

🚥 Pre-merge checks | ✅ 2
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately describes the main change: updating embeds to display continuous charts side-by-side with CP values, which is reflected across multiple file changes in the changeset.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/embeds-continuous-chart-update

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

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/app/(embed)/questions/components/embed_question_header.tsx (1)

129-138: ⚠️ Potential issue | 🟡 Minor

hideLabel prop is always false here — dead code

The outer guard !isContinuousQuestion(post.question) already ensures this branch is never reached for continuous questions, so isContinuousQuestion(post.question) is always false and hideLabel is always false. The prop is either left over from before the guard was added or is a copy-paste of earlier logic. Since hideLabel defaults to false, it can simply be removed.

🧹 Proposed cleanup
 {isQuestionPost(post) && !isContinuousQuestion(post.question) && (
   <div className="[`@container`(max-width:375px)]:hidden">
     <QuestionHeaderCPStatus
       question={post.question as QuestionWithForecasts}
       size="md"
-      hideLabel={isContinuousQuestion(post.question)}
       colorOverride={predictionColor}
       chartTheme={theme?.chart}
     />
   </div>
 )}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@front_end/src/app/`(embed)/questions/components/embed_question_header.tsx
around lines 129 - 138, The hideLabel prop passed to QuestionHeaderCPStatus is
dead code because the surrounding conditional already excludes continuous
questions; remove the hideLabel={isContinuousQuestion(post.question)} attribute
from the JSX branch that renders QuestionHeaderCPStatus (the component rendered
when isQuestionPost(post) && !isContinuousQuestion(post.question)) so the
component relies on its default hideLabel behavior instead.
🧹 Nitpick comments (2)
front_end/src/app/(main)/questions/[id]/components/question_view/forecaster_question_view/question_header/question_header_cp_status.tsx (2)

158-168: Consider extracting the nested height ternary to a named constant

The three-level nested ternary is functional but dense. A named variable makes the intent immediately readable.

♻️ Optional refactor
+const chartHeight =
+  hideLabel && size === "lg"
+    ? 120
+    : isEmbedBelow376
+      ? 32
+      : isEmbedWide
+        ? 90
+        : 50;
+
 <MinifiedContinuousAreaChart
   question={question}
   data={continuousAreaChartData}
-  height={
-    hideLabel && size === "lg"
-      ? 120
-      : isEmbed
-        ? isEmbedBelow376
-          ? 32
-          : isEmbedWide
-            ? 90
-            : 50
-        : 50
-  }
+  height={chartHeight}

Note: the refactored version also drops the redundant outer isEmbed check — when not in embed mode, isEmbedBelow376 and isEmbedWide are both false, so the nested ternary already falls through to 50, which is the same as the current : 50 fallback.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@front_end/src/app/`(main)/questions/[id]/components/question_view/forecaster_question_view/question_header/question_header_cp_status.tsx
around lines 158 - 168, Extract the nested three-level ternary used for the
height prop into a named constant (e.g., const computedHeight) and use that
constant in place of the inline ternary; compute computedHeight from the
existing identifiers hideLabel, size, isEmbed, isEmbedBelow376, and isEmbedWide
and simplify by removing the redundant outer isEmbed branch since
isEmbedBelow376/isEmbedWide will be false when not embedded, preserving the same
fallbacks (120, 32, 90, 50) and improving readability in the
QuestionHeaderCPStatus component where the height prop is set.

109-116: max-w-[130px] and max-w-[195px] conflict when size === "md" && isEmbedWide

When size === "md" and isEmbedWide are both true, both max-w-[130px] (line 109 – triggered by size === "md") and max-w-[195px] (line 116 – triggered by isEmbedWide) are emitted into the class string simultaneously. The correct value (max-w-[195px]) only wins because cn uses tailwind-merge to resolve the conflict. Making the first condition explicitly exclude isEmbedWide removes the implicit dependency:

🛡️ Proposed fix to make the intent explicit
- "max-w-[130px]":
-   size === "md" || (isEmbed && !isEmbedBelow376 && !isEmbedWide),
+ "max-w-[130px]":
+   (size === "md" && !isEmbedWide) || (isEmbed && !isEmbedBelow376 && !isEmbedWide),
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@front_end/src/app/`(main)/questions/[id]/components/question_view/forecaster_question_view/question_header/question_header_cp_status.tsx
around lines 109 - 116, The "max-w-[130px]" class condition currently triggers
for size === "md" even when isEmbedWide is true, causing a conflicting max-w
with "max-w-[195px]"; update the predicate for the "max-w-[130px]" entry in
question_header_cp_status.tsx so it explicitly excludes isEmbedWide (e.g., make
the condition require size === "md" && !isEmbedWide (and keep the existing
isEmbed branch), referencing the variables size, isEmbed, isEmbedBelow376, and
isEmbedWide used in that class list) so only the intended max-w is emitted and
tailwind-merge no longer has to resolve the conflict.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@front_end/src/components/detailed_question_card/detailed_question_card/continuous_chart_card.tsx`:
- Around line 324-344: The parent wrapper for the OverlayableTimeline's
responsive container queries is missing the Tailwind container marker so the
@[23.5rem]: variants never activate; add the `@container` class to the closest
parent div that currently has className="@[23.5rem]:items-center
@[23.5rem]:gap-3 group relative flex" (the wrapper around overlay and timeline)
so the @[23.5rem]: rules take effect, and apply the same `@container` addition to
the sibling parent wrappers where similar @[23.5rem]: queries appear (the other
divs at the same block using cn(...) for overlay and timeline); ensure the
`@container` is present on the nearest ancestor of OverlayableTimeline so the
wide-mode layout can render.

---

Outside diff comments:
In `@front_end/src/app/`(embed)/questions/components/embed_question_header.tsx:
- Around line 129-138: The hideLabel prop passed to QuestionHeaderCPStatus is
dead code because the surrounding conditional already excludes continuous
questions; remove the hideLabel={isContinuousQuestion(post.question)} attribute
from the JSX branch that renders QuestionHeaderCPStatus (the component rendered
when isQuestionPost(post) && !isContinuousQuestion(post.question)) so the
component relies on its default hideLabel behavior instead.

---

Nitpick comments:
In
`@front_end/src/app/`(main)/questions/[id]/components/question_view/forecaster_question_view/question_header/question_header_cp_status.tsx:
- Around line 158-168: Extract the nested three-level ternary used for the
height prop into a named constant (e.g., const computedHeight) and use that
constant in place of the inline ternary; compute computedHeight from the
existing identifiers hideLabel, size, isEmbed, isEmbedBelow376, and isEmbedWide
and simplify by removing the redundant outer isEmbed branch since
isEmbedBelow376/isEmbedWide will be false when not embedded, preserving the same
fallbacks (120, 32, 90, 50) and improving readability in the
QuestionHeaderCPStatus component where the height prop is set.
- Around line 109-116: The "max-w-[130px]" class condition currently triggers
for size === "md" even when isEmbedWide is true, causing a conflicting max-w
with "max-w-[195px]"; update the predicate for the "max-w-[130px]" entry in
question_header_cp_status.tsx so it explicitly excludes isEmbedWide (e.g., make
the condition require size === "md" && !isEmbedWide (and keep the existing
isEmbed branch), referencing the variables size, isEmbed, isEmbedBelow376, and
isEmbedWide used in that class list) so only the intended max-w is emitted and
tailwind-merge no longer has to resolve the conflict.

@github-actions
Copy link
Contributor

🚀 Preview Environment

Your preview environment is ready!

Resource Details
🌐 Preview URL https://metaculus-pr-4388-feat-embeds-continuous-chart-u-preview.mtcl.cc
📦 Docker Image ghcr.io/metaculus/metaculus:feat-embeds-continuous-chart-update-a083d1f
🗄️ PostgreSQL NeonDB branch preview/pr-4388-feat-embeds-continuous-chart-u
Redis Fly Redis mtc-redis-pr-4388-feat-embeds-continuous-chart-u

Details

  • Commit: e835865c896e80e7222fc525f2dfd56f9c73855a
  • Branch: feat/embeds-continuous-chart-update
  • Fly App: metaculus-pr-4388-feat-embeds-continuous-chart-u

ℹ️ Preview Environment Info

Isolation:

  • PostgreSQL and Redis are fully isolated from production
  • Each PR gets its own database branch and Redis instance
  • Changes pushed to this PR will trigger a new deployment

Limitations:

  • Background workers and cron jobs are not deployed in preview environments
  • If you need to test background jobs, use Heroku staging environments

Cleanup:

  • This preview will be automatically destroyed when the PR is closed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

Comments