From 8e27f994db9202b7aeef1118019d1103faa3422e Mon Sep 17 00:00:00 2001 From: jlightner Date: Sat, 4 Apr 2026 10:06:46 +0000 Subject: [PATCH] =?UTF-8?q?feat:=20Added=20getTierLabel()=20helper,=20grad?= =?UTF-8?q?ient=20track=20fill=20via=20--slider-fil=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - "frontend/src/components/ChatWidget.tsx" - "frontend/src/components/ChatWidget.module.css" GSD-Task: S04/T02 --- frontend/src/components/ChatWidget.module.css | 45 ++++++++++++++++--- frontend/src/components/ChatWidget.tsx | 42 +++++++++++------ 2 files changed, 69 insertions(+), 18 deletions(-) diff --git a/frontend/src/components/ChatWidget.module.css b/frontend/src/components/ChatWidget.module.css index 788906f..5d32aaa 100644 --- a/frontend/src/components/ChatWidget.module.css +++ b/frontend/src/components/ChatWidget.module.css @@ -69,13 +69,16 @@ /* ── Personality slider ───────────────────────────────────── */ +.sliderSection { + padding: 0.5rem 1rem; + border-bottom: 1px solid var(--color-border); + flex-shrink: 0; +} + .sliderRow { display: flex; align-items: center; gap: 0.5rem; - padding: 0.5rem 1rem; - border-bottom: 1px solid var(--color-border); - flex-shrink: 0; } .sliderLabel { @@ -91,7 +94,11 @@ appearance: none; height: 4px; border-radius: 2px; - background: var(--color-border); + background: linear-gradient( + to right, + var(--color-accent) var(--slider-fill, 0%), + var(--color-border) var(--slider-fill, 0%) + ); outline: none; cursor: pointer; } @@ -126,7 +133,35 @@ .slider::-moz-range-track { height: 4px; border-radius: 2px; - background: var(--color-border); + background: linear-gradient( + to right, + var(--color-accent) var(--slider-fill, 0%), + var(--color-border) var(--slider-fill, 0%) + ); +} + +/* ── Tier label + value ───────────────────────────────────── */ + +.tierInfo { + display: flex; + justify-content: center; + align-items: baseline; + gap: 0.375rem; + padding-top: 0.25rem; +} + +.tierLabel { + font-size: 0.6875rem; + font-weight: 600; + color: var(--color-text-secondary); + transition: color 0.2s; +} + +.tierValue { + font-size: 0.625rem; + color: var(--color-text-secondary); + opacity: 0.6; + font-variant-numeric: tabular-nums; } .headerTitle { diff --git a/frontend/src/components/ChatWidget.tsx b/frontend/src/components/ChatWidget.tsx index 65c2fc6..624c082 100644 --- a/frontend/src/components/ChatWidget.tsx +++ b/frontend/src/components/ChatWidget.tsx @@ -115,6 +115,15 @@ function parseCitations(text: string, sources: ChatSource[]): React.ReactNode[] return nodes.length > 0 ? nodes : [text]; } +/** Map personality weight to a human-readable tier label. */ +function getTierLabel(weight: number): string { + if (weight < 0.2) return "Encyclopedic"; + if (weight < 0.4) return "Subtle Reference"; + if (weight < 0.6) return "Creator Tone"; + if (weight < 0.8) return "Creator Voice"; + return "Full Embodiment"; +} + export default function ChatWidget({ creatorName, techniques }: ChatWidgetProps) { const [open, setOpen] = useState(false); const [messages, setMessages] = useState([]); @@ -275,19 +284,26 @@ export default function ChatWidget({ creatorName, techniques }: ChatWidgetProps) {/* Personality slider */} -
- Encyclopedic - setPersonalityWeight(parseFloat(e.target.value))} - aria-label="Personality weight" - /> - Creator Voice +
+
+ Encyclopedic + setPersonalityWeight(parseFloat(e.target.value))} + aria-label="Personality weight" + style={{ '--slider-fill': `${personalityWeight * 100}%` } as React.CSSProperties} + /> + Creator Voice +
+
+ {getTierLabel(personalityWeight)} + {personalityWeight.toFixed(1)} +
{/* Messages */}