diff --git a/apps/web/src/data/en/index.ts b/apps/web/src/data/en/index.ts
index 55bde91db2..dc2a9d855e 100644
--- a/apps/web/src/data/en/index.ts
+++ b/apps/web/src/data/en/index.ts
@@ -852,6 +852,8 @@ export const loggedInData = {
mathFormula: 'Math formula (%ctrlOrCmd% + M)',
code: 'Code (%ctrlOrCmd% + ⇧ + `)',
blank: 'Blank',
+ createBlank: 'Create Blank',
+ removeBlank: 'Remove Blank',
bold: 'Bold (%ctrlOrCmd% + B)',
italic: 'Italic (%ctrlOrCmd% + I)',
noItemsFound: 'No items found',
@@ -903,7 +905,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..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
@@ -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'
@@ -227,12 +226,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 +255,7 @@ function createToolbarControls(
title: textStrings.italic,
isActive: isItalicActive,
onClick: toggleItalicMark,
+ group: 'default',
renderIcon: () => ,
},
// Link
@@ -249,6 +264,7 @@ function createToolbarControls(
title: textStrings.link,
isActive: isLinkActive,
onClick: toggleLink,
+ group: 'default',
renderIcon: () => ,
},
// Headings
@@ -257,8 +273,8 @@ 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}`,
@@ -275,12 +291,12 @@ 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,
@@ -315,6 +331,7 @@ function createToolbarControls(
title: textStrings.orderedList,
isActive: isSelectionWithinOrderedList,
onClick: toggleOrderedList,
+ group: 'lists',
renderIcon: () => ,
},
// Unordered list
@@ -323,6 +340,7 @@ function createToolbarControls(
title: textStrings.unorderedList,
isActive: isSelectionWithinUnorderedList,
onClick: toggleUnorderedList,
+ group: 'lists',
renderIcon: () => ,
},
// Math
@@ -331,6 +349,7 @@ function createToolbarControls(
title: textStrings.mathFormula,
isActive: isMathActive,
onClick: toggleMath,
+ group: 'default',
renderIcon: () => (
),
@@ -341,20 +360,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.blank,
- isActive: isBlankActive,
- onClick: toggleBlank,
- renderIcon: () => (
-
- _
-
- ),
- },
].map((option) => {
return {
...option,
@@ -362,7 +370,7 @@ function createToolbarControls(
}
})
- return allFormattingOptions.filter((option) =>
- 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-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-${
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 2f502208af..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
@@ -1,8 +1,10 @@
-import { useState } from 'react'
+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[]
@@ -29,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 (
@@ -36,21 +39,33 @@ export function PluginToolbarTextControls({
{controls.map((control, index) => {
if (mathActive && !isMath(control)) return null
if (blankActive && !isBlank(control)) return null
+
+ const next = controls.at(index + 1)
+ const showSeparator =
+ !isSpecialMode && !!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}
+
)
})}
>
@@ -66,7 +81,7 @@ export function PluginToolbarTextControls({
return false
},
renderIcon() {
- return activeControl.renderCloseMenuIcon()
+ return
},
onClick() {
setSubMenu(undefined)
@@ -77,20 +92,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..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
@@ -11,6 +11,7 @@ export enum TextEditorFormattingOption {
richTextBold = 'richTextBold',
richTextItalic = 'richTextItalic',
textBlank = 'textBlank',
+ separator = 'separator',
}
export type ControlButton = ActionControlButton | NestedControlButton
@@ -18,16 +19,19 @@ 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
}
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
}