scroll: Set tabIndex to -1 for simplebar content wrapper.

Fixes #30403.
Having tabIndex set to 0 led to keyboard focus being put on
a scrollbar container, which led to users having to tab twice
to skip a container.
This commit also removes instances of tabIndex being set to
-1 programatically for certain cases, since it is -1 by default now.
This commit also removes `outline: none` for simplebar since
that property is not needed anymore because the wrapper is
not focusable anymore.
This commit is contained in:
Shubham Padia 2024-06-16 11:46:37 +00:00
parent b4eec7e9fa
commit fe11f3be7c
49 changed files with 53 additions and 58 deletions

View File

@ -685,8 +685,6 @@ export function complete_rerender(): void {
// this, we scroll to top before restoring focus via revive_current_focus.
$("html").scrollTop(0);
setTimeout(() => {
// We don't want to focus on simplebar ever.
$("#inbox-list .simplebar-content-wrapper").attr("tabindex", "-1");
revive_current_focus();
}, 0);

View File

@ -94,7 +94,7 @@ function render_tabbed_sections() {
});
}
new SimpleBar($(".sidebar")[0]);
new SimpleBar($(".sidebar")[0], {tabIndex: -1});
// Scroll to anchor link when clicked. Note that landing-page.js has a
// similar function; this file and landing-page.js are never included

View File

@ -89,7 +89,9 @@ export function show_user_list(message_id: number): void {
$("#read_receipts_modal .read_receipts_list").html(
render_read_receipts(context),
);
new SimpleBar($("#read_receipts_modal .modal__content")[0]!);
new SimpleBar($("#read_receipts_modal .modal__content")[0]!, {
tabIndex: -1,
});
}
},
error(xhr) {

View File

@ -26,7 +26,7 @@ export function get_scroll_element($element: JQueryOrZJQuery): JQuery {
} else if ("simplebar" in element.dataset) {
// The SimpleBar mutation observer hasnt processed this element yet.
// Create the SimpleBar early in case we need to add event listeners.
return $(new SimpleBar(element).getScrollElement()!);
return $(new SimpleBar(element, {tabIndex: -1}).getScrollElement()!);
}
return $element;
}

View File

@ -532,7 +532,6 @@ export function show_user_profile(user, default_tab_key = "profile-tab") {
break;
}
setTimeout(() => {
$(".modal__body .simplebar-content-wrapper").attr("tabindex", "-1");
$(".modal__container .ind-tab").attr("tabindex", "-1");
$(".modal__container .ind-tab.selected").attr("tabindex", "0");
}, 0);

View File

@ -2264,10 +2264,6 @@ body:not(.hide-left-sidebar) {
}
.simplebar-content-wrapper {
/* `simplebar-content-wrapper` has `tabindex=0` set, which makes it focusable
but we don't want it to have an outline when focused anywhere in the app. */
outline: none;
/* This prevents the popover from closing once the top/bottom is reached */
overscroll-behavior: contain;
}

View File

@ -5,7 +5,7 @@
</div>
<label class="poll-label">{{t "Options"}}</label>
<p>{{t "Anyone can add more options after the poll is posted."}}</p>
<ul class="poll-options-list" data-simplebar>
<ul class="poll-options-list" data-simplebar data-simplebar-tab-index="-1">
{{> poll_modal_option }}
{{> poll_modal_option }}
{{> poll_modal_option }}

View File

@ -44,7 +44,7 @@
</div>
</div>
<div class="message_comp">
<div id="compose_banners" data-simplebar></div>
<div id="compose_banners" data-simplebar data-simplebar-tab-index="-1"></div>
<div class="composition-area">
<form id="send_message_form" action="/json/messages" method="post">
<div class="compose_table">
@ -72,7 +72,7 @@
<div id="message-content-container">
<textarea class="new_message_textarea" name="content" id='compose-textarea' placeholder="{{t 'Compose your message here' }}" tabindex="0" aria-label="{{t 'Compose your message here...' }}"></textarea>
<div id="preview-message-area-container">
<div class="scrolling_list preview_message_area" data-simplebar id="preview_message_area" style="display:none;">
<div class="scrolling_list preview_message_area" data-simplebar data-simplebar-tab-index="-1" id="preview_message_area" style="display:none;">
<div class="markdown_preview_spinner"></div>
<div class="preview_content rendered_markdown"></div>
</div>

View File

@ -10,7 +10,7 @@
</h1>
<button class="modal__close" aria-label="{{t 'Close modal' }}" data-micromodal-close></button>
</header>
<main class="modal__content" data-simplebar {{#if always_visible_scrollbar}}data-simplebar-auto-hide="false"{{/if}}>
<main class="modal__content" data-simplebar data-simplebar-tab-index="-1" {{#if always_visible_scrollbar}}data-simplebar-auto-hide="false"{{/if}}>
<div class="alert" id="dialog_error"></div>
{{{ html_body }}}
</main>

View File

@ -2,7 +2,7 @@
<div class="dropdown-list-search">
<input class="dropdown-list-search-input filter_text_input{{#if hide_search_box}} hide{{/if}}" type="text" placeholder="{{t 'Filter' }}" autofocus/>
</div>
<div class="dropdown-list-wrapper" data-simplebar>
<div class="dropdown-list-wrapper" data-simplebar data-simplebar-tab-index="-1">
<ul class="dropdown-list"></ul>
</div>
<div class="no-dropdown-items dropdown-list-item-common-styles">

View File

@ -7,7 +7,7 @@
<i class="fa fa-remove" aria-hidden="true"></i>
</button>
</div>
<div class="giphy-scrolling-container" data-simplebar>
<div class="giphy-scrolling-container" data-simplebar data-simplebar-tab-index="-1">
{{! We need a container we can replace
without removing the simplebar wrappers.
We replace the `giphy-content` when

View File

@ -1,6 +1,6 @@
<div class="overlay-modal" id="keyboard-shortcuts" tabindex="-1" role="dialog"
aria-label="{{t 'Keyboard shortcuts' }}">
<div class="overlay-scroll-container" data-simplebar data-simplebar-auto-hide="false">
<div class="overlay-scroll-container" data-simplebar data-simplebar-tab-index="-1" data-simplebar-auto-hide="false">
<div>
<table class="hotkeys_table table table-striped table-bordered">
<thead>

View File

@ -161,7 +161,7 @@
</a>
</div>
{{~!-- squash whitespace --~}}
<div id="left_sidebar_scroll_container" class="scrolling_list" data-simplebar>
<div id="left_sidebar_scroll_container" class="scrolling_list" data-simplebar data-simplebar-tab-index="-1">
<div class="direct-messages-container zoom-out hidden-for-spectators">
<div id="direct-messages-list"></div>
</div>

View File

@ -1,6 +1,6 @@
<div class="overlay-modal hide" id="message-formatting" tabindex="-1" role="dialog"
aria-label="{{t 'Message formatting' }}">
<div class="overlay-scroll-container" data-simplebar data-simplebar-auto-hide="false">
<div class="overlay-scroll-container" data-simplebar data-simplebar-tab-index="-1" data-simplebar-auto-hide="false">
<div id="markdown-instructions">
<table class="table table-striped table-rounded table-bordered help-table">
<thead>

View File

@ -1,4 +1,4 @@
<div class="popover-menu visibility-policy-popover" data-simplebar>
<div class="popover-menu visibility-policy-popover" data-simplebar data-simplebar-tab-index="-1">
<ul role="menu" class="popover-menu-list">
<li role="none" class="popover-menu-list-item">
<div role="group" class="recipient-bar-topic-visibility-switcher tab-picker tab-picker-vertical" aria-label="{{t 'Topic visibility' }}">

View File

@ -9,9 +9,9 @@
<span class="emoji-popover-tab-item {{#if @first}} active {{/if}}" data-tab-name='{{name}}' title='{{name}}'><i class="fa {{icon}}"></i></span>
{{/each}}
</div>
<div class="emoji-popover-emoji-map" data-simplebar data-simplebar-auto-hide="false" data-message-id="{{message_id}}">
<div class="emoji-popover-emoji-map" data-simplebar data-simplebar-tab-index="-1" data-simplebar-auto-hide="false" data-message-id="{{message_id}}">
</div>
<div class="emoji-search-results-container" data-simplebar data-simplebar-auto-hide="false" data-message-id="{{message_id}}">
<div class="emoji-search-results-container" data-simplebar data-simplebar-tab-index="-1" data-simplebar-auto-hide="false" data-message-id="{{message_id}}">
<div class="emoji-popover-results-heading">{{t "Search results" }}</div>
<div class="emoji-search-results"></div>
</div>

View File

@ -1,4 +1,4 @@
<div class="popover-menu" id="stream-actions-menu-popover" data-simplebar>
<div class="popover-menu" id="stream-actions-menu-popover" data-simplebar data-simplebar-tab-index="-1">
<ul role="menu" class="popover-menu-list" data-stream-id="{{ stream.stream_id }}" data-name="{{ stream.name }}">
<li role="none" class="popover-stream-header text-item popover-menu-inner-list-item">
<span class="stream-privacy-original-color-{{stream.stream_id}} stream-privacy filter-icon" style="color: {{stream.color}}">

View File

@ -1,4 +1,4 @@
<div class="popover-menu" id="topic-actions-menu-popover" data-simplebar>
<div class="popover-menu" id="topic-actions-menu-popover" data-simplebar data-simplebar-tab-index="-1">
<ul role="menu" class="popover-menu-list">
<li role="none" class="popover-topic-header text-item popover-menu-list-item">
<span class="popover-topic-name">{{topic_name}}</span>

View File

@ -1,4 +1,4 @@
<div class="popover-menu" id="message-actions-menu-dropdown" data-simplebar>
<div class="popover-menu" id="message-actions-menu-dropdown" data-simplebar data-simplebar-tab-index="-1">
<ul role="menu" class="popover-menu-list">
{{!-- Group 1 --}}
{{#if should_display_quote_and_reply}}

View File

@ -1,4 +1,4 @@
<div class="popover-menu" id="gear-menu-dropdown" aria-labelledby="settings-dropdown" data-simplebar>
<div class="popover-menu" id="gear-menu-dropdown" aria-labelledby="settings-dropdown" data-simplebar data-simplebar-tab-index="-1">
<div class="org-info-container">
<div class="org-info org-name">{{realm_name}}</div>
<div class="org-info org-url">{{realm_url}}</div>

View File

@ -1,4 +1,4 @@
<div class="popover-menu" id="help-menu-dropdown" aria-labelledby="help-menu" data-simplebar>
<div class="popover-menu" id="help-menu-dropdown" aria-labelledby="help-menu" data-simplebar data-simplebar-tab-index="-1">
<ul role="menu" class="popover-menu-list">
<li role="none" class="link-item popover-menu-list-item">
<a role="menuitem" href="/help/" target="_blank" rel="noopener noreferrer" class="navigate-link-on-enter popover-menu-link">

View File

@ -1,4 +1,4 @@
<div class="popover-menu" id="personal-menu-dropdown" data-simplebar>
<div class="popover-menu" id="personal-menu-dropdown" data-simplebar data-simplebar-tab-index="-1">
<nav class="personal-menu-nav">
<header class="personal-menu-header">
<div class="avatar">

View File

@ -9,7 +9,7 @@
</div>
</div>
<hr />
<ul class="nav nav-list member-list" data-simplebar data-simplebar-auto-hide="false">
<ul class="nav nav-list member-list" data-simplebar data-simplebar-tab-index="-1" data-simplebar-auto-hide="false">
{{#each members}}
<li>
{{#if is_bot}}

View File

@ -13,7 +13,7 @@
<i class="fa fa-remove" aria-hidden="true"></i>
</button>
</div>
<div id="buddy_list_wrapper" class="scrolling_list" data-simplebar>
<div id="buddy_list_wrapper" class="scrolling_list" data-simplebar data-simplebar-tab-index="-1">
<div id="buddy-list-users-matching-view-container">
<div class="buddy-list-subsection-header"></div>
<ul id="buddy-list-users-matching-view" class="buddy-list-section filters" data-search-results-empty="{{t 'None.' }}"></ul>

View File

@ -1,5 +1,5 @@
<div class="overlay-modal hide" id="search-operators" tabindex="-1" role="dialog" aria-label="{{t 'Search filters' }}">
<div class="overlay-scroll-container" data-simplebar data-simplebar-auto-hide="false">
<div class="overlay-scroll-container" data-simplebar data-simplebar-tab-index="-1" data-simplebar-auto-hide="false">
<div id="operators-instructions">
<table class="table table-striped table-rounded table-bordered help-table">
<thead>

View File

@ -9,7 +9,7 @@
</div>
</div>
<div class="progressive-table-wrapper" data-simplebar>
<div class="progressive-table-wrapper" data-simplebar data-simplebar-tab-index="-1">
<table class="table table-striped wrapped-table">
<thead class="table-sticky-headers">
<th class="active" data-sort="alphabetic" data-sort-prop="full_name">{{t "Name" }}</th>

View File

@ -17,7 +17,7 @@
</button>
<span class="alert_word_status_text"></span>
</div>
<div class="progressive-table-wrapper" data-simplebar>
<div class="progressive-table-wrapper" data-simplebar data-simplebar-tab-index="-1">
<table class="table table-striped wrapped-table">
<thead class="table-sticky-headers">
<th data-sort="alphabetic" data-sort-prop="word">{{t "Word" }}</th>

View File

@ -6,7 +6,7 @@
</div>
<div class="clear-float"></div>
<div class="alert" id="delete-upload-status"></div>
<div class="progressive-table-wrapper" data-simplebar>
<div class="progressive-table-wrapper" data-simplebar data-simplebar-tab-index="-1">
<table class="table table-striped wrapped-table">
<thead class="table-sticky-headers">
<th data-sort="alphabetic" data-sort-prop="name" class="upload-file-name">{{t "File" }}</th>

View File

@ -24,7 +24,7 @@
<input type="text" class="search filter_text_input" placeholder="{{t 'Filter bots' }}" aria-label="{{t 'Filter bots' }}"/>
</div>
<div class="progressive-table-wrapper" data-simplebar>
<div class="progressive-table-wrapper" data-simplebar data-simplebar-tab-index="-1">
<table class="table table-striped wrapped-table">
<thead class="table-sticky-headers">
<th class="active" data-sort="alphabetic" data-sort-prop="full_name">{{t "Name" }}</th>

View File

@ -32,7 +32,7 @@
aria-label="{{t 'Filter exports' }}"/>
</div>
<div class="progressive-table-wrapper" data-simplebar>
<div class="progressive-table-wrapper" data-simplebar data-simplebar-tab-index="-1">
<table class="table table-striped wrapped-table admin_exports_table">
<thead class="table-sticky-headers">
<th class="active" data-sort="user">{{t "Requesting user" }}</th>

View File

@ -12,7 +12,7 @@
</div>
</div>
<div class="progressive-table-wrapper" data-simplebar>
<div class="progressive-table-wrapper" data-simplebar data-simplebar-tab-index="-1">
<table class="table table-striped wrapped-table">
<thead class="table-sticky-headers">
<th class="active" data-sort="alphabetic" data-sort-prop="full_name">{{t "Name" }}</th>

View File

@ -11,7 +11,7 @@
</div>
</div>
<div class="progressive-table-wrapper" data-simplebar>
<div class="progressive-table-wrapper" data-simplebar data-simplebar-tab-index="-1">
<table class="table table-striped wrapped-table">
<thead class="table-sticky-headers">
<th class="active" data-sort="alphabetic" data-sort-prop="name">{{t "Name" }}</th>

View File

@ -14,7 +14,7 @@
<input type="text" class="search filter_text_input" placeholder="{{t 'Filter emoji' }}"
aria-label="{{t 'Filter emoji' }}"/>
</div>
<div class="progressive-table-wrapper" data-simplebar>
<div class="progressive-table-wrapper" data-simplebar data-simplebar-tab-index="-1">
<table class="table table-striped wrapped-table admin_emoji_table">
<thead class="table-sticky-headers">
<th class="active" data-sort="alphabetic" data-sort-prop="name">{{t "Name" }}</th>

View File

@ -11,7 +11,7 @@
<input type="text" class="search filter_text_input" placeholder="{{t 'Filter invitations' }}" aria-label="{{t 'Filter invitations' }}"/>
</div>
<div class="progressive-table-wrapper" data-simplebar>
<div class="progressive-table-wrapper" data-simplebar data-simplebar-tab-index="-1">
<table class="table table-striped">
<thead class="table-sticky-headers">
<th class="active" data-sort="invitee">{{t "Invitee" }}</th>

View File

@ -62,7 +62,7 @@
<input type="text" class="search filter_text_input" placeholder="{{t 'Filter linkifiers' }}" aria-label="{{t 'Filter linkifiers' }}"/>
</div>
<div class="progressive-table-wrapper" data-simplebar>
<div class="progressive-table-wrapper" data-simplebar data-simplebar-tab-index="-1">
<table class="table table-striped wrapped-table admin_linkifiers_table">
<thead class="table-sticky-headers">
<th>{{t "Pattern" }}</th>

View File

@ -3,7 +3,7 @@
<h3>{{t "Muted users"}}</h3>
<input id="muted_users_search" class="search filter_text_input" type="text" placeholder="{{t 'Filter muted users' }}" aria-label="{{t 'Filter muted users' }}"/>
</div>
<div class="progressive-table-wrapper" data-simplebar>
<div class="progressive-table-wrapper" data-simplebar data-simplebar-tab-index="-1">
<table class="table table-striped wrapped-table">
<thead class="table-sticky-headers">
<th data-sort="alphabetic" data-sort-prop="user_name">{{t "User" }}</th>

View File

@ -67,7 +67,7 @@
<input type="text" class="search filter_text_input" placeholder="{{t 'Filter code playgrounds' }}" aria-label="{{t 'Filter code playgrounds' }}"/>
</div>
<div class="progressive-table-wrapper" data-simplebar>
<div class="progressive-table-wrapper" data-simplebar data-simplebar-tab-index="-1">
<table class="table table-striped wrapped-table admin_playgrounds_table">
<thead class="table-sticky-headers">
<th class="active" data-sort="alphabetic" data-sort-prop="pygments_language">{{t "Language" }}</th>

View File

@ -6,7 +6,7 @@
<button class="button rounded sea-green" id="add-custom-profile-field-btn">{{t "Add a new profile field" }}</button>
{{/if}}
</div>
<div class="admin-table-wrapper" data-simplebar>
<div class="admin-table-wrapper" data-simplebar data-simplebar-tab-index="-1">
<table class="table table-striped admin_profile_fields_table">
<thead>
<tr>

View File

@ -14,7 +14,7 @@
{{> settings_save_discard_widget section_name="user-topics-settings" show_only_indicator=true }}
<input id="user_topics_search" class="search filter_text_input" type="text" placeholder="{{t 'Filter topics' }}" aria-label="{{t 'Filter topics' }}"/>
</div>
<div class="progressive-table-wrapper" data-simplebar>
<div class="progressive-table-wrapper" data-simplebar data-simplebar-tab-index="-1">
<table class="table table-striped wrapped-table">
<thead class="table-sticky-headers">
<th data-sort="alphabetic" data-sort-prop="stream">{{t "Channel" }}</th>

View File

@ -9,7 +9,7 @@
</div>
<div class="sidebar-wrapper">
<div class="center tab-container settings-sticky-bar"></div>
<div class="sidebar left" data-simplebar>
<div class="sidebar left" data-simplebar data-simplebar-tab-index="-1">
<div class="sidebar-list dark-grey small-text">
<ul class="normal-settings-list">
<li tabindex="0" data-section="profile">
@ -147,7 +147,7 @@
<span class="exit-sign">&times;</span>
</div>
</div>
<div id="settings_content" data-simplebar data-simplebar-auto-hide="false">
<div id="settings_content" data-simplebar data-simplebar-tab-index="-1" data-simplebar-auto-hide="false">
<div class="organization-box organization">
</div>

View File

@ -18,7 +18,7 @@
</div>
<div class="subscriber-list-box">
<div class="subscriber_list_container" data-simplebar>
<div class="subscriber_list_container" data-simplebar data-simplebar-tab-index="-1">
<table class="subscriber-list table table-striped">
<thead class="table-sticky-headers">
<th data-sort="alphabetic" data-sort-prop="full_name">{{t "Name" }}</th>

View File

@ -1,7 +1,7 @@
<div class="hide" id="stream-creation" tabindex="-1" role="dialog"
aria-label="{{t 'Channel creation' }}">
<form id="stream_creation_form">
<div class="stream-creation-simplebar-container" data-simplebar>
<div class="stream-creation-simplebar-container" data-simplebar data-simplebar-tab-index="-1">
<div class="alert stream_create_info"></div>
<div id="stream_creating_indicator"></div>
<div class="stream-creation-body">

View File

@ -17,7 +17,7 @@
</span>
</div>
<div class="subscriber-list-box">
<div class="subscriber_list_container" data-simplebar>
<div class="subscriber_list_container" data-simplebar data-simplebar-tab-index="-1">
<div class="subscriber_list_loading_indicator"></div>
<table id="stream_members_list" class="subscriber-list table table-striped">
<thead class="table-sticky-headers">

View File

@ -50,7 +50,7 @@
</span>
</div>
</div>
<div class="streams-list" data-simplebar>
<div class="streams-list" data-simplebar data-simplebar-tab-index="-1">
</div>
</div>
<div class="right">
@ -68,7 +68,7 @@
</span>
{{/if}}
</div>
<div id="stream_settings" class="settings" data-simplebar data-simplebar-auto-hide="false">
<div id="stream_settings" class="settings" data-simplebar data-simplebar-tab-index="-1" data-simplebar-auto-hide="false">
{{!-- edit stream here --}}
</div>
{{> stream_creation_form }}

View File

@ -13,7 +13,7 @@
</div>
<div class="member-list-box">
<div class="member_list_container" data-simplebar>
<div class="member_list_container" data-simplebar data-simplebar-tab-index="-1">
<table class="member-list table table-striped">
<thead class="table-sticky-headers">
<th data-sort="alphabetic" data-sort-prop="full_name">{{t "Name" }}</th>

View File

@ -1,7 +1,7 @@
<div class="hide" id="user-group-creation" tabindex="-1" role="dialog"
aria-label="{{t 'User group creation' }}">
<form id="user_group_creation_form">
<div class="user-group-creation-simplebar-container" data-simplebar>
<div class="user-group-creation-simplebar-container" data-simplebar data-simplebar-tab-index="-1">
<div class="alert user_group_create_info"></div>
<div id="user_group_creating_indicator"></div>
<div class="user-group-creation-body">

View File

@ -16,7 +16,7 @@
</span>
</div>
<div class="member-list-box">
<div class="member_list_container" data-simplebar>
<div class="member_list_container" data-simplebar data-simplebar-tab-index="-1">
<div class="member_list_loading_indicator"></div>
<table class="member-list table table-striped">
<thead class="table-sticky-headers">

View File

@ -42,7 +42,7 @@
</span>
</div>
</div>
<div class="user-groups-list" data-simplebar>
<div class="user-groups-list" data-simplebar data-simplebar-tab-index="-1">
</div>
</div>
<div class="right">
@ -60,7 +60,7 @@
</span>
{{/if}}
</div>
<div id="user_group_settings" class="settings" data-simplebar data-simplebar-auto-hide="false">
<div id="user_group_settings" class="settings" data-simplebar data-simplebar-tab-index="-1" data-simplebar-auto-hide="false">
{{!-- edit user group here --}}
</div>
{{> user_group_creation_form }}

View File

@ -35,7 +35,7 @@
<button class="modal__close" aria-label="{{t 'Close modal' }}" data-micromodal-close></button>
</div>
<div id="tab-toggle" class="center"></div>
<main class="modal__body" id="body" data-simplebar data-simplebar-auto-hide="false">
<main class="modal__body" id="body" data-simplebar data-simplebar-tab-index="-1" data-simplebar-auto-hide="false">
<div class="tab-data">
<div class="tabcontent active" id="profile-tab">
<div class="top">