From e331990f42dd2f5f52e84e4b72636af4cb3de6e0 Mon Sep 17 00:00:00 2001 From: Botho <1258870+elbotho@users.noreply.github.com> Date: Mon, 8 Jan 2024 16:17:32 +0100 Subject: [PATCH 1/6] feat(blanks-plugin): bigger button in toolbar --- apps/web/src/data/en/index.ts | 3 ++- .../text-controls/hooks/use-formatting-options.tsx | 6 +++--- .../text-controls/plugin-toolbar-text-control-button.tsx | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/apps/web/src/data/en/index.ts b/apps/web/src/data/en/index.ts index 55bde91db2..7512532586 100644 --- a/apps/web/src/data/en/index.ts +++ b/apps/web/src/data/en/index.ts @@ -852,6 +852,7 @@ export const loggedInData = { mathFormula: 'Math formula (%ctrlOrCmd% + M)', code: 'Code (%ctrlOrCmd% + ⇧ + `)', blank: 'Blank', + createBlank: 'Create Blank', bold: 'Bold (%ctrlOrCmd% + B)', italic: 'Italic (%ctrlOrCmd% + I)', noItemsFound: 'No items found', @@ -903,7 +904,7 @@ export const loggedInData = { }, textAreaExercise: { title: 'Text Box Exercise', - description: 'A big text box for long answers. No feedback.' + description: 'A big text box for long answers. No feedback.', }, scMcExercise: { title: 'SC/MC Exercise', diff --git a/packages/editor/src/editor-ui/plugin-toolbar/text-controls/hooks/use-formatting-options.tsx b/packages/editor/src/editor-ui/plugin-toolbar/text-controls/hooks/use-formatting-options.tsx index 905db0d25e..aadbe87a64 100644 --- a/packages/editor/src/editor-ui/plugin-toolbar/text-controls/hooks/use-formatting-options.tsx +++ b/packages/editor/src/editor-ui/plugin-toolbar/text-controls/hooks/use-formatting-options.tsx @@ -346,12 +346,12 @@ function createToolbarControls( // Blank (For Fill in the Blank Exercises) { name: TextEditorFormattingOption.textBlank, - title: textStrings.blank, + title: textStrings.createBlank, isActive: isBlankActive, onClick: toggleBlank, renderIcon: () => ( - - _ + + {textStrings.blank} ), }, diff --git a/packages/editor/src/editor-ui/plugin-toolbar/text-controls/plugin-toolbar-text-control-button.tsx b/packages/editor/src/editor-ui/plugin-toolbar/text-controls/plugin-toolbar-text-control-button.tsx index 619ac555df..9c40123b66 100644 --- a/packages/editor/src/editor-ui/plugin-toolbar/text-controls/plugin-toolbar-text-control-button.tsx +++ b/packages/editor/src/editor-ui/plugin-toolbar/text-controls/plugin-toolbar-text-control-button.tsx @@ -26,7 +26,7 @@ export function PluginToolbarTextControlButton({ active ? 'bg-editor-primary-200 text-almost-black shadow-menu hover:text-black' : '#b6b6b6 hover:text-editor-primary', - 'b-0 m-1 h-6 w-6 cursor-pointer rounded p-0 outline-none', + 'b-0 m-1 h-6 w-auto min-w-[1.5rem] cursor-pointer rounded p-0 outline-none', 'serlo-tooltip-trigger' )} data-qa={`plugin-toolbar-button-${ From b7cbe5c19b3683d4b8d91dad1929f3fe3f20d511 Mon Sep 17 00:00:00 2001 From: Botho <1258870+elbotho@users.noreply.github.com> Date: Mon, 8 Jan 2024 17:21:59 +0100 Subject: [PATCH 2/6] feat(blanks-plugin): more prominent tool button | add separator, move to first position, add active tooltip text --- apps/web/src/data/en/index.ts | 1 + .../hooks/use-formatting-options.tsx | 37 ++++++---- .../plugin-toolbar-text-controls.tsx | 71 +++++++++++-------- .../plugin-toolbar/text-controls/types.ts | 4 ++ 4 files changed, 72 insertions(+), 41 deletions(-) diff --git a/apps/web/src/data/en/index.ts b/apps/web/src/data/en/index.ts index 7512532586..dc2a9d855e 100644 --- a/apps/web/src/data/en/index.ts +++ b/apps/web/src/data/en/index.ts @@ -853,6 +853,7 @@ export const loggedInData = { code: 'Code (%ctrlOrCmd% + ⇧ + `)', blank: 'Blank', createBlank: 'Create Blank', + removeBlank: 'Remove Blank', bold: 'Bold (%ctrlOrCmd% + B)', italic: 'Italic (%ctrlOrCmd% + I)', noItemsFound: 'No items found', diff --git a/packages/editor/src/editor-ui/plugin-toolbar/text-controls/hooks/use-formatting-options.tsx b/packages/editor/src/editor-ui/plugin-toolbar/text-controls/hooks/use-formatting-options.tsx index aadbe87a64..63b4531525 100644 --- a/packages/editor/src/editor-ui/plugin-toolbar/text-controls/hooks/use-formatting-options.tsx +++ b/packages/editor/src/editor-ui/plugin-toolbar/text-controls/hooks/use-formatting-options.tsx @@ -227,12 +227,27 @@ function createToolbarControls( ctrlKey: string ): ControlButton[] { const allFormattingOptions = [ + // Blank (For Fill in the Blank Exercises) + { + name: TextEditorFormattingOption.textBlank, + title: textStrings.createBlank, + activeTitle: textStrings.removeBlank, + isActive: isBlankActive, + onClick: toggleBlank, + group: 'blank', + renderIcon: () => ( + + {textStrings.blank} + + ), + }, // Bold { name: TextEditorFormattingOption.richTextBold, title: textStrings.bold, isActive: isBoldActive, onClick: toggleBoldMark, + group: 'default', renderIcon: () => , }, // Italic @@ -241,6 +256,7 @@ function createToolbarControls( title: textStrings.italic, isActive: isItalicActive, onClick: toggleItalicMark, + group: 'default', renderIcon: () => , }, // Link @@ -249,6 +265,7 @@ function createToolbarControls( title: textStrings.link, isActive: isLinkActive, onClick: toggleLink, + group: 'default', renderIcon: () => , }, // Headings @@ -257,6 +274,7 @@ function createToolbarControls( title: textStrings.headings, closeMenuTitle: textStrings.closeSubMenu, isActive: isAnyHeadingActive, + group: 'default', renderIcon: () => , renderCloseMenuIcon: () => , subMenuButtons: ([1, 2, 3] as const).map((level) => ({ @@ -275,6 +293,7 @@ function createToolbarControls( title: textStrings.colors, closeMenuTitle: textStrings.closeSubMenu, isActive: () => false, + group: 'default', renderIcon: (editor: SlateEditor) => { const colorIndex = getColorIndex(editor) const color = colorIndex ? textColors[colorIndex].value : 'black' @@ -287,6 +306,7 @@ function createToolbarControls( title: textStrings.resetColor, isActive: (editor: SlateEditor) => !isAnyColorActive(editor), onClick: resetColor, + group: undefined, renderIcon: () => (
), @@ -300,6 +320,7 @@ function createToolbarControls( : color.name, isActive: isColorActive(colorIndex), onClick: toggleColor(colorIndex), + group: undefined, renderIcon: () => (
, }, // Unordered list @@ -323,6 +345,7 @@ function createToolbarControls( title: textStrings.unorderedList, isActive: isSelectionWithinUnorderedList, onClick: toggleUnorderedList, + group: 'default', renderIcon: () => , }, // Math @@ -331,6 +354,7 @@ function createToolbarControls( title: textStrings.mathFormula, isActive: isMathActive, onClick: toggleMath, + group: 'default', renderIcon: () => ( ), @@ -341,20 +365,9 @@ function createToolbarControls( title: textStrings.code, isActive: isCodeActive, onClick: toggleCode, + group: 'default', renderIcon: () => , }, - // Blank (For Fill in the Blank Exercises) - { - name: TextEditorFormattingOption.textBlank, - title: textStrings.createBlank, - isActive: isBlankActive, - onClick: toggleBlank, - renderIcon: () => ( - - {textStrings.blank} - - ), - }, ].map((option) => { return { ...option, diff --git a/packages/editor/src/editor-ui/plugin-toolbar/text-controls/plugin-toolbar-text-controls.tsx b/packages/editor/src/editor-ui/plugin-toolbar/text-controls/plugin-toolbar-text-controls.tsx index 567720247f..fc107b77ea 100644 --- a/packages/editor/src/editor-ui/plugin-toolbar/text-controls/plugin-toolbar-text-controls.tsx +++ b/packages/editor/src/editor-ui/plugin-toolbar/text-controls/plugin-toolbar-text-controls.tsx @@ -1,4 +1,4 @@ -import { useState } from 'react' +import { Fragment, useState } from 'react' import { Editor as SlateEditor } from 'slate' import { PluginToolbarTextControlButton } from './plugin-toolbar-text-control-button' @@ -31,21 +31,32 @@ export function PluginToolbarTextControls({ <> {controls.map((control, index) => { if (mathActive && !isMath(control)) return null + + const next = controls[index + 1] + const showSeparator = !!next && next.group !== control.group + return ( - { - event.preventDefault() - event.stopPropagation() - isNestedControlButton(control) - ? setSubMenu(index) - : control.onClick(editor) - }} - key={index} - > - {control.renderIcon(editor)} - + + { + event.preventDefault() + event.stopPropagation() + isNestedControlButton(control) + ? setSubMenu(index) + : control.onClick(editor) + }} + > + {control.renderIcon(editor)} + + {showSeparator ? | : null} + ) })} @@ -72,20 +83,22 @@ export function PluginToolbarTextControls({ return ( <> - {subMenuControls.map((control, index) => ( - { - event.preventDefault() - control.onClick(editor) - setSubMenu(undefined) - }} - key={index} - > - {control.renderIcon(editor)} - - ))} + {subMenuControls.map((control, index) => { + return ( + { + event.preventDefault() + control.onClick(editor) + setSubMenu(undefined) + }} + key={index} + > + {control.renderIcon(editor)} + + ) + })} ) } diff --git a/packages/editor/src/editor-ui/plugin-toolbar/text-controls/types.ts b/packages/editor/src/editor-ui/plugin-toolbar/text-controls/types.ts index 0fac6700f8..e2c38660d2 100644 --- a/packages/editor/src/editor-ui/plugin-toolbar/text-controls/types.ts +++ b/packages/editor/src/editor-ui/plugin-toolbar/text-controls/types.ts @@ -11,6 +11,7 @@ export enum TextEditorFormattingOption { richTextBold = 'richTextBold', richTextItalic = 'richTextItalic', textBlank = 'textBlank', + separator = 'separator', } export type ControlButton = ActionControlButton | NestedControlButton @@ -18,7 +19,9 @@ export type ControlButton = ActionControlButton | NestedControlButton interface ActionControlButton { name: TextEditorFormattingOption title: string + activeTitle?: string isActive(editor: SlateEditor): boolean + group: 'blank' | 'default' onClick(editor: SlateEditor): void renderIcon(editor: SlateEditor): React.ReactNode } @@ -28,6 +31,7 @@ export interface NestedControlButton { closeMenuTitle: string subMenuButtons: ActionControlButton[] isActive(editor: SlateEditor): boolean + group: undefined renderIcon(editor: SlateEditor): React.ReactNode renderCloseMenuIcon(): React.ReactNode } From 6733273251a489721b0b014e0a187678119e97a2 Mon Sep 17 00:00:00 2001 From: Botho <1258870+elbotho@users.noreply.github.com> Date: Tue, 9 Jan 2024 11:24:19 +0100 Subject: [PATCH 3/6] chore(plugin-blanks): cleanup types --- .../text-controls/hooks/use-formatting-options.tsx | 13 +++---------- .../text-controls/plugin-toolbar-text-controls.tsx | 4 +++- .../editor-ui/plugin-toolbar/text-controls/types.ts | 2 +- 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/packages/editor/src/editor-ui/plugin-toolbar/text-controls/hooks/use-formatting-options.tsx b/packages/editor/src/editor-ui/plugin-toolbar/text-controls/hooks/use-formatting-options.tsx index 63b4531525..957ba821a5 100644 --- a/packages/editor/src/editor-ui/plugin-toolbar/text-controls/hooks/use-formatting-options.tsx +++ b/packages/editor/src/editor-ui/plugin-toolbar/text-controls/hooks/use-formatting-options.tsx @@ -16,7 +16,6 @@ import { faListOl, faListUl, faSquareRootVariable, - faXmark, } from '@fortawesome/free-solid-svg-icons' import { onKeyDown as slateListsOnKeyDown } from '@prezly/slate-lists' import { FaIcon } from '@serlo/frontend/src/components/fa-icon' @@ -274,9 +273,7 @@ function createToolbarControls( title: textStrings.headings, closeMenuTitle: textStrings.closeSubMenu, isActive: isAnyHeadingActive, - group: 'default', renderIcon: () => , - renderCloseMenuIcon: () => , subMenuButtons: ([1, 2, 3] as const).map((level) => ({ name: TextEditorFormattingOption.headings, title: `${textStrings.heading} ${level}`, @@ -293,20 +290,17 @@ function createToolbarControls( title: textStrings.colors, closeMenuTitle: textStrings.closeSubMenu, isActive: () => false, - group: 'default', renderIcon: (editor: SlateEditor) => { const colorIndex = getColorIndex(editor) const color = colorIndex ? textColors[colorIndex].value : 'black' return }, - renderCloseMenuIcon: () => , subMenuButtons: [ { name: TextEditorFormattingOption.colors, title: textStrings.resetColor, isActive: (editor: SlateEditor) => !isAnyColorActive(editor), onClick: resetColor, - group: undefined, renderIcon: () => (
), @@ -320,7 +314,6 @@ function createToolbarControls( : color.name, isActive: isColorActive(colorIndex), onClick: toggleColor(colorIndex), - group: undefined, renderIcon: () => (
- formattingOptions.includes(TextEditorFormattingOption[option.name]) - ) + return allFormattingOptions.filter(({ name }) => + formattingOptions.includes(TextEditorFormattingOption[name]) + ) as ControlButton[] } diff --git a/packages/editor/src/editor-ui/plugin-toolbar/text-controls/plugin-toolbar-text-controls.tsx b/packages/editor/src/editor-ui/plugin-toolbar/text-controls/plugin-toolbar-text-controls.tsx index 1558675dd3..2d0063809d 100644 --- a/packages/editor/src/editor-ui/plugin-toolbar/text-controls/plugin-toolbar-text-controls.tsx +++ b/packages/editor/src/editor-ui/plugin-toolbar/text-controls/plugin-toolbar-text-controls.tsx @@ -1,8 +1,10 @@ +import { faXmark } from '@fortawesome/free-solid-svg-icons' import { Fragment, useState } from 'react' import { Editor as SlateEditor } from 'slate' import { PluginToolbarTextControlButton } from './plugin-toolbar-text-control-button' import type { NestedControlButton, ControlButton } from './types' +import { FaIcon } from '@/components/fa-icon' export interface PluginToolbarTextControlsProps { controls: ControlButton[] @@ -77,7 +79,7 @@ export function PluginToolbarTextControls({ return false }, renderIcon() { - return activeControl.renderCloseMenuIcon() + return }, onClick() { setSubMenu(undefined) diff --git a/packages/editor/src/editor-ui/plugin-toolbar/text-controls/types.ts b/packages/editor/src/editor-ui/plugin-toolbar/text-controls/types.ts index e2c38660d2..0eaf187154 100644 --- a/packages/editor/src/editor-ui/plugin-toolbar/text-controls/types.ts +++ b/packages/editor/src/editor-ui/plugin-toolbar/text-controls/types.ts @@ -27,11 +27,11 @@ interface ActionControlButton { } export interface NestedControlButton { + name: TextEditorFormattingOption title: string closeMenuTitle: string subMenuButtons: ActionControlButton[] isActive(editor: SlateEditor): boolean group: undefined renderIcon(editor: SlateEditor): React.ReactNode - renderCloseMenuIcon(): React.ReactNode } From 0a7cc662b666a2f16b5e835f506ec236d7c8c7a9 Mon Sep 17 00:00:00 2001 From: Botho <1258870+elbotho@users.noreply.github.com> Date: Wed, 10 Jan 2024 15:27:02 +0100 Subject: [PATCH 4/6] move up 1px --- .../text-controls/hooks/use-formatting-options.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/editor/src/editor-ui/plugin-toolbar/text-controls/hooks/use-formatting-options.tsx b/packages/editor/src/editor-ui/plugin-toolbar/text-controls/hooks/use-formatting-options.tsx index 957ba821a5..0dee649fb0 100644 --- a/packages/editor/src/editor-ui/plugin-toolbar/text-controls/hooks/use-formatting-options.tsx +++ b/packages/editor/src/editor-ui/plugin-toolbar/text-controls/hooks/use-formatting-options.tsx @@ -235,7 +235,7 @@ function createToolbarControls( onClick: toggleBlank, group: 'blank', renderIcon: () => ( - + {textStrings.blank} ), From 29a52382c54dc8c38b5d29384bfeb67dd4ba32dc Mon Sep 17 00:00:00 2001 From: Botho <1258870+elbotho@users.noreply.github.com> Date: Thu, 11 Jan 2024 23:16:20 +0100 Subject: [PATCH 5/6] refactor(plugin-text): improve types with Array.prototype.at --- .../text-controls/plugin-toolbar-text-controls.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/editor/src/editor-ui/plugin-toolbar/text-controls/plugin-toolbar-text-controls.tsx b/packages/editor/src/editor-ui/plugin-toolbar/text-controls/plugin-toolbar-text-controls.tsx index 2d0063809d..42ee4a1270 100644 --- a/packages/editor/src/editor-ui/plugin-toolbar/text-controls/plugin-toolbar-text-controls.tsx +++ b/packages/editor/src/editor-ui/plugin-toolbar/text-controls/plugin-toolbar-text-controls.tsx @@ -39,7 +39,7 @@ export function PluginToolbarTextControls({ if (mathActive && !isMath(control)) return null if (blankActive && !isBlank(control)) return null - const next = controls[index + 1] + const next = controls.at(index + 1) const showSeparator = !!next && next.group !== control.group return ( From d1c0ae8da3b1a7fc7fbb51fd25b6f18741677ebb Mon Sep 17 00:00:00 2001 From: Botho <1258870+elbotho@users.noreply.github.com> Date: Thu, 11 Jan 2024 23:26:35 +0100 Subject: [PATCH 6/6] fix(plugin-text): improve separators --- .../text-controls/hooks/use-formatting-options.tsx | 6 ++++-- .../text-controls/plugin-toolbar-text-controls.tsx | 4 +++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/editor/src/editor-ui/plugin-toolbar/text-controls/hooks/use-formatting-options.tsx b/packages/editor/src/editor-ui/plugin-toolbar/text-controls/hooks/use-formatting-options.tsx index 0dee649fb0..28d1c2d60e 100644 --- a/packages/editor/src/editor-ui/plugin-toolbar/text-controls/hooks/use-formatting-options.tsx +++ b/packages/editor/src/editor-ui/plugin-toolbar/text-controls/hooks/use-formatting-options.tsx @@ -273,6 +273,7 @@ function createToolbarControls( title: textStrings.headings, closeMenuTitle: textStrings.closeSubMenu, isActive: isAnyHeadingActive, + group: 'default', renderIcon: () => , subMenuButtons: ([1, 2, 3] as const).map((level) => ({ name: TextEditorFormattingOption.headings, @@ -290,6 +291,7 @@ function createToolbarControls( title: textStrings.colors, closeMenuTitle: textStrings.closeSubMenu, isActive: () => false, + group: 'default', renderIcon: (editor: SlateEditor) => { const colorIndex = getColorIndex(editor) const color = colorIndex ? textColors[colorIndex].value : 'black' @@ -329,7 +331,7 @@ function createToolbarControls( title: textStrings.orderedList, isActive: isSelectionWithinOrderedList, onClick: toggleOrderedList, - group: 'default', + group: 'lists', renderIcon: () => , }, // Unordered list @@ -338,7 +340,7 @@ function createToolbarControls( title: textStrings.unorderedList, isActive: isSelectionWithinUnorderedList, onClick: toggleUnorderedList, - group: 'default', + group: 'lists', renderIcon: () => , }, // Math diff --git a/packages/editor/src/editor-ui/plugin-toolbar/text-controls/plugin-toolbar-text-controls.tsx b/packages/editor/src/editor-ui/plugin-toolbar/text-controls/plugin-toolbar-text-controls.tsx index 42ee4a1270..94d1b9bc98 100644 --- a/packages/editor/src/editor-ui/plugin-toolbar/text-controls/plugin-toolbar-text-controls.tsx +++ b/packages/editor/src/editor-ui/plugin-toolbar/text-controls/plugin-toolbar-text-controls.tsx @@ -31,6 +31,7 @@ export function PluginToolbarTextControls({ const mathActive = controls.find(isMath)?.isActive(editor) const blankActive = controls.find(isBlank)?.isActive(editor) + const isSpecialMode = mathActive || blankActive if (typeof subMenu !== 'number') { return ( @@ -40,7 +41,8 @@ export function PluginToolbarTextControls({ if (blankActive && !isBlank(control)) return null const next = controls.at(index + 1) - const showSeparator = !!next && next.group !== control.group + const showSeparator = + !isSpecialMode && !!next && next.group !== control.group return (