chore: make mobile menu ui more native-like (#2594)

This commit is contained in:
Aman Harwara
2023-10-18 21:31:28 +05:30
committed by GitHub
parent 6a40f611f6
commit 2e3ac3ce57
32 changed files with 615 additions and 584 deletions

View File

@@ -6,13 +6,13 @@ import { useCallback, useMemo, useState, FunctionComponent } from 'react'
import { AccountMenuPane } from './AccountMenuPane' import { AccountMenuPane } from './AccountMenuPane'
import Menu from '@/Components/Menu/Menu' import Menu from '@/Components/Menu/Menu'
import MenuItem from '@/Components/Menu/MenuItem' import MenuItem from '@/Components/Menu/MenuItem'
import MenuItemSeparator from '@/Components/Menu/MenuItemSeparator'
import WorkspaceSwitcherOption from './WorkspaceSwitcher/WorkspaceSwitcherOption' import WorkspaceSwitcherOption from './WorkspaceSwitcher/WorkspaceSwitcherOption'
import { WebApplicationGroup } from '@/Application/WebApplicationGroup' import { WebApplicationGroup } from '@/Application/WebApplicationGroup'
import { formatLastSyncDate } from '@/Utils/DateUtils' import { formatLastSyncDate } from '@/Utils/DateUtils'
import Spinner from '@/Components/Spinner/Spinner' import Spinner from '@/Components/Spinner/Spinner'
import { MenuItemIconSize } from '@/Constants/TailwindClassNames' import { MenuItemIconSize } from '@/Constants/TailwindClassNames'
import { useApplication } from '../ApplicationProvider' import { useApplication } from '../ApplicationProvider'
import MenuSection from '../Menu/MenuSection'
type Props = { type Props = {
mainApplicationGroup: WebApplicationGroup mainApplicationGroup: WebApplicationGroup
@@ -92,7 +92,7 @@ const GeneralAccountMenu: FunctionComponent<Props> = ({ setMenuPane, closeMenu,
return ( return (
<> <>
<div className="mb-1 mt-1 hidden items-center justify-between px-3 md:flex"> <div className="mb-1 mt-1 hidden items-center justify-between px-4 md:flex md:px-3">
<div className="text-lg font-bold lg:text-base">Account</div> <div className="text-lg font-bold lg:text-base">Account</div>
<div className="flex cursor-pointer" onClick={closeMenu}> <div className="flex cursor-pointer" onClick={closeMenu}>
<Icon type="close" className="text-neutral" /> <Icon type="close" className="text-neutral" />
@@ -100,12 +100,12 @@ const GeneralAccountMenu: FunctionComponent<Props> = ({ setMenuPane, closeMenu,
</div> </div>
{user ? ( {user ? (
<> <>
<div className="mb-3 px-3 text-lg text-foreground lg:text-sm"> <div className="mb-3 px-4 text-lg text-foreground md:px-3 lg:text-sm">
<div>You're signed in as:</div> <div>You're signed in as:</div>
<div className="wrap my-0.5 font-bold">{user.email}</div> <div className="wrap my-0.5 font-bold">{user.email}</div>
<span className="text-neutral">{application.getHost.execute().getValue()}</span> <span className="text-neutral">{application.getHost.execute().getValue()}</span>
</div> </div>
<div className="mb-2 flex items-start justify-between px-3 text-mobile-menu-item md:text-tablet-menu-item lg:text-menu-item"> <div className="mb-2 flex items-start justify-between px-4 text-mobile-menu-item md:px-3 md:text-tablet-menu-item lg:text-menu-item">
{isSyncingInProgress ? ( {isSyncingInProgress ? (
<div className="flex items-center font-semibold text-info"> <div className="flex items-center font-semibold text-info">
<Spinner className="mr-2 h-5 w-5" /> <Spinner className="mr-2 h-5 w-5" />
@@ -127,7 +127,7 @@ const GeneralAccountMenu: FunctionComponent<Props> = ({ setMenuPane, closeMenu,
</> </>
) : ( ) : (
<> <>
<div className="mb-1 px-3"> <div className="mb-1 px-4 md:px-3">
<div className="mb-3 text-base text-foreground lg:text-sm"> <div className="mb-3 text-base text-foreground lg:text-sm">
Youre offline. Sign in to sync your notes and preferences across all your devices and enable end-to-end Youre offline. Sign in to sync your notes and preferences across all your devices and enable end-to-end
encryption. encryption.
@@ -145,56 +145,57 @@ const GeneralAccountMenu: FunctionComponent<Props> = ({ setMenuPane, closeMenu,
closeMenu={closeMenu} closeMenu={closeMenu}
initialFocus={!application.hasAccount() ? CREATE_ACCOUNT_INDEX : SWITCHER_INDEX} initialFocus={!application.hasAccount() ? CREATE_ACCOUNT_INDEX : SWITCHER_INDEX}
> >
<MenuItemSeparator /> <MenuSection className="md:border-t md:pt-2">
<WorkspaceSwitcherOption mainApplicationGroup={mainApplicationGroup} /> <WorkspaceSwitcherOption mainApplicationGroup={mainApplicationGroup} />
<MenuItemSeparator /> </MenuSection>
{user ? ( <MenuSection>
<MenuItem onClick={openPreferences}> {user ? (
<Icon type="user" className={iconClassName} /> <MenuItem onClick={openPreferences}>
Account settings
</MenuItem>
) : (
<>
<MenuItem onClick={activateRegisterPane}>
<Icon type="user" className={iconClassName} /> <Icon type="user" className={iconClassName} />
Create free account Account settings
</MenuItem> </MenuItem>
<MenuItem onClick={activateSignInPane}> ) : (
<Icon type="signIn" className={iconClassName} /> <>
Sign in <MenuItem onClick={activateRegisterPane}>
</MenuItem> <Icon type="user" className={iconClassName} />
</> Create free account
)} </MenuItem>
<MenuItem <MenuItem onClick={activateSignInPane}>
onClick={() => { <Icon type="signIn" className={iconClassName} />
application.importModalController.setIsVisible(true) Sign in
application.accountMenuController.closeAccountMenu() </MenuItem>
}} </>
> )}
<Icon type="archive" className={iconClassName} /> <MenuItem
Import onClick={() => {
</MenuItem> application.importModalController.setIsVisible(true)
{application.isNativeMobileWeb() && ( application.accountMenuController.closeAccountMenu()
<MenuItem onClick={openEmail}> }}
<Icon type="email-filled" className={iconClassName} /> >
Email us <Icon type="archive" className={iconClassName} />
Import
</MenuItem> </MenuItem>
)} {application.isNativeMobileWeb() && (
<MenuItem className="justify-between" onClick={openHelp}> <MenuItem onClick={openEmail}>
<div className="flex items-center"> <Icon type="email-filled" className={iconClassName} />
<Icon type="help" className={iconClassName} /> Email us
Help &amp; feedback </MenuItem>
</div> )}
<span className="text-neutral">v{application.version}</span> <MenuItem className="justify-between" onClick={openHelp}>
</MenuItem> <div className="flex items-center">
<Icon type="help" className={iconClassName} />
Help &amp; feedback
</div>
<span className="text-neutral">v{application.version}</span>
</MenuItem>
</MenuSection>
{user ? ( {user ? (
<> <MenuSection>
<MenuItemSeparator />
<MenuItem onClick={signOut}> <MenuItem onClick={signOut}>
<Icon type="signOut" className={iconClassName} /> <Icon type="signOut" className={iconClassName} />
Sign out workspace Sign out workspace
</MenuItem> </MenuItem>
</> </MenuSection>
) : null} ) : null}
</Menu> </Menu>
</> </>

View File

@@ -5,9 +5,9 @@ import { FunctionComponent, useCallback, useEffect, useState } from 'react'
import Icon from '@/Components/Icon/Icon' import Icon from '@/Components/Icon/Icon'
import Menu from '@/Components/Menu/Menu' import Menu from '@/Components/Menu/Menu'
import MenuItem from '@/Components/Menu/MenuItem' import MenuItem from '@/Components/Menu/MenuItem'
import MenuItemSeparator from '@/Components/Menu/MenuItemSeparator'
import WorkspaceMenuItem from './WorkspaceMenuItem' import WorkspaceMenuItem from './WorkspaceMenuItem'
import { useApplication } from '@/Components/ApplicationProvider' import { useApplication } from '@/Components/ApplicationProvider'
import MenuSection from '@/Components/Menu/MenuSection'
type Props = { type Props = {
mainApplicationGroup: WebApplicationGroup mainApplicationGroup: WebApplicationGroup
@@ -71,30 +71,32 @@ const WorkspaceSwitcherMenu: FunctionComponent<Props> = ({
}, [mainApplicationGroup]) }, [mainApplicationGroup])
return ( return (
<Menu a11yLabel="Workspace switcher menu" className="px-0 focus:shadow-none" isOpen={isOpen}> <Menu a11yLabel="Workspace switcher menu" className="focus:shadow-none" isOpen={isOpen}>
{applicationDescriptors.map((descriptor) => ( <MenuSection>
<WorkspaceMenuItem {applicationDescriptors.map((descriptor) => (
key={descriptor.identifier} <WorkspaceMenuItem
descriptor={descriptor} key={descriptor.identifier}
hideOptions={hideWorkspaceOptions} descriptor={descriptor}
onDelete={destroyWorkspace} hideOptions={hideWorkspaceOptions}
onClick={() => activateWorkspace(descriptor)} onDelete={destroyWorkspace}
renameDescriptor={(label: string) => mainApplicationGroup.renameDescriptor(descriptor, label)} onClick={() => activateWorkspace(descriptor)}
/> renameDescriptor={(label: string) => mainApplicationGroup.renameDescriptor(descriptor, label)}
))} />
<MenuItemSeparator /> ))}
</MenuSection>
<MenuItem onClick={addAnotherWorkspace}> <MenuSection>
<Icon type="user-add" className="mr-2 text-neutral" /> <MenuItem onClick={addAnotherWorkspace}>
Add another workspace <Icon type="user-add" className="mr-2 text-neutral" />
</MenuItem> Add another workspace
{!hideWorkspaceOptions && (
<MenuItem onClick={signoutAll}>
<Icon type="signOut" className="mr-2 text-neutral" />
Sign out all workspaces
</MenuItem> </MenuItem>
)} {!hideWorkspaceOptions && (
<MenuItem onClick={signoutAll}>
<Icon type="signOut" className="mr-2 text-neutral" />
Sign out all workspaces
</MenuItem>
)}
</MenuSection>
</Menu> </Menu>
) )
} }

View File

@@ -33,7 +33,7 @@ const WorkspaceSwitcherOption: FunctionComponent<Props> = ({ mainApplicationGrou
title="Switch workspace" title="Switch workspace"
align="end" align="end"
anchorElement={buttonRef} anchorElement={buttonRef}
className="py-2" className="pb-2"
open={isOpen} open={isOpen}
side="right" side="right"
togglePopover={toggleMenu} togglePopover={toggleMenu}

View File

@@ -28,7 +28,6 @@ const LockscreenWorkspaceSwitcher: FunctionComponent<Props> = ({ mainApplication
title="Switch workspace" title="Switch workspace"
align="center" align="center"
anchorElement={buttonRef} anchorElement={buttonRef}
className="py-2"
open={isOpen} open={isOpen}
overrideZIndex="z-modal" overrideZIndex="z-modal"
side="right" side="right"

View File

@@ -79,7 +79,7 @@ const ChangeEditorButton: FunctionComponent<Props> = ({ noteViewController, onCl
disableClickOutside={isClickOutsideDisabled} disableClickOutside={isClickOutsideDisabled}
anchorElement={buttonRef} anchorElement={buttonRef}
open={isOpen} open={isOpen}
className="pt-2 md:pt-0" className="md:pb-1"
> >
<ChangeEditorMenu <ChangeEditorMenu
application={application} application={application}

View File

@@ -13,7 +13,7 @@ import {
PrefKey, PrefKey,
SNNote, SNNote,
} from '@standardnotes/snjs' } from '@standardnotes/snjs'
import { Fragment, FunctionComponent, useCallback, useEffect, useMemo, useState } from 'react' import { FunctionComponent, useCallback, useEffect, useMemo, useState } from 'react'
import { EditorMenuGroup } from '@/Components/NotesOptions/EditorMenuGroup' import { EditorMenuGroup } from '@/Components/NotesOptions/EditorMenuGroup'
import { EditorMenuItem } from '@/Components/NotesOptions/EditorMenuItem' import { EditorMenuItem } from '@/Components/NotesOptions/EditorMenuItem'
import { createEditorMenuGroups } from '../../Utils/createEditorMenuGroups' import { createEditorMenuGroups } from '../../Utils/createEditorMenuGroups'
@@ -24,6 +24,7 @@ import MenuRadioButtonItem from '../Menu/MenuRadioButtonItem'
import { Pill } from '../Preferences/PreferencesComponents/Content' import { Pill } from '../Preferences/PreferencesComponents/Content'
import ModalOverlay from '../Modal/ModalOverlay' import ModalOverlay from '../Modal/ModalOverlay'
import SuperNoteConverter from '../SuperEditor/SuperNoteConverter' import SuperNoteConverter from '../SuperEditor/SuperNoteConverter'
import MenuSection from '../Menu/MenuSection'
type ChangeEditorMenuProps = { type ChangeEditorMenuProps = {
application: WebApplication application: WebApplication
@@ -210,48 +211,42 @@ const ChangeEditorMenu: FunctionComponent<ChangeEditorMenuProps> = ({
<Menu className="pb-1 pt-0.5" a11yLabel="Change note type menu" isOpen={isVisible}> <Menu className="pb-1 pt-0.5" a11yLabel="Change note type menu" isOpen={isVisible}>
{groups {groups
.filter((group) => group.items && group.items.length) .filter((group) => group.items && group.items.length)
.map((group, index) => { .map((group) => {
const groupId = getGroupId(group) const groupId = getGroupId(group)
return ( return (
<Fragment key={groupId}> <MenuSection key={groupId}>
<div {group.items.map((menuItem) => {
className={`border-0 border-t border-solid border-[--separator-color] py-1 ${ const onClickEditorItem = () => {
index === 0 ? 'border-t-0' : '' handleMenuSelection(menuItem).catch(console.error)
}`} }
>
{group.items.map((menuItem) => {
const onClickEditorItem = () => {
handleMenuSelection(menuItem).catch(console.error)
}
return ( return (
<MenuRadioButtonItem <MenuRadioButtonItem
key={menuItem.uiFeature.uniqueIdentifier.value} key={menuItem.uiFeature.uniqueIdentifier.value}
onClick={onClickEditorItem} onClick={onClickEditorItem}
className={'flex-row-reversed py-2'} className={'flex-row-reversed py-2'}
checked={isSelected(menuItem)} checked={isSelected(menuItem)}
info={menuItem.uiFeature.description} info={menuItem.uiFeature.description}
> >
<div className="flex flex-grow items-center justify-between"> <div className="flex flex-grow items-center justify-between">
<div className={`flex items-center ${group.featured ? 'font-bold' : ''}`}> <div className={`flex items-center ${group.featured ? 'font-bold' : ''}`}>
{group.icon && <Icon type={group.icon} className={`mr-2 ${group.iconClassName}`} />} {group.icon && <Icon type={group.icon} className={`mr-2 ${group.iconClassName}`} />}
{menuItem.uiFeature.displayName} {menuItem.uiFeature.displayName}
{menuItem.isLabs && ( {menuItem.isLabs && (
<Pill className="px-1.5 py-0.5" style="success"> <Pill className="px-1.5 py-0.5" style="success">
Labs Labs
</Pill> </Pill>
)}
</div>
{!menuItem.isEntitled && (
<Icon type={PremiumFeatureIconName} className={PremiumFeatureIconClass} />
)} )}
</div> </div>
</MenuRadioButtonItem> {!menuItem.isEntitled && (
) <Icon type={PremiumFeatureIconName} className={PremiumFeatureIconClass} />
})} )}
</div> </div>
</Fragment> </MenuRadioButtonItem>
)
})}
</MenuSection>
) )
})} })}
</Menu> </Menu>

View File

@@ -10,7 +10,7 @@ import {
NoteType, NoteType,
SNNote, SNNote,
} from '@standardnotes/snjs' } from '@standardnotes/snjs'
import { Fragment, useCallback, useMemo, useState } from 'react' import { useCallback, useMemo, useState } from 'react'
import Icon from '../Icon/Icon' import Icon from '../Icon/Icon'
import { PremiumFeatureIconName, PremiumFeatureIconClass } from '../Icon/PremiumFeatureIcon' import { PremiumFeatureIconName, PremiumFeatureIconClass } from '../Icon/PremiumFeatureIcon'
import Menu from '../Menu/Menu' import Menu from '../Menu/Menu'
@@ -20,6 +20,7 @@ import { EditorMenuItem } from '../NotesOptions/EditorMenuItem'
import { SuperNoteImporter } from '../SuperEditor/SuperNoteImporter' import { SuperNoteImporter } from '../SuperEditor/SuperNoteImporter'
import { Pill } from '../Preferences/PreferencesComponents/Content' import { Pill } from '../Preferences/PreferencesComponents/Content'
import ModalOverlay from '../Modal/ModalOverlay' import ModalOverlay from '../Modal/ModalOverlay'
import MenuSection from '../Menu/MenuSection'
const getGroupId = (group: EditorMenuGroup) => group.title.toLowerCase().replace(/\s/, '-') const getGroupId = (group: EditorMenuGroup) => group.title.toLowerCase().replace(/\s/, '-')
@@ -132,36 +133,34 @@ const ChangeEditorMultipleMenu = ({ application, notes, setDisableClickOutside }
return ( return (
<> <>
<Menu isOpen={true} a11yLabel="Change note type"> <Menu isOpen={true} a11yLabel="Change note type">
{groupsWithItems.map((group, index) => ( {groupsWithItems.map((group) => (
<Fragment key={getGroupId(group)}> <MenuSection key={getGroupId(group)}>
<div className={`border-0 border-t border-solid border-border py-1 ${index === 0 ? 'border-t-0' : ''}`}> {group.items.map((item) => {
{group.items.map((item) => { const onClickEditorItem = () => {
const onClickEditorItem = () => { handleMenuSelection(item).catch(console.error)
handleMenuSelection(item).catch(console.error) }
} return (
return ( <MenuItem
<MenuItem key={item.uiFeature.uniqueIdentifier.value}
key={item.uiFeature.uniqueIdentifier.value} onClick={onClickEditorItem}
onClick={onClickEditorItem} className={'flex-row-reversed py-2'}
className={'flex-row-reversed py-2'} >
> <div className="flex flex-grow items-center justify-between">
<div className="flex flex-grow items-center justify-between"> <div className={'flex items-center'}>
<div className={'flex items-center'}> {group.icon && <Icon type={group.icon} className={`mr-2 ${group.iconClassName}`} />}
{group.icon && <Icon type={group.icon} className={`mr-2 ${group.iconClassName}`} />} {item.uiFeature.displayName}
{item.uiFeature.displayName} {item.isLabs && (
{item.isLabs && ( <Pill className="px-1.5 py-0.5" style="success">
<Pill className="px-1.5 py-0.5" style="success"> Labs
Labs </Pill>
</Pill> )}
)}
</div>
{!item.isEntitled && <Icon type={PremiumFeatureIconName} className={PremiumFeatureIconClass} />}
</div> </div>
</MenuItem> {!item.isEntitled && <Icon type={PremiumFeatureIconName} className={PremiumFeatureIconClass} />}
) </div>
})} </MenuItem>
</div> )
</Fragment> })}
</MenuSection>
))} ))}
</Menu> </Menu>
<ModalOverlay isOpen={showSuperImporter} close={closeCurrentSuperNoteImporter}> <ModalOverlay isOpen={showSuperImporter} close={closeCurrentSuperNoteImporter}>

View File

@@ -25,7 +25,7 @@ const ChangeMultipleButton = ({ application, notesController }: Props) => {
disableClickOutside={disableClickOutside} disableClickOutside={disableClickOutside}
anchorElement={changeButtonRef} anchorElement={changeButtonRef}
open={isChangeMenuOpen} open={isChangeMenuOpen}
className="pt-2 md:pt-0" className="md:pb-1"
> >
<ChangeEditorMultipleMenu <ChangeEditorMultipleMenu
application={application} application={application}

View File

@@ -15,7 +15,6 @@ import { observer } from 'mobx-react-lite'
import { FunctionComponent, useCallback, useEffect, useState } from 'react' import { FunctionComponent, useCallback, useEffect, useState } from 'react'
import Icon from '@/Components/Icon/Icon' import Icon from '@/Components/Icon/Icon'
import Menu from '@/Components/Menu/Menu' import Menu from '@/Components/Menu/Menu'
import MenuItemSeparator from '@/Components/Menu/MenuItemSeparator'
import { DisplayOptionsMenuProps } from './DisplayOptionsMenuProps' import { DisplayOptionsMenuProps } from './DisplayOptionsMenuProps'
import NewNotePreferences from './NewNotePreferences' import NewNotePreferences from './NewNotePreferences'
import { PreferenceMode } from './PreferenceMode' import { PreferenceMode } from './PreferenceMode'
@@ -26,6 +25,7 @@ import MenuSwitchButtonItem from '@/Components/Menu/MenuSwitchButtonItem'
import { Pill } from '@/Components/Preferences/PreferencesComponents/Content' import { Pill } from '@/Components/Preferences/PreferencesComponents/Content'
import { MutuallyExclusiveMediaQueryBreakpoints, useMediaQuery } from '@/Hooks/useMediaQuery' import { MutuallyExclusiveMediaQueryBreakpoints, useMediaQuery } from '@/Hooks/useMediaQuery'
import { PaneLayout } from '@/Controllers/PaneController/PaneLayout' import { PaneLayout } from '@/Controllers/PaneController/PaneLayout'
import MenuSection from '@/Components/Menu/MenuSection'
const DailyEntryModeEnabled = true const DailyEntryModeEnabled = true
@@ -316,45 +316,43 @@ const DisplayOptionsMenu: FunctionComponent<DisplayOptionsMenuProps> = ({
/> />
)} )}
<MenuItemSeparator /> <MenuSection title="Sort by">
<MenuRadioButtonItem
disabled={controlsDisabled || isDailyEntry}
className="py-2"
onClick={toggleSortByDateModified}
checked={preferences.sortBy === CollectionSort.UpdatedAt}
>
<div className="ml-1 flex flex-grow items-center justify-between md:ml-2">
<span>Date modified</span>
<SortIcon enabled={preferences.sortBy === CollectionSort.UpdatedAt} reverse={preferences.sortReverse} />
</div>
</MenuRadioButtonItem>
<MenuRadioButtonItem
disabled={controlsDisabled || isDailyEntry}
className="py-2"
onClick={toggleSortByCreationDate}
checked={preferences.sortBy === CollectionSort.CreatedAt}
>
<div className="ml-1 flex flex-grow items-center justify-between md:ml-2">
<span>Creation date</span>
<SortIcon enabled={preferences.sortBy === CollectionSort.CreatedAt} reverse={preferences.sortReverse} />
</div>
</MenuRadioButtonItem>
<MenuRadioButtonItem
disabled={controlsDisabled || isDailyEntry}
className="py-2"
onClick={toggleSortByTitle}
checked={preferences.sortBy === CollectionSort.Title}
>
<div className="ml-1 flex flex-grow items-center justify-between md:ml-2">
<span>Title</span>
<SortIcon enabled={preferences.sortBy === CollectionSort.Title} reverse={preferences.sortReverse} />
</div>
</MenuRadioButtonItem>
</MenuSection>
<div className="my-1 px-3 text-base font-semibold uppercase text-text lg:text-xs">Sort by</div> <MenuSection title="View">
<MenuRadioButtonItem
disabled={controlsDisabled || isDailyEntry}
className="py-2"
onClick={toggleSortByDateModified}
checked={preferences.sortBy === CollectionSort.UpdatedAt}
>
<div className="ml-1 flex flex-grow items-center justify-between md:ml-2">
<span>Date modified</span>
<SortIcon enabled={preferences.sortBy === CollectionSort.UpdatedAt} reverse={preferences.sortReverse} />
</div>
</MenuRadioButtonItem>
<MenuRadioButtonItem
disabled={controlsDisabled || isDailyEntry}
className="py-2"
onClick={toggleSortByCreationDate}
checked={preferences.sortBy === CollectionSort.CreatedAt}
>
<div className="ml-1 flex flex-grow items-center justify-between md:ml-2">
<span>Creation date</span>
<SortIcon enabled={preferences.sortBy === CollectionSort.CreatedAt} reverse={preferences.sortReverse} />
</div>
</MenuRadioButtonItem>
<MenuRadioButtonItem
disabled={controlsDisabled || isDailyEntry}
className="py-2"
onClick={toggleSortByTitle}
checked={preferences.sortBy === CollectionSort.Title}
>
<div className="ml-1 flex flex-grow items-center justify-between md:ml-2">
<span>Title</span>
<SortIcon enabled={preferences.sortBy === CollectionSort.Title} reverse={preferences.sortReverse} />
</div>
</MenuRadioButtonItem>
<>
<MenuItemSeparator />
<div className="px-3 py-1 text-base font-semibold uppercase text-text lg:text-xs">View</div>
{!shouldHideNonApplicableOptions && !isFilesSmartView && ( {!shouldHideNonApplicableOptions && !isFilesSmartView && (
<MenuSwitchButtonItem <MenuSwitchButtonItem
disabled={controlsDisabled} disabled={controlsDisabled}
@@ -389,49 +387,47 @@ const DisplayOptionsMenu: FunctionComponent<DisplayOptionsMenuProps> = ({
> >
Show icon Show icon
</MenuSwitchButtonItem> </MenuSwitchButtonItem>
{!shouldHideNonApplicableOptions && ( </MenuSection>
<>
<MenuItemSeparator /> {!shouldHideNonApplicableOptions && (
<div className="px-3 py-1 text-base font-semibold uppercase text-text lg:text-xs">Other</div> <MenuSection title="Other">
<MenuSwitchButtonItem <MenuSwitchButtonItem
disabled={controlsDisabled} disabled={controlsDisabled}
className="py-1 hover:bg-contrast focus:bg-info-backdrop" className="py-1 hover:bg-contrast focus:bg-info-backdrop"
checked={!preferences.hidePinned} checked={!preferences.hidePinned}
onChange={toggleHidePinned} onChange={toggleHidePinned}
> >
Show pinned Show pinned
</MenuSwitchButtonItem> </MenuSwitchButtonItem>
<MenuSwitchButtonItem <MenuSwitchButtonItem
disabled={controlsDisabled} disabled={controlsDisabled}
className="py-1 hover:bg-contrast focus:bg-info-backdrop" className="py-1 hover:bg-contrast focus:bg-info-backdrop"
checked={!preferences.hideProtected} checked={!preferences.hideProtected}
onChange={toggleHideProtected} onChange={toggleHideProtected}
> >
Show protected Show protected
</MenuSwitchButtonItem> </MenuSwitchButtonItem>
<MenuSwitchButtonItem <MenuSwitchButtonItem
disabled={controlsDisabled} disabled={controlsDisabled}
className="py-1 hover:bg-contrast focus:bg-info-backdrop" className="py-1 hover:bg-contrast focus:bg-info-backdrop"
checked={Boolean(preferences.showArchived)} checked={Boolean(preferences.showArchived)}
onChange={toggleShowArchived} onChange={toggleShowArchived}
> >
Show archived Show archived
</MenuSwitchButtonItem> </MenuSwitchButtonItem>
<MenuSwitchButtonItem <MenuSwitchButtonItem
disabled={controlsDisabled} disabled={controlsDisabled}
className="py-1 hover:bg-contrast focus:bg-info-backdrop" className="py-1 hover:bg-contrast focus:bg-info-backdrop"
checked={Boolean(preferences.showTrashed)} checked={Boolean(preferences.showTrashed)}
onChange={toggleShowTrashed} onChange={toggleShowTrashed}
> >
Show trashed Show trashed
</MenuSwitchButtonItem> </MenuSwitchButtonItem>
</> </MenuSection>
)} )}
</>
{currentMode === 'tag' && !isSystemTag && DailyEntryModeEnabled && !isTableViewEnabled && ( {currentMode === 'tag' && !isSystemTag && DailyEntryModeEnabled && !isTableViewEnabled && (
<> <MenuSection>
<MenuItemSeparator />
<MenuSwitchButtonItem <MenuSwitchButtonItem
disabled={controlsDisabled} disabled={controlsDisabled}
className="py-1 hover:bg-contrast focus:bg-info-backdrop" className="py-1 hover:bg-contrast focus:bg-info-backdrop"
@@ -441,19 +437,18 @@ const DisplayOptionsMenu: FunctionComponent<DisplayOptionsMenuProps> = ({
<div className="flex flex-col pr-5"> <div className="flex flex-col pr-5">
<div className="flex flex-row items-center"> <div className="flex flex-row items-center">
<div className="text-base font-semibold uppercase text-text lg:text-xs">Daily Notebook</div> <div className="text-base font-semibold uppercase text-text lg:text-xs">Daily Notebook</div>
<Pill className="px-1.5 !py-0.5" style="success"> <Pill className="!py-0.5 px-1.5" style="success">
Labs Labs
</Pill> </Pill>
</div> </div>
<div className="mt-1">Capture new notes daily with a calendar-based layout</div> <div className="mt-1">Capture new notes daily with a calendar-based layout</div>
</div> </div>
</MenuSwitchButtonItem> </MenuSwitchButtonItem>
</> </MenuSection>
)} )}
{currentMode === 'tag' && !isSystemTag && !isDailyEntry && ( {currentMode === 'tag' && !isSystemTag && !isDailyEntry && (
<> <MenuSection>
<MenuItemSeparator />
<MenuSwitchButtonItem <MenuSwitchButtonItem
disabled={controlsDisabled} disabled={controlsDisabled}
className="py-1 hover:bg-contrast focus:bg-info-backdrop" className="py-1 hover:bg-contrast focus:bg-info-backdrop"
@@ -463,19 +458,18 @@ const DisplayOptionsMenu: FunctionComponent<DisplayOptionsMenuProps> = ({
<div className="flex flex-col pr-5"> <div className="flex flex-col pr-5">
<div className="flex flex-row items-center"> <div className="flex flex-row items-center">
<div className="text-base font-semibold uppercase text-text lg:text-xs">Table view</div> <div className="text-base font-semibold uppercase text-text lg:text-xs">Table view</div>
<Pill className="px-1.5 !py-0.5" style="success"> <Pill className="!py-0.5 px-1.5" style="success">
Labs Labs
</Pill> </Pill>
</div> </div>
<div className="mt-1">Display the notes and files in the current tag in a table layout</div> <div className="mt-1">Display the notes and files in the current tag in a table layout</div>
</div> </div>
</MenuSwitchButtonItem> </MenuSwitchButtonItem>
</> </MenuSection>
)} )}
{!shouldHideNonApplicableOptions && (!isSystemTag || currentMode === 'global') && ( {!shouldHideNonApplicableOptions && (!isSystemTag || currentMode === 'global') && (
<> <MenuSection title="New note defaults">
<MenuItemSeparator />
<NewNotePreferences <NewNotePreferences
disabled={controlsDisabled} disabled={controlsDisabled}
application={application} application={application}
@@ -483,7 +477,7 @@ const DisplayOptionsMenu: FunctionComponent<DisplayOptionsMenuProps> = ({
mode={currentMode} mode={currentMode}
changePreferencesCallback={changePreferences} changePreferencesCallback={changePreferences}
/> />
</> </MenuSection>
)} )}
</Menu> </Menu>
) )

View File

@@ -173,10 +173,9 @@ const NewNotePreferences: FunctionComponent<Props> = ({
} }
return ( return (
<div className="my-1 px-3 pb-2 pt-1"> <div className="px-3 py-3">
<div className="text-base font-semibold uppercase text-text lg:text-xs">New Note Defaults</div>
<div> <div>
<div className="mt-3 text-mobile-menu-item md:text-menu-item">Note Type</div> <div className="text-mobile-menu-item md:text-menu-item">Note Type</div>
<div className="mt-2"> <div className="mt-2">
<Dropdown <Dropdown
disabled={disabled} disabled={disabled}

View File

@@ -22,7 +22,7 @@ const FileContextMenu: FunctionComponent<Props> = observer(({ filesController, i
anchorPoint={fileContextMenuLocation} anchorPoint={fileContextMenuLocation}
togglePopover={() => setShowFileContextMenu(!showFileContextMenu)} togglePopover={() => setShowFileContextMenu(!showFileContextMenu)}
align="start" align="start"
className="py-2" className="md:pb-2"
> >
<Menu a11yLabel="File context menu" isOpen={showFileContextMenu}> <Menu a11yLabel="File context menu" isOpen={showFileContextMenu}>
<FileMenuOptions <FileMenuOptions

View File

@@ -4,6 +4,7 @@ import { useApplication } from '../ApplicationProvider'
import { FileBackupRecord, FileItem } from '@standardnotes/snjs' import { FileBackupRecord, FileItem } from '@standardnotes/snjs'
import { dateToStringStyle1 } from '@/Utils/DateUtils' import { dateToStringStyle1 } from '@/Utils/DateUtils'
import { MenuItemIconSize } from '@/Constants/TailwindClassNames' import { MenuItemIconSize } from '@/Constants/TailwindClassNames'
import MenuSection from '../Menu/MenuSection'
export const FileContextMenuBackupOption: FunctionComponent<{ file: FileItem }> = ({ file }) => { export const FileContextMenuBackupOption: FunctionComponent<{ file: FileItem }> = ({ file }) => {
const application = useApplication() const application = useApplication()
@@ -33,8 +34,12 @@ export const FileContextMenuBackupOption: FunctionComponent<{ file: FileItem }>
application.openPreferences('backups') application.openPreferences('backups')
}, [application]) }, [application])
if (!application.fileBackups) {
return null
}
return ( return (
<> <MenuSection>
{backupInfo && ( {backupInfo && (
<MenuItem <MenuItem
icon={'check-circle'} icon={'check-circle'}
@@ -62,6 +67,6 @@ export const FileContextMenuBackupOption: FunctionComponent<{ file: FileItem }>
</div> </div>
</MenuItem> </MenuItem>
)} )}
</> </MenuSection>
) )
} }

View File

@@ -2,7 +2,6 @@ import { FunctionComponent, useCallback, useMemo } from 'react'
import { FileItemActionType } from '../AttachedFilesPopover/PopoverFileItemAction' import { FileItemActionType } from '../AttachedFilesPopover/PopoverFileItemAction'
import Icon from '@/Components/Icon/Icon' import Icon from '@/Components/Icon/Icon'
import { observer } from 'mobx-react-lite' import { observer } from 'mobx-react-lite'
import HorizontalSeparator from '../Shared/HorizontalSeparator'
import { formatSizeToReadableString } from '@standardnotes/filepicker' import { formatSizeToReadableString } from '@standardnotes/filepicker'
import { useResponsiveAppPane } from '../Panes/ResponsivePaneProvider' import { useResponsiveAppPane } from '../Panes/ResponsivePaneProvider'
import { AppPaneId } from '../Panes/AppPaneMetadata' import { AppPaneId } from '../Panes/AppPaneMetadata'
@@ -15,6 +14,7 @@ import { MenuItemIconSize } from '@/Constants/TailwindClassNames'
import AddToVaultMenuOption from '../Vaults/AddToVaultMenuOption' import AddToVaultMenuOption from '../Vaults/AddToVaultMenuOption'
import { iconClass } from '../NotesOptions/ClassNames' import { iconClass } from '../NotesOptions/ClassNames'
import { useApplication } from '../ApplicationProvider' import { useApplication } from '../ApplicationProvider'
import MenuSection from '../Menu/MenuSection'
type Props = { type Props = {
closeMenu: () => void closeMenu: () => void
@@ -87,8 +87,8 @@ const FileMenuOptions: FunctionComponent<Props> = ({
return ( return (
<> <>
{selectedFiles.length === 1 && ( {selectedFiles.length === 1 && (isFileAttachedToNote || shouldShowAttachOption) && (
<> <MenuSection>
{isFileAttachedToNote ? ( {isFileAttachedToNote ? (
<MenuItem onClick={onDetach}> <MenuItem onClick={onDetach}>
<Icon type="link-off" className="mr-2 text-neutral" /> <Icon type="link-off" className="mr-2 text-neutral" />
@@ -100,67 +100,69 @@ const FileMenuOptions: FunctionComponent<Props> = ({
Attach to note Attach to note
</MenuItem> </MenuItem>
) : null} ) : null}
</> </MenuSection>
)} )}
{application.featuresController.isVaultsEnabled() && ( <MenuSection>
<AddToVaultMenuOption {application.featuresController.isVaultsEnabled() && (
iconClassName={iconClass} <AddToVaultMenuOption
items={selectedFiles} iconClassName={iconClass}
disabled={!hasAdminPermissionForAllSharedFiles} items={selectedFiles}
disabled={!hasAdminPermissionForAllSharedFiles}
/>
)}
<AddTagOption
navigationController={application.navigationController}
linkingController={application.linkingController}
selectedItems={selectedFiles}
iconClassName={`text-neutral mr-2 ${MenuItemIconSize}`}
disabled={areSomeFilesInReadonlySharedVault}
/> />
)} <MenuSwitchButtonItem
<AddTagOption checked={hasProtectedFiles}
navigationController={application.navigationController} onChange={(hasProtectedFiles) => {
linkingController={application.linkingController} void application.filesController.setProtectionForFiles(hasProtectedFiles, selectedFiles)
selectedItems={selectedFiles}
iconClassName={`text-neutral mr-2 ${MenuItemIconSize}`}
disabled={areSomeFilesInReadonlySharedVault}
/>
<MenuSwitchButtonItem
checked={hasProtectedFiles}
onChange={(hasProtectedFiles) => {
void application.filesController.setProtectionForFiles(hasProtectedFiles, selectedFiles)
}}
disabled={areSomeFilesInReadonlySharedVault}
>
<Icon type="lock" className={`mr-2 text-neutral ${MenuItemIconSize}`} />
Password protect
</MenuSwitchButtonItem>
<HorizontalSeparator classes="my-1" />
<MenuItem
onClick={() => {
void application.filesController.downloadFiles(selectedFiles)
closeMenu()
}}
>
<Icon type="download" className={`mr-2 text-neutral ${MenuItemIconSize}`} />
Download
</MenuItem>
{shouldShowRenameOption && (
<MenuItem
onClick={() => {
renameToggleCallback?.(true)
}} }}
disabled={areSomeFilesInReadonlySharedVault} disabled={areSomeFilesInReadonlySharedVault}
> >
<Icon type="pencil" className={`mr-2 text-neutral ${MenuItemIconSize}`} /> <Icon type="lock" className={`mr-2 text-neutral ${MenuItemIconSize}`} />
Rename Password protect
</MenuSwitchButtonItem>
</MenuSection>
<MenuSection>
<MenuItem
onClick={() => {
void application.filesController.downloadFiles(selectedFiles)
closeMenu()
}}
>
<Icon type="download" className={`mr-2 text-neutral ${MenuItemIconSize}`} />
Download
</MenuItem> </MenuItem>
)} {shouldShowRenameOption && (
<MenuItem <MenuItem
onClick={() => { onClick={() => {
closeMenuAndToggleFilesList() renameToggleCallback?.(true)
void application.filesController.deleteFilesPermanently(selectedFiles) }}
}} disabled={areSomeFilesInReadonlySharedVault}
disabled={areSomeFilesInReadonlySharedVault} >
> <Icon type="pencil" className={`mr-2 text-neutral ${MenuItemIconSize}`} />
<Icon type="trash" className={`mr-2 text-danger ${MenuItemIconSize}`} /> Rename
<span className="text-danger">Delete permanently</span> </MenuItem>
</MenuItem> )}
<MenuItem
onClick={() => {
closeMenuAndToggleFilesList()
void application.filesController.deleteFilesPermanently(selectedFiles)
}}
disabled={areSomeFilesInReadonlySharedVault}
>
<Icon type="trash" className={`mr-2 text-danger ${MenuItemIconSize}`} />
<span className="text-danger">Delete permanently</span>
</MenuItem>
</MenuSection>
<FileContextMenuBackupOption file={selectedFiles[0]} /> <FileContextMenuBackupOption file={selectedFiles[0]} />
<HorizontalSeparator classes="my-2" />
<div className="px-3 pb-0.5 pt-1 text-xs font-medium text-neutral"> <div className="px-3 pb-0.5 pt-1 text-xs font-medium text-neutral">
{!hasSelectedMultipleFiles && ( {!hasSelectedMultipleFiles && (
<div className="mb-1"> <div className="mb-1">

View File

@@ -19,7 +19,13 @@ const FilesOptionsPanel = ({ itemListController }: Props) => {
return ( return (
<> <>
<RoundIconButton label="File options menu" onClick={toggleMenu} ref={buttonRef} icon="more" /> <RoundIconButton label="File options menu" onClick={toggleMenu} ref={buttonRef} icon="more" />
<Popover title="File options" togglePopover={toggleMenu} anchorElement={buttonRef} open={isOpen} className="py-2"> <Popover
title="File options"
togglePopover={toggleMenu}
anchorElement={buttonRef}
open={isOpen}
className="md:pb-2"
>
<Menu a11yLabel="File options panel" isOpen={isOpen}> <Menu a11yLabel="File options panel" isOpen={isOpen}>
<FileMenuOptions <FileMenuOptions
selectedFiles={itemListController.selectedFiles} selectedFiles={itemListController.selectedFiles}

View File

@@ -221,7 +221,7 @@ const FilePreviewModal = observer(({ application }: Props) => {
togglePopover={closeOptionsMenu} togglePopover={closeOptionsMenu}
side="bottom" side="bottom"
align="start" align="start"
className="py-2" className="md:pb-2"
overrideZIndex="z-modal" overrideZIndex="z-modal"
> >
<Menu a11yLabel="File context menu" isOpen={showOptionsMenu}> <Menu a11yLabel="File context menu" isOpen={showOptionsMenu}>

View File

@@ -55,7 +55,7 @@ const QuickSettingsButton = ({ application, isMobileNavigation = false }: Props)
open={isOpen} open={isOpen}
side="top" side="top"
align="start" align="start"
className="py-2" className="md:py-2"
> >
<QuickSettingsMenu closeMenu={toggleMenu} /> <QuickSettingsMenu closeMenu={toggleMenu} />
</Popover> </Popover>

View File

@@ -68,7 +68,7 @@ const Menu = forwardRef(
return ( return (
<menu <menu
className={`m-0 list-none pl-0 focus:shadow-none ${className}`} className={`m-0 list-none px-4 focus:shadow-none md:px-0 ${className}`}
onKeyDown={handleKeyDown} onKeyDown={handleKeyDown}
ref={mergeRefs([menuElementRef, forwardedRef])} ref={mergeRefs([menuElementRef, forwardedRef])}
style={style} style={style}

View File

@@ -40,7 +40,7 @@ const MenuItem = forwardRef(
role="menuitem" role="menuitem"
tabIndex={typeof tabIndex === 'number' ? tabIndex : FOCUSABLE_BUT_NOT_TABBABLE} tabIndex={typeof tabIndex === 'number' ? tabIndex : FOCUSABLE_BUT_NOT_TABBABLE}
className={classNames( className={classNames(
'flex w-full cursor-pointer select-none border-0 bg-transparent px-3 py-2 text-left md:py-1.5', 'flex w-full cursor-pointer select-none border-0 bg-transparent px-3 py-2.5 text-left md:py-1.5',
'text-mobile-menu-item text-text enabled:hover:bg-contrast enabled:hover:text-foreground', 'text-mobile-menu-item text-text enabled:hover:bg-contrast enabled:hover:text-foreground',
'focus:bg-info-backdrop focus:shadow-none md:text-tablet-menu-item lg:text-menu-item', 'focus:bg-info-backdrop focus:shadow-none md:text-tablet-menu-item lg:text-menu-item',
'disabled:cursor-not-allowed disabled:opacity-60', 'disabled:cursor-not-allowed disabled:opacity-60',

View File

@@ -74,7 +74,7 @@ const MenuRadioButtonItem = forwardRef(
role="menuitemradio" role="menuitemradio"
tabIndex={typeof tabIndex === 'number' ? tabIndex : FOCUSABLE_BUT_NOT_TABBABLE} tabIndex={typeof tabIndex === 'number' ? tabIndex : FOCUSABLE_BUT_NOT_TABBABLE}
className={classNames( className={classNames(
'flex w-full cursor-pointer gap-2 border-0 bg-transparent px-3 py-2 text-left md:py-1.5', 'flex w-full cursor-pointer gap-2 border-0 bg-transparent px-3 py-2.5 text-left md:py-1.5',
'text-mobile-menu-item text-text hover:bg-contrast hover:text-foreground', 'text-mobile-menu-item text-text hover:bg-contrast hover:text-foreground',
'focus:bg-info-backdrop focus:shadow-none md:text-tablet-menu-item lg:text-menu-item', 'focus:bg-info-backdrop focus:shadow-none md:text-tablet-menu-item lg:text-menu-item',
className, className,

View File

@@ -0,0 +1,26 @@
import { classNames } from '@standardnotes/snjs'
import { ReactNode } from 'react'
const MenuSection = ({
title,
className,
children,
}: {
title?: ReactNode
className?: string
children: ReactNode
}) => {
return (
<div
className={classNames(
'my-4 md:my-2 md:border-b md:border-border md:pb-2 md:last:mb-0 md:last:border-b-0 md:last:pb-0 md:translucent-ui:border-[--popover-border-color]',
className,
)}
>
{title && <div className="px-3 py-1 text-sm font-semibold uppercase text-text lg:text-xs">{title}</div>}
<div className="divide-y divide-passive-3 rounded bg-passive-4 md:divide-none md:bg-transparent">{children}</div>
</div>
)
}
export default MenuSection

View File

@@ -36,7 +36,7 @@ const MenuSwitchButtonItem = forwardRef(
disabled={disabled} disabled={disabled}
ref={ref} ref={ref}
className={classNames( className={classNames(
'flex w-full cursor-pointer items-center border-0 bg-transparent px-3 py-1.5', 'flex w-full cursor-pointer items-center border-0 bg-transparent px-3 py-2 md:py-1.5',
'text-left text-text focus:bg-info-backdrop focus:shadow-none enabled:hover:bg-contrast enabled:hover:text-foreground', 'text-left text-text focus:bg-info-backdrop focus:shadow-none enabled:hover:bg-contrast enabled:hover:text-foreground',
'text-mobile-menu-item md:text-tablet-menu-item lg:text-menu-item', 'text-mobile-menu-item md:text-tablet-menu-item lg:text-menu-item',
'disabled:cursor-not-allowed disabled:opacity-60', 'disabled:cursor-not-allowed disabled:opacity-60',

View File

@@ -26,7 +26,6 @@ const NotesContextMenu = () => {
y: contextMenuClickLocation.y, y: contextMenuClickLocation.y,
}} }}
disableClickOutside={disableClickOutside} disableClickOutside={disableClickOutside}
className="py-2"
open={contextMenuOpen} open={contextMenuOpen}
togglePopover={closeMenu} togglePopover={closeMenu}
> >

View File

@@ -77,7 +77,7 @@ const AddTagOption: FunctionComponent<Props> = ({
className="py-2" className="py-2"
overrideZIndex="z-modal" overrideZIndex="z-modal"
> >
<Menu a11yLabel="Tag selection menu" isOpen={isOpen}> <Menu a11yLabel="Tag selection menu" isOpen={isOpen} className="!px-0">
{navigationController.tags.map((tag) => ( {navigationController.tags.map((tag) => (
<MenuItem <MenuItem
key={tag.uuid} key={tag.uuid}

View File

@@ -60,7 +60,7 @@ const ChangeEditorOption: FunctionComponent<ChangeEditorOptionProps> = ({
title="Change note type" title="Change note type"
align="start" align="start"
anchorElement={buttonRef} anchorElement={buttonRef}
className="pt-2 md:pt-0" className="md:pb-1"
open={isOpen} open={isOpen}
side="right" side="right"
togglePopover={toggleMenu} togglePopover={toggleMenu}

View File

@@ -1,10 +1,11 @@
import { WebApplication } from '@/Application/WebApplication' import { WebApplication } from '@/Application/WebApplication'
import { Action, SNNote } from '@standardnotes/snjs' import { Action, SNNote } from '@standardnotes/snjs'
import { Fragment, useCallback, useEffect, useState } from 'react' import { useCallback, useEffect, useState } from 'react'
import Icon from '@/Components/Icon/Icon' import Icon from '@/Components/Icon/Icon'
import { ListedMenuGroup } from './ListedMenuGroup' import { ListedMenuGroup } from './ListedMenuGroup'
import ListedMenuItem from './ListedMenuItem' import ListedMenuItem from './ListedMenuItem'
import Spinner from '@/Components/Spinner/Spinner' import Spinner from '@/Components/Spinner/Spinner'
import MenuSection from '@/Components/Menu/MenuSection'
type ListedActionsMenuProps = { type ListedActionsMenuProps = {
application: WebApplication application: WebApplication
@@ -125,15 +126,15 @@ const ListedActionsMenu = ({ application, note }: ListedActionsMenuProps) => {
)} )}
{!isFetchingAccounts && menuGroups.length ? ( {!isFetchingAccounts && menuGroups.length ? (
<> <>
{menuGroups.map((group, index) => ( {menuGroups.map((group) => (
<Fragment key={group.account.authorId}> <MenuSection
<div key={group.account.authorId}
className={`text-input flex w-full items-center border-y border-solid border-border px-2.5 py-2 font-semibold text-text ${ title={
index === 0 ? 'mb-1 border-t-0' : 'my-1' <div className="flex items-center">
}`} <Icon type="notes" className="mr-2 text-info" /> {group.name}
> </div>
<Icon type="notes" className="mr-2 text-info" /> {group.name} }
</div> >
{group.actions.length ? ( {group.actions.length ? (
group.actions.map((action) => ( group.actions.map((action) => (
<ListedMenuItem <ListedMenuItem
@@ -148,7 +149,7 @@ const ListedActionsMenu = ({ application, note }: ListedActionsMenuProps) => {
) : ( ) : (
<div className="select-none px-3 py-2 text-sm text-passive-0">No actions available</div> <div className="select-none px-3 py-2 text-sm text-passive-0">No actions available</div>
)} )}
</Fragment> </MenuSection>
))} ))}
</> </>
) : null} ) : null}

View File

@@ -54,7 +54,7 @@ const ListedActionsOption: FunctionComponent<Props> = ({ application, note, icon
open={isOpen} open={isOpen}
side="right" side="right"
align="end" align="end"
className="pt-2 md:pt-0" className="px-4 md:px-0 md:pt-0"
> >
<ListedActionsMenu application={application} note={note} /> <ListedActionsMenu application={application} note={note} />
</Popover> </Popover>

View File

@@ -18,7 +18,6 @@ import ListedActionsOption from './Listed/ListedActionsOption'
import AddTagOption from './AddTagOption' import AddTagOption from './AddTagOption'
import { addToast, dismissToast, ToastType } from '@standardnotes/toast' import { addToast, dismissToast, ToastType } from '@standardnotes/toast'
import { NotesOptionsProps } from './NotesOptionsProps' import { NotesOptionsProps } from './NotesOptionsProps'
import HorizontalSeparator from '../Shared/HorizontalSeparator'
import { useResponsiveAppPane } from '../Panes/ResponsivePaneProvider' import { useResponsiveAppPane } from '../Panes/ResponsivePaneProvider'
import { AppPaneId } from '../Panes/AppPaneMetadata' import { AppPaneId } from '../Panes/AppPaneMetadata'
import { getNoteBlob, getNoteFileName } from '@/Utils/NoteExportUtils' import { getNoteBlob, getNoteFileName } from '@/Utils/NoteExportUtils'
@@ -42,6 +41,7 @@ import { MutuallyExclusiveMediaQueryBreakpoints } from '@/Hooks/useMediaQuery'
import AddToVaultMenuOption from '../Vaults/AddToVaultMenuOption' import AddToVaultMenuOption from '../Vaults/AddToVaultMenuOption'
import Menu from '../Menu/Menu' import Menu from '../Menu/Menu'
import Popover from '../Popover/Popover' import Popover from '../Popover/Popover'
import MenuSection from '../Menu/MenuSection'
const iconSize = MenuItemIconSize const iconSize = MenuItemIconSize
const iconClassDanger = `text-danger mr-2 ${iconSize}` const iconClassDanger = `text-danger mr-2 ${iconSize}`
@@ -230,271 +230,282 @@ const NotesOptions = ({ notes, closeMenu }: NotesOptionsProps) => {
<> <>
{notes.length === 1 && ( {notes.length === 1 && (
<> <>
<MenuItem onClick={openRevisionHistoryModal}> <MenuSection>
<Icon type="history" className={iconClass} /> <MenuItem onClick={openRevisionHistoryModal}>
Note history <Icon type="history" className={iconClass} />
{historyShortcut && <KeyboardShortcutIndicator className="ml-auto" shortcut={historyShortcut} />} Note history
</MenuItem> {historyShortcut && <KeyboardShortcutIndicator className="ml-auto" shortcut={historyShortcut} />}
<HorizontalSeparator classes="my-2" /> </MenuItem>
<MenuItem onClick={toggleLineWidthModal} disabled={areSomeNotesInReadonlySharedVault}> </MenuSection>
<Icon type="line-width" className={iconClass} /> <MenuSection>
Editor width <MenuItem onClick={toggleLineWidthModal} disabled={areSomeNotesInReadonlySharedVault}>
{editorWidthShortcut && <KeyboardShortcutIndicator className="ml-auto" shortcut={editorWidthShortcut} />} <Icon type="line-width" className={iconClass} />
</MenuItem> Editor width
{editorWidthShortcut && <KeyboardShortcutIndicator className="ml-auto" shortcut={editorWidthShortcut} />}
</MenuItem>
</MenuSection>
</> </>
)} )}
<MenuSwitchButtonItem <MenuSection>
checked={locked} <MenuSwitchButtonItem
onChange={(locked) => { checked={locked}
application.notesController.setLockSelectedNotes(locked) onChange={(locked) => {
}} application.notesController.setLockSelectedNotes(locked)
disabled={areSomeNotesInReadonlySharedVault} }}
> disabled={areSomeNotesInReadonlySharedVault}
<Icon type="pencil-off" className={iconClass} /> >
Prevent editing <Icon type="pencil-off" className={iconClass} />
</MenuSwitchButtonItem> Prevent editing
<MenuSwitchButtonItem </MenuSwitchButtonItem>
checked={!hidePreviews} <MenuSwitchButtonItem
onChange={(hidePreviews) => { checked={!hidePreviews}
application.notesController.setHideSelectedNotePreviews(!hidePreviews) onChange={(hidePreviews) => {
}} application.notesController.setHideSelectedNotePreviews(!hidePreviews)
disabled={areSomeNotesInReadonlySharedVault} }}
> disabled={areSomeNotesInReadonlySharedVault}
<Icon type="rich-text" className={iconClass} /> >
Show preview <Icon type="rich-text" className={iconClass} />
</MenuSwitchButtonItem> Show preview
<MenuSwitchButtonItem </MenuSwitchButtonItem>
checked={protect} <MenuSwitchButtonItem
onChange={(protect) => { checked={protect}
application.notesController.setProtectSelectedNotes(protect).catch(console.error) onChange={(protect) => {
}} application.notesController.setProtectSelectedNotes(protect).catch(console.error)
disabled={areSomeNotesInReadonlySharedVault} }}
> disabled={areSomeNotesInReadonlySharedVault}
<Icon type="lock" className={iconClass} /> >
Password protect <Icon type="lock" className={iconClass} />
</MenuSwitchButtonItem> Password protect
</MenuSwitchButtonItem>
</MenuSection>
{notes.length === 1 && ( {notes.length === 1 && (
<> <MenuSection>
<HorizontalSeparator classes="my-2" />
<ChangeEditorOption <ChangeEditorOption
iconClassName={iconClass} iconClassName={iconClass}
application={application} application={application}
note={notes[0]} note={notes[0]}
disabled={areSomeNotesInReadonlySharedVault} disabled={areSomeNotesInReadonlySharedVault}
/> />
</> </MenuSection>
)}
<HorizontalSeparator classes="my-2" />
{application.featuresController.isVaultsEnabled() && (
<AddToVaultMenuOption iconClassName={iconClass} items={notes} disabled={!hasAdminPermissionForAllSharedNotes} />
)} )}
{application.navigationController.tagsCount > 0 && ( <MenuSection>
<AddTagOption {application.featuresController.isVaultsEnabled() && (
iconClassName={iconClass} <AddToVaultMenuOption
navigationController={application.navigationController} iconClassName={iconClass}
selectedItems={notes} items={notes}
linkingController={application.linkingController} disabled={!hasAdminPermissionForAllSharedNotes}
disabled={areSomeNotesInReadonlySharedVault} />
/> )}
)}
<MenuItem
onClick={() => {
application.notesController.setStarSelectedNotes(!starred)
}}
disabled={areSomeNotesInReadonlySharedVault}
>
<Icon type="star" className={iconClass} />
{starred ? 'Unstar' : 'Star'}
{starShortcut && <KeyboardShortcutIndicator className="ml-auto" shortcut={starShortcut} />}
</MenuItem>
{unpinned && ( {application.navigationController.tagsCount > 0 && (
<AddTagOption
iconClassName={iconClass}
navigationController={application.navigationController}
selectedItems={notes}
linkingController={application.linkingController}
disabled={areSomeNotesInReadonlySharedVault}
/>
)}
<MenuItem <MenuItem
onClick={() => { onClick={() => {
application.notesController.setPinSelectedNotes(true) application.notesController.setStarSelectedNotes(!starred)
}} }}
disabled={areSomeNotesInReadonlySharedVault} disabled={areSomeNotesInReadonlySharedVault}
> >
<Icon type="pin" className={iconClass} /> <Icon type="star" className={iconClass} />
Pin to top {starred ? 'Unstar' : 'Star'}
{pinShortcut && <KeyboardShortcutIndicator className="ml-auto" shortcut={pinShortcut} />} {starShortcut && <KeyboardShortcutIndicator className="ml-auto" shortcut={starShortcut} />}
</MenuItem> </MenuItem>
)}
{pinned && ( {unpinned && (
<MenuItem
onClick={() => {
application.notesController.setPinSelectedNotes(false)
}}
disabled={areSomeNotesInReadonlySharedVault}
>
<Icon type="unpin" className={iconClass} />
Unpin
{pinShortcut && <KeyboardShortcutIndicator className="ml-auto" shortcut={pinShortcut} />}
</MenuItem>
)}
{isOnlySuperNoteSelected ? (
<>
<MenuItem
ref={superExportButtonRef}
onClick={() => {
setIsSuperExportMenuOpen((open) => !open)
}}
>
<div className="flex items-center">
<Icon type="download" className={iconClass} />
Export
</div>
<Icon type="chevron-right" className="ml-auto text-neutral" />
</MenuItem>
<Popover
title="Export note"
side="left"
align="start"
open={isSuperExportMenuOpen}
anchorElement={superExportButtonRef.current}
togglePopover={() => {
setIsSuperExportMenuOpen(!isSuperExportMenuOpen)
}}
className="py-1"
>
<Menu a11yLabel={'Super note export menu'} isOpen={isSuperExportMenuOpen}>
<MenuItem onClick={() => commandService.triggerCommand(SUPER_EXPORT_JSON, notes[0].title)}>
<Icon type="code" className={iconClass} />
Export as JSON
</MenuItem>
<MenuItem onClick={() => commandService.triggerCommand(SUPER_EXPORT_MARKDOWN, notes[0].title)}>
<Icon type="markdown" className={iconClass} />
Export as Markdown
</MenuItem>
<MenuItem onClick={() => commandService.triggerCommand(SUPER_EXPORT_HTML, notes[0].title)}>
<Icon type="rich-text" className={iconClass} />
Export as HTML
</MenuItem>
</Menu>
</Popover>
</>
) : (
<>
<MenuItem <MenuItem
onClick={() => { onClick={() => {
if (application.isNativeMobileWeb()) { application.notesController.setPinSelectedNotes(true)
void shareSelectedNotes(application, notes)
} else {
const hasSuperNote = notes.some((note) => note.noteType === NoteType.Super)
if (hasSuperNote) {
setShowExportSuperModal(true)
return
}
void downloadSelectedItems()
}
}}
>
<Icon type={application.platform === Platform.Android ? 'share' : 'download'} className={iconClass} />
{application.platform === Platform.Android ? 'Share' : 'Export'}
</MenuItem>
{application.platform === Platform.Android && (
<MenuItem onClick={() => downloadSelectedNotesOnAndroid(application, notes)}>
<Icon type="download" className={iconClass} />
Export
</MenuItem>
)}
</>
)}
<MenuItem onClick={duplicateSelectedItems} disabled={areSomeNotesInReadonlySharedVault}>
<Icon type="copy" className={iconClass} />
Duplicate
</MenuItem>
{unarchived && (
<MenuItem
onClick={async () => {
await application.notesController.setArchiveSelectedNotes(true).catch(console.error)
closeMenuAndToggleNotesList()
}}
disabled={areSomeNotesInReadonlySharedVault}
>
<Icon type="archive" className={iconClassWarning} />
<span className="text-warning">Archive</span>
</MenuItem>
)}
{archived && (
<MenuItem
onClick={async () => {
await application.notesController.setArchiveSelectedNotes(false).catch(console.error)
closeMenuAndToggleNotesList()
}}
disabled={areSomeNotesInReadonlySharedVault}
>
<Icon type="unarchive" className={iconClassWarning} />
<span className="text-warning">Unarchive</span>
</MenuItem>
)}
{notTrashed &&
(altKeyDown ? (
<MenuItem
disabled={areSomeNotesInReadonlySharedVault}
onClick={async () => {
await application.notesController.deleteNotesPermanently()
closeMenuAndToggleNotesList()
}}
>
<Icon type="close" className="mr-2 text-danger" />
<span className="text-danger">Delete permanently</span>
</MenuItem>
) : (
<MenuItem
onClick={async () => {
await application.notesController.setTrashSelectedNotes(true)
closeMenuAndToggleNotesList()
}} }}
disabled={areSomeNotesInReadonlySharedVault} disabled={areSomeNotesInReadonlySharedVault}
> >
<Icon type="trash" className={iconClassDanger} /> <Icon type="pin" className={iconClass} />
<span className="text-danger">Move to trash</span> Pin to top
{pinShortcut && <KeyboardShortcutIndicator className="ml-auto" shortcut={pinShortcut} />}
</MenuItem> </MenuItem>
))} )}
{trashed && ( {pinned && (
<>
<MenuItem <MenuItem
onClick={async () => { onClick={() => {
await application.notesController.setTrashSelectedNotes(false) application.notesController.setPinSelectedNotes(false)
closeMenuAndToggleNotesList()
}} }}
disabled={areSomeNotesInReadonlySharedVault} disabled={areSomeNotesInReadonlySharedVault}
> >
<Icon type="restore" className={iconClassSuccess} /> <Icon type="unpin" className={iconClass} />
<span className="text-success">Restore</span> Unpin
{pinShortcut && <KeyboardShortcutIndicator className="ml-auto" shortcut={pinShortcut} />}
</MenuItem> </MenuItem>
<MenuItem )}
disabled={areSomeNotesInReadonlySharedVault} {isOnlySuperNoteSelected ? (
onClick={async () => { <>
await application.notesController.deleteNotesPermanently() <MenuItem
closeMenuAndToggleNotesList() ref={superExportButtonRef}
}} onClick={() => {
> setIsSuperExportMenuOpen((open) => !open)
<Icon type="close" className="mr-2 text-danger" /> }}
<span className="text-danger">Delete permanently</span> >
</MenuItem> <div className="flex items-center">
<MenuItem <Icon type="download" className={iconClass} />
onClick={async () => { Export
await application.notesController.emptyTrash()
closeMenuAndToggleNotesList()
}}
disabled={areSomeNotesInReadonlySharedVault}
>
<div className="flex items-start">
<Icon type="trash-sweep" className="mr-2 text-danger" />
<div className="flex-row">
<div className="text-danger">Empty Trash</div>
<div className="text-xs">{application.notesController.trashedNotesCount} notes in Trash</div>
</div> </div>
</div> <Icon type="chevron-right" className="ml-auto text-neutral" />
</MenuItem>
<Popover
title="Export note"
side="left"
align="start"
open={isSuperExportMenuOpen}
anchorElement={superExportButtonRef.current}
togglePopover={() => {
setIsSuperExportMenuOpen(!isSuperExportMenuOpen)
}}
className="md:py-1"
>
<Menu a11yLabel={'Super note export menu'} isOpen={isSuperExportMenuOpen}>
<MenuSection>
<MenuItem onClick={() => commandService.triggerCommand(SUPER_EXPORT_JSON, notes[0].title)}>
<Icon type="code" className={iconClass} />
Export as JSON
</MenuItem>
<MenuItem onClick={() => commandService.triggerCommand(SUPER_EXPORT_MARKDOWN, notes[0].title)}>
<Icon type="markdown" className={iconClass} />
Export as Markdown
</MenuItem>
<MenuItem onClick={() => commandService.triggerCommand(SUPER_EXPORT_HTML, notes[0].title)}>
<Icon type="rich-text" className={iconClass} />
Export as HTML
</MenuItem>
</MenuSection>
</Menu>
</Popover>
</>
) : (
<>
<MenuItem
onClick={() => {
if (application.isNativeMobileWeb()) {
void shareSelectedNotes(application, notes)
} else {
const hasSuperNote = notes.some((note) => note.noteType === NoteType.Super)
if (hasSuperNote) {
setShowExportSuperModal(true)
return
}
void downloadSelectedItems()
}
}}
>
<Icon type={application.platform === Platform.Android ? 'share' : 'download'} className={iconClass} />
{application.platform === Platform.Android ? 'Share' : 'Export'}
</MenuItem>
{application.platform === Platform.Android && (
<MenuItem onClick={() => downloadSelectedNotesOnAndroid(application, notes)}>
<Icon type="download" className={iconClass} />
Export
</MenuItem>
)}
</>
)}
<MenuItem onClick={duplicateSelectedItems} disabled={areSomeNotesInReadonlySharedVault}>
<Icon type="copy" className={iconClass} />
Duplicate
</MenuItem>
{unarchived && (
<MenuItem
onClick={async () => {
await application.notesController.setArchiveSelectedNotes(true).catch(console.error)
closeMenuAndToggleNotesList()
}}
disabled={areSomeNotesInReadonlySharedVault}
>
<Icon type="archive" className={iconClassWarning} />
<span className="text-warning">Archive</span>
</MenuItem> </MenuItem>
</> )}
)} {archived && (
<MenuItem
onClick={async () => {
await application.notesController.setArchiveSelectedNotes(false).catch(console.error)
closeMenuAndToggleNotesList()
}}
disabled={areSomeNotesInReadonlySharedVault}
>
<Icon type="unarchive" className={iconClassWarning} />
<span className="text-warning">Unarchive</span>
</MenuItem>
)}
{notTrashed &&
(altKeyDown ? (
<MenuItem
disabled={areSomeNotesInReadonlySharedVault}
onClick={async () => {
await application.notesController.deleteNotesPermanently()
closeMenuAndToggleNotesList()
}}
>
<Icon type="close" className="mr-2 text-danger" />
<span className="text-danger">Delete permanently</span>
</MenuItem>
) : (
<MenuItem
onClick={async () => {
await application.notesController.setTrashSelectedNotes(true)
closeMenuAndToggleNotesList()
}}
disabled={areSomeNotesInReadonlySharedVault}
>
<Icon type="trash" className={iconClassDanger} />
<span className="text-danger">Move to trash</span>
</MenuItem>
))}
{trashed && (
<>
<MenuItem
onClick={async () => {
await application.notesController.setTrashSelectedNotes(false)
closeMenuAndToggleNotesList()
}}
disabled={areSomeNotesInReadonlySharedVault}
>
<Icon type="restore" className={iconClassSuccess} />
<span className="text-success">Restore</span>
</MenuItem>
<MenuItem
disabled={areSomeNotesInReadonlySharedVault}
onClick={async () => {
await application.notesController.deleteNotesPermanently()
closeMenuAndToggleNotesList()
}}
>
<Icon type="close" className="mr-2 text-danger" />
<span className="text-danger">Delete permanently</span>
</MenuItem>
<MenuItem
onClick={async () => {
await application.notesController.emptyTrash()
closeMenuAndToggleNotesList()
}}
disabled={areSomeNotesInReadonlySharedVault}
>
<div className="flex items-start">
<Icon type="trash-sweep" className="mr-2 text-danger" />
<div className="flex-row">
<div className="text-danger">Empty Trash</div>
<div className="text-xs">{application.notesController.trashedNotesCount} notes in Trash</div>
</div>
</div>
</MenuItem>
</>
)}
</MenuSection>
{notes.length === 1 ? ( {notes.length === 1 ? (
<> <>
@@ -507,25 +518,22 @@ const NotesOptions = ({ notes, closeMenu }: NotesOptionsProps) => {
)} )}
{!areSomeNotesInSharedVault && ( {!areSomeNotesInSharedVault && (
<> <MenuSection>
<HorizontalSeparator classes="my-2" />
<ListedActionsOption iconClassName={iconClass} application={application} note={notes[0]} /> <ListedActionsOption iconClassName={iconClass} application={application} note={notes[0]} />
</> </MenuSection>
)} )}
<HorizontalSeparator classes="my-2" />
{editorForNote && ( {editorForNote && (
<SpellcheckOptions <MenuSection>
editorForNote={editorForNote} <SpellcheckOptions
notesController={application.notesController} editorForNote={editorForNote}
note={notes[0]} notesController={application.notesController}
disabled={areSomeNotesInReadonlySharedVault} note={notes[0]}
/> disabled={areSomeNotesInReadonlySharedVault}
/>
</MenuSection>
)} )}
<HorizontalSeparator classes="my-2" />
<NoteAttributes className="mb-2" application={application} note={notes[0]} /> <NoteAttributes className="mb-2" application={application} note={notes[0]} />
<NoteSizeWarning note={notes[0]} /> <NoteSizeWarning note={notes[0]} />

View File

@@ -37,7 +37,7 @@ const NotesOptionsPanel = ({ notesController, onClickPreprocessing }: Props) =>
togglePopover={toggleMenu} togglePopover={toggleMenu}
anchorElement={buttonRef} anchorElement={buttonRef}
open={isOpen} open={isOpen}
className="select-none pt-2" className="select-none"
> >
<Menu a11yLabel="Note options menu" isOpen={isOpen}> <Menu a11yLabel="Note options menu" isOpen={isOpen}>
<NotesOptions <NotesOptions

View File

@@ -3,8 +3,8 @@ import { PlatformedKeyboardShortcut } from '@standardnotes/ui-services'
import Icon from '../Icon/Icon' import Icon from '../Icon/Icon'
import { KeyboardShortcutIndicator } from '../KeyboardShortcutIndicator/KeyboardShortcutIndicator' import { KeyboardShortcutIndicator } from '../KeyboardShortcutIndicator/KeyboardShortcutIndicator'
import MenuItem from '../Menu/MenuItem' import MenuItem from '../Menu/MenuItem'
import HorizontalSeparator from '../Shared/HorizontalSeparator'
import { iconClass } from './ClassNames' import { iconClass } from './ClassNames'
import MenuSection from '../Menu/MenuSection'
type Props = { type Props = {
note: SNNote note: SNNote
@@ -14,17 +14,13 @@ type Props = {
const SuperNoteOptions = ({ markdownShortcut, enableSuperMarkdownPreview }: Props) => { const SuperNoteOptions = ({ markdownShortcut, enableSuperMarkdownPreview }: Props) => {
return ( return (
<> <MenuSection>
<HorizontalSeparator classes="my-2" />
<div className="my-1 px-3 text-base font-semibold uppercase text-text lg:text-xs">Super</div>
<MenuItem onClick={enableSuperMarkdownPreview}> <MenuItem onClick={enableSuperMarkdownPreview}>
<Icon type="markdown" className={iconClass} /> <Icon type="markdown" className={iconClass} />
Show Markdown Show Markdown
{markdownShortcut && <KeyboardShortcutIndicator className="ml-auto" shortcut={markdownShortcut} />} {markdownShortcut && <KeyboardShortcutIndicator className="ml-auto" shortcut={markdownShortcut} />}
</MenuItem> </MenuItem>
</> </MenuSection>
) )
} }

View File

@@ -19,7 +19,7 @@ import MenuSwitchButtonItem from '../Menu/MenuSwitchButtonItem'
import MenuRadioButtonItem from '../Menu/MenuRadioButtonItem' import MenuRadioButtonItem from '../Menu/MenuRadioButtonItem'
import { useApplication } from '../ApplicationProvider' import { useApplication } from '../ApplicationProvider'
import { GetAllThemesUseCase } from '@standardnotes/ui-services' import { GetAllThemesUseCase } from '@standardnotes/ui-services'
import MenuItemSeparator from '../Menu/MenuItemSeparator' import MenuSection from '../Menu/MenuSection'
type MenuProps = { type MenuProps = {
closeMenu: () => void closeMenu: () => void
@@ -117,8 +117,7 @@ const QuickSettingsMenu: FunctionComponent<MenuProps> = ({ closeMenu }) => {
return ( return (
<Menu a11yLabel="Quick settings menu" isOpen> <Menu a11yLabel="Quick settings menu" isOpen>
{editorStackComponents.length > 0 && ( {editorStackComponents.length > 0 && (
<> <MenuSection title="Tools">
<div className="my-1 px-3 text-sm font-semibold uppercase text-text">Tools</div>
{editorStackComponents.map((component) => ( {editorStackComponents.map((component) => (
<MenuSwitchButtonItem <MenuSwitchButtonItem
onChange={() => { onChange={() => {
@@ -131,17 +130,17 @@ const QuickSettingsMenu: FunctionComponent<MenuProps> = ({ closeMenu }) => {
{component.displayName} {component.displayName}
</MenuSwitchButtonItem> </MenuSwitchButtonItem>
))} ))}
<MenuItemSeparator /> </MenuSection>
</>
)} )}
<div className="my-1 px-3 text-sm font-semibold uppercase text-text">Appearance</div> <MenuSection title="Appearance">
<MenuRadioButtonItem checked={defaultThemeOn} onClick={toggleDefaultTheme} ref={defaultThemeButtonRef}> <MenuRadioButtonItem checked={defaultThemeOn} onClick={toggleDefaultTheme} ref={defaultThemeButtonRef}>
Default Default
</MenuRadioButtonItem> </MenuRadioButtonItem>
{themes.map((theme) => ( {themes.map((theme) => (
<ThemesMenuButton uiFeature={theme} key={theme.uniqueIdentifier.value} /> <ThemesMenuButton uiFeature={theme} key={theme.uniqueIdentifier.value} />
))} ))}
<MenuItemSeparator /> </MenuSection>
<FocusModeSwitch <FocusModeSwitch
application={application} application={application}
onToggle={setFocusModeEnabled} onToggle={setFocusModeEnabled}

View File

@@ -390,7 +390,7 @@ function TableActionMenu({ onClose, tableCellNode: _tableCellNode, cellMerge }:
(tableCellNode.__headerState & TableCellHeaderStates.COLUMN) === TableCellHeaderStates.COLUMN (tableCellNode.__headerState & TableCellHeaderStates.COLUMN) === TableCellHeaderStates.COLUMN
return ( return (
<Menu className="dropdown" ref={dropDownRef} a11yLabel="Table actions menu" isOpen> <Menu className="dropdown !px-0" ref={dropDownRef} a11yLabel="Table actions menu" isOpen>
{mergeCellButton} {mergeCellButton}
{!!mergeCellButton && <MenuItemSeparator />} {!!mergeCellButton && <MenuItemSeparator />}
<MenuItem onClick={() => insertTableRowAtSelection(false)}> <MenuItem onClick={() => insertTableRowAtSelection(false)}>

View File

@@ -685,7 +685,7 @@ const ToolbarPlugin = () => {
} }
return ( return (
<Menu a11yLabel="Table of contents" isOpen> <Menu a11yLabel="Table of contents" isOpen className="!px-0">
{tableOfContents.map(([key, text, tag]) => ( {tableOfContents.map(([key, text, tag]) => (
<MenuItem <MenuItem
key={key} key={key}