mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-09-22 19:53:48 +08:00
fix(editor): reactive heading icon (#9729)
Close [BS-2407](https://linear.app/affine-design/issue/BS-2407/[bug]-edgeless-里选中-title-后更改,hint-没有改变)
This commit is contained in:
@@ -8,7 +8,7 @@ import {
|
|||||||
} from '@blocksuite/affine-components/icons';
|
} from '@blocksuite/affine-components/icons';
|
||||||
import type { ParagraphBlockModel } from '@blocksuite/affine-model';
|
import type { ParagraphBlockModel } from '@blocksuite/affine-model';
|
||||||
import { ShadowlessElement } from '@blocksuite/block-std';
|
import { ShadowlessElement } from '@blocksuite/block-std';
|
||||||
import { WithDisposable } from '@blocksuite/global/utils';
|
import { SignalWatcher, WithDisposable } from '@blocksuite/global/utils';
|
||||||
import { cssVarV2 } from '@toeverything/theme/v2';
|
import { cssVarV2 } from '@toeverything/theme/v2';
|
||||||
import { css, html, nothing, unsafeCSS } from 'lit';
|
import { css, html, nothing, unsafeCSS } from 'lit';
|
||||||
import { property } from 'lit/decorators.js';
|
import { property } from 'lit/decorators.js';
|
||||||
@@ -32,7 +32,9 @@ function HeadingIcon(i: number) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ParagraphHeadingIcon extends WithDisposable(ShadowlessElement) {
|
export class ParagraphHeadingIcon extends SignalWatcher(
|
||||||
|
WithDisposable(ShadowlessElement)
|
||||||
|
) {
|
||||||
static override styles = css`
|
static override styles = css`
|
||||||
affine-paragraph-heading-icon .heading-icon {
|
affine-paragraph-heading-icon .heading-icon {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -65,12 +67,14 @@ export class ParagraphHeadingIcon extends WithDisposable(ShadowlessElement) {
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
override render() {
|
override render() {
|
||||||
const type = this.model.type;
|
const type = this.model.type$.value;
|
||||||
if (!type.startsWith('h')) return nothing;
|
if (!type.startsWith('h')) return nothing;
|
||||||
|
|
||||||
const i = parseInt(type.slice(1));
|
const i = parseInt(type.slice(1));
|
||||||
|
|
||||||
return html`<div class="heading-icon">${HeadingIcon(i)}</div>`;
|
return html`<div class="heading-icon" data-testid="heading-icon-${i}">
|
||||||
|
${HeadingIcon(i)}
|
||||||
|
</div>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@property({ attribute: false })
|
@property({ attribute: false })
|
||||||
|
|||||||
@@ -157,7 +157,7 @@ export class ParagraphBlockComponent extends CaptionedBlockComponent<
|
|||||||
this._readonlyCollapsed = collapsed;
|
this._readonlyCollapsed = collapsed;
|
||||||
|
|
||||||
// reset text selection when selected block is collapsed
|
// reset text selection when selected block is collapsed
|
||||||
if (this.model.type.startsWith('h') && collapsed) {
|
if (this.model.type$.value.startsWith('h') && collapsed) {
|
||||||
const collapsedSiblings = this.collapsedSiblings;
|
const collapsedSiblings = this.collapsedSiblings;
|
||||||
const textSelection = this.host.selection.find(TextSelection);
|
const textSelection = this.host.selection.find(TextSelection);
|
||||||
|
|
||||||
@@ -177,7 +177,7 @@ export class ParagraphBlockComponent extends CaptionedBlockComponent<
|
|||||||
// # 456
|
// # 456
|
||||||
//
|
//
|
||||||
// we need to update collapsed state of 123 when 456 converted to text
|
// we need to update collapsed state of 123 when 456 converted to text
|
||||||
let beforeType = this.model.type;
|
let beforeType = this.model.type$.peek();
|
||||||
this.disposables.add(
|
this.disposables.add(
|
||||||
effect(() => {
|
effect(() => {
|
||||||
const type = this.model.type$.value;
|
const type = this.model.type$.value;
|
||||||
@@ -211,7 +211,7 @@ export class ParagraphBlockComponent extends CaptionedBlockComponent<
|
|||||||
const collapsedSiblings = this.collapsedSiblings;
|
const collapsedSiblings = this.collapsedSiblings;
|
||||||
|
|
||||||
let style = html``;
|
let style = html``;
|
||||||
if (this.model.type.startsWith('h') && collapsed) {
|
if (this.model.type$.value.startsWith('h') && collapsed) {
|
||||||
style = html`
|
style = html`
|
||||||
<style>
|
<style>
|
||||||
${collapsedSiblings.map(sibling =>
|
${collapsedSiblings.map(sibling =>
|
||||||
@@ -245,7 +245,8 @@ export class ParagraphBlockComponent extends CaptionedBlockComponent<
|
|||||||
[TOGGLE_BUTTON_PARENT_CLASS]: true,
|
[TOGGLE_BUTTON_PARENT_CLASS]: true,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
${this.model.type.startsWith('h') && collapsedSiblings.length > 0
|
${this.model.type$.value.startsWith('h') &&
|
||||||
|
collapsedSiblings.length > 0
|
||||||
? html`
|
? html`
|
||||||
<affine-paragraph-heading-icon
|
<affine-paragraph-heading-icon
|
||||||
.model=${this.model}
|
.model=${this.model}
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
import { test } from '@affine-test/kit/playwright';
|
||||||
|
import { locateFormatBar } from '@affine-test/kit/utils/editor';
|
||||||
|
import { selectAllByKeyboard } from '@affine-test/kit/utils/keyboard';
|
||||||
|
import { openHomePage } from '@affine-test/kit/utils/load-page';
|
||||||
|
import {
|
||||||
|
clickNewPageButton,
|
||||||
|
waitForEditorLoad,
|
||||||
|
} from '@affine-test/kit/utils/page-logic';
|
||||||
|
import { expect } from '@playwright/test';
|
||||||
|
|
||||||
|
test.beforeEach(async ({ page }) => {
|
||||||
|
await openHomePage(page);
|
||||||
|
await clickNewPageButton(page, 'Paragraph Test');
|
||||||
|
await waitForEditorLoad(page);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('heading icon should be updated after change heading level', async ({
|
||||||
|
page,
|
||||||
|
}) => {
|
||||||
|
await page.keyboard.press('Enter');
|
||||||
|
await page.keyboard.type('Hello');
|
||||||
|
// Hello|
|
||||||
|
// empty paragraph
|
||||||
|
|
||||||
|
const paragraph = page.locator('affine-note affine-paragraph').nth(0);
|
||||||
|
|
||||||
|
await selectAllByKeyboard(page);
|
||||||
|
const formatBar = locateFormatBar(page);
|
||||||
|
await formatBar.locator('.paragraph-button').hover();
|
||||||
|
await formatBar.getByTestId('affine:paragraph/h1').click();
|
||||||
|
|
||||||
|
await paragraph.hover();
|
||||||
|
await expect(page.getByTestId('heading-icon-1')).toBeVisible();
|
||||||
|
|
||||||
|
await selectAllByKeyboard(page);
|
||||||
|
await formatBar.locator('.paragraph-button').hover();
|
||||||
|
await formatBar.getByTestId('affine:paragraph/h2').click();
|
||||||
|
|
||||||
|
await paragraph.hover();
|
||||||
|
await expect(page.getByTestId('heading-icon-1')).toBeHidden();
|
||||||
|
await expect(page.getByTestId('heading-icon-2')).toBeVisible();
|
||||||
|
});
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import { test } from '@affine-test/kit/playwright';
|
import { test } from '@affine-test/kit/playwright';
|
||||||
|
import { locateFormatBar } from '@affine-test/kit/utils/editor';
|
||||||
import { openHomePage } from '@affine-test/kit/utils/load-page';
|
import { openHomePage } from '@affine-test/kit/utils/load-page';
|
||||||
import {
|
import {
|
||||||
clickNewPageButton,
|
clickNewPageButton,
|
||||||
@@ -21,7 +22,7 @@ test.describe('Format bar', () => {
|
|||||||
await page.keyboard.press('Shift+ArrowLeft');
|
await page.keyboard.press('Shift+ArrowLeft');
|
||||||
await page.keyboard.press('Shift+ArrowLeft');
|
await page.keyboard.press('Shift+ArrowLeft');
|
||||||
|
|
||||||
const formatBar = page.locator('.affine-format-bar-widget');
|
const formatBar = locateFormatBar(page);
|
||||||
await formatBar.locator('.highlight-icon').hover();
|
await formatBar.locator('.highlight-icon').hover();
|
||||||
const fgGreenButton = formatBar.locator(
|
const fgGreenButton = formatBar.locator(
|
||||||
'[data-testid="var(--affine-text-highlight-foreground-green)"]'
|
'[data-testid="var(--affine-text-highlight-foreground-green)"]'
|
||||||
@@ -49,7 +50,7 @@ test.describe('Format bar', () => {
|
|||||||
await page.keyboard.press('Shift+ArrowLeft');
|
await page.keyboard.press('Shift+ArrowLeft');
|
||||||
await page.keyboard.press('Shift+ArrowLeft');
|
await page.keyboard.press('Shift+ArrowLeft');
|
||||||
|
|
||||||
const formatBar = page.locator('.affine-format-bar-widget');
|
const formatBar = locateFormatBar(page);
|
||||||
await formatBar.locator('.highlight-icon').hover();
|
await formatBar.locator('.highlight-icon').hover();
|
||||||
|
|
||||||
const fgGreenButton = formatBar.locator(
|
const fgGreenButton = formatBar.locator(
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import type { AffineEditorContainer } from '@blocksuite/affine/presets';
|
import type { AffineEditorContainer } from '@blocksuite/affine/presets';
|
||||||
import {
|
import {
|
||||||
|
AFFINE_FORMAT_BAR_WIDGET,
|
||||||
EDGELESS_ELEMENT_TOOLBAR_WIDGET,
|
EDGELESS_ELEMENT_TOOLBAR_WIDGET,
|
||||||
EDGELESS_TOOLBAR_WIDGET,
|
EDGELESS_TOOLBAR_WIDGET,
|
||||||
} from '@blocksuite/blocks';
|
} from '@blocksuite/blocks';
|
||||||
@@ -52,6 +53,13 @@ export function locateEditorContainer(page: Page, editorIndex = 0) {
|
|||||||
return page.locator('[data-affine-editor-container]').nth(editorIndex);
|
return page.locator('[data-affine-editor-container]').nth(editorIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ================== Page ==================
|
||||||
|
export function locateFormatBar(page: Page, editorIndex = 0) {
|
||||||
|
return locateEditorContainer(page, editorIndex).locator(
|
||||||
|
AFFINE_FORMAT_BAR_WIDGET
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// ================== Edgeless ==================
|
// ================== Edgeless ==================
|
||||||
|
|
||||||
export async function getEdgelessSelectedIds(page: Page, editorIndex = 0) {
|
export async function getEdgelessSelectedIds(page: Page, editorIndex = 0) {
|
||||||
|
|||||||
Reference in New Issue
Block a user