♻️(frontend) refactor options menu
@manuhabitela introduced Menu and MenuTrigger components. Refactor the options menu to benefits from his components. Few details are not perfect yet. wip
This commit is contained in:
committed by
aleb_the_flash
parent
5b8c8d493a
commit
03b3630611
@@ -1,22 +1,38 @@
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { RiMore2Line } from '@remixicon/react'
|
||||
import { Button } from '@/primitives'
|
||||
import { OptionsMenu } from '@/features/rooms/livekit/components/controls/Options/OptionsMenu.tsx'
|
||||
import { MenuTrigger } from 'react-aria-components'
|
||||
import { Button, Menu } from '@/primitives'
|
||||
|
||||
import { useState } from 'react'
|
||||
import { UsernameDialog } from '@/features/rooms/livekit/components/dialogs/UsernameDialog'
|
||||
import { SettingsDialog } from '@/features/settings'
|
||||
import { OptionsMenuItems } from '@/features/rooms/livekit/components/controls/Options/OptionsMenuItems'
|
||||
|
||||
export type DialogState = 'username' | 'settings' | null
|
||||
|
||||
export const OptionsButton = () => {
|
||||
const { t } = useTranslation('rooms')
|
||||
const [dialogOpen, setDialogOpen] = useState<DialogState>(null)
|
||||
return (
|
||||
<MenuTrigger>
|
||||
<Button
|
||||
square
|
||||
legacyStyle
|
||||
aria-label={t('options.buttonLabel')}
|
||||
tooltip={t('options.buttonLabel')}
|
||||
>
|
||||
<RiMore2Line />
|
||||
</Button>
|
||||
<OptionsMenu />
|
||||
</MenuTrigger>
|
||||
<>
|
||||
<Menu>
|
||||
<Button
|
||||
square
|
||||
legacyStyle
|
||||
aria-label={t('options.buttonLabel')}
|
||||
tooltip={t('options.buttonLabel')}
|
||||
>
|
||||
<RiMore2Line />
|
||||
</Button>
|
||||
<OptionsMenuItems onOpenDialog={setDialogOpen} />
|
||||
</Menu>
|
||||
<UsernameDialog
|
||||
isOpen={dialogOpen === 'username'}
|
||||
onOpenChange={(v) => !v && setDialogOpen(null)}
|
||||
/>
|
||||
<SettingsDialog
|
||||
isOpen={dialogOpen === 'settings'}
|
||||
onOpenChange={(v) => !v && setDialogOpen(null)}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,118 +0,0 @@
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import {
|
||||
RiFeedbackLine,
|
||||
RiQuestionLine,
|
||||
RiSettings3Line,
|
||||
RiUser5Line,
|
||||
} from '@remixicon/react'
|
||||
import { useState } from 'react'
|
||||
import { styled } from '@/styled-system/jsx'
|
||||
import {
|
||||
Menu as RACMenu,
|
||||
MenuItem as RACMenuItem,
|
||||
Popover as RACPopover,
|
||||
Separator as RACSeparator,
|
||||
} from 'react-aria-components'
|
||||
import { SettingsDialog } from '@/features/settings'
|
||||
import { UsernameDialog } from '../../dialogs/UsernameDialog'
|
||||
|
||||
// Styled components to be refactored
|
||||
const StyledMenu = styled(RACMenu, {
|
||||
base: {
|
||||
maxHeight: 'inherit',
|
||||
boxSizing: 'border-box',
|
||||
overflow: 'auto',
|
||||
padding: '2px',
|
||||
minWidth: '150px',
|
||||
outline: 'none',
|
||||
},
|
||||
})
|
||||
|
||||
const StyledMenuItem = styled(RACMenuItem, {
|
||||
base: {
|
||||
margin: '2px',
|
||||
padding: '0.286rem 0.571rem',
|
||||
borderRadius: '6px',
|
||||
outline: 'none',
|
||||
cursor: 'default',
|
||||
color: 'black',
|
||||
fontSize: '1.072rem',
|
||||
position: 'relative',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '20px',
|
||||
forcedColorAdjust: 'none',
|
||||
'&[data-focused]': {
|
||||
color: 'primary.text',
|
||||
backgroundColor: 'primary',
|
||||
outline: 'none!',
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
const StyledPopover = styled(RACPopover, {
|
||||
base: {
|
||||
border: '1px solid #9ca3af',
|
||||
boxShadow: '0 8px 20px rgba(0, 0, 0, 0.1)',
|
||||
borderRadius: '4px',
|
||||
background: 'white',
|
||||
color: 'var(--text-color)',
|
||||
outline: 'none',
|
||||
minWidth: '112px',
|
||||
width: '300px',
|
||||
},
|
||||
})
|
||||
|
||||
const StyledSeparator = styled(RACSeparator, {
|
||||
base: {
|
||||
height: '1px',
|
||||
background: '#9ca3af',
|
||||
margin: '2px 4px',
|
||||
},
|
||||
})
|
||||
|
||||
type DialogState = 'username' | 'settings' | null
|
||||
|
||||
export const OptionsMenu = () => {
|
||||
const { t } = useTranslation('rooms')
|
||||
const [dialogOpen, setDialogOpen] = useState<DialogState>(null)
|
||||
return (
|
||||
<>
|
||||
<StyledPopover>
|
||||
<StyledMenu>
|
||||
<StyledMenuItem onAction={() => setDialogOpen('username')}>
|
||||
<RiUser5Line size={18} />
|
||||
{t('options.items.username')}
|
||||
</StyledMenuItem>
|
||||
<StyledSeparator />
|
||||
<StyledMenuItem
|
||||
href="https://tchap.gouv.fr/#/room/!aGImQayAgBLjSBycpm:agent.dinum.tchap.gouv.fr?via=agent.dinum.tchap.gouv.fr"
|
||||
target="_blank"
|
||||
>
|
||||
<RiQuestionLine size={18} />
|
||||
{t('options.items.support')}
|
||||
</StyledMenuItem>
|
||||
<StyledMenuItem
|
||||
href="https://grist.incubateur.net/o/docs/forms/1YrfNP1QSSy8p2gCxMFnSf/4"
|
||||
target="_blank"
|
||||
>
|
||||
<RiFeedbackLine size={18} />
|
||||
{t('options.items.feedbacks')}
|
||||
</StyledMenuItem>
|
||||
<StyledMenuItem onAction={() => setDialogOpen('settings')}>
|
||||
<RiSettings3Line size={18} />
|
||||
{t('options.items.settings')}
|
||||
</StyledMenuItem>
|
||||
</StyledMenu>
|
||||
</StyledPopover>
|
||||
<UsernameDialog
|
||||
isOpen={dialogOpen === 'username'}
|
||||
onOpenChange={(v) => !v && setDialogOpen(null)}
|
||||
/>
|
||||
<SettingsDialog
|
||||
isOpen={dialogOpen === 'settings'}
|
||||
onOpenChange={(v) => !v && setDialogOpen(null)}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
import { menuItemRecipe } from '@/primitives/menuItemRecipe'
|
||||
import {
|
||||
RiFeedbackLine,
|
||||
RiQuestionLine,
|
||||
RiSettings3Line,
|
||||
RiUser5Line,
|
||||
} from '@remixicon/react'
|
||||
import { styled } from '@/styled-system/jsx'
|
||||
import {
|
||||
MenuItem,
|
||||
Menu as RACMenu,
|
||||
Separator as RACSeparator,
|
||||
} from 'react-aria-components'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Dispatch, SetStateAction } from 'react'
|
||||
import { DialogState } from '@/features/rooms/livekit/components/controls/Options/OptionsButton'
|
||||
|
||||
const StyledSeparator = styled(RACSeparator, {
|
||||
base: {
|
||||
height: '1px',
|
||||
background: 'gray.300',
|
||||
margin: '4px 0',
|
||||
},
|
||||
})
|
||||
|
||||
// @todo try refactoring it to use MenuList component
|
||||
export const OptionsMenuItems = ({
|
||||
onOpenDialog,
|
||||
}: {
|
||||
onOpenDialog: Dispatch<SetStateAction<DialogState>>
|
||||
}) => {
|
||||
const { t } = useTranslation('rooms')
|
||||
|
||||
return (
|
||||
<RACMenu
|
||||
style={{
|
||||
minWidth: '150px',
|
||||
width: '300px',
|
||||
}}
|
||||
>
|
||||
<MenuItem
|
||||
className={menuItemRecipe({ icon: true })}
|
||||
onAction={() => onOpenDialog('username')}
|
||||
>
|
||||
<RiUser5Line size={18} />
|
||||
{t('options.items.username')}
|
||||
</MenuItem>
|
||||
<StyledSeparator />
|
||||
<MenuItem
|
||||
href="https://tchap.gouv.fr/#/room/!aGImQayAgBLjSBycpm:agent.dinum.tchap.gouv.fr?via=agent.dinum.tchap.gouv.fr"
|
||||
target="_blank"
|
||||
className={menuItemRecipe({ icon: true })}
|
||||
>
|
||||
<RiQuestionLine size={18} />
|
||||
{t('options.items.support')}
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
href="https://grist.incubateur.net/o/docs/forms/1YrfNP1QSSy8p2gCxMFnSf/4"
|
||||
target="_blank"
|
||||
className={menuItemRecipe({ icon: true })}
|
||||
>
|
||||
<RiFeedbackLine size={18} />
|
||||
{t('options.items.feedbacks')}
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
className={menuItemRecipe({ icon: true })}
|
||||
onAction={() => onOpenDialog('settings')}
|
||||
>
|
||||
<RiSettings3Line size={18} />
|
||||
{t('options.items.settings')}
|
||||
</MenuItem>
|
||||
</RACMenu>
|
||||
)
|
||||
}
|
||||
@@ -8,9 +8,8 @@ import { cva } from '@/styled-system/css'
|
||||
*/
|
||||
export const menuItemRecipe = cva({
|
||||
base: {
|
||||
paddingY: 0.125,
|
||||
paddingY: '0.4rem',
|
||||
paddingX: 0.5,
|
||||
paddingLeft: 1.5,
|
||||
textAlign: 'left',
|
||||
width: 'full',
|
||||
borderRadius: 4,
|
||||
@@ -37,4 +36,13 @@ export const menuItemRecipe = cva({
|
||||
outline: 'none!',
|
||||
},
|
||||
},
|
||||
variants: {
|
||||
icon: {
|
||||
true: {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '1rem',
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user