mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-21 00:07:01 +08:00
feat(editor): inner toolbar layout for block (#11243)
Close [BS-2808](https://linear.app/affine-design/issue/BS-2808/组件内-toolbar-重构)
This commit is contained in:
@@ -17,6 +17,7 @@ import {
|
||||
ToolbarFlag as Flag,
|
||||
ToolbarRegistryIdentifier,
|
||||
} from '@blocksuite/affine-shared/services';
|
||||
import { unsafeCSSVar, unsafeCSSVarV2 } from '@blocksuite/affine-shared/theme';
|
||||
import { matchModels } from '@blocksuite/affine-shared/utils';
|
||||
import {
|
||||
type BlockComponent,
|
||||
@@ -36,7 +37,7 @@ import {
|
||||
getCommonBoundWithRotation,
|
||||
} from '@blocksuite/global/gfx';
|
||||
import { nextTick } from '@blocksuite/global/utils';
|
||||
import type { Placement, ReferenceElement, SideObject } from '@floating-ui/dom';
|
||||
import type { ReferenceElement, SideObject } from '@floating-ui/dom';
|
||||
import { batch, effect, signal } from '@preact/signals-core';
|
||||
import { css, unsafeCSS } from 'lit';
|
||||
import groupBy from 'lodash-es/groupBy';
|
||||
@@ -76,15 +77,32 @@ export class AffineToolbarWidget extends WidgetComponent {
|
||||
}
|
||||
}
|
||||
|
||||
editor-toolbar[data-app-theme='dark'] {
|
||||
${unsafeCSS(darkToolbarStyles.join('\n'))}
|
||||
}
|
||||
editor-toolbar[data-app-theme='light'] {
|
||||
${unsafeCSS(lightToolbarStyles.join('\n'))}
|
||||
}
|
||||
`;
|
||||
editor-toolbar[data-placement='inner'] {
|
||||
background-color: unset;
|
||||
box-shadow: unset;
|
||||
height: fit-content;
|
||||
padding-top: 4px;
|
||||
border-radius: 0;
|
||||
border: unset;
|
||||
justify-content: flex-end;
|
||||
box-sizing: border-box;
|
||||
gap: 4px;
|
||||
|
||||
placement$ = signal<Placement>('top');
|
||||
editor-icon-button,
|
||||
editor-menu-button {
|
||||
background: ${unsafeCSSVarV2('button/iconButtonSolid')};
|
||||
color: ${unsafeCSSVarV2('text/primary')};
|
||||
box-shadow: ${unsafeCSSVar('buttonShadow')};
|
||||
border-radius: 4px;
|
||||
}
|
||||
editor-menu-button > div {
|
||||
gap: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
${unsafeCSS(darkToolbarStyles('editor-toolbar'))}
|
||||
${unsafeCSS(lightToolbarStyles('editor-toolbar'))}
|
||||
`;
|
||||
|
||||
sideOptions$ = signal<Partial<SideObject> | null>(null);
|
||||
|
||||
@@ -213,7 +231,7 @@ export class AffineToolbarWidget extends WidgetComponent {
|
||||
|
||||
this.sideOptions$.value = sideOptions;
|
||||
ctx.flavour$.value = flavour;
|
||||
this.placement$.value = hasLocked ? 'top' : 'top-start';
|
||||
ctx.placement$.value = hasLocked ? 'top' : 'top-start';
|
||||
ctx.flags.refresh(Flag.Surface);
|
||||
});
|
||||
}
|
||||
@@ -228,7 +246,6 @@ export class AffineToolbarWidget extends WidgetComponent {
|
||||
super.connectedCallback();
|
||||
|
||||
const {
|
||||
placement$,
|
||||
sideOptions$,
|
||||
referenceElement$,
|
||||
disposables,
|
||||
@@ -237,7 +254,7 @@ export class AffineToolbarWidget extends WidgetComponent {
|
||||
host,
|
||||
std,
|
||||
} = this;
|
||||
const { flags, flavour$, message$ } = toolbarRegistry;
|
||||
const { flags, flavour$, message$, placement$ } = toolbarRegistry;
|
||||
const context = new ToolbarContext(std);
|
||||
|
||||
// TODO(@fundon): fix toolbar position shaking when the wheel scrolls
|
||||
@@ -266,7 +283,7 @@ export class AffineToolbarWidget extends WidgetComponent {
|
||||
|
||||
sideOptions$.value = null;
|
||||
flavour$.value = 'affine:note';
|
||||
placement$.value = 'top';
|
||||
placement$.value = toolbarRegistry.getModulePlacement('affine:note');
|
||||
flags.refresh(Flag.Text);
|
||||
});
|
||||
})
|
||||
@@ -317,7 +334,7 @@ export class AffineToolbarWidget extends WidgetComponent {
|
||||
|
||||
sideOptions$.value = null;
|
||||
flavour$.value = 'affine:note';
|
||||
placement$.value = 'top';
|
||||
placement$.value = toolbarRegistry.getModulePlacement('affine:note');
|
||||
flags.refresh(Flag.Native);
|
||||
});
|
||||
});
|
||||
@@ -338,7 +355,7 @@ export class AffineToolbarWidget extends WidgetComponent {
|
||||
if (block) {
|
||||
const modelFlavour = block.model.flavour;
|
||||
const existed =
|
||||
toolbarRegistry.modules.has(modelFlavour) ??
|
||||
toolbarRegistry.modules.has(modelFlavour) ||
|
||||
toolbarRegistry.modules.has(`custom:${modelFlavour}`);
|
||||
if (existed) {
|
||||
flavour = modelFlavour;
|
||||
@@ -366,7 +383,10 @@ export class AffineToolbarWidget extends WidgetComponent {
|
||||
|
||||
sideOptions$.value = null;
|
||||
flavour$.value = flavour;
|
||||
placement$.value = flavour === 'affine:note' ? 'top' : 'top-start';
|
||||
placement$.value = toolbarRegistry.getModulePlacement(
|
||||
flavour,
|
||||
flavour === 'affine:note' ? 'top' : 'top-start'
|
||||
);
|
||||
flags.refresh(Flag.Block);
|
||||
});
|
||||
})
|
||||
@@ -494,7 +514,7 @@ export class AffineToolbarWidget extends WidgetComponent {
|
||||
})
|
||||
);
|
||||
|
||||
// Handles elemets when updating
|
||||
// Handles elements when updating
|
||||
disposables.add(
|
||||
context.gfx.surface$.subscribe(surface => {
|
||||
if (!surface) return;
|
||||
@@ -580,7 +600,7 @@ export class AffineToolbarWidget extends WidgetComponent {
|
||||
|
||||
sideOptions$.value = null;
|
||||
flavour$.value = flavour;
|
||||
placement$.value = 'top';
|
||||
placement$.value = toolbarRegistry.getModulePlacement(flavour);
|
||||
flags.refresh(Flag.Hovering);
|
||||
});
|
||||
})
|
||||
@@ -593,6 +613,13 @@ export class AffineToolbarWidget extends WidgetComponent {
|
||||
})
|
||||
);
|
||||
|
||||
// Update layout when placement changing to `inner`
|
||||
disposables.add(
|
||||
effect(() => {
|
||||
toolbar.dataset.placement = placement$.value;
|
||||
})
|
||||
);
|
||||
|
||||
disposables.add(
|
||||
effect(() => {
|
||||
const value = flags.value$.value;
|
||||
|
||||
Reference in New Issue
Block a user