С ссылками (якорями) похожая история, кстати.
Ссылка по умолчанию имеет tabindex 0, но при этом, если отсутствует `href`, то она не табается, не смотря на то, что tabindex все еще 0. Но если явно его переопределить, то все начинает работать правильно.
<a id="link" href="">Табается</a>
<script>
console.log(link.tabIndex); // 0
</script>
<a id="link">Не табается</a>
<script>
console.log(link.tabIndex); // 0
</script>
<a id="link">табается</a>
<script>
console.log(link.tabIndex); // 0
link.tabIndex = link.tabIndex;
</script>
------
Угадайте какой tabIndex будет здесь
<a contenteditable="true">123</a>
------
Финальный костыль:
function getRealTabIndex(element: HTMLElement) {
// Anchors without the "href" attribute have a default tab index of 0, although they behave like -1.
// If this is the case, then treat the tabindex as -1
if (
element instanceof HTMLAnchorElement &&
!element.hasAttribute('href') &&
!element.hasAttribute('tabindex')
) {
return -1;
}
// ContentEditable elements have a default tabindex of -1, although they behave like 0.
// If this is the case, then treat the tabindex as 0
if (element.isContentEditable && element.tabIndex === -1 && !element.hasAttribute('tabindex')) {
return 0;
}
return element.tabIndex;
}