Skip to content

Commit dd08ff1

Browse files
committed
fixed the maximum feat in the rich text editor
Signed-off-by: RAWx18 <rawx18.dev@gmail.com>
1 parent 2ce982a commit dd08ff1

File tree

1 file changed

+139
-56
lines changed

1 file changed

+139
-56
lines changed

frontend/src/modules/devspace/components/RichTextEditor.vue

Lines changed: 139 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,72 @@
11
<template>
2-
<div class="rich-text-editor">
2+
<div class="rich-text-editor" :class="{ 'is-fullscreen': isFullscreen }">
33
<div v-if="editor" class="editor-toolbar">
4-
<button
5-
@click="editor.chain().focus().toggleBold().run()"
6-
:class="{ 'is-active': editor.isActive('bold') }"
7-
>
8-
<i class="ri-bold"></i>
9-
</button>
10-
<button
11-
@click="editor.chain().focus().toggleItalic().run()"
12-
:class="{ 'is-active': editor.isActive('italic') }"
13-
>
14-
<i class="ri-italic"></i>
15-
</button>
16-
<button
17-
@click="editor.chain().focus().toggleStrike().run()"
18-
:class="{ 'is-active': editor.isActive('strike') }"
19-
>
20-
<i class="ri-strikethrough"></i>
21-
</button>
22-
<button
23-
@click="editor.chain().focus().toggleCode().run()"
24-
:class="{ 'is-active': editor.isActive('code') }"
25-
>
26-
<i class="ri-code-line"></i>
27-
</button>
28-
<div class="divider"></div>
29-
<button
30-
@click="editor.chain().focus().toggleHeading({ level: 1 }).run()"
31-
:class="{ 'is-active': editor.isActive('heading', { level: 1 }) }"
32-
>
33-
H1
34-
</button>
35-
<button
36-
@click="editor.chain().focus().toggleHeading({ level: 2 }).run()"
37-
:class="{ 'is-active': editor.isActive('heading', { level: 2 }) }"
38-
>
39-
H2
40-
</button>
41-
<button
42-
@click="editor.chain().focus().toggleBulletList().run()"
43-
:class="{ 'is-active': editor.isActive('bulletList') }"
44-
>
45-
<i class="ri-list-unordered"></i>
46-
</button>
47-
<button
48-
@click="editor.chain().focus().toggleOrderedList().run()"
49-
:class="{ 'is-active': editor.isActive('orderedList') }"
50-
>
51-
<i class="ri-list-ordered"></i>
52-
</button>
53-
<button
54-
@click="editor.chain().focus().toggleBlockquote().run()"
55-
:class="{ 'is-active': editor.isActive('blockquote') }"
56-
>
57-
<i class="ri-double-quotes-l"></i>
58-
</button>
4+
<div class="toolbar-left">
5+
<button
6+
@click="editor.chain().focus().toggleBold().run()"
7+
:class="{ 'is-active': editor.isActive('bold') }"
8+
>
9+
<i class="ri-bold"></i>
10+
</button>
11+
<button
12+
@click="editor.chain().focus().toggleItalic().run()"
13+
:class="{ 'is-active': editor.isActive('italic') }"
14+
>
15+
<i class="ri-italic"></i>
16+
</button>
17+
<button
18+
@click="editor.chain().focus().toggleStrike().run()"
19+
:class="{ 'is-active': editor.isActive('strike') }"
20+
>
21+
<i class="ri-strikethrough"></i>
22+
</button>
23+
<button
24+
@click="editor.chain().focus().toggleCode().run()"
25+
:class="{ 'is-active': editor.isActive('code') }"
26+
>
27+
<i class="ri-code-line"></i>
28+
</button>
29+
<div class="divider"></div>
30+
<button
31+
@click="editor.chain().focus().toggleHeading({ level: 1 }).run()"
32+
:class="{ 'is-active': editor.isActive('heading', { level: 1 }) }"
33+
>
34+
H1
35+
</button>
36+
<button
37+
@click="editor.chain().focus().toggleHeading({ level: 2 }).run()"
38+
:class="{ 'is-active': editor.isActive('heading', { level: 2 }) }"
39+
>
40+
H2
41+
</button>
42+
<button
43+
@click="editor.chain().focus().toggleBulletList().run()"
44+
:class="{ 'is-active': editor.isActive('bulletList') }"
45+
>
46+
<i class="ri-list-unordered"></i>
47+
</button>
48+
<button
49+
@click="editor.chain().focus().toggleOrderedList().run()"
50+
:class="{ 'is-active': editor.isActive('orderedList') }"
51+
>
52+
<i class="ri-list-ordered"></i>
53+
</button>
54+
<button
55+
@click="editor.chain().focus().toggleBlockquote().run()"
56+
:class="{ 'is-active': editor.isActive('blockquote') }"
57+
>
58+
<i class="ri-double-quotes-l"></i>
59+
</button>
60+
</div>
61+
<div class="toolbar-right">
62+
<button
63+
@click="toggleFullscreen"
64+
class="fullscreen-btn"
65+
:title="isFullscreen ? 'Exit Fullscreen' : 'Fullscreen'"
66+
>
67+
<i :class="isFullscreen ? 'ri-fullscreen-exit-line' : 'ri-fullscreen-line'"></i>
68+
</button>
69+
</div>
5970
</div>
6071
<editor-content :editor="editor" class="editor-content" />
6172
</div>
@@ -66,6 +77,7 @@ import { useEditor, EditorContent } from '@tiptap/vue-3'
6677
import StarterKit from '@tiptap/starter-kit'
6778
import Placeholder from '@tiptap/extension-placeholder'
6879
import Link from '@tiptap/extension-link'
80+
import { ref } from 'vue'
6981
7082
export default {
7183
name: 'RichTextEditor',
@@ -88,6 +100,8 @@ export default {
88100
},
89101
emits: ['update:modelValue', 'blur'],
90102
setup(props, { emit }) {
103+
const isFullscreen = ref(false)
104+
91105
const editor = useEditor({
92106
content: props.modelValue,
93107
extensions: [
@@ -108,8 +122,14 @@ export default {
108122
},
109123
})
110124
125+
const toggleFullscreen = () => {
126+
isFullscreen.value = !isFullscreen.value
127+
}
128+
111129
return {
112130
editor,
131+
isFullscreen,
132+
toggleFullscreen,
113133
}
114134
},
115135
watch: {
@@ -138,17 +158,56 @@ export default {
138158
border-radius: 4px;
139159
overflow: hidden;
140160
background-color: var(--el-bg-color);
161+
position: relative;
162+
transition: all 0.3s ease;
163+
}
164+
165+
.rich-text-editor.is-fullscreen {
166+
position: fixed !important;
167+
top: 56px !important;
168+
left: 0 !important;
169+
right: 0 !important;
170+
bottom: 0 !important;
171+
width: 100vw !important;
172+
height: calc(100vh - 56px) !important;
173+
z-index: 2999 !important;
174+
border-radius: 0;
175+
margin: 0;
176+
}
177+
178+
.is-fullscreen .editor-toolbar {
179+
position: sticky;
180+
top: 0;
181+
z-index: 3000 !important;
182+
background-color: var(--el-fill-color-light);
183+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
141184
}
142185
143186
.editor-toolbar {
144187
display: flex;
188+
justify-content: space-between;
189+
align-items: center;
145190
flex-wrap: wrap;
146191
gap: 4px;
147192
padding: 8px;
148193
border-bottom: 1px solid var(--el-border-color-lighter);
149194
background-color: var(--el-fill-color-light);
150195
}
151196
197+
.toolbar-left {
198+
display: flex;
199+
flex-wrap: wrap;
200+
gap: 4px;
201+
align-items: center;
202+
}
203+
204+
.toolbar-right {
205+
display: flex;
206+
gap: 4px;
207+
align-items: center;
208+
margin-left: auto;
209+
}
210+
152211
.editor-toolbar button {
153212
border: none;
154213
background: transparent;
@@ -157,6 +216,7 @@ export default {
157216
cursor: pointer;
158217
color: var(--el-text-color-regular);
159218
font-size: 14px;
219+
transition: all 0.2s;
160220
}
161221
162222
.editor-toolbar button:hover {
@@ -168,22 +228,45 @@ export default {
168228
color: var(--el-color-primary);
169229
}
170230
231+
.fullscreen-btn {
232+
padding: 6px 10px !important;
233+
}
234+
235+
.fullscreen-btn i {
236+
font-size: 16px;
237+
}
238+
171239
.divider {
172240
width: 1px;
173241
background-color: var(--el-border-color);
174242
margin: 0 4px;
243+
height: 20px;
175244
}
176245
177246
.editor-content {
178247
padding: 12px;
179248
min-height: 150px;
249+
overflow-y: auto;
250+
transition: all 0.3s ease;
251+
}
252+
253+
.is-fullscreen .editor-content {
254+
min-height: calc(100vh - 116px);
255+
max-height: calc(100vh - 116px);
256+
padding: 24px;
180257
}
181258
182259
:deep(.ProseMirror) {
183260
outline: none;
184261
min-height: 150px;
185262
}
186263
264+
.is-fullscreen :deep(.ProseMirror) {
265+
min-height: calc(100vh - 156px);
266+
max-width: 900px;
267+
margin: 0 auto;
268+
}
269+
187270
:deep(.ProseMirror p.is-editor-empty:first-child::before) {
188271
color: #adb5bd;
189272
content: attr(data-placeholder);

0 commit comments

Comments
 (0)