🚸(frontend) auto-close device popover when opening dialogs or sidepanels

Close device control popover automatically when user opens sidepanels
or external dialogs to prevent confusing UI state.

Improves focus management by ensuring only one interface element
demands user attention at a time, reducing cognitive load during
interactions.
This commit is contained in:
lebaudantoine
2025-08-22 02:17:26 +02:00
committed by aleb_the_flash
parent e88aeedbf1
commit a97895c383
4 changed files with 72 additions and 56 deletions

View File

@@ -82,42 +82,47 @@ export const AudioDevicesControl = ({
> >
<RiArrowUpSLine /> <RiArrowUpSLine />
</Button> </Button>
<div {({ close }) => (
className={css({
maxWidth: '36rem',
padding: '0.15rem',
display: 'flex',
gap: '0.5rem',
})}
>
<div <div
style={{ className={css({
flex: '1 1 0', maxWidth: '36rem',
minWidth: 0, padding: '0.15rem',
}} display: 'flex',
gap: '0.5rem',
})}
> >
<SelectDevice <div
context="room" style={{
kind={kind} flex: '1 1 0',
id={audioDeviceId} minWidth: 0,
onSubmit={saveAudioInputDeviceId} }}
>
<SelectDevice
context="room"
kind={kind}
id={audioDeviceId}
onSubmit={saveAudioInputDeviceId}
/>
</div>
<div
style={{
flex: '1 1 0',
minWidth: 0,
}}
>
<SelectDevice
context="room"
kind="audiooutput"
id={audioOutputDeviceId}
onSubmit={saveAudioOutputDeviceId}
/>
</div>
<SettingsButton
settingTab={SettingsDialogExtendedKey.AUDIO}
onPress={close}
/> />
</div> </div>
<div )}
style={{
flex: '1 1 0',
minWidth: 0,
}}
>
<SelectDevice
context="room"
kind="audiooutput"
id={audioOutputDeviceId}
onSubmit={saveAudioOutputDeviceId}
/>
</div>
<SettingsButton settingTab={SettingsDialogExtendedKey.AUDIO} />
</div>
</Popover> </Popover>
)} )}
</div> </div>

View File

@@ -6,8 +6,10 @@ import { SettingsDialogExtendedKey } from '@/features/settings/type'
export const SettingsButton = ({ export const SettingsButton = ({
settingTab, settingTab,
onPress,
}: { }: {
settingTab: SettingsDialogExtendedKey settingTab: SettingsDialogExtendedKey
onPress?: () => void
}) => { }) => {
const { t } = useTranslation('rooms', { keyPrefix: 'selectDevice' }) const { t } = useTranslation('rooms', { keyPrefix: 'selectDevice' })
const { setDialogOpen, setDefaultSelectedKey } = useSettingsDialog() const { setDialogOpen, setDefaultSelectedKey } = useSettingsDialog()
@@ -22,6 +24,7 @@ export const SettingsButton = ({
onPress={() => { onPress={() => {
setDefaultSelectedKey(settingTab) setDefaultSelectedKey(settingTab)
setDialogOpen(true) setDialogOpen(true)
onPress?.()
}} }}
> >
<RiSettings3Line size={24} /> <RiSettings3Line size={24} />

View File

@@ -16,9 +16,9 @@ import { SelectDevice } from './SelectDevice'
import { SettingsButton } from './SettingsButton' import { SettingsButton } from './SettingsButton'
import { SettingsDialogExtendedKey } from '@/features/settings/type' import { SettingsDialogExtendedKey } from '@/features/settings/type'
const EffectsButton = () => { const EffectsButton = ({ onPress }: { onPress: () => void }) => {
const { t } = useTranslation('rooms', { keyPrefix: 'selectDevice' }) const { t } = useTranslation('rooms', { keyPrefix: 'selectDevice' })
const { toggleEffects } = useSidePanel() const { isEffectsOpen, toggleEffects } = useSidePanel()
return ( return (
<Button <Button
size="sm" size="sm"
@@ -26,7 +26,10 @@ const EffectsButton = () => {
tooltip={t('effects')} tooltip={t('effects')}
aria-label={t('effects')} aria-label={t('effects')}
variant="primaryDark" variant="primaryDark"
onPress={toggleEffects} onPress={() => {
if (!isEffectsOpen) toggleEffects()
onPress()
}}
> >
<RiImageCircleAiFill size={24} /> <RiImageCircleAiFill size={24} />
</Button> </Button>
@@ -125,30 +128,35 @@ export const VideoDeviceControl = ({
> >
<RiArrowUpSLine /> <RiArrowUpSLine />
</Button> </Button>
<div {({ close }) => (
className={css({
maxWidth: '36rem',
padding: '0.15rem',
display: 'flex',
gap: '0.5rem',
})}
>
<div <div
style={{ className={css({
flex: '1 1 0', maxWidth: '36rem',
minWidth: 0, padding: '0.15rem',
}} display: 'flex',
gap: '0.5rem',
})}
> >
<SelectDevice <div
context="room" style={{
kind={kind} flex: '1 1 0',
id={userChoices.videoDeviceId} minWidth: 0,
onSubmit={saveVideoInputDeviceId} }}
>
<SelectDevice
context="room"
kind={kind}
id={userChoices.videoDeviceId}
onSubmit={saveVideoInputDeviceId}
/>
</div>
<EffectsButton onPress={close} />
<SettingsButton
settingTab={SettingsDialogExtendedKey.VIDEO}
onPress={close}
/> />
</div> </div>
<EffectsButton /> )}
<SettingsButton settingTab={SettingsDialogExtendedKey.VIDEO} />
</div>
</Popover> </Popover>
)} )}
</div> </div>

View File

@@ -80,7 +80,7 @@ export const Popover = ({
] ]
variant?: 'dark' | 'light' variant?: 'dark' | 'light'
withArrow?: boolean withArrow?: boolean
} & DialogProps) => { } & Omit<DialogProps, 'children'>) => {
const [trigger, popoverContent] = children const [trigger, popoverContent] = children
return ( return (
<DialogTrigger> <DialogTrigger>