mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-09-06 08:50:50 +08:00
fix(editor): code block ui issues (#12609)
Close BS-3423 Close BS-3505 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Style** - Updated toolbar button background color and adjusted layout spacing for toolbar and preview buttons to improve visual consistency. - **Refactor** - Reorganized toolbar menu groups for better clarity, separating toggle and clipboard actions within the code block toolbar. - **Bug Fixes** - Improved UI interaction in code block tests to ensure menus behave as expected without closing prematurely. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -35,14 +35,10 @@ export class AffineCodeToolbar extends WithDisposable(LitElement) {
|
|||||||
|
|
||||||
.code-toolbar-button {
|
.code-toolbar-button {
|
||||||
color: ${unsafeCSSVarV2('icon/primary')};
|
color: ${unsafeCSSVarV2('icon/primary')};
|
||||||
background-color: ${unsafeCSSVarV2('segment/background')};
|
background-color: ${unsafeCSSVarV2('button/secondary')};
|
||||||
box-shadow: var(--affine-shadow-1);
|
box-shadow: var(--affine-shadow-1);
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.copy-code {
|
|
||||||
margin-left: auto;
|
|
||||||
}
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
private _currentOpenMenu: AbortController | null = null;
|
private _currentOpenMenu: AbortController | null = null;
|
||||||
|
|||||||
@@ -13,6 +13,10 @@ import { CodeBlockPreviewIdentifier } from '../../code-preview-extension';
|
|||||||
|
|
||||||
export class PreviewButton extends WithDisposable(SignalWatcher(LitElement)) {
|
export class PreviewButton extends WithDisposable(SignalWatcher(LitElement)) {
|
||||||
static override styles = css`
|
static override styles = css`
|
||||||
|
:host {
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
.preview-toggle-container {
|
.preview-toggle-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 2px;
|
padding: 2px;
|
||||||
|
|||||||
@@ -117,13 +117,12 @@ export const PRIMARY_GROUPS: MenuItemGroup<CodeBlockToolbarContext>[] = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
// Clipboard Group
|
export const toggleGroup: MenuItemGroup<CodeBlockToolbarContext> = {
|
||||||
export const clipboardGroup: MenuItemGroup<CodeBlockToolbarContext> = {
|
type: 'toggle',
|
||||||
type: 'clipboard',
|
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
type: 'wrap',
|
type: 'wrap',
|
||||||
generate: ({ blockComponent, close }) => {
|
generate: ({ blockComponent }) => {
|
||||||
return {
|
return {
|
||||||
action: () => {},
|
action: () => {},
|
||||||
render: () => {
|
render: () => {
|
||||||
@@ -134,7 +133,6 @@ export const clipboardGroup: MenuItemGroup<CodeBlockToolbarContext> = {
|
|||||||
<editor-menu-action
|
<editor-menu-action
|
||||||
@click=${() => {
|
@click=${() => {
|
||||||
blockComponent.setWrap(!wrapped);
|
blockComponent.setWrap(!wrapped);
|
||||||
close();
|
|
||||||
}}
|
}}
|
||||||
aria-label=${label}
|
aria-label=${label}
|
||||||
>
|
>
|
||||||
@@ -155,7 +153,7 @@ export const clipboardGroup: MenuItemGroup<CodeBlockToolbarContext> = {
|
|||||||
when: ({ std }) =>
|
when: ({ std }) =>
|
||||||
std.getOptional(CodeBlockConfigExtension.identifier)?.showLineNumbers ??
|
std.getOptional(CodeBlockConfigExtension.identifier)?.showLineNumbers ??
|
||||||
true,
|
true,
|
||||||
generate: ({ blockComponent, close }) => {
|
generate: ({ blockComponent }) => {
|
||||||
return {
|
return {
|
||||||
action: () => {},
|
action: () => {},
|
||||||
render: () => {
|
render: () => {
|
||||||
@@ -167,8 +165,6 @@ export const clipboardGroup: MenuItemGroup<CodeBlockToolbarContext> = {
|
|||||||
blockComponent.store.updateBlock(blockComponent.model, {
|
blockComponent.store.updateBlock(blockComponent.model, {
|
||||||
lineNumber: !lineNumber,
|
lineNumber: !lineNumber,
|
||||||
});
|
});
|
||||||
|
|
||||||
close();
|
|
||||||
}}
|
}}
|
||||||
aria-label=${label}
|
aria-label=${label}
|
||||||
>
|
>
|
||||||
@@ -184,6 +180,13 @@ export const clipboardGroup: MenuItemGroup<CodeBlockToolbarContext> = {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
// Clipboard Group
|
||||||
|
export const clipboardGroup: MenuItemGroup<CodeBlockToolbarContext> = {
|
||||||
|
type: 'clipboard',
|
||||||
|
items: [
|
||||||
{
|
{
|
||||||
type: 'duplicate',
|
type: 'duplicate',
|
||||||
label: 'Duplicate',
|
label: 'Duplicate',
|
||||||
@@ -233,6 +236,7 @@ export const deleteGroup: MenuItemGroup<CodeBlockToolbarContext> = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const MORE_GROUPS: MenuItemGroup<CodeBlockToolbarContext>[] = [
|
export const MORE_GROUPS: MenuItemGroup<CodeBlockToolbarContext>[] = [
|
||||||
|
toggleGroup,
|
||||||
clipboardGroup,
|
clipboardGroup,
|
||||||
deleteGroup,
|
deleteGroup,
|
||||||
];
|
];
|
||||||
|
|||||||
+32
-29
@@ -15,34 +15,37 @@ import { buildAICodeItemGroups } from '../../_common/config';
|
|||||||
import type { AskAIButtonOptions } from '../../components/ask-ai-button';
|
import type { AskAIButtonOptions } from '../../components/ask-ai-button';
|
||||||
|
|
||||||
export function setupCodeToolbarAIEntry(codeToolbar: AffineCodeToolbarWidget) {
|
export function setupCodeToolbarAIEntry(codeToolbar: AffineCodeToolbarWidget) {
|
||||||
codeToolbar.addPrimaryItems([
|
codeToolbar.addPrimaryItems(
|
||||||
{
|
[
|
||||||
type: 'ask-ai',
|
{
|
||||||
when: ({ doc }) => !doc.readonly,
|
type: 'ask-ai',
|
||||||
generate: ({ host, blockComponent }) => {
|
when: ({ doc }) => !doc.readonly,
|
||||||
return {
|
generate: ({ host, blockComponent }) => {
|
||||||
action: () => {
|
return {
|
||||||
const { selection } = host;
|
action: () => {
|
||||||
selection.setGroup('note', [
|
const { selection } = host;
|
||||||
selection.create(BlockSelection, {
|
selection.setGroup('note', [
|
||||||
blockId: blockComponent.blockId,
|
selection.create(BlockSelection, {
|
||||||
}),
|
blockId: blockComponent.blockId,
|
||||||
]);
|
}),
|
||||||
},
|
]);
|
||||||
render: item =>
|
},
|
||||||
html`<ask-ai-button
|
render: item =>
|
||||||
class="code-toolbar-button ask-ai"
|
html`<ask-ai-button
|
||||||
.host=${host}
|
class="code-toolbar-button ask-ai"
|
||||||
.actionGroups=${AICodeItemGroups}
|
.host=${host}
|
||||||
.toggleType=${'click'}
|
.actionGroups=${AICodeItemGroups}
|
||||||
.options=${buttonOptions}
|
.toggleType=${'click'}
|
||||||
@click=${(e: MouseEvent) => {
|
.options=${buttonOptions}
|
||||||
e.stopPropagation();
|
@click=${(e: MouseEvent) => {
|
||||||
item.action();
|
e.stopPropagation();
|
||||||
}}
|
item.action();
|
||||||
></ask-ai-button>`,
|
}}
|
||||||
};
|
></ask-ai-button>`,
|
||||||
|
};
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
],
|
||||||
]);
|
2
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -219,6 +219,8 @@ test('duplicate code block', async ({ page }, testInfo) => {
|
|||||||
await codeBlockController.codeBlock.hover();
|
await codeBlockController.codeBlock.hover();
|
||||||
await (await codeBlockController.openMore()).wrapButton.click();
|
await (await codeBlockController.openMore()).wrapButton.click();
|
||||||
|
|
||||||
|
await page.mouse.click(300, 300);
|
||||||
|
|
||||||
// duplicate
|
// duplicate
|
||||||
await codeBlockController.codeBlock.hover();
|
await codeBlockController.codeBlock.hover();
|
||||||
await (await codeBlockController.openMore()).duplicateButton.click();
|
await (await codeBlockController.openMore()).duplicateButton.click();
|
||||||
@@ -270,6 +272,8 @@ test('toggle code block wrap can work', async ({ page }, testInfo) => {
|
|||||||
await codeBlockController.codeBlock.hover();
|
await codeBlockController.codeBlock.hover();
|
||||||
await (await codeBlockController.openMore()).wrapButton.click();
|
await (await codeBlockController.openMore()).wrapButton.click();
|
||||||
|
|
||||||
|
await page.mouse.click(300, 300);
|
||||||
|
|
||||||
expect(await getPageSnapshot(page, true)).toMatchSnapshot(
|
expect(await getPageSnapshot(page, true)).toMatchSnapshot(
|
||||||
`${testInfo.title}_2.json`
|
`${testInfo.title}_2.json`
|
||||||
);
|
);
|
||||||
@@ -335,6 +339,8 @@ test('toggle code block line number can work', async ({ page }) => {
|
|||||||
await codeBlockController.codeBlock.hover();
|
await codeBlockController.codeBlock.hover();
|
||||||
await (await codeBlockController.openMore()).cancelLineNumberButton.click();
|
await (await codeBlockController.openMore()).cancelLineNumberButton.click();
|
||||||
|
|
||||||
|
await page.mouse.click(300, 300);
|
||||||
|
|
||||||
await expect(lineNumber).toBeHidden();
|
await expect(lineNumber).toBeHidden();
|
||||||
|
|
||||||
await undoByKeyboard(page);
|
await undoByKeyboard(page);
|
||||||
@@ -389,7 +395,9 @@ test('should tab works in code block', async ({ page }) => {
|
|||||||
await assertRichTexts(page, ['const a = 10;\n \nconst b = "NothingToSay"']);
|
await assertRichTexts(page, ['const a = 10;\n \nconst b = "NothingToSay"']);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should open more menu and close on selecting', async ({ page }) => {
|
test('should open more menu and do not close after selecting', async ({
|
||||||
|
page,
|
||||||
|
}) => {
|
||||||
await enterPlaygroundRoom(page);
|
await enterPlaygroundRoom(page);
|
||||||
await initEmptyCodeBlockState(page);
|
await initEmptyCodeBlockState(page);
|
||||||
await focusRichText(page);
|
await focusRichText(page);
|
||||||
@@ -401,7 +409,7 @@ test('should open more menu and close on selecting', async ({ page }) => {
|
|||||||
|
|
||||||
await expect(moreMenu.menu).toBeVisible();
|
await expect(moreMenu.menu).toBeVisible();
|
||||||
await moreMenu.wrapButton.click();
|
await moreMenu.wrapButton.click();
|
||||||
await expect(moreMenu.menu).toBeHidden();
|
await expect(moreMenu.menu).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should code block lang input supports alias', async ({ page }) => {
|
test('should code block lang input supports alias', async ({ page }) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user