From da6f36f34cdee324339d2c923d61191b373513f3 Mon Sep 17 00:00:00 2001 From: Mo Date: Fri, 11 Nov 2022 12:24:46 -0600 Subject: [PATCH] fix: super improvements (#1995) * feat(super): autolink selection with cmd + k * feat: super note importer * feat: handle html import * fix: ignore load change event emitted by on change plugin --- .../blocks-editor/src/Editor/BlocksEditor.tsx | 10 +- .../src/Editor/BlocksEditorComposer.tsx | 6 +- .../BlockEditor/BlockEditorComponent.tsx | 4 +- .../Plugins/AutoLinkPlugin/AutoLinkPlugin.tsx | 31 +++++ .../Plugins/ImportPlugin/ImportPlugin.tsx | 27 ++++ .../BlockEditor/SuperNoteImporter.tsx | 106 ++++++++++++++++ .../ChangeEditor/ChangeEditorButton.tsx | 14 ++- .../ChangeEditor/ChangeEditorMenu.tsx | 119 ++++++++++++------ .../Components/NoteView/NoteView.tsx | 2 + .../NotesOptions/AccordionMenuGroup.tsx | 1 + .../Components/Popover/Popover.tsx | 3 + .../Popover/PositionedPopoverContent.tsx | 2 + .../javascripts/Components/Popover/Types.ts | 1 + .../Utils/usePopoverCloseOnClickOutside.ts | 8 +- .../Components/Shared/ModalDialog.tsx | 2 +- .../Shared/ModalDialogDescription.tsx | 2 +- .../src/javascripts/Constants/Constants.ts | 2 +- .../Utils/createEditorMenuGroups.ts | 5 +- 18 files changed, 294 insertions(+), 51 deletions(-) create mode 100644 packages/web/src/javascripts/Components/BlockEditor/Plugins/AutoLinkPlugin/AutoLinkPlugin.tsx create mode 100644 packages/web/src/javascripts/Components/BlockEditor/Plugins/ImportPlugin/ImportPlugin.tsx create mode 100644 packages/web/src/javascripts/Components/BlockEditor/SuperNoteImporter.tsx diff --git a/packages/blocks-editor/src/Editor/BlocksEditor.tsx b/packages/blocks-editor/src/Editor/BlocksEditor.tsx index 0c87c8173..e51ff3ca8 100644 --- a/packages/blocks-editor/src/Editor/BlocksEditor.tsx +++ b/packages/blocks-editor/src/Editor/BlocksEditor.tsx @@ -36,7 +36,7 @@ const BlockDragEnabled = false; type BlocksEditorProps = { onChange: (value: string, preview: string) => void; className?: string; - children: React.ReactNode; + children?: React.ReactNode; previewLength: number; spellcheck?: boolean; }; @@ -48,8 +48,14 @@ export const BlocksEditor: FunctionComponent = ({ previewLength, spellcheck, }) => { + const [didIgnoreFirstChange, setDidIgnoreFirstChange] = useState(false); const handleChange = useCallback( (editorState: EditorState, _editor: LexicalEditor) => { + if (!didIgnoreFirstChange) { + setDidIgnoreFirstChange(true); + return; + } + editorState.read(() => { const childrenNodes = $getRoot().getAllTextNodes().slice(0, 2); let previewText = ''; @@ -65,7 +71,7 @@ export const BlocksEditor: FunctionComponent = ({ onChange(stringifiedEditorState, previewText); }); }, - [onChange], + [onChange, didIgnoreFirstChange], ); const [floatingAnchorElem, setFloatingAnchorElem] = diff --git a/packages/blocks-editor/src/Editor/BlocksEditorComposer.tsx b/packages/blocks-editor/src/Editor/BlocksEditorComposer.tsx index 4822b61be..5d334c9bc 100644 --- a/packages/blocks-editor/src/Editor/BlocksEditorComposer.tsx +++ b/packages/blocks-editor/src/Editor/BlocksEditorComposer.tsx @@ -7,17 +7,19 @@ import {Klass, LexicalNode} from 'lexical'; type BlocksEditorComposerProps = { initialValue: string; children: React.ReactNode; - nodes: Array>; + nodes?: Array>; + readonly?: boolean; }; export const BlocksEditorComposer: FunctionComponent< BlocksEditorComposerProps -> = ({initialValue, children, nodes}) => { +> = ({initialValue, children, readonly, nodes = []}) => { return ( console.error(error), editorState: initialValue && initialValue.length > 0 ? initialValue : undefined, diff --git a/packages/web/src/javascripts/Components/BlockEditor/BlockEditorComponent.tsx b/packages/web/src/javascripts/Components/BlockEditor/BlockEditorComponent.tsx index cf2e333f0..4d932cf74 100644 --- a/packages/web/src/javascripts/Components/BlockEditor/BlockEditorComponent.tsx +++ b/packages/web/src/javascripts/Components/BlockEditor/BlockEditorComponent.tsx @@ -16,6 +16,7 @@ import { NodeObserverPlugin } from './Plugins/NodeObserverPlugin/NodeObserverPlu import { FilesController } from '@/Controllers/FilesController' import FilesControllerProvider from '@/Controllers/FilesControllerProvider' import DatetimePlugin from './Plugins/DateTimePlugin/DateTimePlugin' +import AutoLinkPlugin from './Plugins/AutoLinkPlugin/AutoLinkPlugin' const NotePreviewCharLimit = 160 @@ -58,7 +59,7 @@ export const BlockEditor: FunctionComponent = ({ - + = ({ + diff --git a/packages/web/src/javascripts/Components/BlockEditor/Plugins/AutoLinkPlugin/AutoLinkPlugin.tsx b/packages/web/src/javascripts/Components/BlockEditor/Plugins/AutoLinkPlugin/AutoLinkPlugin.tsx new file mode 100644 index 000000000..2773567dc --- /dev/null +++ b/packages/web/src/javascripts/Components/BlockEditor/Plugins/AutoLinkPlugin/AutoLinkPlugin.tsx @@ -0,0 +1,31 @@ +import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext' +import { COMMAND_PRIORITY_EDITOR, KEY_MODIFIER_COMMAND, $getSelection } from 'lexical' +import { useEffect } from 'react' +import { TOGGLE_LINK_COMMAND } from '@lexical/link' +import { mergeRegister } from '@lexical/utils' + +export default function AutoLinkPlugin(): JSX.Element | null { + const [editor] = useLexicalComposerContext() + + useEffect(() => { + return mergeRegister( + editor.registerCommand( + KEY_MODIFIER_COMMAND, + (event: KeyboardEvent) => { + const isCmdK = event.key === 'k' && !event.altKey && (event.metaKey || event.ctrlKey) + if (isCmdK) { + const selection = $getSelection() + if (selection) { + editor.dispatchCommand(TOGGLE_LINK_COMMAND, selection.getTextContent()) + } + } + + return false + }, + COMMAND_PRIORITY_EDITOR, + ), + ) + }, [editor]) + + return null +} diff --git a/packages/web/src/javascripts/Components/BlockEditor/Plugins/ImportPlugin/ImportPlugin.tsx b/packages/web/src/javascripts/Components/BlockEditor/Plugins/ImportPlugin/ImportPlugin.tsx new file mode 100644 index 000000000..87f4512ab --- /dev/null +++ b/packages/web/src/javascripts/Components/BlockEditor/Plugins/ImportPlugin/ImportPlugin.tsx @@ -0,0 +1,27 @@ +import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext' +import { useEffect } from 'react' +import { $convertFromMarkdownString, TRANSFORMERS } from '@lexical/markdown' +import { $generateNodesFromDOM } from '@lexical/html' +import { $createParagraphNode, $createRangeSelection } from 'lexical' + +/** Note that markdown conversion does not insert new lines. See: https://github.com/facebook/lexical/issues/2815 */ +export default function ImportPlugin({ text, format }: { text: string; format: 'md' | 'html' }): JSX.Element | null { + const [editor] = useLexicalComposerContext() + + useEffect(() => { + editor.update(() => { + if (format === 'md') { + $convertFromMarkdownString(text, [...TRANSFORMERS]) + } else { + const parser = new DOMParser() + const dom = parser.parseFromString(text, 'text/html') + const nodes = $generateNodesFromDOM(editor, dom) + const selection = $createRangeSelection() + const newLineNode = $createParagraphNode() + selection.insertNodes([newLineNode, ...nodes]) + } + }) + }, [editor, text, format]) + + return null +} diff --git a/packages/web/src/javascripts/Components/BlockEditor/SuperNoteImporter.tsx b/packages/web/src/javascripts/Components/BlockEditor/SuperNoteImporter.tsx new file mode 100644 index 000000000..3636197f9 --- /dev/null +++ b/packages/web/src/javascripts/Components/BlockEditor/SuperNoteImporter.tsx @@ -0,0 +1,106 @@ +import { WebApplication } from '@/Application/Application' +import { NoteType, SNNote } from '@standardnotes/snjs' +import { FunctionComponent, useCallback, useState } from 'react' +import { BlockEditorController } from './BlockEditorController' +import { BlocksEditor, BlocksEditorComposer } from '@standardnotes/blocks-editor' +import { ErrorBoundary } from '@/Utils/ErrorBoundary' +import ModalDialog from '@/Components/Shared/ModalDialog' +import ModalDialogButtons from '@/Components/Shared/ModalDialogButtons' +import ModalDialogDescription from '@/Components/Shared/ModalDialogDescription' +import ModalDialogLabel from '@/Components/Shared/ModalDialogLabel' +import Button from '@/Components/Button/Button' +import ImportPlugin from './Plugins/ImportPlugin/ImportPlugin' + +export function spaceSeparatedStrings(...strings: string[]): string { + return strings.join(' ') +} + +const NotePreviewCharLimit = 160 + +type Props = { + application: WebApplication + note: SNNote + closeDialog: () => void + onConvertComplete: () => void +} + +export const SuperNoteImporter: FunctionComponent = ({ note, application, closeDialog, onConvertComplete }) => { + const [lastValue, setLastValue] = useState({ text: '', previewPlain: '' }) + + const format = + !note.noteType || [NoteType.Plain, NoteType.Markdown, NoteType.Code, NoteType.Task].includes(note.noteType) + ? 'md' + : 'html' + + const handleChange = useCallback((value: string, preview: string) => { + setLastValue({ text: value, previewPlain: preview }) + }, []) + + const confirmConvert = useCallback(() => { + const controller = new BlockEditorController(note, application) + void controller.save({ text: lastValue.text, previewPlain: lastValue.previewPlain, previewHtml: undefined }) + closeDialog() + onConvertComplete() + }, [closeDialog, application, lastValue, note, onConvertComplete]) + + const convertAsIs = useCallback(async () => { + const confirmed = await application.alertService.confirm( + spaceSeparatedStrings( + "This option is useful if you switched this note's type from Super to another plaintext-based format, and want to return to Super.", + 'To use this option, the preview in the convert window should display a language format known as JSON.', + 'If this is not the case, cancel this prompt.', + ), + 'Are you sure?', + ) + if (!confirmed) { + return + } + + const controller = new BlockEditorController(note, application) + void controller.save({ text: note.text, previewPlain: note.preview_plain, previewHtml: undefined }) + closeDialog() + onConvertComplete() + }, [closeDialog, application, note, onConvertComplete]) + + return ( + + + Convert to Super note +

+ The following is a preview of how your note will look when converted to Super. Super notes use a custom format + under the hood. Converting your note will transition it from plaintext to the custom Super format. +

+
+ +
+ + + + + + + +
+
+ +
+
+ +
+
+ +
+ +
+
+ + + ) +} diff --git a/packages/web/src/javascripts/Components/ChangeEditor/ChangeEditorButton.tsx b/packages/web/src/javascripts/Components/ChangeEditor/ChangeEditorButton.tsx index db770a7b3..f9d8a46a5 100644 --- a/packages/web/src/javascripts/Components/ChangeEditor/ChangeEditorButton.tsx +++ b/packages/web/src/javascripts/Components/ChangeEditor/ChangeEditorButton.tsx @@ -26,6 +26,7 @@ const ChangeEditorButton: FunctionComponent = ({ return note ? application.componentManager.editorForNote(note) : undefined }) const [selectedEditorIcon, selectedEditorIconTint] = getIconAndTintForNoteType(selectedEditor?.package_info.note_type) + const [isClickOutsideDisabled, setIsClickOutsideDisabled] = useState(false) const toggleMenu = useCallback(async () => { const willMenuOpen = !isOpen @@ -35,6 +36,10 @@ const ChangeEditorButton: FunctionComponent = ({ setIsOpen(willMenuOpen) }, [onClickPreprocessing, isOpen]) + const disableClickOutside = useCallback(() => { + setIsClickOutsideDisabled(true) + }, []) + return (
= ({ icon={selectedEditorIcon} iconClassName={`text-accessory-tint-${selectedEditorIconTint}`} /> - + { setIsOpen(false) }} diff --git a/packages/web/src/javascripts/Components/ChangeEditor/ChangeEditorMenu.tsx b/packages/web/src/javascripts/Components/ChangeEditor/ChangeEditorMenu.tsx index 26595d33a..a705543c7 100644 --- a/packages/web/src/javascripts/Components/ChangeEditor/ChangeEditorMenu.tsx +++ b/packages/web/src/javascripts/Components/ChangeEditor/ChangeEditorMenu.tsx @@ -5,13 +5,14 @@ import { MenuItemType } from '@/Components/Menu/MenuItemType' import { usePremiumModal } from '@/Hooks/usePremiumModal' import { STRING_EDIT_LOCKED_ATTEMPT } from '@/Constants/Strings' import { WebApplication } from '@/Application/Application' -import { ComponentArea, NoteMutator, PrefKey, SNComponent, SNNote } from '@standardnotes/snjs' +import { ComponentArea, NoteMutator, NoteType, PrefKey, SNComponent, SNNote } from '@standardnotes/snjs' import { Fragment, FunctionComponent, useCallback, useEffect, useMemo, useState } from 'react' import { EditorMenuGroup } from '@/Components/NotesOptions/EditorMenuGroup' import { EditorMenuItem } from '@/Components/NotesOptions/EditorMenuItem' import { createEditorMenuGroups } from '../../Utils/createEditorMenuGroups' import { reloadFont } from '../NoteView/FontFunctions' import { PremiumFeatureIconClass, PremiumFeatureIconName } from '../Icon/PremiumFeatureIcon' +import { SuperNoteImporter } from '../BlockEditor/SuperNoteImporter' type ChangeEditorMenuProps = { application: WebApplication @@ -19,6 +20,7 @@ type ChangeEditorMenuProps = { isVisible: boolean note: SNNote | undefined onSelect?: (component: SNComponent | undefined) => void + handleDisableClickoutsideRequest?: () => void } const getGroupId = (group: EditorMenuGroup) => group.title.toLowerCase().replace(/\s/, '-') @@ -29,6 +31,7 @@ const ChangeEditorMenu: FunctionComponent = ({ isVisible, note, onSelect, + handleDisableClickoutsideRequest, }) => { const editors = useMemo( () => @@ -39,6 +42,8 @@ const ChangeEditorMenu: FunctionComponent = ({ ) const groups = useMemo(() => createEditorMenuGroups(application, editors), [application, editors]) const [currentComponent, setCurrentComponent] = useState() + const [showSuperImporter, setShowSuperImporter] = useState(false) + const [pendingSuperItem, setPendingSuperItem] = useState(null) useEffect(() => { if (note) { @@ -54,7 +59,7 @@ const ChangeEditorMenu: FunctionComponent = ({ return item.component?.identifier === currentComponent.identifier } - return item.noteType === note?.noteType + return item.noteType === note?.noteType || (!note?.noteType && item.noteType === NoteType.Plain) }, [currentComponent, note], ) @@ -109,6 +114,13 @@ const ChangeEditorMenu: FunctionComponent = ({ return } + if (itemToBeSelected.noteType === NoteType.Blocks) { + setPendingSuperItem(itemToBeSelected) + handleDisableClickoutsideRequest?.() + setShowSuperImporter(true) + return + } + let shouldMakeSelection = true if (itemToBeSelected.component) { @@ -136,46 +148,77 @@ const ChangeEditorMenu: FunctionComponent = ({ onSelect(itemToBeSelected.component) } }, - [application, closeMenu, currentComponent, note, onSelect, premiumModal, selectComponent, selectNonComponent], + [ + application, + closeMenu, + currentComponent, + note, + onSelect, + premiumModal, + selectComponent, + selectNonComponent, + handleDisableClickoutsideRequest, + ], ) - return ( - - {groups - .filter((group) => group.items && group.items.length) - .map((group, index) => { - const groupId = getGroupId(group) + const handleSuperNoteConversionCompletion = useCallback(() => { + if (!pendingSuperItem || !note) { + return + } - return ( - -
- {group.items.map((item) => { - const onClickEditorItem = () => { - selectItem(item).catch(console.error) - } - return ( - -
-
- {group.icon && } - {item.name} + selectNonComponent(pendingSuperItem, note).catch(console.error) + closeMenu() + }, [note, pendingSuperItem, selectNonComponent, closeMenu]) + + return ( + <> + + {groups + .filter((group) => group.items && group.items.length) + .map((group, index) => { + const groupId = getGroupId(group) + + return ( + +
+ {group.items.map((item) => { + const onClickEditorItem = () => { + selectItem(item).catch(console.error) + } + return ( + +
+
+ {group.icon && } + {item.name} +
+ {!item.isEntitled && ( + + )}
- {!item.isEntitled && } -
- - ) - })} -
- - ) - })} -
+ + ) + })} +
+ + ) + })} + + {showSuperImporter && note && ( + setShowSuperImporter(false)} + /> + )} + ) } diff --git a/packages/web/src/javascripts/Components/NoteView/NoteView.tsx b/packages/web/src/javascripts/Components/NoteView/NoteView.tsx index 9310a217c..5f286a019 100644 --- a/packages/web/src/javascripts/Components/NoteView/NoteView.tsx +++ b/packages/web/src/javascripts/Components/NoteView/NoteView.tsx @@ -334,6 +334,8 @@ class NoteView extends AbstractComponent { this.setState({ editorFeatureIdentifier: note.editorIdentifier, noteType: note.noteType, + editorText: note.text, + editorTitle: note.title, }) void this.reloadEditorComponent() diff --git a/packages/web/src/javascripts/Components/NotesOptions/AccordionMenuGroup.tsx b/packages/web/src/javascripts/Components/NotesOptions/AccordionMenuGroup.tsx index afd41da6d..3ea1ce487 100644 --- a/packages/web/src/javascripts/Components/NotesOptions/AccordionMenuGroup.tsx +++ b/packages/web/src/javascripts/Components/NotesOptions/AccordionMenuGroup.tsx @@ -5,4 +5,5 @@ export type AccordionMenuGroup = { iconClassName?: string title: string items: Array + featured?: boolean } diff --git a/packages/web/src/javascripts/Components/Popover/Popover.tsx b/packages/web/src/javascripts/Components/Popover/Popover.tsx index 50279367d..cf6342ddf 100644 --- a/packages/web/src/javascripts/Components/Popover/Popover.tsx +++ b/packages/web/src/javascripts/Components/Popover/Popover.tsx @@ -27,6 +27,7 @@ const useRegisterPopoverToParent = (popoverId: string) => { type Props = PopoverProps & { open: boolean + disableClickOutside?: boolean } const Popover = ({ @@ -39,6 +40,7 @@ const Popover = ({ overrideZIndex, side, togglePopover, + disableClickOutside, }: Props) => { const popoverId = useRef(UuidGenerator.GenerateUuid()) @@ -96,6 +98,7 @@ const Popover = ({ overrideZIndex={overrideZIndex} side={side} togglePopover={togglePopover} + disableClickOutside={disableClickOutside} > {children} diff --git a/packages/web/src/javascripts/Components/Popover/PositionedPopoverContent.tsx b/packages/web/src/javascripts/Components/Popover/PositionedPopoverContent.tsx index c1aea8f59..61e46600f 100644 --- a/packages/web/src/javascripts/Components/Popover/PositionedPopoverContent.tsx +++ b/packages/web/src/javascripts/Components/Popover/PositionedPopoverContent.tsx @@ -23,6 +23,7 @@ const PositionedPopoverContent = ({ overrideZIndex, side = 'bottom', togglePopover, + disableClickOutside, }: PopoverContentProps) => { const [popoverElement, setPopoverElement] = useState(null) const popoverRect = useAutoElementRect(popoverElement) @@ -50,6 +51,7 @@ const PositionedPopoverContent = ({ anchorElement, togglePopover, childPopovers, + disabled: disableClickOutside, }) useDisableBodyScrollOnMobile() diff --git a/packages/web/src/javascripts/Components/Popover/Types.ts b/packages/web/src/javascripts/Components/Popover/Types.ts index 351ea0b0d..62195216a 100644 --- a/packages/web/src/javascripts/Components/Popover/Types.ts +++ b/packages/web/src/javascripts/Components/Popover/Types.ts @@ -44,6 +44,7 @@ export type PopoverContentProps = CommonPopoverProps & { anchorPoint?: Point childPopovers: Set id: string + disableClickOutside?: boolean } export type PopoverProps = diff --git a/packages/web/src/javascripts/Components/Popover/Utils/usePopoverCloseOnClickOutside.ts b/packages/web/src/javascripts/Components/Popover/Utils/usePopoverCloseOnClickOutside.ts index d3b01baf3..f934fc1b4 100644 --- a/packages/web/src/javascripts/Components/Popover/Utils/usePopoverCloseOnClickOutside.ts +++ b/packages/web/src/javascripts/Components/Popover/Utils/usePopoverCloseOnClickOutside.ts @@ -6,6 +6,7 @@ type Options = { anchorElement: HTMLElement | null | undefined togglePopover: () => void childPopovers: Set + disabled?: boolean } export const usePopoverCloseOnClickOutside = ({ @@ -13,6 +14,7 @@ export const usePopoverCloseOnClickOutside = ({ anchorElement, togglePopover, childPopovers, + disabled, }: Options) => { useEffect(() => { const closeIfClickedOutside = (event: MouseEvent) => { @@ -31,7 +33,9 @@ export const usePopoverCloseOnClickOutside = ({ const isDescendantOfChallengeModal = !!target.closest('.challenge-modal') if (!isDescendantOfMenu && !isAnchorElement && !isDescendantOfChildPopover && !isDescendantOfChallengeModal) { - togglePopover() + if (!disabled) { + togglePopover() + } } } @@ -41,5 +45,5 @@ export const usePopoverCloseOnClickOutside = ({ document.removeEventListener('click', closeIfClickedOutside, { capture: true }) document.removeEventListener('contextmenu', closeIfClickedOutside, { capture: true }) } - }, [anchorElement, childPopovers, popoverElement, togglePopover]) + }, [anchorElement, childPopovers, popoverElement, togglePopover, disabled]) } diff --git a/packages/web/src/javascripts/Components/Shared/ModalDialog.tsx b/packages/web/src/javascripts/Components/Shared/ModalDialog.tsx index ecb62af06..94809eea4 100644 --- a/packages/web/src/javascripts/Components/Shared/ModalDialog.tsx +++ b/packages/web/src/javascripts/Components/Shared/ModalDialog.tsx @@ -16,7 +16,7 @@ const ModalDialog = ({ children, onDismiss, className }: Props) => { diff --git a/packages/web/src/javascripts/Components/Shared/ModalDialogDescription.tsx b/packages/web/src/javascripts/Components/Shared/ModalDialogDescription.tsx index 460255748..144eeee71 100644 --- a/packages/web/src/javascripts/Components/Shared/ModalDialogDescription.tsx +++ b/packages/web/src/javascripts/Components/Shared/ModalDialogDescription.tsx @@ -7,7 +7,7 @@ type Props = { } const ModalDialogDescription: FunctionComponent = ({ children, className = '' }) => ( - {children} + {children} ) export default ModalDialogDescription diff --git a/packages/web/src/javascripts/Constants/Constants.ts b/packages/web/src/javascripts/Constants/Constants.ts index 20c9a5a62..d41d097b1 100644 --- a/packages/web/src/javascripts/Constants/Constants.ts +++ b/packages/web/src/javascripts/Constants/Constants.ts @@ -22,7 +22,7 @@ export const TAG_FOLDERS_FEATURE_TOOLTIP = 'A Plus or Pro plan is required to en export const SMART_TAGS_FEATURE_NAME = 'Smart Tags' export const PLAIN_EDITOR_NAME = 'Plain Text' -export const BLOCKS_EDITOR_NAME = 'Super Note' +export const BLOCKS_EDITOR_NAME = 'Super' export const SYNC_TIMEOUT_DEBOUNCE = 350 export const SYNC_TIMEOUT_NO_DEBOUNCE = 100 diff --git a/packages/web/src/javascripts/Utils/createEditorMenuGroups.ts b/packages/web/src/javascripts/Utils/createEditorMenuGroups.ts index d8b014064..4b06324f1 100644 --- a/packages/web/src/javascripts/Utils/createEditorMenuGroups.ts +++ b/packages/web/src/javascripts/Utils/createEditorMenuGroups.ts @@ -126,10 +126,11 @@ const createGroupsFromMap = (map: NoteTypeToEditorRowsMap): EditorMenuGroup[] => if (featureTrunkEnabled(FeatureTrunkName.Blocks)) { groups.splice(1, 0, { - icon: 'dashboard', - iconClassName: 'text-accessory-tint-1', + icon: 'file-doc', + iconClassName: 'text-accessory-tint-4', title: BLOCKS_EDITOR_NAME, items: map[NoteType.Blocks], + featured: true, }) }