mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-02 02:00:49 +08:00
feat(callout): add formatbar with background color selection
- Add background property to CalloutBlockModel with default white color - Implement dynamic background color rendering in CalloutBlockComponent - Create toolbar configuration with color palette for background selection - Register toolbar extension in CalloutViewExtension - Support all note background colors with visual feedback for current selection - Maintain consistency with other block formatbar implementations
This commit is contained in:
@@ -1,14 +1,13 @@
|
||||
import { CaptionedBlockComponent } from '@blocksuite/affine-components/caption';
|
||||
import { createLitPortal } from '@blocksuite/affine-components/portal';
|
||||
import { DefaultInlineManagerExtension } from '@blocksuite/affine-inline-preset';
|
||||
import { type CalloutBlockModel } from '@blocksuite/affine-model';
|
||||
import { type CalloutBlockModel, DefaultTheme } from '@blocksuite/affine-model';
|
||||
import { focusTextModel } from '@blocksuite/affine-rich-text';
|
||||
import { EDGELESS_TOP_CONTENTEDITABLE_SELECTOR } from '@blocksuite/affine-shared/consts';
|
||||
import {
|
||||
DocModeProvider,
|
||||
ThemeProvider,
|
||||
} from '@blocksuite/affine-shared/services';
|
||||
import { unsafeCSSVarV2 } from '@blocksuite/affine-shared/theme';
|
||||
import type { BlockComponent } from '@blocksuite/std';
|
||||
import { flip, offset } from '@floating-ui/dom';
|
||||
import { css, html } from 'lit';
|
||||
@@ -26,7 +25,6 @@ export class CalloutBlockComponent extends CaptionedBlockComponent<CalloutBlockM
|
||||
align-items: flex-start;
|
||||
padding: 5px 10px;
|
||||
border-radius: 8px;
|
||||
background-color: ${unsafeCSSVarV2('block/callout/background/grey')};
|
||||
}
|
||||
|
||||
.affine-callout-emoji-container {
|
||||
@@ -139,10 +137,23 @@ export class CalloutBlockComponent extends CaptionedBlockComponent<CalloutBlockM
|
||||
|
||||
override renderBlock() {
|
||||
const emoji = this.model.props.emoji$.value;
|
||||
const background = this.model.props.background$.value;
|
||||
|
||||
const themeProvider = this.std.get(ThemeProvider);
|
||||
const theme = themeProvider.theme$.value;
|
||||
const backgroundColor = themeProvider.generateColorProperty(
|
||||
background,
|
||||
DefaultTheme.NoteBackgroundColorMap.White,
|
||||
theme
|
||||
);
|
||||
|
||||
return html`
|
||||
<div
|
||||
class="affine-callout-block-container"
|
||||
@click=${this._handleBlockClick}
|
||||
style=${styleMap({
|
||||
backgroundColor: backgroundColor,
|
||||
})}
|
||||
>
|
||||
<div
|
||||
@click=${this._toggleEmojiMenu}
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
import { CalloutBlockModel, DefaultTheme } from '@blocksuite/affine-model';
|
||||
import {
|
||||
type ToolbarAction,
|
||||
type ToolbarActionGroup,
|
||||
type ToolbarModuleConfig,
|
||||
ToolbarModuleExtension,
|
||||
} from '@blocksuite/affine-shared/services';
|
||||
import { PaletteIcon } from '@blocksuite/icons/lit';
|
||||
import { BlockFlavourIdentifier } from '@blocksuite/std';
|
||||
import type { ExtensionType } from '@blocksuite/store';
|
||||
import { html } from 'lit';
|
||||
|
||||
const backgroundColorAction = {
|
||||
id: 'background-color',
|
||||
label: 'Background Color',
|
||||
tooltip: 'Change background color',
|
||||
icon: PaletteIcon(),
|
||||
run() {
|
||||
// This will be handled by the content function
|
||||
},
|
||||
content(ctx) {
|
||||
const model = ctx.getCurrentModelByType(CalloutBlockModel);
|
||||
if (!model) return null;
|
||||
|
||||
const currentBackground = model.props.background;
|
||||
const colors = DefaultTheme.NoteBackgroundColorPalettes;
|
||||
|
||||
return html`
|
||||
<div
|
||||
style="display: flex; flex-wrap: wrap; gap: 4px; padding: 8px; max-width: 200px;"
|
||||
>
|
||||
${colors.map(
|
||||
color => html`
|
||||
<button
|
||||
style="width: 24px; height: 24px; border-radius: 4px; border: 2px solid ${currentBackground ===
|
||||
color.value
|
||||
? 'var(--affine-primary-color)'
|
||||
: 'transparent'}; background-color: ${color.value}; cursor: pointer; padding: 0; margin: 0;"
|
||||
@click=${() => {
|
||||
ctx.store.updateBlock(model, { background: color.value });
|
||||
}}
|
||||
title=${color.key}
|
||||
></button>
|
||||
`
|
||||
)}
|
||||
</div>
|
||||
`;
|
||||
},
|
||||
} satisfies ToolbarAction;
|
||||
|
||||
const builtinToolbarConfig = {
|
||||
actions: [
|
||||
{
|
||||
id: 'style',
|
||||
actions: [backgroundColorAction],
|
||||
} satisfies ToolbarActionGroup<ToolbarAction>,
|
||||
],
|
||||
} as const satisfies ToolbarModuleConfig;
|
||||
|
||||
export const createBuiltinToolbarConfigExtension = (
|
||||
flavour: string
|
||||
): ExtensionType[] => {
|
||||
return [
|
||||
ToolbarModuleExtension({
|
||||
id: BlockFlavourIdentifier(flavour),
|
||||
config: builtinToolbarConfig,
|
||||
}),
|
||||
];
|
||||
};
|
||||
@@ -8,6 +8,7 @@ import { literal } from 'lit/static-html.js';
|
||||
|
||||
import { CalloutKeymapExtension } from './callout-keymap';
|
||||
import { calloutSlashMenuConfig } from './configs/slash-menu';
|
||||
import { createBuiltinToolbarConfigExtension } from './configs/toolbar';
|
||||
import { effects } from './effects';
|
||||
|
||||
export class CalloutViewExtension extends ViewExtensionProvider {
|
||||
@@ -25,6 +26,7 @@ export class CalloutViewExtension extends ViewExtensionProvider {
|
||||
BlockViewExtension('affine:callout', literal`affine-callout`),
|
||||
CalloutKeymapExtension,
|
||||
SlashMenuConfigExtension('affine:callout', calloutSlashMenuConfig),
|
||||
...createBuiltinToolbarConfigExtension('affine:callout'),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,11 +5,14 @@ import {
|
||||
type Text,
|
||||
} from '@blocksuite/store';
|
||||
|
||||
import type { Color } from '../../themes/index.js';
|
||||
import { DefaultTheme } from '../../themes/index.js';
|
||||
import type { BlockMeta } from '../../utils/types';
|
||||
|
||||
export type CalloutProps = {
|
||||
emoji: string;
|
||||
text: Text;
|
||||
background: Color;
|
||||
} & BlockMeta;
|
||||
|
||||
export const CalloutBlockSchema = defineBlockSchema({
|
||||
@@ -17,6 +20,7 @@ export const CalloutBlockSchema = defineBlockSchema({
|
||||
props: (internal): CalloutProps => ({
|
||||
emoji: '😀',
|
||||
text: internal.Text(),
|
||||
background: DefaultTheme.NoteBackgroundColorMap.White,
|
||||
'meta:createdAt': undefined,
|
||||
'meta:updatedAt': undefined,
|
||||
'meta:createdBy': undefined,
|
||||
|
||||
Reference in New Issue
Block a user