From 1b2a4377fd5580ab648759d99a9ba87e92b66c7f Mon Sep 17 00:00:00 2001 From: donteatfriedrice Date: Mon, 24 Feb 2025 08:15:04 +0000 Subject: [PATCH] feat(editor): update footnote node style and config (#10392) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [BS-2581](https://linear.app/affine-design/issue/BS-2581/优化-footnote-node-正文样式) --- .../nodes/footnote-node/footnote-config.ts | 12 +++++++ .../nodes/footnote-node/footnote-node.ts | 31 +++++++++++++++++-- .../footnote-node/footnote-popup-chip.ts | 1 + .../nodes/footnote-node/footnote-popup.ts | 1 - .../pages/workspace/detail-page/tabs/chat.tsx | 11 +++++-- .../view/ai-chat-block-peek-view/index.tsx | 7 +++++ 6 files changed, 57 insertions(+), 6 deletions(-) diff --git a/blocksuite/affine/components/src/rich-text/inline/presets/nodes/footnote-node/footnote-config.ts b/blocksuite/affine/components/src/rich-text/inline/presets/nodes/footnote-node/footnote-config.ts index 5570879a76..1c71addc4f 100644 --- a/blocksuite/affine/components/src/rich-text/inline/presets/nodes/footnote-node/footnote-config.ts +++ b/blocksuite/affine/components/src/rich-text/inline/presets/nodes/footnote-node/footnote-config.ts @@ -25,6 +25,7 @@ export interface FootNoteNodeConfig { customPopupRenderer?: FootNotePopupRenderer; interactive?: boolean; hidePopup?: boolean; + disableHoverEffect?: boolean; onPopupClick?: FootNotePopupClickHandler; } @@ -33,7 +34,9 @@ export class FootNoteNodeConfigProvider { private _customPopupRenderer?: FootNotePopupRenderer; private _hidePopup: boolean; private _interactive: boolean; + private _disableHoverEffect: boolean; private _onPopupClick?: FootNotePopupClickHandler; + get customNodeRenderer() { return this._customNodeRenderer; } @@ -58,6 +61,10 @@ export class FootNoteNodeConfigProvider { return this._interactive; } + get disableHoverEffect() { + return this._disableHoverEffect; + } + constructor( config: FootNoteNodeConfig, readonly std: BlockStdScope @@ -66,6 +73,7 @@ export class FootNoteNodeConfigProvider { this._customPopupRenderer = config.customPopupRenderer; this._hidePopup = config.hidePopup ?? false; this._interactive = config.interactive ?? true; + this._disableHoverEffect = config.disableHoverEffect ?? false; this._onPopupClick = config.onPopupClick; } @@ -85,6 +93,10 @@ export class FootNoteNodeConfigProvider { this._interactive = interactive; } + setDisableHoverEffect(disableHoverEffect: boolean) { + this._disableHoverEffect = disableHoverEffect; + } + setPopupClick(onPopupClick: FootNotePopupClickHandler) { this._onPopupClick = onPopupClick; } diff --git a/blocksuite/affine/components/src/rich-text/inline/presets/nodes/footnote-node/footnote-node.ts b/blocksuite/affine/components/src/rich-text/inline/presets/nodes/footnote-node/footnote-node.ts index d9ae95c86c..fb122a4b5d 100644 --- a/blocksuite/affine/components/src/rich-text/inline/presets/nodes/footnote-node/footnote-node.ts +++ b/blocksuite/affine/components/src/rich-text/inline/presets/nodes/footnote-node/footnote-node.ts @@ -19,6 +19,7 @@ import { shift } from '@floating-ui/dom'; import { baseTheme } from '@toeverything/theme'; import { css, html, nothing, unsafeCSS } from 'lit'; import { property } from 'lit/decorators.js'; +import { classMap } from 'lit-html/directives/class-map.js'; import { ref } from 'lit-html/directives/ref.js'; import { HoverController } from '../../../../../hover/controller'; @@ -37,7 +38,7 @@ export class AffineFootnoteNode extends WithDisposable(ShadowlessElement) { .footnote-content-default { display: inline-block; - background: ${unsafeCSSVarV2('button/primary')}; + background: ${unsafeCSSVarV2('block/footnote/numberBgHover')}; color: ${unsafeCSSVarV2('button/pureWhiteText')}; width: 14px; height: 14px; @@ -48,6 +49,21 @@ export class AffineFootnoteNode extends WithDisposable(ShadowlessElement) { text-align: center; text-overflow: ellipsis; font-family: ${unsafeCSS(baseTheme.fontSansFamily)}; + transition: background 0.3s ease-in-out; + } + + .footnote-node.hover-effect { + .footnote-content-default { + color: var(--affine-text-primary-color); + background: ${unsafeCSSVarV2('block/footnote/numberBg')}; + } + } + + .footnote-node.hover-effect:hover { + .footnote-content-default { + color: ${unsafeCSSVarV2('button/pureWhiteText')}; + background: ${unsafeCSSVarV2('block/footnote/numberBgHover')}; + } } `; @@ -67,6 +83,10 @@ export class AffineFootnoteNode extends WithDisposable(ShadowlessElement) { return this.config?.hidePopup; } + get disableHoverEffect() { + return this.config?.disableHoverEffect; + } + get onPopupClick() { return this.config?.onPopupClick; } @@ -142,7 +162,7 @@ export class AffineFootnoteNode extends WithDisposable(ShadowlessElement) { }, }; }, - { enterDelay: 500 } + { enterDelay: 300 } ); override render() { @@ -156,9 +176,14 @@ export class AffineFootnoteNode extends WithDisposable(ShadowlessElement) { ? this.customNodeRenderer(footnote, this.std) : this._FootNoteDefaultContent(footnote); + const nodeClasses = classMap({ + 'footnote-node': true, + 'hover-effect': !this.disableHoverEffect, + }); + return html`${node}`; } diff --git a/blocksuite/affine/components/src/rich-text/inline/presets/nodes/footnote-node/footnote-popup-chip.ts b/blocksuite/affine/components/src/rich-text/inline/presets/nodes/footnote-node/footnote-popup-chip.ts index 4a06f183b5..3f7e5031a1 100644 --- a/blocksuite/affine/components/src/rich-text/inline/presets/nodes/footnote-node/footnote-popup-chip.ts +++ b/blocksuite/affine/components/src/rich-text/inline/presets/nodes/footnote-node/footnote-popup-chip.ts @@ -14,6 +14,7 @@ export class FootNotePopupChip extends LitElement { gap: 4px; box-sizing: border-box; cursor: default; + transition: width 0.3s ease-in-out; } .prefix-icon, diff --git a/blocksuite/affine/components/src/rich-text/inline/presets/nodes/footnote-node/footnote-popup.ts b/blocksuite/affine/components/src/rich-text/inline/presets/nodes/footnote-node/footnote-popup.ts index b9aa7bc009..3c2c7cea88 100644 --- a/blocksuite/affine/components/src/rich-text/inline/presets/nodes/footnote-node/footnote-popup.ts +++ b/blocksuite/affine/components/src/rich-text/inline/presets/nodes/footnote-node/footnote-popup.ts @@ -26,7 +26,6 @@ export class FootNotePopup extends SignalWatcher(WithDisposable(LitElement)) { .footnote-popup-container { border-radius: 4px; box-shadow: ${unsafeCSSVar('overlayPanelShadow')}; - border-radius: 4px; background-color: ${unsafeCSSVarV2('layer/background/primary')}; border: 0.5px solid ${unsafeCSSVarV2('layer/insideBorder/border')}; } diff --git a/packages/frontend/core/src/desktop/pages/workspace/detail-page/tabs/chat.tsx b/packages/frontend/core/src/desktop/pages/workspace/detail-page/tabs/chat.tsx index 9cd1937b50..f407489922 100644 --- a/packages/frontend/core/src/desktop/pages/workspace/detail-page/tabs/chat.tsx +++ b/packages/frontend/core/src/desktop/pages/workspace/detail-page/tabs/chat.tsx @@ -8,6 +8,7 @@ import { WorkspaceService } from '@affine/core/modules/workspace'; import { createSignalFromObservable, DocModeProvider, + FootNoteNodeConfigExtension, RefNodeSlotsProvider, } from '@blocksuite/affine/blocks'; import { useFramework } from '@toeverything/infra'; @@ -20,6 +21,11 @@ export interface SidebarTabProps { onLoad?: ((component: HTMLElement) => void) | null; } +// Disable hover effect for footnote node in chat panel +const FOOTNOTE_CONFIG = FootNoteNodeConfigExtension({ + disableHoverEffect: true, +}); + // A wrapper for CopilotPanel export const EditorChatPanel = forwardRef(function EditorChatPanel( { editor, onLoad }: SidebarTabProps, @@ -84,8 +90,9 @@ export const EditorChatPanel = forwardRef(function EditorChatPanel( ); }, }; - chatPanelRef.current.previewSpecBuilder = - createPageModePreviewSpecs(framework); + const previewSpecBuilder = createPageModePreviewSpecs(framework); + previewSpecBuilder.extend([FOOTNOTE_CONFIG]); + chatPanelRef.current.previewSpecBuilder = previewSpecBuilder; } else { chatPanelRef.current.host = editor.host; chatPanelRef.current.doc = editor.doc; diff --git a/packages/frontend/core/src/modules/peek-view/view/ai-chat-block-peek-view/index.tsx b/packages/frontend/core/src/modules/peek-view/view/ai-chat-block-peek-view/index.tsx index b5167e0454..73d2277574 100644 --- a/packages/frontend/core/src/modules/peek-view/view/ai-chat-block-peek-view/index.tsx +++ b/packages/frontend/core/src/modules/peek-view/view/ai-chat-block-peek-view/index.tsx @@ -4,6 +4,7 @@ import type { AIChatBlockModel } from '@affine/core/blocksuite/ai/blocks/ai-chat import { createPageModePreviewSpecs } from '@affine/core/blocksuite/block-suite-editor/specs/preview'; import { AINetworkSearchService } from '@affine/core/modules/ai-button/services/network-search'; import type { EditorHost } from '@blocksuite/affine/block-std'; +import { FootNoteNodeConfigExtension } from '@blocksuite/affine/blocks'; import { useFramework } from '@toeverything/infra'; import { useMemo } from 'react'; @@ -12,6 +13,11 @@ export type AIChatBlockPeekViewProps = { host: EditorHost; }; +// Disable hover effect for footnote node in center peek preview mode +const FOOTNOTE_CONFIG = FootNoteNodeConfigExtension({ + disableHoverEffect: true, +}); + export const AIChatBlockPeekView = ({ model, host, @@ -20,6 +26,7 @@ export const AIChatBlockPeekView = ({ const searchService = framework.get(AINetworkSearchService); return useMemo(() => { const previewSpecBuilder = createPageModePreviewSpecs(framework); + previewSpecBuilder.extend([FOOTNOTE_CONFIG]); const networkSearchConfig = { visible: searchService.visible, enabled: searchService.enabled,