Skip to content

Commit 8716855

Browse files
Text colors, background colors, and text alignment (#91)
* Added block font and background colors * Added inline block font and background colors * Changed block text and background colors to extensions * Improved color mark commands * Small naming/formatting changes * Added text alignment * Text alignment is now applied to whole selection * Minor changes & fixes * Added PR feedback * Implemented PR feedback * Fixed build issues * Small improvements * Updated slash menu snapshots * Updated placeholder test and snapshots * Updated keyboard handler snapshots * Updated copy/paste snapshots * Updated copy/paste snapshots * Updated drag & drop snapshots * Updated drag handle snapshots * Added text & background color tests * Added text & background color screenshots * Added text alignment tests * Fixed formatting toolbar block indentation buttons * Changed color picker menu chevron orientation * Added block indentation tests * Updated test screenshots * Reverted Chromium slash menu screenshot * Reverted Chromium slash menu screenshot * Updated Chromium slash menu screenshot * Adjusted chevron in the drag handle menu color picker button * Updates drag handle menu screenshots
1 parent 5d79391 commit 8716855

File tree

102 files changed

+3807
-318
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

102 files changed

+3807
-318
lines changed

packages/core/src/BlockNoteExtensions.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ import { SuggestionsMenuFactory } from "./shared/plugins/suggestion/SuggestionsM
2525
import { BlockSideMenuFactory } from "./extensions/DraggableBlocks/BlockSideMenuFactoryTypes";
2626
import { Link } from "@tiptap/extension-link";
2727
import { SlashMenuItem } from "./extensions/SlashMenu/SlashMenuItem";
28+
import { BackgroundColorMark } from "./extensions/BackgroundColor/BackgroundColorMark";
29+
import { TextColorMark } from "./extensions/TextColor/TextColorMark";
30+
import { BackgroundColorExtension } from "./extensions/BackgroundColor/BackgroundColorExtension";
31+
import { TextColorExtension } from "./extensions/TextColor/TextColorExtension";
32+
import { TextAlignmentExtension } from "./extensions/TextAlignment/TextAlignmentExtension";
2833

2934
export type UiFactories = Partial<{
3035
formattingToolbarFactory: FormattingToolbarFactory;
@@ -70,6 +75,11 @@ export const getBlockNoteExtensions = (uiFactories: UiFactories) => {
7075
Italic,
7176
Strike,
7277
Underline,
78+
TextColorMark,
79+
TextColorExtension,
80+
BackgroundColorMark,
81+
BackgroundColorExtension,
82+
TextAlignmentExtension,
7383

7484
// custom blocks:
7585
...blocks,
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import { Extension } from "@tiptap/core";
2+
import { getBlockInfoFromPos } from "../Blocks/helpers/getBlockInfoFromPos";
3+
4+
declare module "@tiptap/core" {
5+
interface Commands<ReturnType> {
6+
blockBackgroundColor: {
7+
setBlockBackgroundColor: (
8+
posInBlock: number,
9+
color: string
10+
) => ReturnType;
11+
};
12+
}
13+
}
14+
15+
export const BackgroundColorExtension = Extension.create({
16+
name: "blockBackgroundColor",
17+
18+
addGlobalAttributes() {
19+
return [
20+
{
21+
types: ["blockContainer"],
22+
attributes: {
23+
backgroundColor: {
24+
default: "default",
25+
parseHTML: (element) =>
26+
element.hasAttribute("data-background-color")
27+
? element.getAttribute("data-background-color")
28+
: "default",
29+
renderHTML: (attributes) =>
30+
attributes.backgroundColor !== "default" && {
31+
"data-background-color": attributes.backgroundColor,
32+
},
33+
},
34+
},
35+
},
36+
];
37+
},
38+
39+
addCommands() {
40+
return {
41+
setBlockBackgroundColor:
42+
(posInBlock, color) =>
43+
({ state, view }) => {
44+
const blockInfo = getBlockInfoFromPos(state.doc, posInBlock);
45+
if (blockInfo === undefined) {
46+
return false;
47+
}
48+
49+
state.tr.setNodeAttribute(
50+
blockInfo.startPos - 1,
51+
"backgroundColor",
52+
color
53+
);
54+
55+
view.focus();
56+
57+
return true;
58+
},
59+
};
60+
},
61+
});
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import { Mark } from "@tiptap/core";
2+
3+
declare module "@tiptap/core" {
4+
interface Commands<ReturnType> {
5+
backgroundColor: {
6+
setBackgroundColor: (color: string) => ReturnType;
7+
};
8+
}
9+
}
10+
11+
export const BackgroundColorMark = Mark.create({
12+
name: "backgroundColor",
13+
14+
addAttributes() {
15+
return {
16+
color: {
17+
default: undefined,
18+
parseHTML: (element) => element.getAttribute("data-background-color"),
19+
renderHTML: (attributes) => ({
20+
"data-background-color": attributes.color,
21+
}),
22+
},
23+
};
24+
},
25+
26+
parseHTML() {
27+
return [
28+
{
29+
tag: "span",
30+
getAttrs: (element) => {
31+
if (typeof element === "string") {
32+
return false;
33+
}
34+
35+
if (element.hasAttribute("data-background-color")) {
36+
return { color: element.getAttribute("data-background-color") };
37+
}
38+
39+
return false;
40+
},
41+
},
42+
];
43+
},
44+
45+
renderHTML({ HTMLAttributes }) {
46+
return ["span", HTMLAttributes, 0];
47+
},
48+
49+
addCommands() {
50+
return {
51+
setBackgroundColor:
52+
(color) =>
53+
({ commands }) => {
54+
if (color !== "default") {
55+
return commands.setMark(this.name, { color: color });
56+
}
57+
58+
return commands.unsetMark(this.name);
59+
},
60+
};
61+
},
62+
});

packages/core/src/extensions/Blocks/nodes/Block.module.css

Lines changed: 91 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,6 @@ BASIC STYLES
1010
font-weight: normal;
1111
}
1212

13-
.block {
14-
border-left: 2px solid white;
15-
border-color: white;
16-
transition: all 0.2s;
17-
}
18-
1913
.block {
2014
/* content: ""; */
2115
transition: all 0.2s;
@@ -268,3 +262,94 @@ NESTED BLOCKS
268262
> :first-child:before {
269263
content: "List";
270264
}
265+
266+
/* TEXT COLORS */
267+
[data-text-color="gray"] {
268+
color: #9b9a97;
269+
}
270+
271+
[data-text-color="brown"] {
272+
color: #64473a;
273+
}
274+
275+
[data-text-color="red"] {
276+
color: #e03e3e;
277+
}
278+
279+
[data-text-color="orange"] {
280+
color: #d9730d;
281+
}
282+
283+
[data-text-color="yellow"] {
284+
color: #dfab01;
285+
}
286+
287+
[data-text-color="green"] {
288+
color: #4d6461;
289+
}
290+
291+
[data-text-color="blue"] {
292+
color: #0b6e99;
293+
}
294+
295+
[data-text-color="purple"] {
296+
color: #6940a5;
297+
}
298+
299+
[data-text-color="pink"] {
300+
color: #ad1a72;
301+
}
302+
303+
/* BACKGROUND COLORS */
304+
[data-background-color="gray"] {
305+
background-color: #ebeced;
306+
}
307+
308+
[data-background-color="brown"] {
309+
background-color: #e9e5e3;
310+
}
311+
312+
[data-background-color="red"] {
313+
background-color: #fbe4e4;
314+
}
315+
316+
[data-background-color="orange"] {
317+
background-color: #faebdd;
318+
}
319+
320+
[data-background-color="yellow"] {
321+
background-color: #fbf3db;
322+
}
323+
324+
[data-background-color="green"] {
325+
background-color: #ddedea;
326+
}
327+
328+
[data-background-color="blue"] {
329+
background-color: #ddebf1;
330+
}
331+
332+
[data-background-color="purple"] {
333+
background-color: #eae4f2;
334+
}
335+
336+
[data-background-color="pink"] {
337+
background-color: #f4dfeb;
338+
}
339+
340+
/* TEXT ALIGNMENT */
341+
[data-text-alignment="left"] {
342+
text-align: left;
343+
}
344+
345+
[data-text-alignment="center"] {
346+
text-align: center;
347+
}
348+
349+
[data-text-alignment="right"] {
350+
text-align: right;
351+
}
352+
353+
[data-text-alignment="justify"] {
354+
text-align: justify;
355+
}

packages/core/src/extensions/Blocks/nodes/BlockContainer.ts

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -49,17 +49,6 @@ export const BlockContainer = Node.create<IBlock>({
4949
};
5050
},
5151

52-
addAttributes() {
53-
return {
54-
blockColor: {
55-
default: undefined,
56-
},
57-
blockStyle: {
58-
default: undefined,
59-
},
60-
};
61-
},
62-
6352
parseHTML() {
6453
return [
6554
{

packages/core/src/extensions/Blocks/nodes/BlockContent/ParagraphBlockContent/ParagraphBlockContent.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Node } from "@tiptap/core";
1+
import { mergeAttributes, Node } from "@tiptap/core";
22
import styles from "../../Block.module.css";
33

44
export const ParagraphBlockContent = Node.create({
@@ -16,13 +16,13 @@ export const ParagraphBlockContent = Node.create({
1616
];
1717
},
1818

19-
renderHTML() {
19+
renderHTML({ HTMLAttributes }) {
2020
return [
2121
"div",
22-
{
22+
mergeAttributes(HTMLAttributes, {
2323
class: styles.blockContent,
2424
"data-content-type": this.name,
25-
},
25+
}),
2626
["p", 0],
2727
];
2828
},

packages/core/src/extensions/DraggableBlocks/BlockSideMenuFactoryTypes.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,21 @@ import { EditorElement, ElementFactory } from "../../shared/EditorElement";
33
export type BlockSideMenuStaticParams = {
44
addBlock: () => void;
55
deleteBlock: () => void;
6+
67
blockDragStart: (event: DragEvent) => void;
78
blockDragEnd: () => void;
9+
810
freezeMenu: () => void;
911
unfreezeMenu: () => void;
12+
13+
setBlockTextColor: (color: string) => void;
14+
setBlockBackgroundColor: (color: string) => void;
1015
};
1116

1217
export type BlockSideMenuDynamicParams = {
18+
blockTextColor: string;
19+
blockBackgroundColor: string;
20+
1321
referenceRect: DOMRect;
1422
};
1523

0 commit comments

Comments
 (0)