diff --git a/src/components/ui/typography.tsx b/src/components/ui/typography.tsx index 69fdddbe4..7f1b52353 100644 --- a/src/components/ui/typography.tsx +++ b/src/components/ui/typography.tsx @@ -49,7 +49,7 @@ const textVariants = cva("", { }, }); -interface TextProps +export interface TextProps extends PropsWithChildren, VariantProps { /** * The role of the text element. diff --git a/src/routes/tangent/components/OpportunityScoreRing.tsx b/src/routes/tangent/components/OpportunityScoreRing.tsx index 616c2885b..ee9925bff 100644 --- a/src/routes/tangent/components/OpportunityScoreRing.tsx +++ b/src/routes/tangent/components/OpportunityScoreRing.tsx @@ -3,7 +3,7 @@ import { TooltipContent, TooltipTrigger, } from "@/components/ui/tooltip"; -import { Text } from "@/components/ui/typography"; +import { Text, type TextProps } from "@/components/ui/typography"; import { cn } from "@/lib/utils"; import { getScoreColorClass, @@ -14,6 +14,8 @@ interface OpportunityScoreRingProps { score: number | null; /** Pixel diameter of the ring. */ size?: number; + strokeWidth?: number; + labelTextSize?: TextProps["size"]; /** Show the "Opportunity" label beneath the ring. */ showLabel?: boolean; } @@ -23,9 +25,11 @@ const STROKE_WIDTH = 6; export function OpportunityScoreRing({ score, size = 64, + strokeWidth = STROKE_WIDTH, + labelTextSize = "md", showLabel = false, }: OpportunityScoreRingProps) { - const radius = (size - STROKE_WIDTH) / 2; + const radius = (size - strokeWidth) / 2; const circumference = 2 * Math.PI * radius; const progress = score === null ? 0 : Math.max(0, Math.min(100, score)) / 100; const dashOffset = circumference * (1 - progress); @@ -73,7 +77,7 @@ export function OpportunityScoreRing({ )} diff --git a/src/routes/v2/shared/components/AiChat/components/TangentScenario.tsx b/src/routes/v2/shared/components/AiChat/components/TangentScenario.tsx index 19f2b9135..8cacb8528 100644 --- a/src/routes/v2/shared/components/AiChat/components/TangentScenario.tsx +++ b/src/routes/v2/shared/components/AiChat/components/TangentScenario.tsx @@ -1,12 +1,11 @@ import { useState } from "react"; -import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; -import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Checkbox } from "@/components/ui/checkbox"; import { BlockStack, InlineStack } from "@/components/ui/layout"; import { Paragraph, Text } from "@/components/ui/typography"; import { useExecutionDataOptional } from "@/providers/ExecutionDataProvider"; +import { OpportunityScoreRing } from "@/routes/tangent/components/OpportunityScoreRing"; import { saveScenario, type ScenarioEntry, @@ -36,21 +35,6 @@ interface Scenario { ideas: ScenarioIdeaData[]; } -const IDEA_TYPE_LABEL: Record = { - feature_engineering: "Feature engineering", - hyperparameter_optimization: "Hyperparameter optimization", - input_data: "Input data", - model_architecture: "Model architecture", -}; - -type BadgeVariant = "default" | "secondary" | "outline"; - -const IMPACT_VARIANT: Record = { - high: "default", - medium: "secondary", - low: "outline", -}; - function isRecord(value: unknown): value is Record { return typeof value === "object" && value !== null; } @@ -95,56 +79,25 @@ function parseScenario(raw: string): Scenario | null { return { score, rationale, summary, ideas: parsedIdeas }; } -function scoreVariant(score: number): BadgeVariant { - if (score >= 70) return "default"; - if (score >= 40) return "secondary"; - return "outline"; -} - interface IdeaCardProps { idea: ScenarioIdeaData; checked: boolean; onCheckedChange: (checked: boolean) => void; } -function IdeaCard({ idea, checked, onCheckedChange }: IdeaCardProps) { +function CondensedIdeaCard({ idea, checked, onCheckedChange }: IdeaCardProps) { return ( - - - - onCheckedChange(value === true)} - aria-label={`Include idea ${idea.title}`} - className="mt-0.5" - /> - - - - {idea.title} - - - - - {IDEA_TYPE_LABEL[idea.ideaType]} - - - {idea.impact} impact - - - - - - - - {idea.evidence} - - - + + onCheckedChange(value === true)} + aria-label={`Include idea ${idea.title}`} + className="mt-0.5" + /> + + {idea.title} + + ); } @@ -212,30 +165,34 @@ export function TangentScenario({ raw }: { raw: string }) { return ( - - - {scenario.score}/100 - + Optimization potential + {scenario.rationale} - - {scenario.summary} - - {scenario.ideas.length > 0 && ( Ideas {scenario.ideas.map((idea, index) => ( -