diff --git a/docs/content/docs/react/components/formatting-toolbar.mdx b/docs/content/docs/react/components/formatting-toolbar.mdx
index 962035ba57..a880274254 100644
--- a/docs/content/docs/react/components/formatting-toolbar.mdx
+++ b/docs/content/docs/react/components/formatting-toolbar.mdx
@@ -38,3 +38,29 @@ The first element in the default Formatting Toolbar is the Block Type Select, an
Here, we use the `FormattingToolbar` component but keep the default buttons (we don't pass any children). Instead, we pass our customized Block Type Select items using the `blockTypeSelectItems` prop.
+
+## Adding a Text Align Select
+
+You can replace the default text alignment buttons with a `TextAlignSelect` dropdown, which groups all four alignment options (Left, Center, Right, Justify) into a single compact select.
+
+To use it, pass `` as a child of `FormattingToolbar` in a custom toolbar:
+
+```tsx
+import {
+ BlockTypeSelect,
+ FormattingToolbar,
+ FormattingToolbarController,
+ TextAlignSelect,
+} from "@blocknote/react";
+
+const CustomFormattingToolbar = () => (
+
+
+ {/* ... other toolbar items ... */}
+
+ {/* ... other toolbar items ... */}
+
+);
+```
+
+The select is only rendered when the cursor or selection is on a block that supports the `textAlignment` prop (e.g. paragraphs and headings). For table blocks, it applies the chosen alignment to the individual cells covered by the current cell selection.
diff --git a/packages/core/src/i18n/locales/ar.ts b/packages/core/src/i18n/locales/ar.ts
index 37abc3e30b..04e2c6ed52 100644
--- a/packages/core/src/i18n/locales/ar.ts
+++ b/packages/core/src/i18n/locales/ar.ts
@@ -310,15 +310,19 @@ export const ar: Dictionary = {
},
align_left: {
tooltip: "محاذاة النص إلى اليسار",
+ label: "يسار",
},
align_center: {
tooltip: "محاذاة النص في المنتصف",
+ label: "وسط",
},
align_right: {
tooltip: "محاذاة النص إلى اليمين",
+ label: "يمين",
},
align_justify: {
tooltip: "ضبط النص",
+ label: "ضبط",
},
table_cell_merge: {
tooltip: "جمع الخلايا",
diff --git a/packages/core/src/i18n/locales/de.ts b/packages/core/src/i18n/locales/de.ts
index 40944212b3..9d064ed9dd 100644
--- a/packages/core/src/i18n/locales/de.ts
+++ b/packages/core/src/i18n/locales/de.ts
@@ -344,15 +344,19 @@ export const de: Dictionary = {
},
align_left: {
tooltip: "Text linksbündig",
+ label: "Links",
},
align_center: {
tooltip: "Text zentrieren",
+ label: "Zentriert",
},
align_right: {
tooltip: "Text rechtsbündig",
+ label: "Rechts",
},
align_justify: {
tooltip: "Text Blocksatz",
+ label: "Blocksatz",
},
table_cell_merge: {
tooltip: "Zellen zusammenführen",
diff --git a/packages/core/src/i18n/locales/en.ts b/packages/core/src/i18n/locales/en.ts
index 784d130094..0927e75f04 100644
--- a/packages/core/src/i18n/locales/en.ts
+++ b/packages/core/src/i18n/locales/en.ts
@@ -325,15 +325,19 @@ export const en = {
},
align_left: {
tooltip: "Align text left",
+ label: "Left"
},
align_center: {
tooltip: "Align text center",
+ label: "Center"
},
align_right: {
tooltip: "Align text right",
+ label: "Right"
},
align_justify: {
tooltip: "Justify text",
+ label: "Justify"
},
table_cell_merge: {
tooltip: "Merge cells",
diff --git a/packages/core/src/i18n/locales/es.ts b/packages/core/src/i18n/locales/es.ts
index 4757d9784f..dc4a568de9 100644
--- a/packages/core/src/i18n/locales/es.ts
+++ b/packages/core/src/i18n/locales/es.ts
@@ -323,15 +323,19 @@ export const es: Dictionary = {
},
align_left: {
tooltip: "Alinear texto a la izquierda",
+ label: "Izquierda",
},
align_center: {
tooltip: "Alinear texto al centro",
+ label: "Centro",
},
align_right: {
tooltip: "Alinear texto a la derecha",
+ label: "Derecha",
},
align_justify: {
tooltip: "Justificar texto",
+ label: "Justificar",
},
table_cell_merge: {
tooltip: "Combinar celdas",
diff --git a/packages/core/src/i18n/locales/fa.ts b/packages/core/src/i18n/locales/fa.ts
index dff80beb81..486fcf282e 100644
--- a/packages/core/src/i18n/locales/fa.ts
+++ b/packages/core/src/i18n/locales/fa.ts
@@ -293,15 +293,19 @@ export const fa = {
},
align_left: {
tooltip: "تراز متن چپ",
+ label: "چپ",
},
align_center: {
tooltip: "تراز متن وسط",
+ label: "وسط",
},
align_right: {
tooltip: "تراز متن راست",
+ label: "راست",
},
align_justify: {
tooltip: "تراز متن دوطرفه",
+ label: "دوطرفه",
},
table_cell_merge: {
tooltip: "ادغام سلولها",
diff --git a/packages/core/src/i18n/locales/fr.ts b/packages/core/src/i18n/locales/fr.ts
index b05d346409..be9c51d75e 100644
--- a/packages/core/src/i18n/locales/fr.ts
+++ b/packages/core/src/i18n/locales/fr.ts
@@ -371,15 +371,19 @@ export const fr: Dictionary = {
},
align_left: {
tooltip: "Aligner le texte à gauche",
+ label: "Gauche",
},
align_center: {
tooltip: "Aligner le texte au centre",
+ label: "Centre",
},
align_right: {
tooltip: "Aligner le texte à droite",
+ label: "Droite",
},
align_justify: {
tooltip: "Justifier le texte",
+ label: "Justifier",
},
table_cell_merge: {
tooltip: "Fusionner les cellules",
diff --git a/packages/core/src/i18n/locales/he.ts b/packages/core/src/i18n/locales/he.ts
index 59cdc56414..5240454b8d 100644
--- a/packages/core/src/i18n/locales/he.ts
+++ b/packages/core/src/i18n/locales/he.ts
@@ -325,15 +325,19 @@ export const he: Dictionary = {
},
align_left: {
tooltip: "ישר טקסט לשמאל",
+ label: "שמאל",
},
align_center: {
tooltip: "מרכז טקסט",
+ label: "מרכז",
},
align_right: {
tooltip: "ישר טקסט לימין",
+ label: "ימין",
},
align_justify: {
tooltip: "ישר טקסט לשני הצדדים",
+ label: "יישור",
},
table_cell_merge: {
tooltip: "מיזוג תאים",
diff --git a/packages/core/src/i18n/locales/hr.ts b/packages/core/src/i18n/locales/hr.ts
index c2081599cc..79e8a57578 100644
--- a/packages/core/src/i18n/locales/hr.ts
+++ b/packages/core/src/i18n/locales/hr.ts
@@ -338,15 +338,19 @@ export const hr: Dictionary = {
},
align_left: {
tooltip: "Poravnaj tekst lijevo",
+ label: "Lijevo",
},
align_center: {
tooltip: "Poravnaj tekst po sredini",
+ label: "Sredina",
},
align_right: {
tooltip: "Poravnaj tekst desno",
+ label: "Desno",
},
align_justify: {
tooltip: "Poravnaj tekst obostrano",
+ label: "Obostrano",
},
table_cell_merge: {
tooltip: "Spoji ćelije",
diff --git a/packages/core/src/i18n/locales/is.ts b/packages/core/src/i18n/locales/is.ts
index fcde471e56..5da8541257 100644
--- a/packages/core/src/i18n/locales/is.ts
+++ b/packages/core/src/i18n/locales/is.ts
@@ -338,15 +338,19 @@ export const is: Dictionary = {
},
align_left: {
tooltip: "Vinstrijafna texta",
+ label: "Vinstri",
},
align_center: {
tooltip: "Miðjustilla texta",
+ label: "Miðja",
},
align_right: {
tooltip: "Hægrijafna texta",
+ label: "Hægri",
},
align_justify: {
tooltip: "Jafna texta",
+ label: "Jafna",
},
table_cell_merge: {
tooltip: "Sameina dálka",
diff --git a/packages/core/src/i18n/locales/it.ts b/packages/core/src/i18n/locales/it.ts
index 4053581107..30c7c5d989 100644
--- a/packages/core/src/i18n/locales/it.ts
+++ b/packages/core/src/i18n/locales/it.ts
@@ -347,15 +347,19 @@ export const it: Dictionary = {
},
align_left: {
tooltip: "Allinea testo a sinistra",
+ label: "Sinistra",
},
align_center: {
tooltip: "Allinea testo al centro",
+ label: "Centro",
},
align_right: {
tooltip: "Allinea testo a destra",
+ label: "Destra",
},
align_justify: {
tooltip: "Giustifica testo",
+ label: "Giustifica",
},
table_cell_merge: {
tooltip: "Unisci celle",
diff --git a/packages/core/src/i18n/locales/ja.ts b/packages/core/src/i18n/locales/ja.ts
index ce5ba87a77..8944f6d3b8 100644
--- a/packages/core/src/i18n/locales/ja.ts
+++ b/packages/core/src/i18n/locales/ja.ts
@@ -365,15 +365,19 @@ export const ja: Dictionary = {
},
align_left: {
tooltip: "左揃え",
+ label: "左",
},
align_center: {
tooltip: "中央揃え",
+ label: "中央",
},
align_right: {
tooltip: "右揃え",
+ label: "右",
},
align_justify: {
tooltip: "両端揃え",
+ label: "両端",
},
table_cell_merge: {
tooltip: "セルを結合",
diff --git a/packages/core/src/i18n/locales/ko.ts b/packages/core/src/i18n/locales/ko.ts
index 53a5def39e..e492432cfb 100644
--- a/packages/core/src/i18n/locales/ko.ts
+++ b/packages/core/src/i18n/locales/ko.ts
@@ -338,15 +338,19 @@ export const ko: Dictionary = {
},
align_left: {
tooltip: "텍스트 왼쪽 맞춤",
+ label: "왼쪽",
},
align_center: {
tooltip: "텍스트 가운데 맞춤",
+ label: "가운데",
},
align_right: {
tooltip: "텍스트 오른쪽 맞춤",
+ label: "오른쪽",
},
align_justify: {
tooltip: "텍스트 양쪽 맞춤",
+ label: "양쪽",
},
table_cell_merge: {
tooltip: "셀 병합",
diff --git a/packages/core/src/i18n/locales/nl.ts b/packages/core/src/i18n/locales/nl.ts
index a1bff3fc6b..3e39640c33 100644
--- a/packages/core/src/i18n/locales/nl.ts
+++ b/packages/core/src/i18n/locales/nl.ts
@@ -325,15 +325,19 @@ export const nl: Dictionary = {
},
align_left: {
tooltip: "Tekst links uitlijnen",
+ label: "Links",
},
align_center: {
tooltip: "Tekst centreren",
+ label: "Midden",
},
align_right: {
tooltip: "Tekst rechts uitlijnen",
+ label: "Rechts",
},
align_justify: {
tooltip: "Tekst uitvullen",
+ label: "Uitvullen",
},
table_cell_merge: {
tooltip: "Voeg cellen samen",
diff --git a/packages/core/src/i18n/locales/no.ts b/packages/core/src/i18n/locales/no.ts
index 5d518d116b..b3a3cb33e6 100644
--- a/packages/core/src/i18n/locales/no.ts
+++ b/packages/core/src/i18n/locales/no.ts
@@ -342,15 +342,19 @@ export const no: Dictionary = {
},
align_left: {
tooltip: "Venstrejuster tekst",
+ label: "Venstre",
},
align_center: {
tooltip: "Midtstill tekst",
+ label: "Midtstilt",
},
align_right: {
tooltip: "Høyrejuster tekst",
+ label: "Høyre",
},
align_justify: {
tooltip: "Juster tekst",
+ label: "Justert",
},
comment: {
tooltip: "Legg til kommentar",
diff --git a/packages/core/src/i18n/locales/pl.ts b/packages/core/src/i18n/locales/pl.ts
index 614f64e9f2..efee25e29c 100644
--- a/packages/core/src/i18n/locales/pl.ts
+++ b/packages/core/src/i18n/locales/pl.ts
@@ -316,15 +316,19 @@ export const pl: Dictionary = {
},
align_left: {
tooltip: "Wyrównaj tekst do lewej",
+ label: "Lewo",
},
align_center: {
tooltip: "Wyśrodkuj tekst",
+ label: "Środek",
},
align_right: {
tooltip: "Wyrównaj tekst do prawej",
+ label: "Prawo",
},
align_justify: {
tooltip: "Wyjustuj tekst",
+ label: "Wyjustuj",
},
table_cell_merge: {
tooltip: "Połącz komórki",
diff --git a/packages/core/src/i18n/locales/pt.ts b/packages/core/src/i18n/locales/pt.ts
index c12c94012e..45df8081df 100644
--- a/packages/core/src/i18n/locales/pt.ts
+++ b/packages/core/src/i18n/locales/pt.ts
@@ -317,15 +317,19 @@ export const pt: Dictionary = {
},
align_left: {
tooltip: "Alinhar à esquerda",
+ label: "Esquerda"
},
align_center: {
tooltip: "Alinhar ao centro",
+ label: "Centro"
},
align_right: {
tooltip: "Alinhar à direita",
+ label: "Direita"
},
align_justify: {
tooltip: "Justificar texto",
+ label: "Justificar"
},
table_cell_merge: {
tooltip: "Juntar células",
diff --git a/packages/core/src/i18n/locales/ru.ts b/packages/core/src/i18n/locales/ru.ts
index 2982c8f5f6..9a3029f293 100644
--- a/packages/core/src/i18n/locales/ru.ts
+++ b/packages/core/src/i18n/locales/ru.ts
@@ -368,15 +368,19 @@ export const ru: Dictionary = {
},
align_left: {
tooltip: "Текст по левому краю",
+ label: "Влево",
},
align_center: {
tooltip: "Текст по середине",
+ label: "По центру",
},
align_right: {
tooltip: "Текст по правому краю",
+ label: "Вправо",
},
align_justify: {
tooltip: "По середине текст",
+ label: "По ширине",
},
table_cell_merge: {
tooltip: "Объединить ячейки",
diff --git a/packages/core/src/i18n/locales/sk.ts b/packages/core/src/i18n/locales/sk.ts
index c1691e17e7..015b21ab7b 100644
--- a/packages/core/src/i18n/locales/sk.ts
+++ b/packages/core/src/i18n/locales/sk.ts
@@ -323,15 +323,19 @@ export const sk = {
},
align_left: {
tooltip: "Zarovnať text vľavo",
+ label: "Vľavo",
},
align_center: {
tooltip: "Zarovnať text na stred",
+ label: "Stred",
},
align_right: {
tooltip: "Zarovnať text vpravo",
+ label: "Vpravo",
},
align_justify: {
tooltip: "Zarovnať text do bloku",
+ label: "Do bloku",
},
table_cell_merge: {
tooltip: "Zlúčiť bunky",
diff --git a/packages/core/src/i18n/locales/uk.ts b/packages/core/src/i18n/locales/uk.ts
index a5d7d8f9af..dce8c7af73 100644
--- a/packages/core/src/i18n/locales/uk.ts
+++ b/packages/core/src/i18n/locales/uk.ts
@@ -349,15 +349,19 @@ export const uk: Dictionary = {
},
align_left: {
tooltip: "Вирівняти за лівим краєм",
+ label: "Ліво",
},
align_center: {
tooltip: "Вирівняти по центру",
+ label: "По центру",
},
align_right: {
tooltip: "Вирівняти за правим краєм",
+ label: "Право",
},
align_justify: {
tooltip: "Вирівняти за шириною",
+ label: "По ширині",
},
table_cell_merge: {
tooltip: "Об'єднати клітинки",
diff --git a/packages/core/src/i18n/locales/uz.ts b/packages/core/src/i18n/locales/uz.ts
index ffc8d04ac6..a8f464ee8c 100644
--- a/packages/core/src/i18n/locales/uz.ts
+++ b/packages/core/src/i18n/locales/uz.ts
@@ -370,10 +370,10 @@ export const uz: Dictionary = {
nest: { tooltip: "O‘ngga surish", secondary_tooltip: "Tab" },
unnest: { tooltip: "Chapga surish", secondary_tooltip: "Shift+Tab" },
- align_left: { tooltip: "Chapga tekislash" },
- align_center: { tooltip: "Markazga tekislash" },
- align_right: { tooltip: "O‘ngga tekislash" },
- align_justify: { tooltip: "Eniga tekislash" },
+ align_left: { tooltip: "Chapga tekislash", label: "Chap" },
+ align_center: { tooltip: "Markazga tekislash", label: "Markaz" },
+ align_right: { tooltip: "O’ngga tekislash", label: "O’ng" },
+ align_justify: { tooltip: "Eniga tekislash", label: "Eni bo’yicha" },
table_cell_merge: { tooltip: "Kataklarni birlashtirish" },
comment: { tooltip: "Izoh qo‘shish" },
diff --git a/packages/core/src/i18n/locales/vi.ts b/packages/core/src/i18n/locales/vi.ts
index cbe0e5e628..5c3a731923 100644
--- a/packages/core/src/i18n/locales/vi.ts
+++ b/packages/core/src/i18n/locales/vi.ts
@@ -324,15 +324,19 @@ export const vi: Dictionary = {
},
align_left: {
tooltip: "Căn trái văn bản",
+ label: "Trái",
},
align_center: {
tooltip: "Căn giữa văn bản",
+ label: "Giữa",
},
align_right: {
tooltip: "Căn phải văn bản",
+ label: "Phải",
},
align_justify: {
tooltip: "Căn đều văn bản",
+ label: "Đều",
},
table_cell_merge: {
tooltip: "Gộp các ô",
diff --git a/packages/core/src/i18n/locales/zh-tw.ts b/packages/core/src/i18n/locales/zh-tw.ts
index b64912255f..4257ab5e31 100644
--- a/packages/core/src/i18n/locales/zh-tw.ts
+++ b/packages/core/src/i18n/locales/zh-tw.ts
@@ -366,15 +366,19 @@ export const zhTW: Dictionary = {
},
align_left: {
tooltip: "靠左對齊",
+ label: "靠左",
},
align_center: {
tooltip: "置中",
+ label: "置中",
},
align_right: {
tooltip: "靠右對齊",
+ label: "靠右",
},
align_justify: {
tooltip: "兩端對齊",
+ label: "兩端",
},
table_cell_merge: {
tooltip: "合併儲存格",
diff --git a/packages/core/src/i18n/locales/zh.ts b/packages/core/src/i18n/locales/zh.ts
index ba5a2fe73b..3396171476 100644
--- a/packages/core/src/i18n/locales/zh.ts
+++ b/packages/core/src/i18n/locales/zh.ts
@@ -366,15 +366,19 @@ export const zh: Dictionary = {
},
align_left: {
tooltip: "左对齐",
+ label: "左对齐",
},
align_center: {
tooltip: "居中",
+ label: "居中",
},
align_right: {
tooltip: "右对齐",
+ label: "右对齐",
},
align_justify: {
tooltip: "文本对齐",
+ label: "两端对齐",
},
table_cell_merge: {
tooltip: "合并单元格",
diff --git a/packages/react/src/components/FormattingToolbar/DefaultSelects/TextAlignSelect.tsx b/packages/react/src/components/FormattingToolbar/DefaultSelects/TextAlignSelect.tsx
new file mode 100644
index 0000000000..1d11e95eca
--- /dev/null
+++ b/packages/react/src/components/FormattingToolbar/DefaultSelects/TextAlignSelect.tsx
@@ -0,0 +1,192 @@
+import {
+ blockHasType,
+ BlockSchema,
+ defaultProps,
+ DefaultProps,
+ editorHasBlockWithType,
+ InlineContentSchema,
+ mapTableCell,
+ StyleSchema,
+ TableContent,
+} from "@blocknote/core";
+import { TableHandlesExtension } from "@blocknote/core/extensions";
+import { useCallback, useMemo } from "react";
+import { IconType } from "react-icons";
+import {
+ RiAlignCenter,
+ RiAlignJustify,
+ RiAlignLeft,
+ RiAlignRight,
+} from "react-icons/ri";
+
+import {
+ ComponentProps,
+ useComponentsContext,
+} from "../../../editor/ComponentsContext.js";
+import { useBlockNoteEditor } from "../../../hooks/useBlockNoteEditor.js";
+import { useEditorState } from "../../../hooks/useEditorState.js";
+import { useDictionary } from "../../../i18n/dictionary.js";
+
+type TextAlignment = DefaultProps["textAlignment"];
+
+const icons: Record = {
+ left: RiAlignLeft,
+ center: RiAlignCenter,
+ right: RiAlignRight,
+ justify: RiAlignJustify,
+};
+
+const alignments: TextAlignment[] = ["left", "center", "right", "justify"];
+
+export const TextAlignSelect = () => {
+ const Components = useComponentsContext()!;
+ const dict = useDictionary();
+
+ const editor = useBlockNoteEditor<
+ BlockSchema,
+ InlineContentSchema,
+ StyleSchema
+ >();
+
+ const state = useEditorState({
+ editor,
+ selector: ({ editor }) => {
+ if (!editor.isEditable) {
+ return undefined;
+ }
+
+ const selectedBlocks = editor.getSelection()?.blocks || [
+ editor.getTextCursorPosition().block,
+ ];
+
+ const firstBlock = selectedBlocks[0];
+
+ if (
+ blockHasType(firstBlock, editor, firstBlock.type, {
+ textAlignment: defaultProps.textAlignment,
+ })
+ ) {
+ return {
+ textAlignment: firstBlock.props.textAlignment,
+ blocks: selectedBlocks,
+ };
+ }
+
+ if (
+ selectedBlocks.length === 1 &&
+ blockHasType(firstBlock, editor, "table")
+ ) {
+ const cellSelection = editor
+ .getExtension(TableHandlesExtension)
+ ?.getCellSelection();
+
+ if (!cellSelection || cellSelection.cells.length === 0) {
+ return undefined;
+ }
+
+ const { row, col } = cellSelection.cells[0];
+ const tableContent = firstBlock.content as TableContent;
+ const selectedCell = tableContent.rows[row]?.cells[col];
+
+ if (!selectedCell) {
+ return undefined;
+ }
+
+ return {
+ textAlignment: mapTableCell(selectedCell).props.textAlignment,
+ blocks: [firstBlock],
+ };
+ }
+
+ return undefined;
+ },
+ });
+
+ const setTextAlignment = useCallback(
+ (textAlignment: TextAlignment) => {
+ if (state === undefined) {
+ return;
+ }
+
+ editor.focus();
+
+ for (const block of state.blocks) {
+ if (
+ blockHasType(block, editor, block.type, {
+ textAlignment: defaultProps.textAlignment,
+ }) &&
+ editorHasBlockWithType(editor, block.type, {
+ textAlignment: defaultProps.textAlignment,
+ })
+ ) {
+ editor.updateBlock(block, {
+ props: { textAlignment },
+ });
+ } else if (block.type === "table") {
+ const cellSelection = editor
+ .getExtension(TableHandlesExtension)
+ ?.getCellSelection();
+ if (!cellSelection) {
+ continue;
+ }
+
+ const newTable = (block.content as TableContent).rows.map(
+ (row) => ({
+ ...row,
+ cells: row.cells.map((cell) => mapTableCell(cell)),
+ }),
+ );
+
+ cellSelection.cells.forEach(({ row, col }) => {
+ if (!newTable[row]?.cells[col]) { return; }
+ newTable[row].cells[col] = {
+ ...newTable[row].cells[col],
+ props: {
+ ...newTable[row].cells[col].props,
+ textAlignment,
+ },
+ };
+ });
+
+ editor.updateBlock(block, {
+ type: "table",
+ content: {
+ ...(block.content as TableContent),
+ type: "tableContent",
+ rows: newTable,
+ } as any,
+ });
+
+ editor.setTextCursorPosition(block);
+ }
+ }
+ },
+ [editor, state],
+ );
+
+ const selectItems: ComponentProps["FormattingToolbar"]["Select"]["items"] =
+ useMemo(
+ () =>
+ alignments.map((alignment) => {
+ const Icon = icons[alignment];
+ return {
+ text: dict.formatting_toolbar[`align_${alignment}`].label,
+ icon: ,
+ isSelected: state?.textAlignment === alignment,
+ onClick: () => setTextAlignment(alignment),
+ };
+ }),
+ [dict, setTextAlignment, state?.textAlignment],
+ );
+
+ if (state === undefined) {
+ return null;
+ }
+
+ return (
+
+ );
+};
diff --git a/packages/react/src/index.ts b/packages/react/src/index.ts
index 6ed745a789..836e8a43b1 100644
--- a/packages/react/src/index.ts
+++ b/packages/react/src/index.ts
@@ -34,6 +34,7 @@ export * from "./components/FormattingToolbar/DefaultButtons/NestBlockButtons.js
export * from "./components/FormattingToolbar/DefaultButtons/TableCellMergeButton.js";
export * from "./components/FormattingToolbar/DefaultButtons/TextAlignButton.js";
export * from "./components/FormattingToolbar/DefaultSelects/BlockTypeSelect.js";
+export * from "./components/FormattingToolbar/DefaultSelects/TextAlignSelect.js";
export * from "./components/FormattingToolbar/FormattingToolbar.js";
export * from "./components/FormattingToolbar/FormattingToolbarController.js";
export * from "./components/FormattingToolbar/ExperimentalMobileFormattingToolbarController.js";
diff --git a/tests/src/unit/react/TextAlignSelect.test.tsx b/tests/src/unit/react/TextAlignSelect.test.tsx
new file mode 100644
index 0000000000..acdfa5b77e
--- /dev/null
+++ b/tests/src/unit/react/TextAlignSelect.test.tsx
@@ -0,0 +1,88 @@
+import { BlockNoteEditor } from "@blocknote/core";
+import { BlockNoteView } from "@blocknote/mantine";
+import "@blocknote/mantine/style.css";
+import { TextAlignSelect } from "@blocknote/react";
+import { flushSync } from "react-dom";
+import { createRoot } from "react-dom/client";
+import { afterEach, beforeEach, describe, expect, it } from "vitest";
+
+describe("TextAlignSelect", () => {
+ let container: HTMLDivElement;
+
+ beforeEach(() => {
+ container = document.createElement("div");
+ document.body.appendChild(container);
+ });
+
+ afterEach(() => {
+ document.body.removeChild(container);
+ });
+
+ it("renders null when editor is not editable", () => {
+ const editor = BlockNoteEditor.create();
+ editor.isEditable = false;
+ const root = createRoot(container);
+
+ flushSync(() => {
+ root.render(
+
+
+ ,
+ );
+ });
+
+ expect(container.querySelector("button")).toBeNull();
+
+ root.unmount();
+ editor._tiptapEditor.destroy();
+ });
+
+ it("renders select button for an alignable block", () => {
+ const editor = BlockNoteEditor.create();
+ const root = createRoot(container);
+
+ flushSync(() => {
+ root.render(
+
+
+ ,
+ );
+ });
+
+ expect(container.querySelector("button")).not.toBeNull();
+
+ root.unmount();
+ editor._tiptapEditor.destroy();
+ });
+
+ it("reactively updates button label when block alignment changes", () => {
+ const editor = BlockNoteEditor.create();
+ const root = createRoot(container);
+
+ flushSync(() => {
+ root.render(
+
+
+ ,
+ );
+ });
+
+ expect(container.querySelector("button")?.textContent).toContain("Left");
+
+ const block = editor.document[0];
+ flushSync(() => {
+ editor.updateBlock(block, { props: { textAlignment: "center" } });
+ });
+
+ expect(container.querySelector("button")?.textContent).toContain("Center");
+
+ flushSync(() => {
+ editor.updateBlock(block, { props: { textAlignment: "right" } });
+ });
+
+ expect(container.querySelector("button")?.textContent).toContain("Right");
+
+ root.unmount();
+ editor._tiptapEditor.destroy();
+ });
+});