mirror of
https://github.com/wu736139669/hapi.git
synced 2026-08-05 06:24:37 +00:00
fix(web): align session list status description (#1243)
This commit is contained in:
@@ -1,7 +1,14 @@
|
||||
import type { ReactNode } from 'react'
|
||||
|
||||
export function SettingsFieldLabel(props: { children: ReactNode; hidden?: boolean }) {
|
||||
return props.hidden ? null : <div className="mb-2 text-sm font-medium text-[var(--app-fg)]">{props.children}</div>
|
||||
export function SettingsFieldLabel(props: { children: ReactNode; hidden?: boolean; description?: string }) {
|
||||
if (props.hidden) return null
|
||||
if (!props.description) return <div className="mb-2 text-sm font-medium text-[var(--app-fg)]">{props.children}</div>
|
||||
return (
|
||||
<div className="mb-2">
|
||||
<div className="text-sm font-medium text-[var(--app-fg)]">{props.children}</div>
|
||||
<div className="mt-0.5 text-xs leading-snug text-[var(--app-hint)]">{props.description}</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export function ChevronRightIcon(props: { className?: string }) {
|
||||
@@ -70,6 +77,7 @@ export function SettingsSwitch(props: { label: string; description?: string; che
|
||||
|
||||
export function SettingsChoiceGroup<T extends string | number>(props: {
|
||||
label: string
|
||||
description?: string
|
||||
hideLabel?: boolean
|
||||
value: T
|
||||
options: ReadonlyArray<{ value: T; label: string; description?: string }>
|
||||
@@ -79,7 +87,7 @@ export function SettingsChoiceGroup<T extends string | number>(props: {
|
||||
const columns = props.columns === 5 ? 'grid-cols-5' : props.columns === 4 ? 'grid-cols-2 sm:grid-cols-4' : 'grid-cols-2'
|
||||
return (
|
||||
<div className="px-3 py-3">
|
||||
<SettingsFieldLabel hidden={props.hideLabel}>{props.label}</SettingsFieldLabel>
|
||||
<SettingsFieldLabel hidden={props.hideLabel} description={props.description}>{props.label}</SettingsFieldLabel>
|
||||
<div role="radiogroup" aria-label={props.label} className={`grid ${columns} gap-2`}>
|
||||
{props.options.map((option) => {
|
||||
const selected = props.value === option.value
|
||||
|
||||
@@ -160,11 +160,11 @@ export default function SettingsDisplayPage() {
|
||||
<SettingsSwitch label={t('settings.display.activeSessionsOnly')} description={t('settings.display.activeSessionsOnly.desc')} checked={showActiveSessionsOnly} onChange={setShowActiveSessionsOnly} />
|
||||
<SettingsChoiceGroup
|
||||
label={t('settings.display.sessionListStatus')}
|
||||
description={t('settings.display.sessionListStatus.detailedDescription')}
|
||||
value={sessionListStatusMode}
|
||||
options={getSessionListStatusModeOptions().map((option) => ({ value: option.value, label: t(option.labelKey) }))}
|
||||
onChange={setSessionListStatusMode}
|
||||
/>
|
||||
{sessionListStatusMode === 'detailed' ? <div className="px-3 pb-3 text-xs text-[var(--app-hint)]">{t('settings.display.sessionListStatus.detailedDescription')}</div> : null}
|
||||
</SettingsSection>
|
||||
</SettingsPageContent>
|
||||
)
|
||||
|
||||
@@ -213,6 +213,15 @@ describe('responsive settings pages', () => {
|
||||
expect(screen.queryByRole('listbox')).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('keeps the session status description visible with its choice group', () => {
|
||||
renderPage(<SettingsDisplayPage />)
|
||||
|
||||
const description = screen.getByText('Shows why a session stopped: permission, input, background work, new activity, or a scheduled message (clock icon).')
|
||||
const choices = screen.getByRole('radiogroup', { name: 'Session list status' })
|
||||
expect(description.parentElement?.parentElement).toBe(choices.parentElement)
|
||||
expect(description.compareDocumentPosition(choices) & Node.DOCUMENT_POSITION_FOLLOWING).toBeTruthy()
|
||||
})
|
||||
|
||||
it('keeps chat enum choices inline', () => {
|
||||
renderPage(<SettingsChatPage />)
|
||||
fireEvent.click(screen.getByRole('radio', { name: 'Insert newline' }))
|
||||
|
||||
Reference in New Issue
Block a user