refactor(editor): move getTooltipWithShortcut to affine-tooltip-content-with-shortcut (#10743)

I'm refactoring the edgeless note toolbar config extension and find that I need to move this.

cac05e720a/blocksuite/affine/blocks/block-root/src/widgets/element-toolbar/change-note-button.ts (L525)
This commit is contained in:
fundon
2025-03-10 11:58:58 +00:00
parent cac05e720a
commit 6244bbbd11
19 changed files with 152 additions and 80 deletions

View File

@@ -131,6 +131,7 @@
"./components/toggle-switch": "./src/components/toggle-switch.ts",
"./components/toolbar": "./src/components/toolbar.ts",
"./components/view-dropdown-menu": "./src/components/view-dropdown-menu.ts",
"./components/tooltip-content-with-shortcut": "./src/components/tooltip-content-with-shortcut.ts",
"./rich-text": "./src/rich-text/index.ts",
"./rich-text/effects": "./src/rich-text/effects.ts",
"./shared/adapters": "./src/shared/adapters.ts",

View File

@@ -0,0 +1 @@
export * from '@blocksuite/affine-components/tooltip-content-with-shortcut';

View File

@@ -36,6 +36,7 @@ import { SmoothCorner } from '@blocksuite/affine-components/smooth-corner';
import { effects as componentToggleButtonEffects } from '@blocksuite/affine-components/toggle-button';
import { ToggleSwitch } from '@blocksuite/affine-components/toggle-switch';
import { effects as componentToolbarEffects } from '@blocksuite/affine-components/toolbar';
import { effects as componentTooltipContentWithShortcutEffects } from '@blocksuite/affine-components/tooltip-content-with-shortcut';
import { effects as componentViewDropdownMenuEffects } from '@blocksuite/affine-components/view-dropdown-menu';
import { effects as fragmentDocTitleEffects } from '@blocksuite/affine-fragment-doc-title/effects';
import { effects as fragmentFramePanelEffects } from '@blocksuite/affine-fragment-frame-panel/effects';
@@ -145,6 +146,7 @@ export function effects() {
componentCardStyleDropdownMenuEffects();
componentHighlightDropdownMenuEffects();
componentViewDropdownMenuEffects();
componentTooltipContentWithShortcutEffects();
widgetScrollAnchoringEffects();
widgetFrameTitleEffects();

View File

@@ -7,7 +7,6 @@ import { computed } from '@preact/signals-core';
import { css, html, LitElement } from 'lit';
import { styleMap } from 'lit/directives/style-map.js';
import { getTooltipWithShortcut } from '../../utils.js';
import { EdgelessToolbarToolMixin } from '../mixins/tool.mixin.js';
import { EdgelessPenDarkIcon, EdgelessPenLightIcon } from './icons.js';
@@ -78,7 +77,12 @@ export class EdgelessBrushToolButton extends EdgelessToolbarToolMixin(
return html`
<edgeless-toolbar-button
class="edgeless-brush-button"
.tooltip=${this.popper ? '' : getTooltipWithShortcut('Pen', 'P')}
.tooltip=${this.popper
? ''
: html`<affine-tooltip-content-with-shortcut
data-tip="${'Pen'}"
data-shortcut="${'P'}"
></affine-tooltip-content-with-shortcut>`}
.tooltipOffset=${4}
.active=${active}
.withHover=${true}

View File

@@ -9,7 +9,6 @@ import {
import { computed } from '@preact/signals-core';
import { css, html, LitElement } from 'lit';
import { getTooltipWithShortcut } from '../../utils.js';
import { QuickToolMixin } from '../mixins/quick-tool.mixin.js';
const IcomMap = {
@@ -55,7 +54,10 @@ export class EdgelessConnectorToolButton extends QuickToolMixin(
class="edgeless-connector-button"
.tooltip=${this.popper
? ''
: getTooltipWithShortcut(getConnectorModeName(mode), 'C')}
: html`<affine-tooltip-content-with-shortcut
data-tip="${getConnectorModeName(mode)}"
data-shortcut="${'C'}"
></affine-tooltip-content-with-shortcut>`}
.tooltipOffset=${17}
.active=${active}
.iconContainerPadding=${6}

View File

@@ -4,7 +4,6 @@ import { effect } from '@preact/signals-core';
import { css, html, LitElement } from 'lit';
import { query } from 'lit/decorators.js';
import { getTooltipWithShortcut } from '../../utils.js';
import { QuickToolMixin } from '../mixins/quick-tool.mixin.js';
export class EdgelessDefaultToolButton extends QuickToolMixin(LitElement) {
static override styles = css`
@@ -74,12 +73,17 @@ export class EdgelessDefaultToolButton extends QuickToolMixin(LitElement) {
override render() {
const type = this.edgelessTool?.type;
const { active } = this;
const tipInfo =
type === 'pan'
? { tip: 'Hand', shortcut: 'H' }
: { tip: 'Select', shortcut: 'V' };
return html`
<edgeless-tool-icon-button
class="edgeless-default-button ${type}"
.tooltip=${type === 'pan'
? getTooltipWithShortcut('Hand', 'H')
: getTooltipWithShortcut('Select', 'V')}
.tooltip=${html`<affine-tooltip-content-with-shortcut
data-tip="${tipInfo.tip}"
data-shortcut="${tipInfo.shortcut}"
></affine-tooltip-content-with-shortcut>`}
.tooltipOffset=${17}
.active=${active}
.iconContainerPadding=${6}

View File

@@ -2,7 +2,6 @@ import { ThemeProvider } from '@blocksuite/affine-shared/services';
import type { GfxToolsFullOptionValue } from '@blocksuite/block-std/gfx';
import { css, html, LitElement } from 'lit';
import { getTooltipWithShortcut } from '../../utils.js';
import { EdgelessToolbarToolMixin } from '../mixins/tool.mixin.js';
import { EdgelessEraserDarkIcon, EdgelessEraserLightIcon } from './icons.js';
@@ -60,7 +59,10 @@ export class EdgelessEraserToolButton extends EdgelessToolbarToolMixin(
return html`
<edgeless-toolbar-button
class="edgeless-eraser-button"
.tooltip=${getTooltipWithShortcut('Eraser', 'E')}
.tooltip=${html`<affine-tooltip-content-with-shortcut
data-tip="${'Eraser'}"
data-shortcut="${'E'}"
></affine-tooltip-content-with-shortcut>`}
.tooltipOffset=${4}
.active=${type === 'eraser'}
@click=${() => this.setEdgelessTool({ type: 'eraser' })}

View File

@@ -2,7 +2,6 @@ import type { GfxToolsFullOptionValue } from '@blocksuite/block-std/gfx';
import { FrameIcon } from '@blocksuite/icons/lit';
import { css, html, LitElement } from 'lit';
import { getTooltipWithShortcut } from '../../../components/utils.js';
import { QuickToolMixin } from '../mixins/quick-tool.mixin.js';
export class EdgelessFrameToolButton extends QuickToolMixin(LitElement) {
@@ -26,7 +25,12 @@ export class EdgelessFrameToolButton extends QuickToolMixin(LitElement) {
return html`
<edgeless-tool-icon-button
class="edgeless-frame-button"
.tooltip=${this.popper ? '' : getTooltipWithShortcut('Frame', 'F')}
.tooltip=${this.popper
? ''
: html`<affine-tooltip-content-with-shortcut
data-tip="${'Frame'}"
data-shortcut="${'F'}"
></affine-tooltip-content-with-shortcut>`}
.tooltipOffset=${17}
.iconSize=${'24px'}
.active=${type === 'frame'}

View File

@@ -4,7 +4,6 @@ import { effect } from '@preact/signals-core';
import { css, html, LitElement } from 'lit';
import { query, state } from 'lit/decorators.js';
import { getTooltipWithShortcut } from '../../utils.js';
import { QuickToolMixin } from '../mixins/quick-tool.mixin.js';
import { LassoFreeHandIcon, LassoPolygonalIcon } from './icons.js';
@@ -72,7 +71,10 @@ export class EdgelessLassoToolButton extends QuickToolMixin(
return html`
<edgeless-tool-icon-button
class="edgeless-lasso-button ${mode}"
.tooltip=${getTooltipWithShortcut('Lasso', 'L')}
.tooltip=${html`<affine-tooltip-content-with-shortcut
data-tip="${'Lasso'}"
data-shortcut="${'L'}"
></affine-tooltip-content-with-shortcut>`}
.tooltipOffset=${17}
.active=${type === 'lasso'}
.iconContainerPadding=${6}

View File

@@ -3,7 +3,6 @@ import { LinkIcon } from '@blocksuite/affine-components/icons';
import { TelemetryProvider } from '@blocksuite/affine-shared/services';
import { css, html, LitElement } from 'lit';
import { getTooltipWithShortcut } from '../../utils.js';
import { QuickToolMixin } from '../mixins/quick-tool.mixin.js';
export class EdgelessLinkToolButton extends QuickToolMixin(LitElement) {
@@ -53,7 +52,10 @@ export class EdgelessLinkToolButton extends QuickToolMixin(LitElement) {
override render() {
return html`<edgeless-tool-icon-button
.iconContainerPadding="${6}"
.tooltip="${getTooltipWithShortcut('Link', '@')}"
.tooltip="${html`<affine-tooltip-content-with-shortcut
data-tip="${'Link'}"
data-shortcut="${'@'}"
></affine-tooltip-content-with-shortcut>`}"
.tooltipOffset=${17}
class="edgeless-link-tool-button"
@click=${this._onClick}

View File

@@ -18,7 +18,6 @@ import { property } from 'lit/decorators.js';
import { repeat } from 'lit/directives/repeat.js';
import type { EdgelessRootBlockComponent } from '../../../index.js';
import { getTooltipWithShortcut } from '../../utils.js';
import { EdgelessDraggableElementController } from '../common/draggable/draggable-element.controller.js';
import { EdgelessToolbarToolMixin } from '../mixins/tool.mixin.js';
import { getMindMaps, type ToolbarMindmapItem } from './assets.js';
@@ -174,7 +173,9 @@ export class EdgelessMindmapMenu extends EdgelessToolbarToolMixin(
${importMindMapIcon}
</button>
<affine-tooltip tip-position="top" .offset=${12}>
${getTooltipWithShortcut('Support import of FreeMind,OPML.')}
<affine-tooltip-content-with-shortcut
data-tip="${'Support import of FreeMind,OPML.'}"
></affine-tooltip-content-with-shortcut>
</affine-tooltip>
</div>`;
}
@@ -292,7 +293,9 @@ export class EdgelessMindmapMenu extends EdgelessToolbarToolMixin(
${mediaItem.icon}
</button>
<affine-tooltip tip-position="top" .offset=${12}>
${getTooltipWithShortcut('Add media')}
<affine-tooltip-content-with-shortcut
data-tip="${'Add media'}"
></affine-tooltip-content-with-shortcut>
</affine-tooltip>
</div>
<div class="thin-divider"></div>
@@ -321,7 +324,10 @@ export class EdgelessMindmapMenu extends EdgelessToolbarToolMixin(
${textItem.icon}
</button>
<affine-tooltip tip-position="top" .offset=${12}>
${getTooltipWithShortcut('Edgeless Text', 'T')}
<affine-tooltip-content-with-shortcut
data-tip="${'Edgeless Text'}"
data-shortcup="${'T'}"
></affine-tooltip-content-with-shortcut>
</affine-tooltip>
</div>
<div class="thin-divider"></div>
@@ -364,7 +370,10 @@ export class EdgelessMindmapMenu extends EdgelessToolbarToolMixin(
${mindMap.icon}
</button>
<affine-tooltip tip-position="top" .offset=${12}>
${getTooltipWithShortcut('Mind Map', 'M')}
<affine-tooltip-content-with-shortcut
data-tip="${'Mind Map'}"
data-shortcup="${'M'}"
></affine-tooltip-content-with-shortcut>
</affine-tooltip>
</div>
`;

View File

@@ -16,7 +16,6 @@ import { property, state } from 'lit/decorators.js';
import { repeat } from 'lit/directives/repeat.js';
import type { NoteToolOption } from '../../../gfx-tool/note-tool.js';
import { getTooltipWithShortcut } from '../../utils.js';
import { EdgelessToolbarToolMixin } from '../mixins/tool.mixin.js';
import { NOTE_MENU_ITEMS } from './note-menu-config.js';
@@ -123,7 +122,10 @@ export class EdgelessNoteMenu extends EdgelessToolbarToolMixin(LitElement) {
<edgeless-tool-icon-button
.activeMode=${'background'}
.tooltip=${getTooltipWithShortcut('Link', '@')}
.tooltip=${html`<affine-tooltip-content-with-shortcut
data-tip="${'Link'}"
data-shortcut="${'@'}"
></affine-tooltip-content-with-shortcut>`}
@click=${() => {
this._onHandleLinkButtonClick();
}}

View File

@@ -13,7 +13,6 @@ import { css, html, LitElement } from 'lit';
import { state } from 'lit/decorators.js';
import type { NoteToolOption } from '../../../gfx-tool/note-tool.js';
import { getTooltipWithShortcut } from '../../utils.js';
import { EdgelessToolbarToolMixin } from '../mixins/tool.mixin.js';
import { toShapeNotToAdapt } from './icon.js';
@@ -187,7 +186,12 @@ export class EdgelessNoteSeniorButton extends EdgelessToolbarToolMixin(
return html`<edgeless-toolbar-button
class="edgeless-note-button"
.tooltip=${this.popper ? '' : getTooltipWithShortcut('Note', 'N')}
.tooltip=${this.popper
? ''
: html`<affine-tooltip-content-with-shortcut
data-tip="${'Note'}"
data-shortcut="${'N'}"
></affine-tooltip-content-with-shortcut>`}
.tooltipOffset=${5}
>
<div

View File

@@ -4,7 +4,6 @@ import { effect } from '@preact/signals-core';
import { css, html, LitElement } from 'lit';
import { state } from 'lit/decorators.js';
import { getTooltipWithShortcut } from '../../../components/utils.js';
import type { NoteToolOption } from '../../../gfx-tool/note-tool.js';
import { createPopper, type MenuPopper } from '../common/create-popper.js';
import { QuickToolMixin } from '../mixins/quick-tool.mixin.js';
@@ -88,7 +87,12 @@ export class EdgelessNoteToolButton extends QuickToolMixin(LitElement) {
return html`
<edgeless-tool-icon-button
class="edgeless-note-button"
.tooltip=${this._noteMenu ? '' : getTooltipWithShortcut('Note', 'N')}
.tooltip=${this._noteMenu
? ''
: html`<affine-tooltip-content-with-shortcut
data-tip="${'Note'}"
data-shortcut="${'N'}"
></affine-tooltip-content-with-shortcut>`}
.tooltipOffset=${17}
.active=${active}
.iconContainerPadding=${6}

View File

@@ -3,7 +3,6 @@ import { SignalWatcher } from '@blocksuite/global/lit';
import { css, html, LitElement } from 'lit';
import { ShapeTool } from '../../../gfx-tool/shape-tool.js';
import { getTooltipWithShortcut } from '../../utils.js';
import { EdgelessToolbarToolMixin } from '../mixins/tool.mixin.js';
import type { DraggableShape } from './utils.js';
@@ -68,7 +67,12 @@ export class EdgelessShapeToolButton extends EdgelessToolbarToolMixin(
return html`
<edgeless-toolbar-button
class="edgeless-shape-button"
.tooltip=${this.popper ? '' : getTooltipWithShortcut('Shape', 'S')}
.tooltip=${this.popper
? ''
: html`<affine-tooltip-content-with-shortcut
data-tip="${'Shape'}"
data-shortcut="${'S'}"
></affine-tooltip-content-with-shortcut>`}
.tooltipOffset=${5}
.active=${active}
>

View File

@@ -1,7 +1,6 @@
import type { CursorType, StandardCursor } from '@blocksuite/block-std/gfx';
import type { IVec } from '@blocksuite/global/gfx';
import { normalizeDegAngle, Vec } from '@blocksuite/global/gfx';
import { css, html } from 'lit';
export function generateCursorUrl(
angle = 0,
@@ -25,53 +24,6 @@ export function getCommonRectStyle(
};
}
export function getTooltipWithShortcut(
tip: string,
shortcut?: string,
postfix?: string
) {
// style for shortcut tooltip
const styles = css`
.tooltip-with-shortcut {
display: flex;
flex-wrap: nowrap;
align-items: center;
gap: 10px;
}
.tooltip__shortcut {
font-size: 12px;
position: relative;
display: flex;
align-items: center;
justify-content: center;
height: 16px;
min-width: 16px;
}
.tooltip__shortcut::before {
content: '';
border-radius: 4px;
position: absolute;
inset: 0;
background: currentColor;
opacity: 0.2;
}
.tooltip__label {
white-space: pre;
}
`;
return html`<style>
${styles}
</style>
<div class="tooltip-with-shortcut">
<span class="tooltip__label">${tip}</span>
${shortcut
? html`<span class="tooltip__shortcut">${shortcut}</span>`
: ''}
${postfix ? html`<span class="tooltip__postfix">${postfix}</span>` : ''}
</div>`;
}
const RESIZE_CURSORS: CursorType[] = [
'ew-resize',
'nwse-resize',

View File

@@ -54,7 +54,6 @@ import {
type LineStyleEvent,
LineStylesPanel,
} from '../../edgeless/components/panel/line-styles-panel.js';
import { getTooltipWithShortcut } from '../../edgeless/components/utils.js';
import type { EdgelessRootBlockComponent } from '../../edgeless/edgeless-root-block.js';
import { SmallArrowDownIcon } from './icons.js';
import * as styles from './styles.css';
@@ -522,7 +521,10 @@ export class EdgelessChangeNoteButton extends WithDisposable(LitElement) {
? html`
<editor-icon-button
aria-label="Slicer"
.tooltip=${getTooltipWithShortcut('Cutting mode', '-')}
.tooltip=${html`<affine-tooltip-content-with-shortcut
data-tip="${'Cutting mode'}"
data-shortcut="${'-'}"
></affine-tooltip-content-with-shortcut>`}
.active=${this.enableNoteSlicer}
.iconSize=${'20px'}
@click=${() => this._handleNoteSlicerButtonClick()}

View File

@@ -66,7 +66,8 @@
"./linked-doc-title": "./src/linked-doc-title/index.ts",
"./view-dropdown-menu": "./src/view-dropdown-menu/index.ts",
"./card-style-dropdown-menu": "./src/card-style-dropdown-menu/index.ts",
"./highlight-dropdown-menu": "./src/highlight-dropdown-menu/index.ts"
"./highlight-dropdown-menu": "./src/highlight-dropdown-menu/index.ts",
"./tooltip-content-with-shortcut": "./src/tooltip-content-with-shortcut/index.ts"
},
"files": [
"src",

View File

@@ -0,0 +1,70 @@
import { css, html, LitElement } from 'lit';
import { property } from 'lit/decorators.js';
export class TooltipContentWithShortcut extends LitElement {
static override styles = css`
.tooltip-with-shortcut {
display: flex;
flex-wrap: nowrap;
align-items: center;
gap: 10px;
}
.tooltip__shortcut {
font-size: 12px;
position: relative;
display: flex;
align-items: center;
justify-content: center;
height: 16px;
min-width: 16px;
}
.tooltip__shortcut::before {
content: '';
border-radius: 4px;
position: absolute;
inset: 0;
background: currentColor;
opacity: 0.2;
}
.tooltip__label {
white-space: pre;
}
`;
override render() {
const { tip, shortcut, postfix } = this;
return html`
<div class="tooltip-with-shortcut">
<span class="tooltip__label">${tip}</span>
${shortcut
? html`<span class="tooltip__shortcut">${shortcut}</span>`
: ''}
${postfix ? html`<span class="tooltip__postfix">${postfix}</span>` : ''}
</div>
`;
}
@property({ attribute: 'data-tip' })
accessor tip!: string;
@property({ attribute: 'data-shortcut' })
accessor shortcut: string | undefined = undefined;
@property({ attribute: 'data-postfix' })
accessor postfix: string | undefined = undefined;
}
export function effects() {
customElements.define(
'affine-tooltip-content-with-shortcut',
TooltipContentWithShortcut
);
}
declare global {
interface HTMLElementTagNameMap {
'affine-tooltip-content-with-shortcut': TooltipContentWithShortcut;
}
}