feat(settings): ✨ Enhance SettingsPanel UI with new configuration options and improved layout
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
parent
757d04828b
commit
e5a818de87
1 changed files with 85 additions and 1 deletions
|
|
@ -1,4 +1,4 @@
|
|||
import { useCallback } from 'react';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import type { ReactElement } from 'react';
|
||||
import styled from '@lilith/ui-styled-components';
|
||||
import { Tooltip } from '@lilith/ui-feedback';
|
||||
|
|
@ -6,6 +6,12 @@ import { AnimatePresence, motion } from '@lilith/ui-motion';
|
|||
import type { VoiceSessionState } from '../voice/VoiceSession';
|
||||
import type { Settings, SettingsActions } from './useSettings';
|
||||
|
||||
interface PersonaOption {
|
||||
id: string;
|
||||
slug: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface SettingsPanelProps {
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
|
|
@ -13,6 +19,9 @@ export interface SettingsPanelProps {
|
|||
connectionState: VoiceSessionState | 'disconnected';
|
||||
settings: Settings;
|
||||
onSettings: SettingsActions;
|
||||
apiBaseUrl: string;
|
||||
currentPersonaId: string;
|
||||
onPersonaChange: (personaId: string) => void;
|
||||
}
|
||||
|
||||
const Overlay = styled(motion.div)`
|
||||
|
|
@ -203,6 +212,41 @@ const VolumeLabel = styled.span`
|
|||
text-align: right;
|
||||
`;
|
||||
|
||||
const PersonaGrid = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
padding: 8px 20px 12px;
|
||||
`;
|
||||
|
||||
const PersonaButton = styled.button<{ $active: boolean }>`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
padding: 10px 14px;
|
||||
border-radius: 10px;
|
||||
border: 1px solid ${({ $active }) => ($active ? '#553c9a' : '#2d3748')};
|
||||
background: ${({ $active }) => ($active ? 'rgba(85,60,154,0.15)' : 'transparent')};
|
||||
color: ${({ $active }) => ($active ? '#e2e8f0' : '#a0aec0')};
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
text-align: left;
|
||||
width: 100%;
|
||||
transition: border-color 150ms ease, background 150ms ease;
|
||||
|
||||
&:active {
|
||||
background: rgba(85,60,154,0.25);
|
||||
}
|
||||
`;
|
||||
|
||||
const PersonaActiveDot = styled.span<{ $active: boolean }>`
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
background: ${({ $active }) => ($active ? '#553c9a' : '#2d3748')};
|
||||
flex-shrink: 0;
|
||||
`;
|
||||
|
||||
function Toggle({ on, onChange, label }: { on: boolean; onChange: (v: boolean) => void; label: string }): ReactElement {
|
||||
return (
|
||||
<ToggleTrack
|
||||
|
|
@ -224,7 +268,26 @@ export function SettingsPanel({
|
|||
connectionState,
|
||||
settings,
|
||||
onSettings,
|
||||
apiBaseUrl,
|
||||
currentPersonaId,
|
||||
onPersonaChange,
|
||||
}: SettingsPanelProps): ReactElement {
|
||||
const [personas, setPersonas] = useState<PersonaOption[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!open) return;
|
||||
fetch(`${apiBaseUrl}/personalities`)
|
||||
.then((r) => r.json() as Promise<PersonaOption[]>)
|
||||
.then(setPersonas)
|
||||
.catch(() => {/* non-fatal */});
|
||||
}, [open, apiBaseUrl]);
|
||||
|
||||
const handlePersonaChange = useCallback((id: string) => {
|
||||
if (id === currentPersonaId) return;
|
||||
onPersonaChange(id);
|
||||
onClose();
|
||||
}, [currentPersonaId, onPersonaChange, onClose]);
|
||||
|
||||
const handleCopySession = useCallback(() => {
|
||||
void navigator.clipboard.writeText(sessionId);
|
||||
}, [sessionId]);
|
||||
|
|
@ -253,6 +316,27 @@ export function SettingsPanel({
|
|||
>
|
||||
<Handle />
|
||||
|
||||
{personas.length > 0 && (
|
||||
<Section>
|
||||
<SectionTitle>Personality</SectionTitle>
|
||||
<PersonaGrid>
|
||||
{personas.map((p) => {
|
||||
const isActive = p.id === currentPersonaId || p.slug === currentPersonaId;
|
||||
return (
|
||||
<PersonaButton
|
||||
key={p.id}
|
||||
$active={isActive}
|
||||
onClick={() => handlePersonaChange(p.id)}
|
||||
>
|
||||
<PersonaActiveDot $active={isActive} />
|
||||
{p.name}
|
||||
</PersonaButton>
|
||||
);
|
||||
})}
|
||||
</PersonaGrid>
|
||||
</Section>
|
||||
)}
|
||||
|
||||
<Section>
|
||||
<SectionTitle>Voice Output (TTS)</SectionTitle>
|
||||
<Row>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue