fix(editor): add recent open doc with mode button (#11419)

Closes: [BS-3013](https://linear.app/affine-design/issue/BS-3013/open-doc-分开两个按钮:一个快捷按钮和一个菜单)

Split into two buttons: `recent open doc with mode button` and `open doc with dropdown menu`.
This commit is contained in:
fundon
2025-04-03 02:06:14 +00:00
parent b53b2acfe3
commit 03dd073cb4
5 changed files with 58 additions and 33 deletions
@@ -6,7 +6,7 @@ import {
import { unsafeCSSVarV2 } from '@blocksuite/affine-shared/theme';
import { SignalWatcher, WithDisposable } from '@blocksuite/global/lit';
import { PropTypes, requiredProperties } from '@blocksuite/std';
import type { ReadonlySignal } from '@preact/signals-core';
import { computed, type ReadonlySignal } from '@preact/signals-core';
import { css, html, LitElement } from 'lit';
import { property } from 'lit/decorators.js';
import { ifDefined } from 'lit-html/directives/if-defined.js';
@@ -24,6 +24,17 @@ export class OpenDocDropdownMenu extends SignalWatcher(
WithDisposable(LitElement)
) {
static override styles = css`
:host {
display: flex;
gap: unset !important;
}
editor-icon-button {
.label {
font-weight: 400;
}
}
div[data-orientation] {
width: 264px;
gap: 4px;
@@ -59,31 +70,36 @@ export class OpenDocDropdownMenu extends SignalWatcher(
@property({ attribute: false })
accessor updateOpenDocMode!: (mode: OpenDocMode) => void;
currentAction$ = computed(() => {
const currentOpenDocMode = this.openDocMode$.value;
return (
this.actions.find(a => a.mode === currentOpenDocMode) ?? this.actions[0]
);
});
override render() {
const {
actions,
context,
openDocMode$: { value: openDocMode },
updateOpenDocMode,
currentAction$: { value: currentAction },
} = this;
const currentAction =
actions.find(a => a.mode === openDocMode) ?? actions[0];
return html`
<editor-icon-button
aria-label="${currentAction.label}"
.tooltip="${currentAction.label}"
@click=${() => currentAction.run?.(context)}
>
${currentAction.icon}
<span class="label">Open</span>
</editor-icon-button>
<editor-menu-button
aria-label="Open doc menu"
.contentPadding="${'8px'}"
.button=${html`
<editor-icon-button
data-open-doc-mode="${currentAction.label}"
aria-label="Open doc"
.tooltip="${'Open doc'}"
.justify="${'space-between'}"
.labelHeight="${'20px'}"
.iconContainerWidth="${'84px'}"
>
${currentAction.icon}
<span class="label">Open</span> ${EditorChevronDown}
<editor-icon-button aria-label="Open doc with">
${EditorChevronDown}
</editor-icon-button>
`}
>
@@ -716,18 +716,20 @@ function renderOpenDocMenu(
}));
if (!actions.length) return null;
const openDocMode = computed(
() => settings.settingSignal.value.openDocMode ?? 'open-in-active-view'
);
const updateOpenDocMode = (mode: OpenDocMode) =>
settings.openDocMode.set(mode);
return html`${keyed(
target,
html`
<affine-open-doc-dropdown-menu
.actions=${actions}
.context=${ctx}
.openDocMode$=${computed(
() =>
settings.settingSignal.value.openDocMode ?? 'open-in-active-view'
)}
.updateOpenDocMode=${(mode: OpenDocMode) =>
settings.openDocMode.set(mode)}
.openDocMode$=${openDocMode}
.updateOpenDocMode=${updateOpenDocMode}
>
</affine-open-doc-dropdown-menu>
`
@@ -190,7 +190,7 @@ test('outline viewer should be useable in doc peek preview', async ({
const toolbar = page.locator('affine-toolbar-widget editor-toolbar');
await expect(toolbar).toBeVisible();
await toolbar.getByLabel(/^Open doc$/).click();
await toolbar.getByLabel(/^Open doc with$/).click();
await toolbar
.getByLabel('Open doc menu')
.getByLabel('Open in center peek')
+18 -11
View File
@@ -1054,11 +1054,18 @@ test('should save open doc mode of internal links', async ({ page }) => {
const inlineLink = page.locator('affine-reference');
await inlineLink.hover();
const openDocBtn = toolbar.getByLabel(/^Open doc$/);
await expect(openDocBtn).toHaveAttribute(
'data-open-doc-mode',
const recentOpenModeBtn = toolbar.locator(
'editor-icon-button:has-text("Open")'
);
await expect(recentOpenModeBtn).toHaveAttribute(
'aria-label',
'Open this doc'
);
await expect(
recentOpenModeBtn.locator('span.label:has-text("Open")')
).toBeVisible();
const openDocBtn = toolbar.getByLabel(/^Open doc with$/);
await openDocBtn.click();
const openDocMenu = toolbar.getByLabel('Open doc menu');
@@ -1081,8 +1088,8 @@ test('should save open doc mode of internal links', async ({ page }) => {
await inlineLink.hover();
await expect(toolbar).toBeVisible();
await expect(openDocBtn).toHaveAttribute(
'data-open-doc-mode',
await expect(recentOpenModeBtn).toHaveAttribute(
'aria-label',
'Open in center peek'
);
@@ -1090,8 +1097,8 @@ test('should save open doc mode of internal links', async ({ page }) => {
await cardViewBtn.click();
await expect(toolbar).toBeVisible();
await expect(openDocBtn).toHaveAttribute(
'data-open-doc-mode',
await expect(recentOpenModeBtn).toHaveAttribute(
'aria-label',
'Open in center peek'
);
@@ -1099,8 +1106,8 @@ test('should save open doc mode of internal links', async ({ page }) => {
await embedViewBtn.click();
await expect(toolbar).toBeVisible();
await expect(openDocBtn).toHaveAttribute(
'data-open-doc-mode',
await expect(recentOpenModeBtn).toHaveAttribute(
'aria-label',
'Open in center peek'
);
@@ -1112,8 +1119,8 @@ test('should save open doc mode of internal links', async ({ page }) => {
await page.waitForTimeout(250);
await expect(toolbar).toBeVisible();
await expect(openDocBtn).toHaveAttribute(
'data-open-doc-mode',
await expect(recentOpenModeBtn).toHaveAttribute(
'aria-label',
'Open in center peek'
);
});
+1 -1
View File
@@ -28,7 +28,7 @@ test('can open peek view via link popover', async ({ page }) => {
const toolbar = page.locator('affine-toolbar-widget editor-toolbar');
await expect(toolbar).toBeVisible();
await toolbar.getByLabel(/^Open doc$/).click();
await toolbar.getByLabel(/^Open doc with$/).click();
await toolbar
.getByLabel('Open doc menu')
.getByLabel('Open in center peek')