From 2e3ac3ce579ffeecf4c28e607d09779e67265333 Mon Sep 17 00:00:00 2001 From: Aman Harwara Date: Wed, 18 Oct 2023 21:31:28 +0530 Subject: [PATCH] chore: make mobile menu ui more native-like (#2594) --- .../AccountMenu/GeneralAccountMenu.tsx | 95 ++-- .../WorkspaceSwitcherMenu.tsx | 48 +- .../WorkspaceSwitcherOption.tsx | 2 +- .../LockscreenWorkspaceSwitcher.tsx | 1 - .../ChangeEditor/ChangeEditorButton.tsx | 2 +- .../ChangeEditor/ChangeEditorMenu.tsx | 69 ++- .../ChangeEditor/ChangeEditorMultipleMenu.tsx | 59 +- .../ChangeEditor/ChangeMultipleButton.tsx | 2 +- .../Header/DisplayOptionsMenu.tsx | 172 +++--- .../Header/NewNotePreferences.tsx | 5 +- .../FileContextMenu/FileContextMenu.tsx | 2 +- .../FileContextMenuBackupOption.tsx | 9 +- .../FileContextMenu/FileMenuOptions.tsx | 112 ++-- .../FileContextMenu/FileOptionsPanel.tsx | 8 +- .../FilePreview/FilePreviewModal.tsx | 2 +- .../Components/Footer/QuickSettingsButton.tsx | 2 +- .../src/javascripts/Components/Menu/Menu.tsx | 2 +- .../javascripts/Components/Menu/MenuItem.tsx | 2 +- .../Components/Menu/MenuRadioButtonItem.tsx | 2 +- .../Components/Menu/MenuSection.tsx | 26 + .../Components/Menu/MenuSwitchButtonItem.tsx | 2 +- .../NotesContextMenu/NotesContextMenu.tsx | 1 - .../Components/NotesOptions/AddTagOption.tsx | 2 +- .../NotesOptions/ChangeEditorOption.tsx | 2 +- .../NotesOptions/Listed/ListedActionsMenu.tsx | 23 +- .../Listed/ListedActionsOption.tsx | 2 +- .../Components/NotesOptions/NotesOptions.tsx | 504 +++++++++--------- .../NotesOptions/NotesOptionsPanel.tsx | 2 +- .../NotesOptions/SuperNoteOptions.tsx | 10 +- .../QuickSettingsMenu/QuickSettingsMenu.tsx | 25 +- .../TableCellActionMenuPlugin/index.tsx | 2 +- .../Plugins/ToolbarPlugin/ToolbarPlugin.tsx | 2 +- 32 files changed, 615 insertions(+), 584 deletions(-) create mode 100644 packages/web/src/javascripts/Components/Menu/MenuSection.tsx diff --git a/packages/web/src/javascripts/Components/AccountMenu/GeneralAccountMenu.tsx b/packages/web/src/javascripts/Components/AccountMenu/GeneralAccountMenu.tsx index 9fa1b7c80..4fc31c35f 100644 --- a/packages/web/src/javascripts/Components/AccountMenu/GeneralAccountMenu.tsx +++ b/packages/web/src/javascripts/Components/AccountMenu/GeneralAccountMenu.tsx @@ -6,13 +6,13 @@ import { useCallback, useMemo, useState, FunctionComponent } from 'react' import { AccountMenuPane } from './AccountMenuPane' import Menu from '@/Components/Menu/Menu' import MenuItem from '@/Components/Menu/MenuItem' -import MenuItemSeparator from '@/Components/Menu/MenuItemSeparator' import WorkspaceSwitcherOption from './WorkspaceSwitcher/WorkspaceSwitcherOption' import { WebApplicationGroup } from '@/Application/WebApplicationGroup' import { formatLastSyncDate } from '@/Utils/DateUtils' import Spinner from '@/Components/Spinner/Spinner' import { MenuItemIconSize } from '@/Constants/TailwindClassNames' import { useApplication } from '../ApplicationProvider' +import MenuSection from '../Menu/MenuSection' type Props = { mainApplicationGroup: WebApplicationGroup @@ -92,7 +92,7 @@ const GeneralAccountMenu: FunctionComponent = ({ setMenuPane, closeMenu, return ( <> -
+
Account
@@ -100,12 +100,12 @@ const GeneralAccountMenu: FunctionComponent = ({ setMenuPane, closeMenu,
{user ? ( <> -
+
You're signed in as:
{user.email}
{application.getHost.execute().getValue()}
-
+
{isSyncingInProgress ? (
@@ -127,7 +127,7 @@ const GeneralAccountMenu: FunctionComponent = ({ setMenuPane, closeMenu, ) : ( <> -
+
You’re offline. Sign in to sync your notes and preferences across all your devices and enable end-to-end encryption. @@ -145,56 +145,57 @@ const GeneralAccountMenu: FunctionComponent = ({ setMenuPane, closeMenu, closeMenu={closeMenu} initialFocus={!application.hasAccount() ? CREATE_ACCOUNT_INDEX : SWITCHER_INDEX} > - - - - {user ? ( - - - Account settings - - ) : ( - <> - + + + + + {user ? ( + - Create free account + Account settings - - - Sign in - - - )} - { - application.importModalController.setIsVisible(true) - application.accountMenuController.closeAccountMenu() - }} - > - - Import - - {application.isNativeMobileWeb() && ( - - - Email us + ) : ( + <> + + + Create free account + + + + Sign in + + + )} + { + application.importModalController.setIsVisible(true) + application.accountMenuController.closeAccountMenu() + }} + > + + Import - )} - -
- - Help & feedback -
- v{application.version} -
+ {application.isNativeMobileWeb() && ( + + + Email us + + )} + +
+ + Help & feedback +
+ v{application.version} +
+
{user ? ( - <> - + Sign out workspace - + ) : null} diff --git a/packages/web/src/javascripts/Components/AccountMenu/WorkspaceSwitcher/WorkspaceSwitcherMenu.tsx b/packages/web/src/javascripts/Components/AccountMenu/WorkspaceSwitcher/WorkspaceSwitcherMenu.tsx index 8644cadeb..7aeedd848 100644 --- a/packages/web/src/javascripts/Components/AccountMenu/WorkspaceSwitcher/WorkspaceSwitcherMenu.tsx +++ b/packages/web/src/javascripts/Components/AccountMenu/WorkspaceSwitcher/WorkspaceSwitcherMenu.tsx @@ -5,9 +5,9 @@ import { FunctionComponent, useCallback, useEffect, useState } from 'react' import Icon from '@/Components/Icon/Icon' import Menu from '@/Components/Menu/Menu' import MenuItem from '@/Components/Menu/MenuItem' -import MenuItemSeparator from '@/Components/Menu/MenuItemSeparator' import WorkspaceMenuItem from './WorkspaceMenuItem' import { useApplication } from '@/Components/ApplicationProvider' +import MenuSection from '@/Components/Menu/MenuSection' type Props = { mainApplicationGroup: WebApplicationGroup @@ -71,30 +71,32 @@ const WorkspaceSwitcherMenu: FunctionComponent = ({ }, [mainApplicationGroup]) return ( - - {applicationDescriptors.map((descriptor) => ( - activateWorkspace(descriptor)} - renameDescriptor={(label: string) => mainApplicationGroup.renameDescriptor(descriptor, label)} - /> - ))} - + + + {applicationDescriptors.map((descriptor) => ( + activateWorkspace(descriptor)} + renameDescriptor={(label: string) => mainApplicationGroup.renameDescriptor(descriptor, label)} + /> + ))} + - - - Add another workspace - - - {!hideWorkspaceOptions && ( - - - Sign out all workspaces + + + + Add another workspace - )} + {!hideWorkspaceOptions && ( + + + Sign out all workspaces + + )} + ) } diff --git a/packages/web/src/javascripts/Components/AccountMenu/WorkspaceSwitcher/WorkspaceSwitcherOption.tsx b/packages/web/src/javascripts/Components/AccountMenu/WorkspaceSwitcher/WorkspaceSwitcherOption.tsx index 96c1467e1..19dfe6c87 100644 --- a/packages/web/src/javascripts/Components/AccountMenu/WorkspaceSwitcher/WorkspaceSwitcherOption.tsx +++ b/packages/web/src/javascripts/Components/AccountMenu/WorkspaceSwitcher/WorkspaceSwitcherOption.tsx @@ -33,7 +33,7 @@ const WorkspaceSwitcherOption: FunctionComponent = ({ mainApplicationGrou title="Switch workspace" align="end" anchorElement={buttonRef} - className="py-2" + className="pb-2" open={isOpen} side="right" togglePopover={toggleMenu} diff --git a/packages/web/src/javascripts/Components/ChallengeModal/LockscreenWorkspaceSwitcher.tsx b/packages/web/src/javascripts/Components/ChallengeModal/LockscreenWorkspaceSwitcher.tsx index 14d4ae349..d5543c43a 100644 --- a/packages/web/src/javascripts/Components/ChallengeModal/LockscreenWorkspaceSwitcher.tsx +++ b/packages/web/src/javascripts/Components/ChallengeModal/LockscreenWorkspaceSwitcher.tsx @@ -28,7 +28,6 @@ const LockscreenWorkspaceSwitcher: FunctionComponent = ({ mainApplication title="Switch workspace" align="center" anchorElement={buttonRef} - className="py-2" open={isOpen} overrideZIndex="z-modal" side="right" diff --git a/packages/web/src/javascripts/Components/ChangeEditor/ChangeEditorButton.tsx b/packages/web/src/javascripts/Components/ChangeEditor/ChangeEditorButton.tsx index fc7db1a32..793bbe4c1 100644 --- a/packages/web/src/javascripts/Components/ChangeEditor/ChangeEditorButton.tsx +++ b/packages/web/src/javascripts/Components/ChangeEditor/ChangeEditorButton.tsx @@ -79,7 +79,7 @@ const ChangeEditorButton: FunctionComponent = ({ noteViewController, onCl disableClickOutside={isClickOutsideDisabled} anchorElement={buttonRef} open={isOpen} - className="pt-2 md:pt-0" + className="md:pb-1" > = ({ {groups .filter((group) => group.items && group.items.length) - .map((group, index) => { + .map((group) => { const groupId = getGroupId(group) return ( - -
- {group.items.map((menuItem) => { - const onClickEditorItem = () => { - handleMenuSelection(menuItem).catch(console.error) - } + + {group.items.map((menuItem) => { + const onClickEditorItem = () => { + handleMenuSelection(menuItem).catch(console.error) + } - return ( - -
-
- {group.icon && } - {menuItem.uiFeature.displayName} - {menuItem.isLabs && ( - - Labs - - )} -
- {!menuItem.isEntitled && ( - + return ( + +
+
+ {group.icon && } + {menuItem.uiFeature.displayName} + {menuItem.isLabs && ( + + Labs + )}
- - ) - })} -
- + {!menuItem.isEntitled && ( + + )} +
+
+ ) + })} +
) })}
diff --git a/packages/web/src/javascripts/Components/ChangeEditor/ChangeEditorMultipleMenu.tsx b/packages/web/src/javascripts/Components/ChangeEditor/ChangeEditorMultipleMenu.tsx index d4b829525..0b5e42c3d 100644 --- a/packages/web/src/javascripts/Components/ChangeEditor/ChangeEditorMultipleMenu.tsx +++ b/packages/web/src/javascripts/Components/ChangeEditor/ChangeEditorMultipleMenu.tsx @@ -10,7 +10,7 @@ import { NoteType, SNNote, } from '@standardnotes/snjs' -import { Fragment, useCallback, useMemo, useState } from 'react' +import { useCallback, useMemo, useState } from 'react' import Icon from '../Icon/Icon' import { PremiumFeatureIconName, PremiumFeatureIconClass } from '../Icon/PremiumFeatureIcon' import Menu from '../Menu/Menu' @@ -20,6 +20,7 @@ import { EditorMenuItem } from '../NotesOptions/EditorMenuItem' import { SuperNoteImporter } from '../SuperEditor/SuperNoteImporter' import { Pill } from '../Preferences/PreferencesComponents/Content' import ModalOverlay from '../Modal/ModalOverlay' +import MenuSection from '../Menu/MenuSection' const getGroupId = (group: EditorMenuGroup) => group.title.toLowerCase().replace(/\s/, '-') @@ -132,36 +133,34 @@ const ChangeEditorMultipleMenu = ({ application, notes, setDisableClickOutside } return ( <> - {groupsWithItems.map((group, index) => ( - -
- {group.items.map((item) => { - const onClickEditorItem = () => { - handleMenuSelection(item).catch(console.error) - } - return ( - -
-
- {group.icon && } - {item.uiFeature.displayName} - {item.isLabs && ( - - Labs - - )} -
- {!item.isEntitled && } + {groupsWithItems.map((group) => ( + + {group.items.map((item) => { + const onClickEditorItem = () => { + handleMenuSelection(item).catch(console.error) + } + return ( + +
+
+ {group.icon && } + {item.uiFeature.displayName} + {item.isLabs && ( + + Labs + + )}
- - ) - })} -
- + {!item.isEntitled && } +
+
+ ) + })} + ))}
diff --git a/packages/web/src/javascripts/Components/ChangeEditor/ChangeMultipleButton.tsx b/packages/web/src/javascripts/Components/ChangeEditor/ChangeMultipleButton.tsx index 5b1fc2725..fe47c31c3 100644 --- a/packages/web/src/javascripts/Components/ChangeEditor/ChangeMultipleButton.tsx +++ b/packages/web/src/javascripts/Components/ChangeEditor/ChangeMultipleButton.tsx @@ -25,7 +25,7 @@ const ChangeMultipleButton = ({ application, notesController }: Props) => { disableClickOutside={disableClickOutside} anchorElement={changeButtonRef} open={isChangeMenuOpen} - className="pt-2 md:pt-0" + className="md:pb-1" > = ({ /> )} - + + +
+ Date modified + +
+
+ +
+ Creation date + +
+
+ +
+ Title + +
+
+
-
Sort by
- -
- Date modified - -
-
- -
- Creation date - -
-
- -
- Title - -
-
- <> - -
View
+ {!shouldHideNonApplicableOptions && !isFilesSmartView && ( = ({ > Show icon - {!shouldHideNonApplicableOptions && ( - <> - -
Other
- - Show pinned - - - Show protected - - - Show archived - - - Show trashed - - - )} - +
+ + {!shouldHideNonApplicableOptions && ( + + + Show pinned + + + Show protected + + + Show archived + + + Show trashed + + + )} {currentMode === 'tag' && !isSystemTag && DailyEntryModeEnabled && !isTableViewEnabled && ( - <> - + = ({
Daily Notebook
- + Labs
Capture new notes daily with a calendar-based layout
- +
)} {currentMode === 'tag' && !isSystemTag && !isDailyEntry && ( - <> - + = ({
Table view
- + Labs
Display the notes and files in the current tag in a table layout
- +
)} {!shouldHideNonApplicableOptions && (!isSystemTag || currentMode === 'global') && ( - <> - + = ({ mode={currentMode} changePreferencesCallback={changePreferences} /> - + )}
) diff --git a/packages/web/src/javascripts/Components/ContentListView/Header/NewNotePreferences.tsx b/packages/web/src/javascripts/Components/ContentListView/Header/NewNotePreferences.tsx index ea0d4b8b7..b25eeba03 100644 --- a/packages/web/src/javascripts/Components/ContentListView/Header/NewNotePreferences.tsx +++ b/packages/web/src/javascripts/Components/ContentListView/Header/NewNotePreferences.tsx @@ -173,10 +173,9 @@ const NewNotePreferences: FunctionComponent = ({ } return ( -
-
New Note Defaults
+
-
Note Type
+
Note Type
= observer(({ filesController, i anchorPoint={fileContextMenuLocation} togglePopover={() => setShowFileContextMenu(!showFileContextMenu)} align="start" - className="py-2" + className="md:pb-2" > = ({ file }) => { const application = useApplication() @@ -33,8 +34,12 @@ export const FileContextMenuBackupOption: FunctionComponent<{ file: FileItem }> application.openPreferences('backups') }, [application]) + if (!application.fileBackups) { + return null + } + return ( - <> + {backupInfo && (
)} - + ) } diff --git a/packages/web/src/javascripts/Components/FileContextMenu/FileMenuOptions.tsx b/packages/web/src/javascripts/Components/FileContextMenu/FileMenuOptions.tsx index edabe6efb..286f48e68 100644 --- a/packages/web/src/javascripts/Components/FileContextMenu/FileMenuOptions.tsx +++ b/packages/web/src/javascripts/Components/FileContextMenu/FileMenuOptions.tsx @@ -2,7 +2,6 @@ import { FunctionComponent, useCallback, useMemo } from 'react' import { FileItemActionType } from '../AttachedFilesPopover/PopoverFileItemAction' import Icon from '@/Components/Icon/Icon' import { observer } from 'mobx-react-lite' -import HorizontalSeparator from '../Shared/HorizontalSeparator' import { formatSizeToReadableString } from '@standardnotes/filepicker' import { useResponsiveAppPane } from '../Panes/ResponsivePaneProvider' import { AppPaneId } from '../Panes/AppPaneMetadata' @@ -15,6 +14,7 @@ import { MenuItemIconSize } from '@/Constants/TailwindClassNames' import AddToVaultMenuOption from '../Vaults/AddToVaultMenuOption' import { iconClass } from '../NotesOptions/ClassNames' import { useApplication } from '../ApplicationProvider' +import MenuSection from '../Menu/MenuSection' type Props = { closeMenu: () => void @@ -87,8 +87,8 @@ const FileMenuOptions: FunctionComponent = ({ return ( <> - {selectedFiles.length === 1 && ( - <> + {selectedFiles.length === 1 && (isFileAttachedToNote || shouldShowAttachOption) && ( + {isFileAttachedToNote ? ( @@ -100,67 +100,69 @@ const FileMenuOptions: FunctionComponent = ({ Attach to note ) : null} - + )} - {application.featuresController.isVaultsEnabled() && ( - + {application.featuresController.isVaultsEnabled() && ( + + )} + - )} - - { - void application.filesController.setProtectionForFiles(hasProtectedFiles, selectedFiles) - }} - disabled={areSomeFilesInReadonlySharedVault} - > - - Password protect - - - { - void application.filesController.downloadFiles(selectedFiles) - closeMenu() - }} - > - - Download - - {shouldShowRenameOption && ( - { - renameToggleCallback?.(true) + { + void application.filesController.setProtectionForFiles(hasProtectedFiles, selectedFiles) }} disabled={areSomeFilesInReadonlySharedVault} > - - Rename + + Password protect + + + + { + void application.filesController.downloadFiles(selectedFiles) + closeMenu() + }} + > + + Download - )} - { - closeMenuAndToggleFilesList() - void application.filesController.deleteFilesPermanently(selectedFiles) - }} - disabled={areSomeFilesInReadonlySharedVault} - > - - Delete permanently - + {shouldShowRenameOption && ( + { + renameToggleCallback?.(true) + }} + disabled={areSomeFilesInReadonlySharedVault} + > + + Rename + + )} + { + closeMenuAndToggleFilesList() + void application.filesController.deleteFilesPermanently(selectedFiles) + }} + disabled={areSomeFilesInReadonlySharedVault} + > + + Delete permanently + + -
{!hasSelectedMultipleFiles && (
diff --git a/packages/web/src/javascripts/Components/FileContextMenu/FileOptionsPanel.tsx b/packages/web/src/javascripts/Components/FileContextMenu/FileOptionsPanel.tsx index c3564fdf6..ef747e75d 100644 --- a/packages/web/src/javascripts/Components/FileContextMenu/FileOptionsPanel.tsx +++ b/packages/web/src/javascripts/Components/FileContextMenu/FileOptionsPanel.tsx @@ -19,7 +19,13 @@ const FilesOptionsPanel = ({ itemListController }: Props) => { return ( <> - + { togglePopover={closeOptionsMenu} side="bottom" align="start" - className="py-2" + className="md:pb-2" overrideZIndex="z-modal" > diff --git a/packages/web/src/javascripts/Components/Footer/QuickSettingsButton.tsx b/packages/web/src/javascripts/Components/Footer/QuickSettingsButton.tsx index e6d0d8134..cacaad449 100644 --- a/packages/web/src/javascripts/Components/Footer/QuickSettingsButton.tsx +++ b/packages/web/src/javascripts/Components/Footer/QuickSettingsButton.tsx @@ -55,7 +55,7 @@ const QuickSettingsButton = ({ application, isMobileNavigation = false }: Props) open={isOpen} side="top" align="start" - className="py-2" + className="md:py-2" > diff --git a/packages/web/src/javascripts/Components/Menu/Menu.tsx b/packages/web/src/javascripts/Components/Menu/Menu.tsx index ce0677372..86a1e2c0d 100644 --- a/packages/web/src/javascripts/Components/Menu/Menu.tsx +++ b/packages/web/src/javascripts/Components/Menu/Menu.tsx @@ -68,7 +68,7 @@ const Menu = forwardRef( return ( { + return ( +
+ {title &&
{title}
} +
{children}
+
+ ) +} + +export default MenuSection diff --git a/packages/web/src/javascripts/Components/Menu/MenuSwitchButtonItem.tsx b/packages/web/src/javascripts/Components/Menu/MenuSwitchButtonItem.tsx index 9493dc1f1..fcee2c39c 100644 --- a/packages/web/src/javascripts/Components/Menu/MenuSwitchButtonItem.tsx +++ b/packages/web/src/javascripts/Components/Menu/MenuSwitchButtonItem.tsx @@ -36,7 +36,7 @@ const MenuSwitchButtonItem = forwardRef( disabled={disabled} ref={ref} 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-mobile-menu-item md:text-tablet-menu-item lg:text-menu-item', 'disabled:cursor-not-allowed disabled:opacity-60', diff --git a/packages/web/src/javascripts/Components/NotesContextMenu/NotesContextMenu.tsx b/packages/web/src/javascripts/Components/NotesContextMenu/NotesContextMenu.tsx index 385088392..02c793955 100644 --- a/packages/web/src/javascripts/Components/NotesContextMenu/NotesContextMenu.tsx +++ b/packages/web/src/javascripts/Components/NotesContextMenu/NotesContextMenu.tsx @@ -26,7 +26,6 @@ const NotesContextMenu = () => { y: contextMenuClickLocation.y, }} disableClickOutside={disableClickOutside} - className="py-2" open={contextMenuOpen} togglePopover={closeMenu} > diff --git a/packages/web/src/javascripts/Components/NotesOptions/AddTagOption.tsx b/packages/web/src/javascripts/Components/NotesOptions/AddTagOption.tsx index 38565c496..208676bcf 100644 --- a/packages/web/src/javascripts/Components/NotesOptions/AddTagOption.tsx +++ b/packages/web/src/javascripts/Components/NotesOptions/AddTagOption.tsx @@ -77,7 +77,7 @@ const AddTagOption: FunctionComponent = ({ className="py-2" overrideZIndex="z-modal" > - + {navigationController.tags.map((tag) => ( = ({ title="Change note type" align="start" anchorElement={buttonRef} - className="pt-2 md:pt-0" + className="md:pb-1" open={isOpen} side="right" togglePopover={toggleMenu} diff --git a/packages/web/src/javascripts/Components/NotesOptions/Listed/ListedActionsMenu.tsx b/packages/web/src/javascripts/Components/NotesOptions/Listed/ListedActionsMenu.tsx index cc5cd6325..d76489623 100644 --- a/packages/web/src/javascripts/Components/NotesOptions/Listed/ListedActionsMenu.tsx +++ b/packages/web/src/javascripts/Components/NotesOptions/Listed/ListedActionsMenu.tsx @@ -1,10 +1,11 @@ import { WebApplication } from '@/Application/WebApplication' 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 { ListedMenuGroup } from './ListedMenuGroup' import ListedMenuItem from './ListedMenuItem' import Spinner from '@/Components/Spinner/Spinner' +import MenuSection from '@/Components/Menu/MenuSection' type ListedActionsMenuProps = { application: WebApplication @@ -125,15 +126,15 @@ const ListedActionsMenu = ({ application, note }: ListedActionsMenuProps) => { )} {!isFetchingAccounts && menuGroups.length ? ( <> - {menuGroups.map((group, index) => ( - -
- {group.name} -
+ {menuGroups.map((group) => ( + + {group.name} +
+ } + > {group.actions.length ? ( group.actions.map((action) => ( { ) : (
No actions available
)} - + ))} ) : null} diff --git a/packages/web/src/javascripts/Components/NotesOptions/Listed/ListedActionsOption.tsx b/packages/web/src/javascripts/Components/NotesOptions/Listed/ListedActionsOption.tsx index d4e67a444..973e93190 100644 --- a/packages/web/src/javascripts/Components/NotesOptions/Listed/ListedActionsOption.tsx +++ b/packages/web/src/javascripts/Components/NotesOptions/Listed/ListedActionsOption.tsx @@ -54,7 +54,7 @@ const ListedActionsOption: FunctionComponent = ({ application, note, icon open={isOpen} side="right" align="end" - className="pt-2 md:pt-0" + className="px-4 md:px-0 md:pt-0" > diff --git a/packages/web/src/javascripts/Components/NotesOptions/NotesOptions.tsx b/packages/web/src/javascripts/Components/NotesOptions/NotesOptions.tsx index 0bd87b003..d7ed92fea 100644 --- a/packages/web/src/javascripts/Components/NotesOptions/NotesOptions.tsx +++ b/packages/web/src/javascripts/Components/NotesOptions/NotesOptions.tsx @@ -18,7 +18,6 @@ import ListedActionsOption from './Listed/ListedActionsOption' import AddTagOption from './AddTagOption' import { addToast, dismissToast, ToastType } from '@standardnotes/toast' import { NotesOptionsProps } from './NotesOptionsProps' -import HorizontalSeparator from '../Shared/HorizontalSeparator' import { useResponsiveAppPane } from '../Panes/ResponsivePaneProvider' import { AppPaneId } from '../Panes/AppPaneMetadata' import { getNoteBlob, getNoteFileName } from '@/Utils/NoteExportUtils' @@ -42,6 +41,7 @@ import { MutuallyExclusiveMediaQueryBreakpoints } from '@/Hooks/useMediaQuery' import AddToVaultMenuOption from '../Vaults/AddToVaultMenuOption' import Menu from '../Menu/Menu' import Popover from '../Popover/Popover' +import MenuSection from '../Menu/MenuSection' const iconSize = MenuItemIconSize const iconClassDanger = `text-danger mr-2 ${iconSize}` @@ -230,271 +230,282 @@ const NotesOptions = ({ notes, closeMenu }: NotesOptionsProps) => { <> {notes.length === 1 && ( <> - - - Note history - {historyShortcut && } - - - - - Editor width - {editorWidthShortcut && } - + + + + Note history + {historyShortcut && } + + + + + + Editor width + {editorWidthShortcut && } + + )} - { - application.notesController.setLockSelectedNotes(locked) - }} - disabled={areSomeNotesInReadonlySharedVault} - > - - Prevent editing - - { - application.notesController.setHideSelectedNotePreviews(!hidePreviews) - }} - disabled={areSomeNotesInReadonlySharedVault} - > - - Show preview - - { - application.notesController.setProtectSelectedNotes(protect).catch(console.error) - }} - disabled={areSomeNotesInReadonlySharedVault} - > - - Password protect - + + { + application.notesController.setLockSelectedNotes(locked) + }} + disabled={areSomeNotesInReadonlySharedVault} + > + + Prevent editing + + { + application.notesController.setHideSelectedNotePreviews(!hidePreviews) + }} + disabled={areSomeNotesInReadonlySharedVault} + > + + Show preview + + { + application.notesController.setProtectSelectedNotes(protect).catch(console.error) + }} + disabled={areSomeNotesInReadonlySharedVault} + > + + Password protect + + {notes.length === 1 && ( - <> - + - - )} - - - {application.featuresController.isVaultsEnabled() && ( - + )} - {application.navigationController.tagsCount > 0 && ( - - )} - { - application.notesController.setStarSelectedNotes(!starred) - }} - disabled={areSomeNotesInReadonlySharedVault} - > - - {starred ? 'Unstar' : 'Star'} - {starShortcut && } - + + {application.featuresController.isVaultsEnabled() && ( + + )} - {unpinned && ( + {application.navigationController.tagsCount > 0 && ( + + )} { - application.notesController.setPinSelectedNotes(true) + application.notesController.setStarSelectedNotes(!starred) }} disabled={areSomeNotesInReadonlySharedVault} > - - Pin to top - {pinShortcut && } + + {starred ? 'Unstar' : 'Star'} + {starShortcut && } - )} - {pinned && ( - { - application.notesController.setPinSelectedNotes(false) - }} - disabled={areSomeNotesInReadonlySharedVault} - > - - Unpin - {pinShortcut && } - - )} - {isOnlySuperNoteSelected ? ( - <> - { - setIsSuperExportMenuOpen((open) => !open) - }} - > -
- - Export -
- -
- { - setIsSuperExportMenuOpen(!isSuperExportMenuOpen) - }} - className="py-1" - > - - commandService.triggerCommand(SUPER_EXPORT_JSON, notes[0].title)}> - - Export as JSON - - commandService.triggerCommand(SUPER_EXPORT_MARKDOWN, notes[0].title)}> - - Export as Markdown - - commandService.triggerCommand(SUPER_EXPORT_HTML, notes[0].title)}> - - Export as HTML - - - - - ) : ( - <> + + {unpinned && ( { - if (application.isNativeMobileWeb()) { - void shareSelectedNotes(application, notes) - } else { - const hasSuperNote = notes.some((note) => note.noteType === NoteType.Super) - - if (hasSuperNote) { - setShowExportSuperModal(true) - return - } - - void downloadSelectedItems() - } - }} - > - - {application.platform === Platform.Android ? 'Share' : 'Export'} - - {application.platform === Platform.Android && ( - downloadSelectedNotesOnAndroid(application, notes)}> - - Export - - )} - - )} - - - Duplicate - - {unarchived && ( - { - await application.notesController.setArchiveSelectedNotes(true).catch(console.error) - closeMenuAndToggleNotesList() - }} - disabled={areSomeNotesInReadonlySharedVault} - > - - Archive - - )} - {archived && ( - { - await application.notesController.setArchiveSelectedNotes(false).catch(console.error) - closeMenuAndToggleNotesList() - }} - disabled={areSomeNotesInReadonlySharedVault} - > - - Unarchive - - )} - {notTrashed && - (altKeyDown ? ( - { - await application.notesController.deleteNotesPermanently() - closeMenuAndToggleNotesList() - }} - > - - Delete permanently - - ) : ( - { - await application.notesController.setTrashSelectedNotes(true) - closeMenuAndToggleNotesList() + application.notesController.setPinSelectedNotes(true) }} disabled={areSomeNotesInReadonlySharedVault} > - - Move to trash + + Pin to top + {pinShortcut && } - ))} - {trashed && ( - <> + )} + {pinned && ( { - await application.notesController.setTrashSelectedNotes(false) - closeMenuAndToggleNotesList() + onClick={() => { + application.notesController.setPinSelectedNotes(false) }} disabled={areSomeNotesInReadonlySharedVault} > - - Restore + + Unpin + {pinShortcut && } - { - await application.notesController.deleteNotesPermanently() - closeMenuAndToggleNotesList() - }} - > - - Delete permanently - - { - await application.notesController.emptyTrash() - closeMenuAndToggleNotesList() - }} - disabled={areSomeNotesInReadonlySharedVault} - > -
- -
-
Empty Trash
-
{application.notesController.trashedNotesCount} notes in Trash
+ )} + {isOnlySuperNoteSelected ? ( + <> + { + setIsSuperExportMenuOpen((open) => !open) + }} + > +
+ + Export
-
+ + + { + setIsSuperExportMenuOpen(!isSuperExportMenuOpen) + }} + className="md:py-1" + > + + + commandService.triggerCommand(SUPER_EXPORT_JSON, notes[0].title)}> + + Export as JSON + + commandService.triggerCommand(SUPER_EXPORT_MARKDOWN, notes[0].title)}> + + Export as Markdown + + commandService.triggerCommand(SUPER_EXPORT_HTML, notes[0].title)}> + + Export as HTML + + + + + + ) : ( + <> + { + if (application.isNativeMobileWeb()) { + void shareSelectedNotes(application, notes) + } else { + const hasSuperNote = notes.some((note) => note.noteType === NoteType.Super) + + if (hasSuperNote) { + setShowExportSuperModal(true) + return + } + + void downloadSelectedItems() + } + }} + > + + {application.platform === Platform.Android ? 'Share' : 'Export'} + + {application.platform === Platform.Android && ( + downloadSelectedNotesOnAndroid(application, notes)}> + + Export + + )} + + )} + + + Duplicate + + {unarchived && ( + { + await application.notesController.setArchiveSelectedNotes(true).catch(console.error) + closeMenuAndToggleNotesList() + }} + disabled={areSomeNotesInReadonlySharedVault} + > + + Archive - - )} + )} + {archived && ( + { + await application.notesController.setArchiveSelectedNotes(false).catch(console.error) + closeMenuAndToggleNotesList() + }} + disabled={areSomeNotesInReadonlySharedVault} + > + + Unarchive + + )} + {notTrashed && + (altKeyDown ? ( + { + await application.notesController.deleteNotesPermanently() + closeMenuAndToggleNotesList() + }} + > + + Delete permanently + + ) : ( + { + await application.notesController.setTrashSelectedNotes(true) + closeMenuAndToggleNotesList() + }} + disabled={areSomeNotesInReadonlySharedVault} + > + + Move to trash + + ))} + {trashed && ( + <> + { + await application.notesController.setTrashSelectedNotes(false) + closeMenuAndToggleNotesList() + }} + disabled={areSomeNotesInReadonlySharedVault} + > + + Restore + + { + await application.notesController.deleteNotesPermanently() + closeMenuAndToggleNotesList() + }} + > + + Delete permanently + + { + await application.notesController.emptyTrash() + closeMenuAndToggleNotesList() + }} + disabled={areSomeNotesInReadonlySharedVault} + > +
+ +
+
Empty Trash
+
{application.notesController.trashedNotesCount} notes in Trash
+
+
+
+ + )} + {notes.length === 1 ? ( <> @@ -507,25 +518,22 @@ const NotesOptions = ({ notes, closeMenu }: NotesOptionsProps) => { )} {!areSomeNotesInSharedVault && ( - <> - + - + )} - - {editorForNote && ( - + + + )} - - diff --git a/packages/web/src/javascripts/Components/NotesOptions/NotesOptionsPanel.tsx b/packages/web/src/javascripts/Components/NotesOptions/NotesOptionsPanel.tsx index 5ec3288ad..13b2be8bd 100644 --- a/packages/web/src/javascripts/Components/NotesOptions/NotesOptionsPanel.tsx +++ b/packages/web/src/javascripts/Components/NotesOptions/NotesOptionsPanel.tsx @@ -37,7 +37,7 @@ const NotesOptionsPanel = ({ notesController, onClickPreprocessing }: Props) => togglePopover={toggleMenu} anchorElement={buttonRef} open={isOpen} - className="select-none pt-2" + className="select-none" > { return ( - <> - - -
Super
- + Show Markdown {markdownShortcut && } - + ) } diff --git a/packages/web/src/javascripts/Components/QuickSettingsMenu/QuickSettingsMenu.tsx b/packages/web/src/javascripts/Components/QuickSettingsMenu/QuickSettingsMenu.tsx index af4468890..48604dcb7 100644 --- a/packages/web/src/javascripts/Components/QuickSettingsMenu/QuickSettingsMenu.tsx +++ b/packages/web/src/javascripts/Components/QuickSettingsMenu/QuickSettingsMenu.tsx @@ -19,7 +19,7 @@ import MenuSwitchButtonItem from '../Menu/MenuSwitchButtonItem' import MenuRadioButtonItem from '../Menu/MenuRadioButtonItem' import { useApplication } from '../ApplicationProvider' import { GetAllThemesUseCase } from '@standardnotes/ui-services' -import MenuItemSeparator from '../Menu/MenuItemSeparator' +import MenuSection from '../Menu/MenuSection' type MenuProps = { closeMenu: () => void @@ -117,8 +117,7 @@ const QuickSettingsMenu: FunctionComponent = ({ closeMenu }) => { return ( {editorStackComponents.length > 0 && ( - <> -
Tools
+ {editorStackComponents.map((component) => ( { @@ -131,17 +130,17 @@ const QuickSettingsMenu: FunctionComponent = ({ closeMenu }) => { {component.displayName} ))} - - + )} -
Appearance
- - Default - - {themes.map((theme) => ( - - ))} - + + + Default + + {themes.map((theme) => ( + + ))} + + + {mergeCellButton} {!!mergeCellButton && } insertTableRowAtSelection(false)}> diff --git a/packages/web/src/javascripts/Components/SuperEditor/Plugins/ToolbarPlugin/ToolbarPlugin.tsx b/packages/web/src/javascripts/Components/SuperEditor/Plugins/ToolbarPlugin/ToolbarPlugin.tsx index 35e3c6ea9..5c3d4bc25 100644 --- a/packages/web/src/javascripts/Components/SuperEditor/Plugins/ToolbarPlugin/ToolbarPlugin.tsx +++ b/packages/web/src/javascripts/Components/SuperEditor/Plugins/ToolbarPlugin/ToolbarPlugin.tsx @@ -685,7 +685,7 @@ const ToolbarPlugin = () => { } return ( - + {tableOfContents.map(([key, text, tag]) => (