mirror of
https://github.com/suitenumerique/meet.git
synced 2026-08-28 19:27:50 +00:00
wip poc
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { useMemo } from 'react'
|
import { useEffect, useMemo, useRef } from 'react'
|
||||||
import { VStack } from '@/styled-system/jsx'
|
import { VStack } from '@/styled-system/jsx'
|
||||||
import { css } from '@/styled-system/css'
|
import { css } from '@/styled-system/css'
|
||||||
import { RiCheckLine, RiFileCopyLine } from '@remixicon/react'
|
import { RiCheckLine, RiFileCopyLine } from '@remixicon/react'
|
||||||
@@ -9,16 +9,24 @@ import { useRoomData } from '../hooks/useRoomData'
|
|||||||
import { formatPinCode } from '../../utils/telephony'
|
import { formatPinCode } from '../../utils/telephony'
|
||||||
import { useTelephony } from '../hooks/useTelephony'
|
import { useTelephony } from '../hooks/useTelephony'
|
||||||
import { useCopyRoomToClipboard } from '../hooks/useCopyRoomToClipboard'
|
import { useCopyRoomToClipboard } from '../hooks/useCopyRoomToClipboard'
|
||||||
import { useSidePanel } from '../hooks/useSidePanel'
|
|
||||||
import { useRestoreFocus } from '@/hooks/useRestoreFocus'
|
const useFocusOnOpen = ({ ref, key }) => {
|
||||||
import { useSidePanelRef } from '../hooks/useSidePanelRef'
|
useEffect(() => {
|
||||||
import { useSidePanelTriggers } from '../hooks/useSidePanelTriggers'
|
requestAnimationFrame(() => {
|
||||||
|
const panel = ref.current
|
||||||
|
if (panel) {
|
||||||
|
const firstButton = panel.querySelector<HTMLElement>(key)
|
||||||
|
if (firstButton) {
|
||||||
|
firstButton.focus({ preventScroll: true })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}, [])
|
||||||
|
}
|
||||||
|
|
||||||
export const Info = () => {
|
export const Info = () => {
|
||||||
const { t } = useTranslation('rooms', { keyPrefix: 'info' })
|
const { t } = useTranslation('rooms', { keyPrefix: 'info' })
|
||||||
const { isInfoOpen } = useSidePanel()
|
const panelRef = useRef()
|
||||||
const panelRef = useSidePanelRef()
|
|
||||||
const { getTrigger } = useSidePanelTriggers()
|
|
||||||
|
|
||||||
const data = useRoomData()
|
const data = useRoomData()
|
||||||
const roomUrl = getRouteUrl('room', data?.slug)
|
const roomUrl = getRouteUrl('room', data?.slug)
|
||||||
@@ -31,26 +39,7 @@ export const Info = () => {
|
|||||||
|
|
||||||
const { isCopied, copyRoomToClipboard } = useCopyRoomToClipboard(data)
|
const { isCopied, copyRoomToClipboard } = useCopyRoomToClipboard(data)
|
||||||
|
|
||||||
// Restore focus to the element that opened the Info panel
|
useFocusOnOpen({ ref: panelRef, key: '[data-attr="copy-info-sidepanel"]' })
|
||||||
useRestoreFocus(isInfoOpen, {
|
|
||||||
resolveTrigger: (activeEl) => getTrigger('info') ?? activeEl,
|
|
||||||
// Focus the first focusable element when the panel opens
|
|
||||||
onOpened: () => {
|
|
||||||
requestAnimationFrame(() => {
|
|
||||||
const panel = panelRef.current
|
|
||||||
if (panel) {
|
|
||||||
const firstButton = panel.querySelector<HTMLElement>(
|
|
||||||
'[data-attr="copy-info-sidepanel"]'
|
|
||||||
)
|
|
||||||
if (firstButton) {
|
|
||||||
firstButton.focus({ preventScroll: true })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
restoreFocusRaf: true,
|
|
||||||
preventScroll: true,
|
|
||||||
})
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Div
|
<Div
|
||||||
@@ -60,6 +49,7 @@ export const Info = () => {
|
|||||||
flexGrow={1}
|
flexGrow={1}
|
||||||
flexDirection="column"
|
flexDirection="column"
|
||||||
alignItems="start"
|
alignItems="start"
|
||||||
|
ref={panelRef}
|
||||||
>
|
>
|
||||||
<VStack alignItems="start">
|
<VStack alignItems="start">
|
||||||
<Text
|
<Text
|
||||||
|
|||||||
@@ -206,7 +206,7 @@ const SidePanelContent = () => {
|
|||||||
<Panel isOpen={isAdminOpen} keepAlive={true}>
|
<Panel isOpen={isAdminOpen} keepAlive={true}>
|
||||||
<Admin />
|
<Admin />
|
||||||
</Panel>
|
</Panel>
|
||||||
<Panel isOpen={isInfoOpen} keepAlive={true}>
|
<Panel isOpen={isInfoOpen}>
|
||||||
<Info />
|
<Info />
|
||||||
</Panel>
|
</Panel>
|
||||||
</StyledSidePanel>
|
</StyledSidePanel>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useCallback } from 'react'
|
import { useCallback, useRef } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { RiInformationLine } from '@remixicon/react'
|
import { RiInformationLine } from '@remixicon/react'
|
||||||
import { css } from '@/styled-system/css'
|
import { css } from '@/styled-system/css'
|
||||||
@@ -14,14 +14,17 @@ export const InfoToggle = ({
|
|||||||
const { t } = useTranslation('rooms', { keyPrefix: 'controls.info' })
|
const { t } = useTranslation('rooms', { keyPrefix: 'controls.info' })
|
||||||
|
|
||||||
const { isInfoOpen, toggleInfo } = useSidePanel()
|
const { isInfoOpen, toggleInfo } = useSidePanel()
|
||||||
const { setTrigger } = useSidePanelTriggers()
|
// const { setTrigger } = useSidePanelTriggers()
|
||||||
const tooltipLabel = isInfoOpen ? 'open' : 'closed'
|
const tooltipLabel = isInfoOpen ? 'open' : 'closed'
|
||||||
const setInfoTriggerRef = useCallback(
|
|
||||||
(el: HTMLElement | null) => {
|
const wip = useRef<HTMLElement | null>()
|
||||||
setTrigger('info', el)
|
|
||||||
},
|
// const setInfoTriggerRef = useCallback(
|
||||||
[setTrigger]
|
// (el: HTMLElement | null) => {
|
||||||
)
|
// setTrigger('info', el)
|
||||||
|
// },
|
||||||
|
// [setTrigger]
|
||||||
|
// )
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@@ -36,9 +39,9 @@ export const InfoToggle = ({
|
|||||||
aria-label={t(tooltipLabel)}
|
aria-label={t(tooltipLabel)}
|
||||||
tooltip={t(tooltipLabel)}
|
tooltip={t(tooltipLabel)}
|
||||||
isSelected={isInfoOpen}
|
isSelected={isInfoOpen}
|
||||||
ref={setInfoTriggerRef}
|
ref={wip}
|
||||||
onPress={(e) => {
|
onPress={(e) => {
|
||||||
toggleInfo()
|
toggleInfo(wip)
|
||||||
onPress?.(e)
|
onPress?.(e)
|
||||||
}}
|
}}
|
||||||
data-attr={`controls-info-${tooltipLabel}`}
|
data-attr={`controls-info-${tooltipLabel}`}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { useSnapshot } from 'valtio'
|
import { ref, useSnapshot } from 'valtio'
|
||||||
import { layoutStore } from '@/stores/layout'
|
import { layoutStore } from '@/stores/layout'
|
||||||
|
import { useEffect } from 'react'
|
||||||
|
|
||||||
export enum PanelId {
|
export enum PanelId {
|
||||||
PARTICIPANTS = 'participants',
|
PARTICIPANTS = 'participants',
|
||||||
@@ -56,8 +57,13 @@ export const useSidePanel = () => {
|
|||||||
if (layoutSnap.activeSubPanelId) layoutStore.activeSubPanelId = null
|
if (layoutSnap.activeSubPanelId) layoutStore.activeSubPanelId = null
|
||||||
}
|
}
|
||||||
|
|
||||||
const toggleInfo = () => {
|
const toggleInfo = (wip) => {
|
||||||
layoutStore.activePanelId = isInfoOpen ? null : PanelId.INFO
|
layoutStore.activePanelId = isInfoOpen ? null : PanelId.INFO
|
||||||
|
|
||||||
|
if (!isInfoOpen) {
|
||||||
|
layoutStore.genericRef = ref(wip)
|
||||||
|
}
|
||||||
|
|
||||||
if (layoutSnap.activeSubPanelId) layoutStore.activeSubPanelId = null
|
if (layoutSnap.activeSubPanelId) layoutStore.activeSubPanelId = null
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,6 +77,18 @@ export const useSidePanel = () => {
|
|||||||
layoutStore.activePanelId = PanelId.TOOLS
|
layoutStore.activePanelId = PanelId.TOOLS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!layoutSnap.activePanelId) {
|
||||||
|
console.log('$$prout closing')
|
||||||
|
const trigger = layoutSnap?.genericRef?.current
|
||||||
|
console.log(trigger)
|
||||||
|
if (trigger) {
|
||||||
|
trigger.focus({ preventScroll: true })
|
||||||
|
trigger.setAttribute('data-restore-focus-visible', '')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [layoutSnap.activePanelId, layoutSnap?.genericRef])
|
||||||
|
|
||||||
return {
|
return {
|
||||||
activePanelId,
|
activePanelId,
|
||||||
activeSubPanelId,
|
activeSubPanelId,
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ type State = {
|
|||||||
showSubtitles: boolean
|
showSubtitles: boolean
|
||||||
activePanelId: PanelId | null
|
activePanelId: PanelId | null
|
||||||
activeSubPanelId: SubPanelId | null
|
activeSubPanelId: SubPanelId | null
|
||||||
|
genericRef: HTMLElement | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export const layoutStore = proxy<State>({
|
export const layoutStore = proxy<State>({
|
||||||
@@ -18,4 +19,5 @@ export const layoutStore = proxy<State>({
|
|||||||
showSubtitles: false,
|
showSubtitles: false,
|
||||||
activePanelId: null,
|
activePanelId: null,
|
||||||
activeSubPanelId: null,
|
activeSubPanelId: null,
|
||||||
|
genericRef: null,
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user