chore: add options menu to vault selection menu items (#2497)

This commit is contained in:
Aman Harwara
2023-09-14 22:02:40 +05:30
committed by GitHub
parent 6759457f39
commit c3996be0fa
7 changed files with 193 additions and 57 deletions

View File

@@ -1,10 +1,11 @@
import { FunctionComponent, useCallback, useEffect, useState } from 'react'
import Menu from '../Menu/Menu'
import { useApplication } from '../ApplicationProvider'
import MenuSwitchButtonItem from '../Menu/MenuSwitchButtonItem'
import Icon from '../Icon/Icon'
import { ContentType, VaultListingInterface } from '@standardnotes/snjs'
import { observer } from 'mobx-react-lite'
import VaultSelectMenuItemWithOptions from './MenuItemWithVaultOption'
import Icon from '../Icon/Icon'
import MenuSwitchButtonItem from '../Menu/MenuSwitchButtonItem'
const ManyVaultSelectionMenu: FunctionComponent = () => {
const application = useApplication()
@@ -38,19 +39,22 @@ const ManyVaultSelectionMenu: FunctionComponent = () => {
<Menu a11yLabel="Vault selection menu" isOpen>
{!vaults.length && <div className="py-1 text-center">No vaults found</div>}
{vaults.map((vault) => (
<MenuSwitchButtonItem
onChange={() => {
toggleVault(vault)
}}
checked={isVaultVisible(vault)}
key={vault.uuid}
>
<Icon type={vault.iconString} className="mr-2 text-neutral" />
<div className="flex w-full items-center gap-1">
{vault.name}
{application.vaultLocks.isVaultLocked(vault) && <Icon className="ml-1" type="lock" size={'small'} />}
</div>
</MenuSwitchButtonItem>
<VaultSelectMenuItemWithOptions vault={vault}>
<MenuSwitchButtonItem
className="flex-grow !px-0 focus:!bg-transparent"
onChange={() => {
toggleVault(vault)
}}
checked={isVaultVisible(vault)}
key={vault.uuid}
>
<Icon type={vault.iconString} className="mr-2 text-neutral" />
<div className="flex w-full items-center gap-1">
{vault.name}
{application.vaultLocks.isVaultLocked(vault) && <Icon className="ml-1" type="lock" size={'small'} />}
</div>
</MenuSwitchButtonItem>
</VaultSelectMenuItemWithOptions>
))}
</Menu>
)

View File

@@ -0,0 +1,49 @@
import { VaultListingInterface, classNames } from '@standardnotes/snjs'
import { useState, useRef } from 'react'
import Icon from '../Icon/Icon'
import VaultOptionsMenu from './VaultOptionsMenu'
import Popover from '../Popover/Popover'
const VaultSelectMenuItemWithOptions = ({
vault,
children,
}: {
vault: VaultListingInterface
children: React.ReactNode
}) => {
const [isOptionsMenuOpen, setIsOptionsMenuOpen] = useState(false)
const optionsButtonRef = useRef<HTMLButtonElement>(null)
const toggleOptionsMenu = () => {
setIsOptionsMenuOpen((open) => !open)
}
return (
<div className="group flex items-center gap-3 px-3 focus-within:bg-info-backdrop">
{children}
<button
className={classNames(
'flex-shrink-0 rounded-full border border-border p-1 hover:bg-default focus:bg-default group-focus-within:bg-default',
isOptionsMenuOpen && 'bg-default',
)}
onClick={toggleOptionsMenu}
ref={optionsButtonRef}
>
<Icon type="more" size="small" />
</button>
<Popover
title="Vault options"
open={isOptionsMenuOpen}
anchorElement={optionsButtonRef}
side="top"
align="start"
className="py-1"
togglePopover={toggleOptionsMenu}
>
<VaultOptionsMenu vault={vault} />
</Popover>
</div>
)
}
export default VaultSelectMenuItemWithOptions

View File

@@ -5,6 +5,7 @@ import { ContentType, VaultListingInterface } from '@standardnotes/snjs'
import MenuRadioButtonItem from '../Menu/MenuRadioButtonItem'
import { observer } from 'mobx-react-lite'
import Icon from '../Icon/Icon'
import VaultSelectMenuItemWithOptions from './MenuItemWithVaultOption'
const SingleVaultSelectionMenu: FunctionComponent = () => {
const application = useApplication()
@@ -34,12 +35,17 @@ const SingleVaultSelectionMenu: FunctionComponent = () => {
<Menu a11yLabel="Vault selection menu" isOpen>
{!vaults.length && <div className="py-1 text-center">No vaults found</div>}
{vaults.map((vault) => (
<MenuRadioButtonItem key={vault.uuid} checked={isVaultVisible(vault)} onClick={() => selectVault(vault)}>
<div className="flex w-full items-center gap-1">
<VaultSelectMenuItemWithOptions vault={vault}>
<MenuRadioButtonItem
className="!px-0 focus:!bg-transparent md:!py-[0.455rem]"
key={vault.uuid}
checked={isVaultVisible(vault)}
onClick={() => selectVault(vault)}
>
{vault.name}
{application.vaultLocks.isVaultLocked(vault) && <Icon className="ml-1" type="lock" size={'small'} />}
</div>
</MenuRadioButtonItem>
</MenuRadioButtonItem>
</VaultSelectMenuItemWithOptions>
))}
</Menu>
)

View File

@@ -0,0 +1,48 @@
import { VaultListingInterface } from '@standardnotes/snjs'
import Menu from '../Menu/Menu'
import MenuItem from '../Menu/MenuItem'
import Icon from '../Icon/Icon'
import { useState, useCallback } from 'react'
import EditVaultModal from '../Preferences/Panes/Vaults/Vaults/VaultModal/EditVaultModal'
import { useVault } from '@/Hooks/useVault'
type Props = {
vault: VaultListingInterface
}
const VaultOptionsMenu = ({ vault }: Props) => {
const { canShowLockOption, isLocked, toggleLock, ensureVaultIsUnlocked } = useVault(vault)
const [isVaultModalOpen, setIsVaultModalOpen] = useState(false)
const openEditModal = useCallback(async () => {
if (!(await ensureVaultIsUnlocked())) {
return
}
setIsVaultModalOpen(true)
}, [ensureVaultIsUnlocked])
return (
<>
<Menu a11yLabel="Vault options menu" isOpen>
<MenuItem onClick={openEditModal}>
<Icon type="pencil-filled" className="mr-2" />
Edit vault
</MenuItem>
{canShowLockOption && (
<MenuItem onClick={toggleLock}>
<Icon type="lock" className="mr-2" />
{isLocked ? 'Unlock' : 'Lock'} vault
</MenuItem>
)}
</Menu>
<EditVaultModal
vault={vault}
isVaultModalOpen={isVaultModalOpen}
closeVaultModal={() => setIsVaultModalOpen(false)}
/>
</>
)
}
export default VaultOptionsMenu