refactor: improve editor ui (#5828)

#### What type of PR is this?

/area ui
/kind improvement
/milestone 2.15.x

#### What this PR does / why we need it:

优化编辑器的部分 UI。

1. 优化顶部工具栏的样式。
2. 统一格式刷和清除格式的图标。

before:

<img width="1001" alt="image" src="https://github.com/halo-dev/halo/assets/21301288/4d3f2e9a-a79d-429e-aaa4-70313f61da6c">

after:

<img width="1021" alt="image" src="https://github.com/halo-dev/halo/assets/21301288/676ce83b-da87-4c5b-bc63-1405106827f8">

#### Does this PR introduce a user-facing change?

```release-note
优化编辑器的部分 UI。
```
pull/5838/head
Ryan Wang 2024-04-29 15:59:34 +08:00 committed by GitHub
parent 546d63740b
commit d1d4705705
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 22 additions and 22 deletions

View File

@ -1,10 +1,10 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { PropType } from "vue"; import type { PropType } from "vue";
import type { Editor, AnyExtension } from "@/tiptap/vue-3"; import type { AnyExtension, Editor } from "@/tiptap/vue-3";
import BubbleMenu from "@/components/bubble/BubbleMenu.vue"; import BubbleMenu from "@/components/bubble/BubbleMenu.vue";
import type { NodeBubbleMenu } from "@/types"; import type { NodeBubbleMenu } from "@/types";
import BubbleItem from "@/components/bubble/BubbleItem.vue"; import BubbleItem from "@/components/bubble/BubbleItem.vue";
import type { EditorView, EditorState } from "@/tiptap/pm"; import type { EditorState, EditorView } from "@/tiptap/pm";
const props = defineProps({ const props = defineProps({
editor: { editor: {
@ -71,7 +71,7 @@ const shouldShow = (
:default-animation="bubbleMenu.defaultAnimation" :default-animation="bubbleMenu.defaultAnimation"
> >
<div <div
class="bubble-menu bg-white flex items-center rounded-md p-1 border drop-shadow space-x-0.5" class="bubble-menu bg-white flex items-center rounded-md p-1 border drop-shadow space-x-1"
> >
<template v-if="bubbleMenu.items"> <template v-if="bubbleMenu.items">
<template <template

View File

@ -1,6 +1,6 @@
<script lang="ts" setup> <script lang="ts" setup>
import { Menu as VMenu, Dropdown as VDropdown } from "floating-vue"; import { Dropdown as VDropdown, Menu as VMenu } from "floating-vue";
import { Editor, type AnyExtension } from "@/tiptap/vue-3"; import { type AnyExtension, Editor } from "@/tiptap/vue-3";
import MdiPlusCircle from "~icons/mdi/plus-circle"; import MdiPlusCircle from "~icons/mdi/plus-circle";
import type { ToolbarItem, ToolboxItem } from "@/types"; import type { ToolbarItem, ToolboxItem } from "@/types";
@ -59,11 +59,11 @@ function getToolboxItemsFromExtensions() {
</script> </script>
<template> <template>
<div <div
class="editor-header flex items-center py-1 space-x-0.5 justify-start px-1 overflow-auto sm:!justify-center border-b drop-shadow-sm bg-white" class="editor-header flex items-center py-1 space-x-1 justify-start px-1 overflow-auto sm:!justify-center border-b drop-shadow-sm bg-white"
> >
<div class="inline-flex items-center justify-center"> <div class="inline-flex items-center justify-center">
<VMenu> <VMenu>
<button class="p-1 rounded-sm hover:bg-gray-100" tabindex="-1"> <button class="p-1.5 rounded-md hover:bg-gray-100" tabindex="-1">
<MdiPlusCircle class="text-[#4CCBA0]" /> <MdiPlusCircle class="text-[#4CCBA0]" />
</button> </button>
<template #popper> <template #popper>
@ -108,7 +108,7 @@ function getToolboxItemsFromExtensions() {
/> />
<template #popper> <template #popper>
<div <div
class="relative rounded-md bg-white overflow-hidden drop-shadow w-48 p-1 max-h-72 overflow-y-auto" class="relative rounded-md bg-white overflow-hidden drop-shadow w-56 p-1 max-h-96 overflow-y-auto space-y-1.5"
> >
<component <component
v-bind="child.props" v-bind="child.props"

View File

@ -78,7 +78,7 @@ function onColorChange(color: Payload) {
</script> </script>
<template> <template>
<VDropdown class="inline-flex"> <VDropdown class="inline-flex items-center">
<slot /> <slot />
<template #popper> <template #popper>
<slot name="prefix" /> <slot name="prefix" />

View File

@ -1,7 +1,7 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { Component } from "vue"; import type { Component } from "vue";
import { VTooltip } from "floating-vue"; import { VTooltip } from "floating-vue";
import IconArrowDown from "~icons/ri/arrow-down-s-fill"; import MdiMenuDown from "~icons/mdi/menu-down";
import type { ToolbarItem } from "@/types"; import type { ToolbarItem } from "@/types";
withDefaults( withDefaults(
@ -11,7 +11,7 @@ withDefaults(
title?: string; title?: string;
action?: () => void; action?: () => void;
icon?: Component; icon?: Component;
children: ToolbarItem[]; children?: ToolbarItem[];
}>(), }>(),
{ {
isActive: false, isActive: false,
@ -28,16 +28,16 @@ withDefaults(
<button <button
v-tooltip="title" v-tooltip="title"
:class="[ :class="[
{ 'bg-gray-200': isActive }, { 'bg-gray-200/70': isActive },
{ 'cursor-not-allowed opacity-70': disabled }, { 'cursor-not-allowed opacity-70': disabled },
{ 'hover:bg-gray-100': !disabled }, { 'hover:bg-gray-100': !disabled },
]" ]"
class="inline-flex items-center space-x-1 p-1 rounded-sm" class="inline-flex items-center space-x-1 p-1.5 rounded-md"
:disabled="disabled" :disabled="disabled"
tabindex="-1" tabindex="-1"
@click="action" @click="action"
> >
<component :is="icon" /> <component :is="icon" />
<IconArrowDown v-if="children?.length" /> <MdiMenuDown v-if="children?.length" />
</button> </button>
</template> </template>

View File

@ -31,19 +31,19 @@ const action = () => {
{ 'cursor-not-allowed opacity-70 ': disabled }, { 'cursor-not-allowed opacity-70 ': disabled },
{ 'hover:bg-gray-100': !disabled }, { 'hover:bg-gray-100': !disabled },
]" ]"
class="flex flex-row items-center rounded gap-4 p-1 group cursor-pointer" class="flex flex-row items-center rounded gap-3 py-1 px-1.5 group cursor-pointer"
@click="action" @click="action"
> >
<component <component
:is="icon" :is="icon"
class="bg-gray-100 p-1 rounded w-6 h-6" class="bg-gray-100 p-1.5 rounded w-7 h-7"
:class="[ :class="[
{ '!bg-white': isActive }, { '!bg-white': isActive },
{ 'group-hover:bg-white': !disabled }, { 'group-hover:bg-white': !disabled },
]" ]"
/> />
<span <span
class="text-xs text-gray-600" class="text-sm text-gray-600"
:class="[ :class="[
{ '!text-gray-900 !font-medium': isActive }, { '!text-gray-900 !font-medium': isActive },
{ 'group-hover:font-medium group-hover:text-gray-900': !disabled }, { 'group-hover:font-medium group-hover:text-gray-900': !disabled },

View File

@ -1,8 +1,8 @@
import type { Editor } from "@/tiptap";
import { Extension } from "@/tiptap"; import { Extension } from "@/tiptap";
import type { ExtensionOptions } from "@/types"; import type { ExtensionOptions } from "@/types";
import type { Editor } from "@/tiptap";
import { markRaw } from "vue"; import { markRaw } from "vue";
import IconParkSolidClearFormat from "~icons/icon-park-solid/clear-format"; import MdiEraser from "~icons/mdi/eraser";
import ToolbarItem from "@/components/toolbar/ToolbarItem.vue"; import ToolbarItem from "@/components/toolbar/ToolbarItem.vue";
import { i18n } from "@/locales"; import { i18n } from "@/locales";
@ -16,7 +16,7 @@ const clearFormat = Extension.create<ExtensionOptions>({
props: { props: {
editor, editor,
isActive: false, isActive: false,
icon: markRaw(IconParkSolidClearFormat), icon: markRaw(MdiEraser),
title: i18n.global.t("editor.common.clear_format"), title: i18n.global.t("editor.common.clear_format"),
action: () => editor.chain().focus().unsetAllMarks().run(), action: () => editor.chain().focus().unsetAllMarks().run(),
}, },

View File

@ -2,7 +2,7 @@ import ToolbarItem from "@/components/toolbar/ToolbarItem.vue";
import { i18n } from "@/locales"; import { i18n } from "@/locales";
import { CoreEditor, Extension, Plugin, PluginKey } from "@/tiptap"; import { CoreEditor, Extension, Plugin, PluginKey } from "@/tiptap";
import { markRaw } from "vue"; import { markRaw } from "vue";
import BxsBrushAlt from "~icons/bxs/brush-alt"; import MdiBrushVariant from "~icons/mdi/brush-variant";
import { getMarksByFirstTextNode, setMarks } from "./util"; import { getMarksByFirstTextNode, setMarks } from "./util";
declare module "@/tiptap" { declare module "@/tiptap" {
@ -32,7 +32,7 @@ const formatBrush = Extension.create<any, FormatBrushStore>({
props: { props: {
editor, editor,
isActive: formatBrush, isActive: formatBrush,
icon: markRaw(BxsBrushAlt), icon: markRaw(MdiBrushVariant),
title: formatBrush title: formatBrush
? i18n.global.t( ? i18n.global.t(
"editor.extensions.format_brush.toolbar_item.cancel" "editor.extensions.format_brush.toolbar_item.cancel"