PluginProbe
Gutenberg / 24.1.0
Gutenberg v24.1.0
24.1.0 24.0.0 23.9.1 23.9.0 23.8.0 23.7.2 23.7.1 23.7.0 23.6.1 23.6.2 23.6.0 23.5.3 23.5.2 23.5.1 23.5.0 23.4.0 23.3.2 23.3.1 23.3.0 23.2.0 23.2.1 23.2.2 23.1.1 23.1.0 23.0.1 All 404 releases
← All changes | build/modules/block-library/tabs/view.js +64 -14 23.7.2 → 24.1.0 View file →
@@ -46,11 +46,29 @@
46 46 const { tabIndex } = state;
47 47 return activeTabIndex === tabIndex;
48 48 },
49 49 /**
50 - * The value of the tabindex attribute for tab buttons.
51 - * Only the active tab should be in the tab sequence.
50 + * The value of the hidden attribute for tab panels.
52 51 *
52 + * Inactive panels use the `until-found` state rather than being
53 + * hidden outright, so their content stays reachable by the
54 + * browser's find-in-page and by fragment navigation. The browser
55 + * fires `beforematch` on the panel before revealing it, which is
56 + * where the matching tab gets activated.
57 + *
58 + * @type {string|null}
59 + */
60 + get isHidden() {
61 + return state.isActiveTab ? null : "until-found";
62 + },
63 + /**
64 + * The value of the tabindex attribute for tab buttons and tab
65 + * panels. Only the active tab should be in the tab sequence.
66 + *
67 + * An inactive panel is hidden with `until-found`, which leaves it
68 + * in the layout, so it stays focusable unless it is taken out of
69 + * the tab sequence here.
70 + *
53 71 * @type {number}
54 72 */
55 73 get tabIndexAttribute() {
56 74 return state.isActiveTab ? 0 : -1;
@@ -62,9 +80,9 @@
62 80 *
63 81 * @param {KeyboardEvent} event The keydown event.
64 82 */
65 83 handleTabKeyDown: withSyncEvent((event) => {
66 - const { tabIndex } = state;
84 + const { tabIndex, tabsList } = state;
67 85 if (tabIndex === null) {
68 86 return;
69 87 }
70 88 if (event.key === "ArrowRight") {
@@ -72,8 +90,14 @@
72 90 actions.moveFocus(tabIndex + 1);
73 91 } else if (event.key === "ArrowLeft") {
74 92 event.preventDefault();
75 93 actions.moveFocus(tabIndex - 1);
94 + } else if (event.key === "Home") {
95 + event.preventDefault();
96 + actions.moveFocus(0);
97 + } else if (event.key === "End") {
98 + event.preventDefault();
99 + actions.moveFocus(tabsList.length - 1);
76 100 }
77 101 }),
78 102 /**
79 103 * Handles the click event for the tab label.
@@ -87,8 +111,20 @@
87 111 actions.setActiveTab(tabIndex);
88 112 }
89 113 }),
90 114 /**
115 + * Activates the tab whose panel the browser is about to reveal.
116 + *
117 + * Fired on a panel hidden with `until-found` when find-in-page or
118 + * a fragment navigation matches content inside it.
119 + */
120 + handleBeforeMatch: () => {
121 + const { tabIndex } = state;
122 + if (tabIndex !== null) {
123 + actions.setActiveTab(tabIndex);
124 + }
125 + },
126 + /**
91 127 * Moves focus to a specific tab without activating it.
92 128 *
93 129 * @param {number} tabIndex The index to move focus to.
94 130 */
@@ -139,23 +175,37 @@
139 175 }
140 176 }
141 177 },
142 178 callbacks: {
143 - /**
144 - * When the tabs are initialized, we need to check if there is a hash in the url and if so if it exists in the current tabsList, set the active tab to that index.
145 - *
146 - */
147 - onTabsInit: () => {
179 + activateTabByHash: () => {
148 180 const { tabsList } = state;
149 - if (tabsList.length === 0) {
181 + if (!tabsList || tabsList.length === 0) {
150 182 return;
151 183 }
152 - const { hash } = window.location;
153 - const tabId = hash.replace("#", "");
154 - const tabIndex = tabsList.findIndex((t) => t === tabId);
155 - if (tabIndex >= 0) {
156 - actions.setActiveTab(tabIndex, true);
184 + const targetElement = document.querySelector(":target");
185 + if (!targetElement) {
186 + return;
157 187 }
188 + const panelIndex = tabsList.findIndex(
189 + (t) => t === targetElement.id
190 + );
191 + if (panelIndex >= 0) {
192 + actions.setActiveTab(panelIndex, true);
193 + return;
194 + }
195 + let panel = targetElement.closest(".wp-block-tab-panel");
196 + let tabIndex = -1;
197 + while (panel && tabIndex < 0) {
198 + tabIndex = tabsList.findIndex((t) => t === panel.id);
199 + panel = panel.parentElement?.closest(".wp-block-tab-panel") ?? null;
200 + }
201 + if (tabIndex < 0) {
202 + return;
203 + }
204 + actions.setActiveTab(tabIndex);
205 + window.setTimeout(() => {
206 + targetElement.scrollIntoView();
207 + }, 0);
158 208 }
159 209 }
160 210 },
161 211 {