diff --git a/src/frontend/apps/impress/src/features/docs/doc-editor/components/BlockNoteEditor.tsx b/src/frontend/apps/impress/src/features/docs/doc-editor/components/BlockNoteEditor.tsx
index 0b6e0d97..92c22780 100644
--- a/src/frontend/apps/impress/src/features/docs/doc-editor/components/BlockNoteEditor.tsx
+++ b/src/frontend/apps/impress/src/features/docs/doc-editor/components/BlockNoteEditor.tsx
@@ -1,6 +1,7 @@
import {
BlockNoteSchema,
Dictionary,
+ defaultBlockSpecs,
locales,
withPageBreak,
} from '@blocknote/core';
@@ -26,8 +27,16 @@ import { randomColor } from '../utils';
import { BlockNoteSuggestionMenu } from './BlockNoteSuggestionMenu';
import { BlockNoteToolbar } from './BlockNoteToolbar';
+import { QuoteBlock } from './custom-blocks';
-export const blockNoteSchema = withPageBreak(BlockNoteSchema.create());
+export const blockNoteSchema = withPageBreak(
+ BlockNoteSchema.create({
+ blockSpecs: {
+ ...defaultBlockSpecs,
+ quote: QuoteBlock,
+ },
+ }),
+);
interface BlockNoteEditorProps {
doc: Doc;
@@ -141,8 +150,8 @@ export const BlockNoteEditor = ({ doc, provider }: BlockNoteEditorProps) => {
editable={!readOnly}
theme="light"
>
-
+
);
diff --git a/src/frontend/apps/impress/src/features/docs/doc-editor/components/BlockNoteSuggestionMenu.tsx b/src/frontend/apps/impress/src/features/docs/doc-editor/components/BlockNoteSuggestionMenu.tsx
index 22b11365..961b33be 100644
--- a/src/frontend/apps/impress/src/features/docs/doc-editor/components/BlockNoteSuggestionMenu.tsx
+++ b/src/frontend/apps/impress/src/features/docs/doc-editor/components/BlockNoteSuggestionMenu.tsx
@@ -5,13 +5,19 @@ import {
getDefaultReactSlashMenuItems,
getPageBreakReactSlashMenuItems,
useBlockNoteEditor,
+ useDictionary,
} from '@blocknote/react';
import React, { useMemo } from 'react';
+import { useTranslation } from 'react-i18next';
-import { DocsBlockNoteEditor } from '../types';
+import { DocsBlockSchema } from '../types';
+
+import { getQuoteReactSlashMenuItems } from './custom-blocks';
export const BlockNoteSuggestionMenu = () => {
- const editor = useBlockNoteEditor() as DocsBlockNoteEditor;
+ const editor = useBlockNoteEditor();
+ const { t } = useTranslation();
+ const basicBlocksName = useDictionary().slash_menu.page_break.group;
const getSlashMenuItems = useMemo(() => {
return async (query: string) =>
@@ -20,11 +26,12 @@ export const BlockNoteSuggestionMenu = () => {
combineByGroup(
getDefaultReactSlashMenuItems(editor),
getPageBreakReactSlashMenuItems(editor),
+ getQuoteReactSlashMenuItems(editor, t, basicBlocksName),
),
query,
),
);
- }, [editor]);
+ }, [basicBlocksName, editor, t]);
return (
{
+ const dict = useDictionary();
+ const { t } = useTranslation();
+
const formattingToolbar = useCallback(
- ({ blockTypeSelectItems }: FormattingToolbarProps) => (
+ () => (
- {getFormattingToolbarItems(blockTypeSelectItems)}
+ {getFormattingToolbarItems([
+ ...blockTypeSelectItems(dict),
+ getQuoteFormattingToolbarItems(t),
+ ])}
{/* Extra button to do some AI powered actions */}
@@ -23,7 +32,7 @@ export const BlockNoteToolbar = () => {
),
- [],
+ [dict, t],
);
return ;
diff --git a/src/frontend/apps/impress/src/features/docs/doc-editor/components/custom-blocks/QuoteBlock.tsx b/src/frontend/apps/impress/src/features/docs/doc-editor/components/custom-blocks/QuoteBlock.tsx
new file mode 100644
index 00000000..e5d99802
--- /dev/null
+++ b/src/frontend/apps/impress/src/features/docs/doc-editor/components/custom-blocks/QuoteBlock.tsx
@@ -0,0 +1,77 @@
+import { defaultProps, insertOrUpdateBlock } from '@blocknote/core';
+import { BlockTypeSelectItem, createReactBlockSpec } from '@blocknote/react';
+import { TFunction } from 'i18next';
+import React from 'react';
+
+import { Text } from '@/components';
+import { useCunninghamTheme } from '@/cunningham';
+
+import { DocsBlockNoteEditor } from '../../types';
+
+export const QuoteBlock = createReactBlockSpec(
+ {
+ type: 'quote',
+ propSchema: {
+ textAlignment: defaultProps.textAlignment,
+ textColor: defaultProps.textColor,
+ },
+ content: 'inline',
+ },
+ {
+ render: (props) => {
+ // eslint-disable-next-line react-hooks/rules-of-hooks
+ const { colorsTokens } = useCunninghamTheme();
+
+ return (
+
+ );
+ },
+ },
+);
+
+export const getQuoteReactSlashMenuItems = (
+ editor: DocsBlockNoteEditor,
+ t: TFunction<'translation', undefined>,
+ group: string,
+) => [
+ {
+ title: t('Quote'),
+ onItemClick: () => {
+ insertOrUpdateBlock(editor, {
+ type: 'quote',
+ });
+ },
+ aliases: ['quote', 'blockquote', 'citation'],
+ group,
+ icon: (
+
+ format_quote
+
+ ),
+ subtext: t('Add a quote block'),
+ },
+];
+
+export const getQuoteFormattingToolbarItems = (
+ t: TFunction<'translation', undefined>,
+): BlockTypeSelectItem => ({
+ name: t('Quote'),
+ type: 'quote',
+ icon: () => (
+
+ format_quote
+
+ ),
+ isSelected: (block) => block.type === 'quote',
+});
diff --git a/src/frontend/apps/impress/src/features/docs/doc-editor/components/custom-blocks/index.ts b/src/frontend/apps/impress/src/features/docs/doc-editor/components/custom-blocks/index.ts
new file mode 100644
index 00000000..e101ddd8
--- /dev/null
+++ b/src/frontend/apps/impress/src/features/docs/doc-editor/components/custom-blocks/index.ts
@@ -0,0 +1 @@
+export * from './QuoteBlock';
diff --git a/src/frontend/apps/impress/src/features/docs/doc-editor/styles.tsx b/src/frontend/apps/impress/src/features/docs/doc-editor/styles.tsx
index 4a4a14bc..1eb356f9 100644
--- a/src/frontend/apps/impress/src/features/docs/doc-editor/styles.tsx
+++ b/src/frontend/apps/impress/src/features/docs/doc-editor/styles.tsx
@@ -6,6 +6,10 @@ export const cssEditor = (readonly: boolean) => css`
& .ProseMirror {
height: 100%;
+ .bn-side-menu[data-block-type='quote'] {
+ height: 46px;
+ }
+
.collaboration-cursor-custom__base {
position: relative;
}