Skip to content

Commit 808c940

Browse files
mejo-backportbot[bot]
authored andcommitted
fix(FloatingButtons): group smartpicker button and drag handle together
- The button group follows the cursor now - The button group is top-aligned to hovered paragraph node - The drag handle button has cursor type `grab` - Not displayed on mobile and full width view Also removes block margin from link previews. We already have margin between paragraphs and it makes the floating buttons look off otherwise. Fixes: #7272 Fixes: #7604 Signed-off-by: Jonas <jonas@freesources.org>
1 parent f985d4e commit 808c940

File tree

6 files changed

+121
-258
lines changed

6 files changed

+121
-258
lines changed

src/components/Editor/ContentContainer.vue

Lines changed: 8 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,7 @@
1414
<EditorOutline />
1515
</div>
1616
<slot />
17-
<DragHandle :editor="editor" class="drag-handle--button">
18-
<NcButton type="tertiary-no-background" size="normal">
19-
<template #icon>
20-
<DragVerticalIcon :size="20" />
21-
</template>
22-
</NcButton>
23-
</DragHandle>
17+
<FloatingButtons v-if="!isMobile && !isFullWidth" />
2418
<EditorContent
2519
role="document"
2620
class="editor__content text-editor__content"
@@ -30,27 +24,27 @@
3024
</template>
3125

3226
<script>
33-
import NcButton from '@nextcloud/vue/components/NcButton'
34-
import { DragHandle } from '@tiptap/extension-drag-handle-vue-2'
27+
import { useIsMobile } from '@nextcloud/vue/composables/useIsMobile'
3528
import { EditorContent } from '@tiptap/vue-2'
36-
import DragVerticalIcon from 'vue-material-design-icons/DragVertical.vue'
3729
import { useEditor } from '../../composables/useEditor.ts'
30+
import { useEditorWidth } from '../../composables/useEditorWidth.ts'
3831
import EditorOutline from './EditorOutline.vue'
32+
import FloatingButtons from './FloatingButtons.vue'
3933
import { useOutlineStateMixin } from './Wrapper.provider.js'
4034
4135
export default {
4236
name: 'ContentContainer',
4337
components: {
4438
EditorContent,
4539
EditorOutline,
46-
NcButton,
47-
DragHandle,
48-
DragVerticalIcon,
40+
FloatingButtons,
4941
},
5042
mixins: [useOutlineStateMixin],
5143
setup() {
44+
const isMobile = useIsMobile()
5245
const { editor } = useEditor()
53-
return { editor }
46+
const { isFullWidth } = useEditorWidth()
47+
return { editor, isMobile, isFullWidth }
5448
},
5549
computed: {
5650
showOutline() {
@@ -72,12 +66,6 @@ export default {
7266
}
7367
}
7468
75-
.ie {
76-
.editor__content:deep(.ProseMirror) {
77-
padding-top: 50px;
78-
}
79-
}
80-
8169
.text-editor__content-wrapper {
8270
--side-width: calc((100% - var(--text-editor-max-width)) / 2);
8371
display: grid;
@@ -104,12 +92,4 @@ export default {
10492
}
10593
}
10694
}
107-
108-
.drag-handle--button {
109-
color: var(--color-maxcontrast);
110-
position: absolute;
111-
left: -60px;
112-
transform: translate(0, -20%);
113-
padding-right: 24px;
114-
}
11595
</style>
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
<!--
2+
- SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
3+
- SPDX-License-Identifier: AGPL-3.0-or-later
4+
-->
5+
6+
<template>
7+
<DragHandle
8+
:editor="editor"
9+
class="floating-buttons"
10+
:class="{ heading: isHeadingNode }"
11+
:on-node-change="onNodeChange">
12+
<NcButton
13+
type="tertiary-no-background"
14+
size="small"
15+
:title="t('text', 'Insert below')"
16+
@click="onOpenSmartPicker">
17+
<template #icon>
18+
<PlusIcon :size="16" />
19+
</template>
20+
</NcButton>
21+
<NcButton
22+
type="tertiary-no-background"
23+
size="small"
24+
class="drag-button"
25+
:title="t('text', 'Click for options, hold to drag')">
26+
<template #icon>
27+
<DragVerticalIcon :size="16" />
28+
</template>
29+
</NcButton>
30+
</DragHandle>
31+
</template>
32+
33+
<script>
34+
import { t } from '@nextcloud/l10n'
35+
import NcButton from '@nextcloud/vue/components/NcButton'
36+
import { DragHandle } from '@tiptap/extension-drag-handle-vue-2'
37+
import DragVerticalIcon from 'vue-material-design-icons/DragVertical.vue'
38+
import PlusIcon from 'vue-material-design-icons/Plus.vue'
39+
import { useEditor } from '../../composables/useEditor.ts'
40+
41+
export default {
42+
name: 'FloatingButtons',
43+
44+
components: {
45+
DragHandle,
46+
DragVerticalIcon,
47+
NcButton,
48+
PlusIcon,
49+
},
50+
51+
setup() {
52+
const { editor } = useEditor()
53+
return { editor }
54+
},
55+
56+
data() {
57+
return {
58+
node: null,
59+
pos: -1,
60+
}
61+
},
62+
63+
computed: {
64+
isHeadingNode() {
65+
return this.node?.type === this.editor.schema.nodes.heading
66+
},
67+
},
68+
69+
methods: {
70+
onNodeChange({ node, pos }) {
71+
this.node = node
72+
this.pos = pos
73+
},
74+
onOpenSmartPicker() {
75+
if (!this.node || this.pos === -1) {
76+
return
77+
}
78+
79+
// Node has no children or just text children and no text content
80+
const { schema } = this.editor
81+
const emptyNode =
82+
this.node.textContent.trim() === ''
83+
&& (this.node.children.length === 0
84+
|| this.node.children.every((n) => n.type === schema.nodes.text))
85+
86+
// Insert at the end of the node
87+
const pos = emptyNode ? this.pos + 1 : this.pos + this.node.nodeSize
88+
this.editor.chain().insertContentAt(pos, '/').focus().run()
89+
},
90+
t,
91+
},
92+
}
93+
</script>
94+
95+
<style scoped lang="scss">
96+
.floating-buttons {
97+
display: flex;
98+
99+
&.heading {
100+
margin-right: 16px;
101+
}
102+
}
103+
104+
.drag-button {
105+
cursor: grab;
106+
107+
:deep(span),
108+
:deep(svg) {
109+
cursor: grab !important;
110+
}
111+
}
112+
</style>

src/components/Editor/SmartPickerMenu.vue

Lines changed: 0 additions & 48 deletions
This file was deleted.

src/nodes/Paragraph.js

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
*/
55

66
import TiptapParagraph from '@tiptap/extension-paragraph'
7-
import currentLineMenu from '../plugins/currentLineMenu.js'
87

98
const Paragraph = TiptapParagraph.extend({
109
parseHTML() {
@@ -42,10 +41,6 @@ const Paragraph = TiptapParagraph.extend({
4241
},
4342
}
4443
},
45-
46-
addProseMirrorPlugins() {
47-
return [currentLineMenu({ editor: this.editor })]
48-
},
4944
})
5045

5146
export default Paragraph

src/nodes/Preview.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ export default {
7979
8080
:deep(div.widgets--list a.widget-default) {
8181
color: var(--color-main-text);
82+
margin: 0;
8283
padding: 0;
8384
text-decoration: none;
8485
max-width: calc(100vw - 156px);

0 commit comments

Comments
 (0)