chore: add options menu to vault selection menu items (#2497)
This commit is contained in:
@@ -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>
|
||||
)
|
||||
|
||||
@@ -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
|
||||
@@ -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>
|
||||
)
|
||||
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user