Skip to content

Commit 23ff013

Browse files
committed
feat: 增加表格悬浮菜单功能
1 parent c55dda6 commit 23ff013

26 files changed

Lines changed: 1872 additions & 3 deletions

app/assets/css/writing-studio/plugins/table.css

Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,3 +167,237 @@
167167
text-align: center;
168168
color: rgba(255, 255, 255, 0.82);
169169
}
170+
171+
.writing-editor .tiptap[data-ws-column-menu-active="true"] table .selectedCell {
172+
border-style: solid;
173+
border-color: oklch(var(--border));
174+
background-color: transparent;
175+
}
176+
177+
.writing-editor .tiptap[data-ws-column-menu-active="true"] table .selectedCell::after {
178+
background: transparent;
179+
}
180+
181+
.ws-table-column-selection {
182+
position: absolute;
183+
pointer-events: none;
184+
}
185+
186+
.ws-table-column-selection-outline {
187+
width: 100%;
188+
height: 100%;
189+
border: 2px solid oklch(var(--primary));
190+
}
191+
192+
/* .ws-table-column-selection-outline--column {
193+
border-radius: 0.45rem;
194+
} */
195+
196+
.ws-table-column-handle-anchor {
197+
position: absolute;
198+
z-index: 90;
199+
transform: translate(-50%, -50%);
200+
}
201+
202+
.ws-table-column-bubble-layer {
203+
position: relative;
204+
z-index: 100;
205+
}
206+
207+
.ws-table-column-handle {
208+
width: 18px;
209+
min-width: 18px;
210+
height: 6px;
211+
min-height: 6px;
212+
padding: 0;
213+
border: 2px solid oklch(var(--background));
214+
border-radius: 9999px;
215+
background: oklch(var(--muted-foreground) / 0.46);
216+
color: transparent;
217+
box-shadow: none;
218+
overflow: hidden;
219+
transition:
220+
width 0.16s ease,
221+
min-width 0.16s ease,
222+
height 0.16s ease,
223+
min-height 0.16s ease,
224+
border-radius 0.16s ease,
225+
background-color 0.16s ease,
226+
color 0.16s ease,
227+
box-shadow 0.16s ease,
228+
transform 0.16s ease;
229+
}
230+
231+
.ws-table-column-handle:hover,
232+
.ws-table-column-handle:focus-visible,
233+
.ws-table-column-handle--active {
234+
width: 2.5rem;
235+
min-width: 2.5rem;
236+
height: 1.5rem;
237+
min-height: 1.5rem;
238+
border-radius: 0.4rem;
239+
border-color: oklch(var(--background));
240+
background: oklch(var(--primary));
241+
color: oklch(var(--primary-foreground));
242+
box-shadow: none;
243+
}
244+
245+
.ws-table-column-handle-icon {
246+
width: 0.95rem;
247+
height: 0.95rem;
248+
opacity: 0;
249+
transform: scale(0.7);
250+
transition: opacity 0.16s ease, transform 0.16s ease;
251+
}
252+
253+
.ws-table-column-handle:hover .ws-table-column-handle-icon,
254+
.ws-table-column-handle:focus-visible .ws-table-column-handle-icon,
255+
.ws-table-column-handle--active .ws-table-column-handle-icon {
256+
opacity: 1;
257+
transform: scale(1);
258+
}
259+
260+
.ws-table-column-menu {
261+
position: relative;
262+
z-index: 110;
263+
width: 16.5625rem;
264+
min-width: 11.25rem;
265+
max-width: calc(100vw - 24px);
266+
border-radius: 0.875rem;
267+
box-shadow: 0 24px 60px -30px oklch(0 0 0 / 0.36);
268+
overflow: hidden;
269+
}
270+
271+
.ws-table-column-menu-main {
272+
display: flex;
273+
flex-direction: column;
274+
width: 100%;
275+
min-height: 0;
276+
max-height: 70vh;
277+
padding: 0.5rem 0.25rem 0.25rem;
278+
}
279+
280+
.ws-table-column-menu-search-wrap {
281+
padding: 0 0.25rem 0.25rem;
282+
}
283+
284+
.ws-table-column-menu-search {
285+
height: 2.25rem;
286+
border-radius: 0.9rem;
287+
background: oklch(var(--background));
288+
padding-inline: 0.9rem;
289+
font-size: 0.95rem;
290+
box-shadow:
291+
0 1px 2px 0 oklch(0 0 0 / 0.04),
292+
inset 0 0 0 1px oklch(var(--border));
293+
}
294+
295+
.ws-table-column-menu-items {
296+
display: flex;
297+
flex-direction: column;
298+
gap: 1px;
299+
padding: 0.25rem;
300+
}
301+
302+
.ws-table-column-menu-item {
303+
display: inline-flex;
304+
width: 100%;
305+
align-items: center;
306+
gap: 0.75rem;
307+
min-height: 2.75rem;
308+
border-radius: 0.625rem;
309+
padding: 0.625rem 0.75rem;
310+
text-align: left;
311+
font-size: 1rem;
312+
font-weight: 600;
313+
line-height: 1.2;
314+
color: oklch(var(--foreground));
315+
transition: background-color 0.16s ease, color 0.16s ease;
316+
}
317+
318+
.ws-table-column-menu-item:hover,
319+
.ws-table-column-menu-item--active {
320+
background: oklch(var(--accent));
321+
}
322+
323+
.ws-table-column-menu-item--danger {
324+
color: oklch(var(--destructive));
325+
}
326+
327+
.ws-table-column-menu-item--danger:hover {
328+
background: oklch(var(--destructive) / 0.08);
329+
}
330+
331+
.ws-table-column-menu-icon {
332+
width: 1.25rem;
333+
height: 1.25rem;
334+
flex-shrink: 0;
335+
}
336+
337+
.ws-table-column-menu-item-hint {
338+
margin-left: auto;
339+
font-size: 0.9rem;
340+
color: oklch(var(--muted-foreground));
341+
}
342+
343+
.ws-table-column-menu-empty {
344+
padding: 1rem 0.75rem;
345+
color: oklch(var(--muted-foreground));
346+
text-align: center;
347+
}
348+
349+
.ws-table-column-color-menu {
350+
z-index: 120;
351+
width: min(22rem, calc(100vw - 40px));
352+
border-radius: 1.25rem;
353+
padding: 0.5rem;
354+
box-shadow: 0 26px 64px -30px oklch(0 0 0 / 0.36);
355+
}
356+
357+
.ws-table-column-color-scroll {
358+
height: min(60vh, 32rem);
359+
max-height: min(60vh, 32rem);
360+
}
361+
362+
.ws-table-column-color-section {
363+
display: flex;
364+
flex-direction: column;
365+
gap: 0.25rem;
366+
padding: 0.25rem;
367+
}
368+
369+
.ws-table-column-color-title {
370+
padding: 0.35rem 0.45rem 0.55rem;
371+
font-size: 1.2rem;
372+
font-weight: 700;
373+
color: oklch(var(--foreground));
374+
}
375+
376+
.ws-table-column-color-item {
377+
display: inline-flex;
378+
width: 100%;
379+
align-items: center;
380+
gap: 1rem;
381+
border-radius: 0.9rem;
382+
padding: 0.6rem 0.55rem;
383+
text-align: left;
384+
font-size: 1.02rem;
385+
font-weight: 600;
386+
color: oklch(var(--foreground));
387+
transition: background-color 0.16s ease, color 0.16s ease;
388+
}
389+
390+
.ws-table-column-color-item:hover {
391+
background: oklch(var(--accent));
392+
}
393+
394+
.ws-table-column-color-swatch {
395+
display: inline-flex;
396+
width: 3.9rem;
397+
height: 3.9rem;
398+
align-items: center;
399+
justify-content: center;
400+
border: 1px solid oklch(var(--border));
401+
border-radius: 1.1rem;
402+
background: oklch(var(--background));
403+
}

app/components/paper/WritingStudio.vue

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import WritingStudioCodeBlockBubbleMenu from "@/components/paper/WritingStudioCo
2222
import WritingStudioImageGroup from "@/components/paper/WritingStudioImageGroup.vue";
2323
import WritingStudioImageNodeBubbleMenu from "@/components/paper/WritingStudioImageNodeBubbleMenu.vue";
2424
import WritingStudioLinkBubbleMenu from "@/components/paper/WritingStudioLinkBubbleMenu.vue";
25+
import WritingStudioTableColumnBubbleMenu from "@/components/paper/WritingStudioTableColumnBubbleMenu.vue";
2526
import WritingStudioTableHoverControls from "@/components/paper/WritingStudioTableHoverControls.vue";
2627
import { Button } from "@/components/ui/button";
2728
import {
@@ -676,6 +677,7 @@ const removeLinkFromMenu = () => {
676677
</DragHandle>
677678
<div ref="editorSurfaceRef" class="relative rounded-lg border bg-background px-4 py-3 shadow-sm max-w-6xl mx-auto">
678679
<WritingStudioTableHoverControls :editor="editor" :container="editorSurfaceRef" />
680+
<WritingStudioTableColumnBubbleMenu :editor="editor" :container="editorSurfaceRef" />
679681
<EditorContent :editor="editor" class="writing-editor" />
680682
</div>
681683
</section>

0 commit comments

Comments
 (0)