Skip to content

Commit

Permalink
Merge pull request #6353 from nextcloud/feat/menubar_list_submenu
Browse files Browse the repository at this point in the history
feat(menu): Put list items in submenu, add indentation options
  • Loading branch information
mejo- committed Sep 16, 2024
2 parents e627769 + 4a3b2bb commit 68486f8
Show file tree
Hide file tree
Showing 12 changed files with 156 additions and 50 deletions.
20 changes: 18 additions & 2 deletions cypress/e2e/workspace.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ describe('Workspace', function() {
['unordered-list', 'ul'],
['ordered-list', 'ol'],
['task-list', 'ul.contains-task-list'],
].forEach(([button, tag]) => testButton(button, tag, 'List me'))
].forEach(([button, tag]) => testListButton(button, tag, 'List me'))
})

it('takes README.md into account', function() {
Expand Down Expand Up @@ -302,7 +302,23 @@ const openSidebar = filename => {
}

/**
*
* @param {string} button Name of the button to click.
* @param {string} tag Html tag expected to be toggled.
* @param {string} content Content expected in the element.
*/
function testListButton(button, tag, content) {
cy.getSubmenuEntry('lists', button)
.should('not.have.class', 'is-active')
.click()
cy.getContent()
.find(`${tag}`)
.should('contain', content)
cy.getSubmenuEntry('lists', button)
.should('have.class', 'is-active')
.click()
}

/**
* @param {string} button Name of the button to click.
* @param {string} tag Html tag expected to be toggled.
* @param {string} content Content expected in the element.
Expand Down
3 changes: 2 additions & 1 deletion src/components/Menu/ActionListItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

<template>
<NextcloudVueNcActionButton class="entry-single-action entry-action entry-action-item"
:title="listItemTooltip || undefined"
:class="state.class"
:disabled="state.disabled"
:aria-keyshortcuts="keyshortcuts || undefined"
Expand Down Expand Up @@ -52,7 +53,7 @@ export default {
} else {
// Some actions run themselves.
// others still need to have .run() called upon them.
actionEntry.action(this.$editor.chain().focus())?.run()
actionEntry.action(this.$editor.chain().focus(), this.$editor)?.run()
}
this.$nextTick(() => {
Expand Down
2 changes: 1 addition & 1 deletion src/components/Menu/ActionSingle.vue
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export default {
} else {
// Some actions run themselves.
// others still need to have .run() called upon them.
actionEntry.action(this.$editor.chain().focus())?.run()
actionEntry.action(this.$editor.chain().focus(), this.$editor)?.run()
}
this.$nextTick(() => {
Expand Down
5 changes: 5 additions & 0 deletions src/components/Menu/BaseActionEntry.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ const BaseActionEntry = {
getKeys(this.$isMobile, this.actionEntry),
].join(' ')
},
listItemTooltip() {
return [
getKeys(this.$isMobile, this.actionEntry),
].join(' ')
},
},
watch: {
/** Handle tabindex for menu toolbar */
Expand Down
139 changes: 95 additions & 44 deletions src/components/Menu/entries.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import {
FormatHeader4,
FormatHeader5,
FormatHeader6,
FormatIndentDecrease,
FormatIndentIncrease,
FormatListNumbered,
FormatListBulleted,
FormatListCheckbox,
Expand Down Expand Up @@ -57,7 +59,7 @@ export default [
keyModifiers: [MODIFIERS.Mod],
icon: Undo,
action: (command) => command.undo(),
priority: 6,
priority: 7,
},
{
key: 'redo',
Expand All @@ -66,7 +68,7 @@ export default [
keyModifiers: [MODIFIERS.Mod],
icon: Redo,
action: (command) => command.redo(),
priority: 12,
priority: 10,
},
{
key: 'bold',
Expand All @@ -78,7 +80,7 @@ export default [
action: (command) => {
return command.toggleBold()
},
priority: 7,
priority: 8,
},
{
key: 'italic',
Expand All @@ -90,7 +92,7 @@ export default [
action: (command) => {
return command.toggleItalic()
},
priority: 8,
priority: 9,
},
{
key: 'underline',
Expand All @@ -102,7 +104,7 @@ export default [
action: (command) => {
return command.toggleUnderline()
},
priority: 15,
priority: 13,
},
{
key: 'strikethrough',
Expand All @@ -114,7 +116,7 @@ export default [
action: (command) => {
return command.toggleStrike()
},
priority: 16,
priority: 14,
},
{
key: 'headings',
Expand All @@ -127,6 +129,8 @@ export default [
{
key: 'headings-h1',
label: t('text', 'Heading 1'),
keyChar: '1',
keyModifiers: [MODIFIERS.Mod, MODIFIERS.Shift],
icon: FormatHeader1,
isActive: ['heading', { level: 1 }],
action: (command) => {
Expand All @@ -136,6 +140,8 @@ export default [
{
key: 'headings-h2',
label: t('text', 'Heading 2'),
keyChar: '2',
keyModifiers: [MODIFIERS.Mod, MODIFIERS.Shift],
icon: FormatHeader2,
isActive: ['heading', { level: 2 }],
action: (command) => {
Expand All @@ -145,6 +151,8 @@ export default [
{
key: 'headings-h3',
label: t('text', 'Heading 3'),
keyChar: '3',
keyModifiers: [MODIFIERS.Mod, MODIFIERS.Shift],
icon: FormatHeader3,
isActive: ['heading', { level: 3 }],
action: (command) => {
Expand All @@ -154,6 +162,8 @@ export default [
{
key: 'headings-h4',
label: t('text', 'Heading 4'),
keyChar: '4',
keyModifiers: [MODIFIERS.Mod, MODIFIERS.Shift],
isActive: ['heading', { level: 4 }],
icon: FormatHeader4,
action: (command) => {
Expand All @@ -163,6 +173,8 @@ export default [
{
key: 'headings-h5',
label: t('text', 'Heading 5'),
keyChar: '5',
keyModifiers: [MODIFIERS.Mod, MODIFIERS.Shift],
isActive: ['heading', { level: 5 }],
icon: FormatHeader5,
action: (command) => {
Expand All @@ -172,6 +184,8 @@ export default [
{
key: 'headings-h6',
label: t('text', 'Heading 6'),
keyChar: '6',
keyModifiers: [MODIFIERS.Mod, MODIFIERS.Shift],
isActive: ['heading', { level: 6 }],
icon: FormatHeader6,
action: (command) => {
Expand Down Expand Up @@ -202,46 +216,83 @@ export default [
priority: 1,
},
{
key: 'unordered-list',
label: t('text', 'Unordered list'),
keyChar: '8',
key: 'lists',
label: t('text', 'Lists'),
keyChar: '7…9',
keyModifiers: [MODIFIERS.Mod, MODIFIERS.Shift],
isActive: 'bulletList',
isActive: [{ isList: true }],
icon: FormatListBulleted,
action: (command) => {
return command.toggleBulletList()
},
priority: 9,
},
{
key: 'ordered-list',
label: t('text', 'Ordered list'),
keyChar: '7',
keyModifiers: [MODIFIERS.Mod, MODIFIERS.Shift],
isActive: 'orderedList',
icon: FormatListNumbered,
action: (command) => {
return command.toggleOrderedList()
},
priority: 10,
},
{
key: 'task-list',
label: t('text', 'To-Do list'),
keyChar: '9',
keyModifiers: [MODIFIERS.Mod, MODIFIERS.Shift],
isActive: 'taskList',
icon: FormatListCheckbox,
action: (command) => command.toggleTaskList(),
priority: 11,
children: [
{
key: 'unordered-list',
label: t('text', 'Unordered list'),
keyChar: '8',
keyModifiers: [MODIFIERS.Mod, MODIFIERS.Shift],
isActive: 'bulletList',
icon: FormatListBulleted,
action: (command) => {
return command.toggleBulletList()
},
},
{
key: 'ordered-list',
label: t('text', 'Ordered list'),
keyChar: '7',
keyModifiers: [MODIFIERS.Mod, MODIFIERS.Shift],
isActive: 'orderedList',
icon: FormatListNumbered,
action: (command) => {
return command.toggleOrderedList()
},
},
{
key: 'task-list',
label: t('text', 'To-Do list'),
keyChar: '9',
keyModifiers: [MODIFIERS.Mod, MODIFIERS.Shift],
isActive: 'taskList',
icon: FormatListCheckbox,
action: (command) => command.toggleTaskList(),
},
{
key: 'lists-separator',
isSeparator: true,
},
{
key: 'list-indent-increase',
label: t('text', 'Increase indentation'),
keyChar: 'Tab',
icon: FormatIndentIncrease,
action: (command, editor = null) => {
if (editor && editor.isActive('taskItem')) {
return command.sinkListItem('taskItem')
}
return command.sinkListItem('listItem')
},
},
{
key: 'list-indent-decrease',
label: t('text', 'Decrease indentation'),
keyChar: 'Tab',
keyModifiers: [MODIFIERS.Shift],
icon: FormatIndentDecrease,
action: (command, editor = null) => {
if (editor && editor.isActive('taskItem')) {
return command.liftListItem('taskItem')
}
return command.liftListItem('listItem')
},
},
],
priority: 2,
},
{
key: 'insert-link',
label: t('text', 'Insert link'),
isActive: 'link',
icon: LinkIcon,
component: ActionInsertLink,
priority: 2,
priority: 3,
},
{
key: 'blockquote',
Expand All @@ -253,7 +304,7 @@ export default [
action: (command) => {
return command.toggleBlockquote()
},
priority: 13,
priority: 11,
},
{
key: 'callouts',
Expand Down Expand Up @@ -299,7 +350,7 @@ export default [
},
},
],
priority: 6,
priority: 4,
},
{
key: 'code-block',
Expand All @@ -311,7 +362,7 @@ export default [
action: (command) => {
return command.toggleCodeBlock()
},
priority: 14,
priority: 12,
},
{
key: 'table',
Expand All @@ -321,7 +372,7 @@ export default [
action: (command) => {
return command.insertTable()
},
priority: 17,
priority: 15,
},
{
key: 'details',
Expand All @@ -331,7 +382,7 @@ export default [
action: (command) => {
return command.toggleDetails()
},
priority: 18,
priority: 16,
},
{
key: 'emoji-picker',
Expand All @@ -341,13 +392,13 @@ export default [
action: (command, emojiObject = {}) => {
return command.emoji(emojiObject)
},
priority: 3,
priority: 5,
},
{
key: 'insert-attachment',
label: t('text', 'Insert attachment'),
icon: Paperclip,
component: ActionAttachmentUpload,
priority: 1,
priority: 6,
},
]
2 changes: 1 addition & 1 deletion src/components/Menu/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ const getKeys = (isMobile, { keyChar, keyModifiers }) => {
}

const isDisabled = (actionEntry, $editor) => {
return actionEntry.action && !actionEntry.action($editor.can())
return actionEntry.action && !actionEntry.action($editor.can(), $editor)
}

const getIsActive = ({ isActive }, $editor) => {
Expand Down
1 change: 1 addition & 0 deletions src/components/Suggestion/LinkPicker/suggestions.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ const formattingSuggestions = (query) => {
return sortImportantFirst(
[
...menuEntries.find(e => e.key === 'headings').children,
...menuEntries.find(e => e.key === 'lists').children,
...menuEntries.filter(e => e.action && !filterOut(e)),
...menuEntries.find(e => e.key === 'callouts').children,
{
Expand Down
4 changes: 4 additions & 0 deletions src/components/icons.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ import MDI_FormatHeader3 from 'vue-material-design-icons/FormatHeader3.vue'
import MDI_FormatHeader4 from 'vue-material-design-icons/FormatHeader4.vue'
import MDI_FormatHeader5 from 'vue-material-design-icons/FormatHeader5.vue'
import MDI_FormatHeader6 from 'vue-material-design-icons/FormatHeader6.vue'
import MDI_FormatIndentDecrease from 'vue-material-design-icons/FormatIndentDecrease.vue'
import MDI_FormatIndentIncrease from 'vue-material-design-icons/FormatIndentIncrease.vue'
import MDI_FormatItalic from 'vue-material-design-icons/FormatItalic.vue'
import MDI_FormatListBulleted from 'vue-material-design-icons/FormatListBulleted.vue'
import MDI_FormatListCheckbox from 'vue-material-design-icons/FormatListCheckbox.vue'
Expand Down Expand Up @@ -105,6 +107,8 @@ export const FormatHeader3 = makeIcon(MDI_FormatHeader3)
export const FormatHeader4 = makeIcon(MDI_FormatHeader4)
export const FormatHeader5 = makeIcon(MDI_FormatHeader5)
export const FormatHeader6 = makeIcon(MDI_FormatHeader6)
export const FormatIndentDecrease = makeIcon(MDI_FormatIndentDecrease)
export const FormatIndentIncrease = makeIcon(MDI_FormatIndentIncrease)
export const FormatItalic = makeIcon(MDI_FormatItalic)
export const FormatListBulleted = makeIcon(MDI_FormatListBulleted)
export const FormatListCheckbox = makeIcon(MDI_FormatListCheckbox)
Expand Down
Loading

0 comments on commit 68486f8

Please sign in to comment.