diff --git a/src/components/input/editor/CommandsList.vue b/src/components/input/editor/CommandsList.vue
index 4b8f55436..6221f3914 100644
--- a/src/components/input/editor/CommandsList.vue
+++ b/src/components/input/editor/CommandsList.vue
@@ -8,7 +8,11 @@
:key="index"
@click="selectItem(index)"
>
- {{ item }}
+
+
+
{{ item.title }}
+
{{ item.description }}
+
@@ -99,17 +103,42 @@ export default {
}
.item {
- display: block;
+ display: flex;
+ align-items: center;
margin: 0;
width: 100%;
text-align: left;
background: transparent;
- border-radius: 0.4rem;
- border: 1px solid transparent;
+ border-radius: $radius;
+ border: 0;
padding: 0.2rem 0.4rem;
+ transition: background-color $transition;
- &.is-selected {
- border-color: #000;
+ &.is-selected, &:hover {
+ background: var(--grey-100);
+ cursor: pointer;
+ }
+
+ > svg {
+ box-sizing: border-box;
+ width: 2rem;
+ height: 2rem;
+ border: 1px solid var(--grey-300);
+ padding: .5rem;
+ margin-right: .5rem;
+ border-radius: $radius;
+ color: var(--grey-700);
+ }
+}
+
+.description {
+ display: flex;
+ flex-direction: column;
+ font-size: .9rem;
+
+ p:last-child {
+ font-size: .75rem;
+ color: var(--grey-500);
}
}
\ No newline at end of file
diff --git a/src/components/input/editor/TipTap.vue b/src/components/input/editor/TipTap.vue
index 6da6de9bc..d6abeae76 100644
--- a/src/components/input/editor/TipTap.vue
+++ b/src/components/input/editor/TipTap.vue
@@ -47,7 +47,7 @@ import StarterKit from '@tiptap/starter-kit'
import {EditorContent, useEditor, VueNodeViewRenderer} from '@tiptap/vue-3'
import Commands from './commands'
-import suggestion from './suggestion'
+import suggestionSetup from './suggestion'
// load all highlight.js languages
import {lowlight} from 'lowlight'
@@ -58,6 +58,9 @@ import type {ITask} from '@/modelTypes/ITask'
import type {IAttachment} from '@/modelTypes/IAttachment'
import AttachmentModel from '@/models/attachment'
import AttachmentService from '@/services/attachment'
+import {useI18n} from 'vue-i18n'
+
+const {t} = useI18n()
// const CustomDocument = Document.extend({
// content: 'taskList',
@@ -204,7 +207,7 @@ const editor = useEditor({
// }).configure({ lowlight }),
Commands.configure({
- suggestion,
+ suggestion: suggestionSetup(t),
}),
],
onUpdate: () => {
diff --git a/src/components/input/editor/suggestion.ts b/src/components/input/editor/suggestion.ts
index 64c8dc3e1..cf47d10f2 100644
--- a/src/components/input/editor/suggestion.ts
+++ b/src/components/input/editor/suggestion.ts
@@ -3,112 +3,212 @@ import tippy from 'tippy.js'
import CommandsList from './CommandsList.vue'
-export default {
- items: ({query}: { query: string }) => {
- return [
- {
- title: 'H1',
- command: ({editor, range}) => {
- editor
- .chain()
- .focus()
- .deleteRange(range)
- .setNode('heading', {level: 1})
- .run()
+export default function suggestionSetup(t) {
+ return {
+ items: ({query}: { query: string }) => {
+ return [
+ {
+ title: t('input.editor.text'),
+ description: t('input.editor.textTooltip'),
+ icon: 'fa-font',
+ command: ({editor, range}) => {
+ editor
+ .chain()
+ .focus()
+ .deleteRange(range)
+ .setNode('paragraph', {level: 1})
+ .run()
+ },
},
- },
- {
- title: 'H2',
- description: 'Lorem ipsum',
- command: ({editor, range}) => {
- editor
- .chain()
- .focus()
- .deleteRange(range)
- .setNode('heading', {level: 2})
- .run()
+ {
+ title: t('input.editor.heading1'),
+ description: t('input.editor.heading1Tooltip'),
+ icon: 'fa-header',
+ command: ({editor, range}) => {
+ editor
+ .chain()
+ .focus()
+ .deleteRange(range)
+ .setNode('heading', {level: 1})
+ .run()
+ },
},
- },
- {
- title: 'bold',
- command: ({editor, range}) => {
- editor
- .chain()
- .focus()
- .deleteRange(range)
- .setMark('bold')
- .run()
+ {
+ title: t('input.editor.heading2'),
+ description: t('input.editor.heading2Tooltip'),
+ icon: 'fa-header',
+ command: ({editor, range}) => {
+ editor
+ .chain()
+ .focus()
+ .deleteRange(range)
+ .setNode('heading', {level: 2})
+ .run()
+ },
},
- },
- {
- title: 'italic',
- command: ({editor, range}) => {
- editor
- .chain()
- .focus()
- .deleteRange(range)
- .setMark('italic')
- .run()
+ {
+ title: t('input.editor.heading3'),
+ description: t('input.editor.heading3Tooltip'),
+ icon: 'fa-header',
+ command: ({editor, range}) => {
+ editor
+ .chain()
+ .focus()
+ .deleteRange(range)
+ .setNode('heading', {level: 2})
+ .run()
+ },
},
- },
- ].filter(item => item.title.toLowerCase().startsWith(query.toLowerCase())).slice(0, 10)
- },
+ {
+ title: t('input.editor.bulletList'),
+ description: t('input.editor.bulletListTooltip'),
+ icon: 'fa-list-ul',
+ command: ({editor, range}) => {
+ editor
+ .chain()
+ .focus()
+ .deleteRange(range)
+ .toggleBulletList()
+ .run()
+ },
+ },
+ {
+ title: t('input.editor.orderedList'),
+ description: t('input.editor.orderedListTooltip'),
+ icon: 'fa-list-ol',
+ command: ({editor, range}) => {
+ editor
+ .chain()
+ .focus()
+ .deleteRange(range)
+ .toggleOrderedList()
+ .run()
+ },
+ },
+ {
+ title: t('input.editor.taskList'),
+ description: t('input.editor.taskListTooltip'),
+ icon: 'fa-list-check',
+ command: ({editor, range}) => {
+ editor
+ .chain()
+ .focus()
+ .deleteRange(range)
+ .toggleTaskList()
+ .run()
+ },
+ },
+ {
+ title: t('input.editor.quote'),
+ description: t('input.editor.quoteTooltip'),
+ icon: 'fa-quote-right',
+ command: ({editor, range}) => {
+ editor
+ .chain()
+ .focus()
+ .deleteRange(range)
+ .toggleBlockquote()
+ .run()
+ },
+ },
+ {
+ title: t('input.editor.code'),
+ description: t('input.editor.codeTooltip'),
+ icon: 'fa-code',
+ command: ({editor, range}) => {
+ editor
+ .chain()
+ .focus()
+ .deleteRange(range)
+ .toggleCodeBlock()
+ .run()
+ },
+ },
+ // {
+ // title: t('input.editor.')'Image',
+ // description: t('input.editor.')'Upload an image from your computer',
+ // icon: 'fa-image',
+ // command: ({editor, range}) => {
+ // editor
+ // .chain()
+ // .focus()
+ // .deleteRange(range)
+ // .toggle()
+ // .run()
+ // },
+ // },
+ {
+ title: t('input.editor.horizontalRule'),
+ description: t('input.editor.horizontalRuleTooltip'),
+ icon: 'fa-ruler-horizontal',
+ command: ({editor, range}) => {
+ editor
+ .chain()
+ .focus()
+ .deleteRange(range)
+ .setHorizontalRule()
+ .run()
+ },
+ },
+ ].filter(item => item.title.toLowerCase().startsWith(query.toLowerCase()))
+ },
- render: () => {
- let component: VueRenderer
- let popup
+ render: () => {
+ let component: VueRenderer
+ let popup
- return {
- onStart: props => {
- component = new VueRenderer(CommandsList, {
- // using vue 2:
- // parent: this,
- // propsData: props,
- props,
- editor: props.editor,
- })
+ return {
+ onStart: props => {
+ component = new VueRenderer(CommandsList, {
+ // using vue 2:
+ // parent: this,
+ // propsData: props,
+ props,
+ editor: props.editor,
+ })
- if (!props.clientRect) {
- return
- }
+ if (!props.clientRect) {
+ return
+ }
- popup = tippy('body', {
- getReferenceClientRect: props.clientRect,
- appendTo: () => document.body,
- content: component.element,
- showOnCreate: true,
- interactive: true,
- trigger: 'manual',
- placement: 'bottom-start',
- })
- },
+ popup = tippy('body', {
+ getReferenceClientRect: props.clientRect,
+ appendTo: () => document.body,
+ content: component.element,
+ showOnCreate: true,
+ interactive: true,
+ trigger: 'manual',
+ placement: 'bottom-start',
+ })
+ },
- onUpdate(props) {
- component.updateProps(props)
+ onUpdate(props) {
+ component.updateProps(props)
- if (!props.clientRect) {
- return
- }
+ if (!props.clientRect) {
+ return
+ }
- popup[0].setProps({
- getReferenceClientRect: props.clientRect,
- })
- },
+ popup[0].setProps({
+ getReferenceClientRect: props.clientRect,
+ })
+ },
- onKeyDown(props) {
- if (props.event.key === 'Escape') {
- popup[0].hide()
+ onKeyDown(props) {
+ if (props.event.key === 'Escape') {
+ popup[0].hide()
- return true
- }
+ return true
+ }
- return component.ref?.onKeyDown(props)
- },
+ return component.ref?.onKeyDown(props)
+ },
- onExit() {
- popup[0].destroy()
- component.destroy()
- },
- }
- },
+ onExit() {
+ popup[0].destroy()
+ component.destroy()
+ },
+ }
+ },
+ }
}
\ No newline at end of file
diff --git a/src/components/misc/Icon.ts b/src/components/misc/Icon.ts
index 5300d07a2..cc8aed567 100644
--- a/src/components/misc/Icon.ts
+++ b/src/components/misc/Icon.ts
@@ -73,7 +73,7 @@ import {
faUnlink,
faParagraph,
faTable,
- faX, faArrowTurnDown, faListCheck, faXmark, faXmarksLines,
+ faX, faArrowTurnDown, faListCheck, faXmark, faXmarksLines, faFont, faRulerHorizontal,
} from '@fortawesome/free-solid-svg-icons'
import {
faBellSlash,
@@ -183,6 +183,8 @@ library.add(faArrowTurnDown)
library.add(faListCheck)
library.add(faXmark)
library.add(faXmarksLines)
+library.add(faFont)
+library.add(faRulerHorizontal)
// overwriting the wrong types
export default FontAwesomeIcon as unknown as FontAwesomeIconFixedTypes
\ No newline at end of file
diff --git a/src/i18n/lang/en.json b/src/i18n/lang/en.json
index e15670dd1..9cd8fafbd 100644
--- a/src/i18n/lang/en.json
+++ b/src/i18n/lang/en.json
@@ -514,24 +514,37 @@
"edit": "Edit",
"done": "Done",
"heading1": "Heading 1",
+ "heading1Tooltip": "Big section heading.",
"heading2": "Heading 2",
+ "heading2Tooltip": "Medium section heading.",
"heading3": "Heading 3",
+ "heading3Tooltip": "Smaller section header.",
"headingSmaller": "Heading Smaller",
"headingBigger": "Heading Bigger",
"bold": "Bold",
"italic": "Italic",
"strikethrough": "Strikethrough",
"code": "Code",
+ "codeTooltip": "Capture a code snippet.",
"quote": "Quote",
+ "quoteTooltip": "Capture a quote.",
+ "bulletList": "Bullet list",
+ "bulletListTooltip": "Create a simple bullet list.",
"unorderedList": "Unordered List",
"orderedList": "Ordered List",
+ "orderedListTooltip": "Create a list with numbering.",
"cleanBlock": "Clean Block",
"link": "Link",
"image": "Image",
"table": "Table",
"horizontalRule": "Horizontal Rule",
+ "horizontalRuleTooltip": "Divide a section.",
"sideBySide": "Side By Side",
"guide": "Guide",
+ "text": "Text",
+ "textTooltip": "Just start typing with plain text.",
+ "taskList": "Task list",
+ "taskListTooltip": "Track tasks with a to-do list.",
"table": {
"insert": "Insert table",
"addColumnBefore": "Add column before",