♻️(frontend) introduce a reusable tools sidepanel

tools will be added in the future, let's generalize the sidepanel
previously reserved to transcription.
This commit is contained in:
lebaudantoine
2025-04-04 17:01:02 +02:00
committed by aleb_the_flash
parent 60321296e5
commit 91562d049c
11 changed files with 167 additions and 46 deletions

View File

@@ -9,9 +9,9 @@ import { ParticipantsList } from './controls/Participants/ParticipantsList'
import { useSidePanel } from '../hooks/useSidePanel'
import { ReactNode } from 'react'
import { Chat } from '../prefabs/Chat'
import { Transcript } from './Transcript'
import { Effects } from './effects/Effects'
import { Admin } from './Admin'
import { Tools } from './Tools'
type StyledSidePanelProps = {
title: string
@@ -114,7 +114,7 @@ export const SidePanel = () => {
isEffectsOpen,
isChatOpen,
isSidePanelOpen,
isTranscriptOpen,
isToolsOpen,
isAdminOpen,
} = useSidePanel()
const { t } = useTranslation('rooms', { keyPrefix: 'sidePanel' })
@@ -137,8 +137,8 @@ export const SidePanel = () => {
<Panel isOpen={isChatOpen}>
<Chat />
</Panel>
<Panel isOpen={isTranscriptOpen}>
<Transcript />
<Panel isOpen={isToolsOpen}>
<Tools />
</Panel>
<Panel isOpen={isAdminOpen}>
<Admin />

View File

@@ -0,0 +1,95 @@
import { A, Div, Text } from '@/primitives'
import { css } from '@/styled-system/css'
import { Button as RACButton } from 'react-aria-components'
import { useTranslation } from 'react-i18next'
import { CRISP_HELP_ARTICLE_MORE_TOOLS } from '@/utils/constants'
import { ReactNode } from 'react'
export interface ToolsButtonProps {
icon: ReactNode
title: string
description: string
onPress: () => void
}
const ToolButton = ({
icon,
title,
description,
onPress,
}: ToolsButtonProps) => {
return (
<RACButton
className={css({
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'start',
paddingY: '0.5rem',
paddingX: '0.75rem 1.5rem',
borderRadius: '5px',
gap: '1.25rem',
width: 'full',
textAlign: 'start',
'&[data-hovered]': {
backgroundColor: 'primary.50',
cursor: 'pointer',
},
})}
onPress={onPress}
>
<div
className={css({
height: '50px',
minWidth: '50px',
borderRadius: '25px',
backgroundColor: 'primary.800',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
})}
>
{icon}
</div>
<div>
<Text margin={false} as="h3">
{title}
</Text>
<Text as="p" variant="smNote" wrap="pretty">
{description}
</Text>
</div>
</RACButton>
)
}
export const Tools = () => {
const { t } = useTranslation('rooms', { keyPrefix: 'moreTools' })
return (
<Div
display="flex"
overflowY="scroll"
padding="0 0.75rem"
flexGrow={1}
flexDirection="column"
alignItems="start"
>
<Text
variant="note"
wrap="balance"
className={css({
textStyle: 'sm',
paddingX: '0.75rem',
})}
margin="md"
>
{t('body')}{' '}
<A href={CRISP_HELP_ARTICLE_MORE_TOOLS} target="_blank">
{t('moreLink')}
</A>
.
</Text>
WIP
</Div>
)
}

View File

@@ -1,24 +1,19 @@
import { ToggleButton } from '@/primitives'
import { RiBardLine } from '@remixicon/react'
import { RiShapesLine } from '@remixicon/react'
import { useTranslation } from 'react-i18next'
import { useSidePanel } from '../../hooks/useSidePanel'
import { useHasTranscriptAccess } from '../../hooks/useHasTranscriptAccess'
import { css } from '@/styled-system/css'
import { ToggleButtonProps } from '@/primitives/ToggleButton'
export const TranscriptToggle = ({
export const ToolsToggle = ({
variant = 'primaryTextDark',
onPress,
...props
}: ToggleButtonProps) => {
const { t } = useTranslation('rooms', { keyPrefix: 'controls.transcript' })
const { t } = useTranslation('rooms', { keyPrefix: 'controls.tools' })
const { isTranscriptOpen, toggleTranscript } = useSidePanel()
const tooltipLabel = isTranscriptOpen ? 'open' : 'closed'
const hasTranscriptAccess = useHasTranscriptAccess()
if (!hasTranscriptAccess) return
const { isToolsOpen, toggleTools } = useSidePanel()
const tooltipLabel = isToolsOpen ? 'open' : 'closed'
return (
<div
@@ -32,15 +27,15 @@ export const TranscriptToggle = ({
variant={variant}
aria-label={t(tooltipLabel)}
tooltip={t(tooltipLabel)}
isSelected={isTranscriptOpen}
isSelected={isToolsOpen}
onPress={(e) => {
toggleTranscript()
toggleTools()
onPress?.(e)
}}
{...props}
data-attr="toggle-transcript"
data-attr="toggle-tools"
>
<RiBardLine />
<RiShapesLine />
</ToggleButton>
</div>
)

View File

@@ -5,7 +5,7 @@ export enum PanelId {
PARTICIPANTS = 'participants',
EFFECTS = 'effects',
CHAT = 'chat',
TRANSCRIPT = 'transcript',
TOOLS = 'tools',
ADMIN = 'admin',
}
@@ -16,7 +16,7 @@ export const useSidePanel = () => {
const isParticipantsOpen = activePanelId == PanelId.PARTICIPANTS
const isEffectsOpen = activePanelId == PanelId.EFFECTS
const isChatOpen = activePanelId == PanelId.CHAT
const isTranscriptOpen = activePanelId == PanelId.TRANSCRIPT
const isToolsOpen = activePanelId == PanelId.TOOLS
const isAdminOpen = activePanelId == PanelId.ADMIN
const isSidePanelOpen = !!activePanelId
@@ -36,8 +36,8 @@ export const useSidePanel = () => {
layoutStore.activePanelId = isEffectsOpen ? null : PanelId.EFFECTS
}
const toggleTranscript = () => {
layoutStore.activePanelId = isTranscriptOpen ? null : PanelId.TRANSCRIPT
const toggleTools = () => {
layoutStore.activePanelId = isToolsOpen ? null : PanelId.TOOLS
}
return {
@@ -45,13 +45,13 @@ export const useSidePanel = () => {
toggleParticipants,
toggleChat,
toggleEffects,
toggleTranscript,
toggleTools,
toggleAdmin,
isChatOpen,
isParticipantsOpen,
isEffectsOpen,
isSidePanelOpen,
isTranscriptOpen,
isToolsOpen,
isAdminOpen,
}
}

View File

@@ -21,7 +21,7 @@ import { useSidePanel } from '../../hooks/useSidePanel'
import { LinkButton } from '@/primitives'
import { useSettingsDialog } from '../../components/controls/SettingsDialogContext'
import { ResponsiveMenu } from './ResponsiveMenu'
import { TranscriptToggle } from '../../components/controls/TranscriptToggle'
import { ToolsToggle } from '../../components/controls/ToolsToggle'
import { CameraSwitchButton } from '../../components/controls/CameraSwitchButton'
export function MobileControlBar({
@@ -133,7 +133,7 @@ export function MobileControlBar({
description={true}
onPress={() => setIsMenuOpened(false)}
/>
<TranscriptToggle
<ToolsToggle
description={true}
onPress={() => setIsMenuOpened(false)}
/>

View File

@@ -1,7 +1,7 @@
import { css } from '@/styled-system/css'
import { ChatToggle } from '../../components/controls/ChatToggle'
import { ParticipantsToggle } from '../../components/controls/Participants/ParticipantsToggle'
import { TranscriptToggle } from '../../components/controls/TranscriptToggle'
import { ToolsToggle } from '../../components/controls/ToolsToggle'
import { AdminToggle } from '../../components/AdminToggle'
import { useSize } from '../../hooks/useResizeObserver'
import { useState, RefObject } from 'react'
@@ -20,7 +20,7 @@ const NavigationControls = ({
<>
<ChatToggle onPress={onPress} tooltipType={tooltipType} />
<ParticipantsToggle onPress={onPress} tooltipType={tooltipType} />
<TranscriptToggle onPress={onPress} tooltipType={tooltipType} />
<ToolsToggle onPress={onPress} tooltipType={tooltipType} />
<AdminToggle onPress={onPress} tooltipType={tooltipType} />
</>
)

View File

@@ -104,7 +104,7 @@
"open": "",
"closed": ""
},
"transcript": {
"tools": {
"open": "",
"closed": ""
},
@@ -169,20 +169,27 @@
"effects": "",
"chat": "",
"transcript": "",
"admin": ""
"admin": "",
"tools": ""
},
"content": {
"participants": "",
"effects": "",
"chat": "",
"transcript": "",
"admin": ""
"admin": "",
"tools": ""
},
"closeButton": ""
},
"chat": {
"disclaimer": ""
},
"moreTools": {
"body": "",
"moreLink": "",
"tools": {}
},
"transcript": {
"start": {
"heading": "",

View File

@@ -103,9 +103,9 @@
"open": "Hide everyone",
"closed": "See everyone"
},
"transcript": {
"open": "Hide AI assistant",
"closed": "Show AI assistant"
"tools": {
"open": "Hide more tools",
"closed": "Show more tools"
},
"admin": {
"open": "Hide admin",
@@ -168,20 +168,27 @@
"effects": "Effects",
"chat": "Messages in the chat",
"transcript": "AI Assistant",
"admin": "Admin settings"
"admin": "Admin settings",
"tools": "More tools"
},
"content": {
"participants": "participants",
"effects": "effects",
"chat": "messages",
"transcript": "AI assistant",
"admin": "Admin settings"
"admin": "admin settings",
"tools": "more tools"
},
"closeButton": "Hide {{content}}"
},
"chat": {
"disclaimer": "The messages are visible to participants only at the time they are sent. All messages are deleted at the end of the call."
},
"moreTools": {
"body": "Access more tools in Visio to enhance your meetings,",
"moreLink": "learn more",
"tools": {}
},
"transcript": {
"start": {
"heading": "Start the Assistant!",

View File

@@ -103,9 +103,9 @@
"open": "Masquer les participants",
"closed": "Afficher les participants"
},
"transcript": {
"open": "Masquer l'assistant IA",
"closed": "Afficher l'assistant IA"
"tools": {
"open": "Masquer plus d'outils",
"closed": "Afficher plus d'outils"
},
"admin": {
"open": "Masquer l'admin",
@@ -168,20 +168,27 @@
"effects": "Effets",
"chat": "Messages dans l'appel",
"transcript": "Assistant IA",
"admin": "Commandes de l'organisateur"
"admin": "Commandes de l'organisateur",
"tools": "Plus d'outils"
},
"content": {
"participants": "les participants",
"effects": "les effets",
"chat": "les messages",
"transcript": "l'assistant IA",
"admin": "Commandes de l'organisateur"
"admin": "commandes de l'organisateur",
"tools": "plus d'outils"
},
"closeButton": "Masquer {{content}}"
},
"chat": {
"disclaimer": "Les messages sont visibles par les participants uniquement au moment de\nleur envoi. Tous les messages sont supprimés à la fin de l'appel."
},
"moreTools": {
"body": "Accèder à d'avantage d'outils dans Visio pour améliorer vos réunions,",
"moreLink": "en savoir plus",
"tools": {}
},
"transcript": {
"start": {
"heading": "Démarrer l'assistant !",

View File

@@ -103,9 +103,9 @@
"open": "Verberg iedereen",
"closed": "Toon iedereen"
},
"transcript": {
"open": "Verberg AI-assistent",
"closed": "Toon AI-assistant"
"tools": {
"open": "Meer tools verbergen",
"closed": "Meer tools weergeven"
},
"admin": {
"open": "Verberg beheerder",
@@ -168,20 +168,27 @@
"effects": "Effecten",
"chat": "Berichten in de chat",
"transcript": "AI-assistent",
"admin": "Beheerdersbediening"
"admin": "Beheerdersbediening",
"tools": "Meer tools"
},
"content": {
"participants": "deelnemers",
"effects": "effecten",
"chat": "berichten",
"transcript": "AI-assistent",
"admin": "Beheerdersbediening"
"admin": "beheerdersbediening",
"tools": "meer tools"
},
"closeButton": "Verberg {{content}}"
},
"chat": {
"disclaimer": "De berichten zijn alleen voor de deelnemers zichtbaar op het moment dat ze worden verzonden. Alle berichten worden verwijderd aan het einde van het gesprek."
},
"moreTools": {
"body": "Toegang tot meer tools in Visio om je vergaderingen te verbeteren,",
"moreLink": "lees meer",
"tools": {}
},
"transcript": {
"start": {
"heading": "Start de assistent!",

View File

@@ -3,3 +3,6 @@ export const GRIST_FEEDBACKS_FORM =
export const BETA_USERS_FORM_URL =
'https://grist.numerique.gouv.fr/o/docs/forms/3fFfvJoTBEQ6ZiMi8zsQwX/17' as const
export const CRISP_HELP_ARTICLE_MORE_TOOLS =
'https://lasuite.crisp.help/fr/article/visio-tools-bvxj23' as const