Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ const forceToggleBlocksShow = (element: HTMLElement) => {
);
hiddenToggleWrappers.forEach((toggleWrapper) => {
toggleWrapper.setAttribute("data-show-children", "true");
toggleWrapper
.querySelector(":scope > .bn-toggle-button")
?.setAttribute("aria-expanded", "true");
});

return element;
Expand Down
49 changes: 49 additions & 0 deletions packages/core/src/blocks/ToggleWrapper/createToggleWrapper.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { afterEach, describe, expect, it } from "vite-plus/test";
import { BlockNoteEditor } from "../../editor/BlockNoteEditor.js";

/**
* @vitest-environment jsdom
*/

describe("Toggle button accessibility", () => {
let editor: BlockNoteEditor;

afterEach(() => {
editor._tiptapEditor.destroy();
window.localStorage.clear();
});

it("has an accessible name and exposes its expanded state", async () => {
editor = BlockNoteEditor.create({
initialContent: [
{
id: "toggle",
type: "toggleListItem",
content: "Toggle",
children: [{ type: "paragraph", content: "Child" }],
},
],
});
const div = document.createElement("div");
editor.mount(div);

const button = div.querySelector<HTMLButtonElement>(".bn-toggle-button")!;
expect(button.getAttribute("aria-label")).toBe(
editor.dictionary.toggle_blocks.toggle_button_label,
);
expect(button.querySelector("svg")!.getAttribute("aria-hidden")).toBe(
"true",
);
expect(button.getAttribute("aria-expanded")).toBe("false");

button.click();
expect(button.getAttribute("aria-expanded")).toBe("true");

// Updating `aria-expanded` must not make ProseMirror re-render the block.
await new Promise((resolve) => setTimeout(resolve));
expect(div.querySelector(".bn-toggle-button")).toBe(button);

button.click();
expect(button.getAttribute("aria-expanded")).toBe("false");
});
});
30 changes: 23 additions & 7 deletions packages/core/src/blocks/ToggleWrapper/createToggleWrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,22 @@ export const createToggleWrapper = (
const toggleButton = document.createElement("button");
toggleButton.className = "bn-toggle-button";
toggleButton.type = "button";
toggleButton.setAttribute(
"aria-label",
editor.dictionary.toggle_blocks.toggle_button_label,
);
toggleButton.innerHTML =
// https://fonts.google.com/icons?selected=Material+Symbols+Rounded:chevron_right:FILL@0;wght@700;GRAD@0;opsz@24&icon.query=chevron&icon.style=Rounded&icon.size=24&icon.color=%23e8eaed
'<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="CURRENTCOLOR"><path d="M320-200v-560l440 280-440 280Z"/></svg>';
'<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="CURRENTCOLOR" aria-hidden="true"><path d="M320-200v-560l440 280-440 280Z"/></svg>';
// Keeps the button's expanded state, which screen readers announce, in sync
// with whether the child blocks are shown.
function setShowChildren(showChildren: boolean) {
toggleWrapper.setAttribute(
"data-show-children",
showChildren ? "true" : "false",
);
toggleButton.setAttribute("aria-expanded", showChildren ? "true" : "false");
}
const toggleButtonMouseDown = (event: MouseEvent) => event.preventDefault();
toggleButton.addEventListener("mousedown", toggleButtonMouseDown);
const toggleButtonOnClick = () => {
Expand All @@ -56,14 +69,14 @@ export const createToggleWrapper = (
}

if (toggleWrapper.getAttribute("data-show-children") === "true") {
toggleWrapper.setAttribute("data-show-children", "false");
setShowChildren(false);
toggledState.set(currentBlock, false);

if (dom.contains(toggleAddBlockButton)) {
dom.removeChild(toggleAddBlockButton);
}
} else {
toggleWrapper.setAttribute("data-show-children", "true");
setShowChildren(true);
toggledState.set(currentBlock, true);

if (
Expand Down Expand Up @@ -115,7 +128,7 @@ export const createToggleWrapper = (
if (newChildCount > childCount) {
// If a child block is added while children are hidden, show children.
if (toggleWrapper.getAttribute("data-show-children") === "false") {
toggleWrapper.setAttribute("data-show-children", "true");
setShowChildren(true);
const currentBlock = editor.getBlock(block);
if (currentBlock) {
toggledState.set(currentBlock, true);
Expand All @@ -131,7 +144,7 @@ export const createToggleWrapper = (
// If the last child block is removed while children are shown, hide
// children.
if (toggleWrapper.getAttribute("data-show-children") === "true") {
toggleWrapper.setAttribute("data-show-children", "false");
setShowChildren(false);
const currentBlock = editor.getBlock(block);
if (currentBlock) {
toggledState.set(currentBlock, false);
Expand All @@ -149,15 +162,15 @@ export const createToggleWrapper = (
});

if (toggledState.get(block)) {
toggleWrapper.setAttribute("data-show-children", "true");
setShowChildren(true);

if (editor.isEditable && block.children.length === 0) {
// If the toggle is set to show children, but there are no children,
// we add the "add block" button.
dom.appendChild(toggleAddBlockButton);
}
} else {
toggleWrapper.setAttribute("data-show-children", "false");
setShowChildren(false);
}

return {
Expand All @@ -172,6 +185,9 @@ export const createToggleWrapper = (
((mutation.type === "attributes" &&
mutation.target === toggleWrapper &&
mutation.attributeName === "data-show-children") ||
(mutation.type === "attributes" &&
mutation.target === toggleButton &&
mutation.attributeName === "aria-expanded") ||
(mutation.type === "childList" &&
(mutation.addedNodes[0] === toggleAddBlockButton ||
mutation.removedNodes[0] === toggleAddBlockButton)))
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/i18n/locales/ar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ export const ar: Dictionary = {
},
toggle_blocks: {
add_block_button: "تبديل فارغ. انقر لإضافة كتلة.",
toggle_button_label: "توسيع أو طي",
},
code_block: {
add_source_button_text: "إضافة كود المصدر",
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/i18n/locales/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ export const de: Dictionary = {
toggle_blocks: {
add_block_button:
"Leerer aufklappbarer Bereich. Klicken, um einen Block hinzuzufügen.",
toggle_button_label: "Ein- oder ausklappen",
},
code_block: {
add_source_button_text: "Quellcode hinzufügen",
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/i18n/locales/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ export const en = {
},
toggle_blocks: {
add_block_button: "Empty toggle. Click to add a block.",
toggle_button_label: "Expand or collapse",
},
code_block: {
add_source_button_text: "Add source code",
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/i18n/locales/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ export const es: Dictionary = {
},
toggle_blocks: {
add_block_button: "Toggle vacío. Haz clic para añadir un bloque.",
toggle_button_label: "Expandir o contraer",
},
code_block: {
add_source_button_text: "Agregar código fuente",
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/i18n/locales/fa.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ export const fa = {
},
toggle_blocks: {
add_block_button: "تاشوی خالی. برای افزودن بلوک کلیک کنید.",
toggle_button_label: "باز یا بسته کردن",
},
code_block: {
add_source_button_text: "افزودن کد منبع",
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/i18n/locales/fr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ export const fr: Dictionary = {
},
toggle_blocks: {
add_block_button: "Liste repliable vide. Cliquez pour ajouter un bloc.",
toggle_button_label: "Déplier ou replier",
},
code_block: {
add_source_button_text: "Ajouter le code source",
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/i18n/locales/he.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ export const he: Dictionary = {
},
toggle_blocks: {
add_block_button: "מתג ריק. לחץ כדי להוסיף בלוק.",
toggle_button_label: "הרחב או כווץ",
},
code_block: {
add_source_button_text: "הוסף קוד מקור",
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/i18n/locales/hr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ export const hr: Dictionary = {
},
toggle_blocks: {
add_block_button: "Prazan sklopivi blok. Klikni da dodaš sadržaj.",
toggle_button_label: "Proširi ili sažmi",
},
code_block: {
add_source_button_text: "Dodaj izvorni kôd",
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/i18n/locales/is.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ export const is: Dictionary = {
},
toggle_blocks: {
add_block_button: "Tóm fellilína. Smelltu til að bæta við blokk.",
toggle_button_label: "Fella út eða saman",
},
code_block: {
add_source_button_text: "Bæta við frumkóða",
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/i18n/locales/it.ts
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ export const it: Dictionary = {
},
toggle_blocks: {
add_block_button: "Toggle vuoto. Clicca per aggiungere un blocco.",
toggle_button_label: "Espandi o comprimi",
},
code_block: {
add_source_button_text: "Aggiungi codice sorgente",
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/i18n/locales/ja.ts
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ export const ja: Dictionary = {
},
toggle_blocks: {
add_block_button: "空のトグルです。クリックしてブロックを追加。",
toggle_button_label: "展開または折りたたみ",
},
code_block: {
add_source_button_text: "ソースコードを追加",
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/i18n/locales/ko.ts
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ export const ko: Dictionary = {
},
toggle_blocks: {
add_block_button: "비어 있는 토글입니다. 클릭하여 블록을 추가하세요.",
toggle_button_label: "펼치기 또는 접기",
},
code_block: {
add_source_button_text: "소스 코드 추가",
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/i18n/locales/nl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ export const nl: Dictionary = {
},
toggle_blocks: {
add_block_button: "Lege uitklapper. Klik om een blok toe te voegen.",
toggle_button_label: "Uitklappen of inklappen",
},
code_block: {
add_source_button_text: "Broncode toevoegen",
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/i18n/locales/no.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ export const no: Dictionary = {
},
toggle_blocks: {
add_block_button: "Tomt toggle. Klikk for å legge til en blokk.",
toggle_button_label: "Utvid eller skjul",
},
code_block: {
add_source_button_text: "Legg til kildekode",
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/i18n/locales/pl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ export const pl: Dictionary = {
toggle_blocks: {
add_block_button:
"Brak bloków do rozwinięcia. Kliknij, aby dodać pierwszego.",
toggle_button_label: "Rozwiń lub zwiń",
},
code_block: {
add_source_button_text: "Dodaj kod źródłowy",
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/i18n/locales/pt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ export const pt: Dictionary = {
},
toggle_blocks: {
add_block_button: "Toggle vazio. Clique para adicionar um bloco.",
toggle_button_label: "Expandir ou recolher",
},
code_block: {
add_source_button_text: "Adicionar código-fonte",
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/i18n/locales/ru.ts
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ export const ru: Dictionary = {
},
toggle_blocks: {
add_block_button: "Пустой переключатель. Нажмите, чтобы добавить блок.",
toggle_button_label: "Развернуть или свернуть",
},
code_block: {
add_source_button_text: "Добавить исходный код",
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/i18n/locales/sk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ export const sk = {
},
toggle_blocks: {
add_block_button: "Prázdne prepínanie. Kliknite pre pridanie bloku.",
toggle_button_label: "Rozbaliť alebo zbaliť",
},
code_block: {
add_source_button_text: "Pridať zdrojový kód",
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/i18n/locales/uk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ export const uk: Dictionary = {
},
toggle_blocks: {
add_block_button: "Порожній перемикач. Натисніть, щоб додати блок.",
toggle_button_label: "Розгорнути або згорнути",
},
code_block: {
add_source_button_text: "Додати вихідний код",
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/i18n/locales/uz.ts
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,7 @@ export const uz: Dictionary = {

toggle_blocks: {
add_block_button: "Bo‘sh toggle. Blok qo‘shish uchun bosing.",
toggle_button_label: "Yoyish yoki yig‘ish",
},

code_block: {
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/i18n/locales/vi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ export const vi: Dictionary = {
},
toggle_blocks: {
add_block_button: "Toggle trống. Nhấp để thêm khối.",
toggle_button_label: "Mở rộng hoặc thu gọn",
},
code_block: {
add_source_button_text: "Thêm mã nguồn",
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/i18n/locales/zh-tw.ts
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ export const zhTW: Dictionary = {
},
toggle_blocks: {
add_block_button: "空的切換區。點擊新增區塊。",
toggle_button_label: "展開或收合",
},
code_block: {
add_source_button_text: "新增原始碼",
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/i18n/locales/zh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ export const zh: Dictionary = {
},
toggle_blocks: {
add_block_button: "空的切换区。点击添加区块。",
toggle_button_label: "展开或折叠",
},
code_block: {
add_source_button_text: "添加源代码",
Expand Down
3 changes: 3 additions & 0 deletions packages/react/src/blocks/ToggleWrapper/ToggleWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ export const ToggleWrapper = (
<button
className="bn-toggle-button"
type="button"
aria-label={editor.dictionary.toggle_blocks.toggle_button_label}
aria-expanded={showChildren}
onMouseDown={(event) => event.preventDefault()}
onClick={() => handleToggle(block)}
>
Expand All @@ -134,6 +136,7 @@ export const ToggleWrapper = (
viewBox="0 -960 960 960"
width="1em"
fill="currentcolor"
aria-hidden="true"
>
{/* https://fonts.google.com/icons?selected=Material+Symbols+Rounded:chevron_right:FILL@0;wght@700;GRAD@0;opsz@24&icon.query=chevron&icon.style=Rounded&icon.size=24&icon.color=%23e8eaed */}
<path d="M472-480 332-620q-18-18-18-44t18-44q18-18 44-18t44 18l183 183q9 9 14 21t5 24q0 12-5 24t-14 21L420-252q-18 18-44 18t-44-18q-18-18-18-44t18-44l140-140Z" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,19 @@
>
<div>
<div class="bn-toggle-wrapper" data-show-children="true">
<button class="bn-toggle-button" type="button">
<button
class="bn-toggle-button"
type="button"
aria-label="Expand or collapse"
aria-expanded="true"
>
<svg
xmlns="http://www.w3.org/2000/svg"
height="24px"
viewBox="0 -960 960 960"
width="24px"
fill="CURRENTCOLOR"
aria-hidden="true"
>
<path d="M320-200v-560l440 280-440 280Z"></path>
</svg>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,19 @@
<div class="bn-block-content" data-content-type="toggleListItem">
<div>
<div class="bn-toggle-wrapper" data-show-children="true">
<button class="bn-toggle-button" type="button">
<button
class="bn-toggle-button"
type="button"
aria-label="Expand or collapse"
aria-expanded="true"
>
<svg
xmlns="http://www.w3.org/2000/svg"
height="24px"
viewBox="0 -960 960 960"
width="24px"
fill="CURRENTCOLOR"
aria-hidden="true"
>
<path d="M320-200v-560l440 280-440 280Z"></path>
</svg>
Expand Down
Loading
Loading