feat: Added personality weight slider (0.0–1.0) to ChatWidget header an…

- "frontend/src/api/chat.ts"
- "frontend/src/components/ChatWidget.tsx"
- "frontend/src/components/ChatWidget.module.css"

GSD-Task: S02/T02
This commit is contained in:
jlightner 2026-04-04 09:30:56 +00:00
parent 0856827b59
commit e9ab6bd9a7
3 changed files with 83 additions and 1 deletions

View file

@ -42,6 +42,7 @@ export function streamChat(
callbacks: ChatCallbacks,
creator?: string,
conversationId?: string,
personalityWeight?: number,
): AbortController {
const controller = new AbortController();
@ -67,6 +68,7 @@ export function streamChat(
query,
creator: creator ?? null,
conversation_id: conversationId ?? null,
personality_weight: personalityWeight ?? 0,
}),
signal: controller.signal,
})

View file

@ -67,6 +67,68 @@
flex-shrink: 0;
}
/* ── Personality slider ───────────────────────────────────── */
.sliderRow {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.5rem 1rem;
border-bottom: 1px solid var(--color-border);
flex-shrink: 0;
}
.sliderLabel {
font-size: 0.6875rem;
color: var(--color-text-secondary);
white-space: nowrap;
user-select: none;
}
.slider {
flex: 1;
-webkit-appearance: none;
appearance: none;
height: 4px;
border-radius: 2px;
background: var(--color-border);
outline: none;
cursor: pointer;
}
.slider::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 14px;
height: 14px;
border-radius: 50%;
background: var(--color-accent);
border: 2px solid var(--color-bg-surface);
box-shadow: 0 1px 4px var(--color-shadow-heavy);
cursor: pointer;
transition: transform 0.1s;
}
.slider::-webkit-slider-thumb:hover {
transform: scale(1.15);
}
.slider::-moz-range-thumb {
width: 14px;
height: 14px;
border-radius: 50%;
background: var(--color-accent);
border: 2px solid var(--color-bg-surface);
box-shadow: 0 1px 4px var(--color-shadow-heavy);
cursor: pointer;
}
.slider::-moz-range-track {
height: 4px;
border-radius: 2px;
background: var(--color-border);
}
.headerTitle {
font-size: 0.875rem;
font-weight: 600;

View file

@ -121,6 +121,7 @@ export default function ChatWidget({ creatorName, techniques }: ChatWidgetProps)
const [input, setInput] = useState("");
const [streaming, setStreaming] = useState(false);
const [conversationId, setConversationId] = useState<string | undefined>(undefined);
const [personalityWeight, setPersonalityWeight] = useState(0);
const abortRef = useRef<AbortController | null>(null);
const messagesEndRef = useRef<HTMLDivElement>(null);
@ -224,9 +225,10 @@ export default function ChatWidget({ creatorName, techniques }: ChatWidgetProps)
},
creatorName,
cid,
personalityWeight,
);
},
[messages, streaming, creatorName, conversationId],
[messages, streaming, creatorName, conversationId, personalityWeight],
);
const handleSubmit = (e: React.FormEvent) => {
@ -272,6 +274,22 @@ export default function ChatWidget({ creatorName, techniques }: ChatWidgetProps)
</button>
</div>
{/* Personality slider */}
<div className={styles.sliderRow}>
<span className={styles.sliderLabel}>Encyclopedic</span>
<input
type="range"
className={styles.slider}
min={0}
max={1}
step={0.1}
value={personalityWeight}
onChange={(e) => setPersonalityWeight(parseFloat(e.target.value))}
aria-label="Personality weight"
/>
<span className={styles.sliderLabel}>Creator Voice</span>
</div>
{/* Messages */}
<div className={styles.messages}>
{showSuggestions && (