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:
Flrande
2025-05-28 10:38:23 +00:00
parent 85def83f5e
commit d4c5b40284
5 changed files with 59 additions and 44 deletions
@@ -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,
]; ];
@@ -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
);
} }
+10 -2
View File
@@ -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 }) => {