Files
deepseek-harness/packages/client/ui-chat/src/client/settings/TranscriptViewRow.tsx
T
lsdsjyandYif 8b09a0be52 feat(ui-conversation): fold turn process before final answer (#2547)
* feat(ui-conversation): fold turn process before final answer

* fix(ui-chat): polish turn-process control row from review

* test(web): drive preset slash catalog with gestures

* fix(ui-chat): keep turn process order stable

* fix(ui-chat): preserve prompt order after pagination

Co-authored-by: Yif <877193178@qq.com>
2026-08-27 10:12:39 +00:00

80 lines
2.6 KiB
TypeScript

/** General Settings row for completed-Turn transcript presentation. */
import { useState } from 'react'
import type { SnapshotStore } from '@deepseek-ai/dsh-client-store'
import { IconChevronDownOutline14, Menu } from '@deepseek-ai/dsh-client-ui-primitives'
import type { InjectFace, PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'
import type { TranscriptViewMode } from '../../chat-settings.ts'
import type { ChatKey } from '../locale.ts'
import css from './TranscriptViewRow.module.css'
/** Registration-side transcript preference face. */
export interface TranscriptViewRowInjected {
hooks: {
/** Persisted transcript preference bound as useTranscriptView. */
transcriptView: SnapshotStore<TranscriptViewMode>
}
/** Change the completed-Turn transcript presentation. */
setTranscriptView: (mode: TranscriptViewMode) => void
}
/** Full Settings-row props. */
export type TranscriptViewRowProps =
PropsRuntime<'settings.general.item'>
& PropsLocale<'chat'>
& InjectFace<TranscriptViewRowInjected>
const OPTIONS: readonly { id: TranscriptViewMode; label: ChatKey }[] = [
{ id: 'normal', label: 'settings.transcript.normal' },
{ id: 'compact', label: 'settings.transcript.compact' },
]
/**
* Render the completed-Turn transcript mode selector.
* @param props - composed Settings slot props.
* @returns the preference row.
*/
export function TranscriptViewRow({ useTranscriptView, setTranscriptView, t }: TranscriptViewRowProps) {
const mode = useTranscriptView(value => value)
const [open, setOpen] = useState(false)
const selectedLabel = mode === 'normal'
? 'settings.transcript.normal'
: 'settings.transcript.compact'
const closeMenu = () => { setOpen(false) }
const selectMode = (id: string) => {
closeMenu()
setTranscriptView(id as TranscriptViewMode)
}
const selector = (
<button
type="button"
className={css.selector}
aria-haspopup="menu"
aria-expanded={open}
onClick={() => { setOpen(value => !value) }}
>
{t(selectedLabel)}
<IconChevronDownOutline14 className={css.chevron} />
</button>
)
return (
<div className={css.row}>
<div className={css.rowText}>
<div className={css.title}>{t('settings.transcript.title')}</div>
<div className={css.desc}>{t('settings.transcript.description')}</div>
</div>
<Menu
open={open}
onClose={closeMenu}
items={OPTIONS.map(option => ({ id: option.id, label: t(option.label) }))}
selectedId={mode}
onSelect={selectMode}
align="end"
portal
anchor={selector}
/>
</div>
)
}