personal_menu_popover: Flatten nested lists for better accessibility.

This refactors popover list structure to use a flattened `ul > li`
structure along with aria-related additions, enabling screen reader
accessibility and announcing menu length and position (`# of n`).

Added ARIA roles:
- `role="menu"` to the parent `<ul>` element, indicating it is a widget
    offering a list of choices.

- `role="menuitem"`, `role="menuitemcheckbox"`,
    or`role="menuitemradio"` to child elements based on their function.

- `role="group"` to the theme switcher, identifying it as a container
    for related menu items.

- `role="none"` to `<li>` elements, removing the implied `listitem`
    role that conflicts with the parent menu structure.
This commit is contained in:
Sayam Samal 2024-05-24 12:00:28 +05:30 committed by Tim Abbott
parent ed9d2a7af6
commit 3dfaca0773
1 changed files with 109 additions and 124 deletions

View File

@ -15,137 +15,122 @@
</div>
</header>
<section class="dropdown-menu-list-section personal-menu-actions" data-user-id="{{user_id}}">
<ul class="popover-menu-outer-list">
<ul role="menu" class="popover-menu-list">
{{#if user_time}}
<li class="popover-menu-outer-list-item">
<ul class="popover-menu-inner-list">
<li class="text-item hidden-for-spectators popover-menu-inner-list-item">
<i class="popover-menu-icon zulip-icon zulip-icon-clock"></i>
{{#tr}}{user_time} local time{{/tr}}
</li>
</ul>
<li role="none" class="text-item hidden-for-spectators popover-menu-list-item">
<i class="popover-menu-icon zulip-icon zulip-icon-clock"></i>
{{#tr}}{user_time} local time{{/tr}}
</li>
<li role="separator" class="popover-menu-separator"></li>
{{/if}}
{{#if status_content_available}}
<li role="none" class="text-item popover-menu-list-item">
<span class="personal-menu-status-wrapper">
{{#if status_emoji_info}}
{{#if status_emoji_info.emoji_alt_code}}
<span class="emoji_alt_code">&nbsp;:{{status_emoji_info.emoji_name}}:</span>
{{else if status_emoji_info.url}}
<img src="{{status_emoji_info.url}}" class="emoji status_emoji" />
{{else}}
<span class="emoji status_emoji emoji-{{status_emoji_info.emoji_code}}"></span>
{{/if}}
{{/if}}
<span class="status_text personal-menu-status-text">
{{#if show_placeholder_for_status_text}}
<i class="personal-menu-no-status-text">{{t "No status text"}}</i>
{{else}}
{{status_text}}
{{/if}}
</span>
</span>
<a role="menuitem" tabindex="0" class="personal-menu-clear-status popover-menu-link" aria-label="{{t 'Clear status'}}" data-tippy-content="{{t 'Clear your status' }}">
<i class="personal-menu-clear-status-icon popover-menu-icon zulip-icon zulip-icon-x-circle"></i>
</a>
</li>
{{!-- Group 1 --}}
<li role="none" class="link-item popover-menu-list-item">
<a role="menuitem" tabindex="0" class="update_status_text popover-menu-link">
<i class="popover-menu-icon zulip-icon zulip-icon-smile-smaller"></i>
<span class="popover-menu-label">{{t 'Edit status' }}</span>
</a>
</li>
{{else}}
<li role="none" class="link-item hidden-for-spectators popover-menu-list-item">
<a role="menuitem" tabindex="0" class="update_status_text popover-menu-link">
<i class="popover-menu-icon zulip-icon zulip-icon-smile-smaller"></i>
<span class="popover-menu-label">{{t 'Set status' }}</span>
</a>
</li>
{{/if}}
<li class="popover-menu-outer-list-item">
<ul class="popover-menu-inner-list">
{{#if status_content_available}}
<li class="text-item popover-menu-inner-list-item">
<span class="personal-menu-status-wrapper">
{{#if status_emoji_info}}
{{#if status_emoji_info.emoji_alt_code}}
<span class="emoji_alt_code">&nbsp;:{{status_emoji_info.emoji_name}}:</span>
{{else if status_emoji_info.url}}
<img src="{{status_emoji_info.url}}" class="emoji status_emoji" />
{{else}}
<span class="emoji status_emoji emoji-{{status_emoji_info.emoji_code}}"></span>
{{/if}}
{{/if}}
<span class="status_text personal-menu-status-text">
{{#if show_placeholder_for_status_text}}
<i class="personal-menu-no-status-text">{{t "No status text"}}</i>
{{else}}
{{status_text}}
{{/if}}
</span>
</span>
<a tabindex="0" class="personal-menu-clear-status popover-menu-link" aria-label="{{t 'Clear status'}}" data-tippy-content="{{t 'Clear your status' }}">
<i class="personal-menu-clear-status-icon popover-menu-icon zulip-icon zulip-icon-x-circle"></i>
</a>
</li>
<li class="link-item popover-menu-inner-list-item">
<a tabindex="0" class="update_status_text popover-menu-link">
<i class="popover-menu-icon zulip-icon zulip-icon-smile-smaller"></i>
<span class="popover-menu-label">{{t 'Edit status' }}</span>
</a>
</li>
{{else}}
<li class="link-item hidden-for-spectators popover-menu-inner-list-item">
<a tabindex="0" class="update_status_text popover-menu-link">
<i class="popover-menu-icon zulip-icon zulip-icon-smile-smaller"></i>
<span class="popover-menu-label">{{t 'Set status' }}</span>
</a>
</li>
{{/if}}
{{#if invisible_mode}}
<li class="link-item hidden-for-spectators popover-menu-inner-list-item">
<a tabindex="0" class="invisible_mode_turn_off popover-menu-link">
<i class="popover-menu-icon zulip-icon zulip-icon-play-circle"></i>
<span class="popover-menu-label">{{t 'Turn off invisible mode' }}</span>
</a>
</li>
{{else}}
<li class="link-item hidden-for-spectators popover-menu-inner-list-item">
<a tabindex="0" class="invisible_mode_turn_on popover-menu-link">
<i class="popover-menu-icon zulip-icon zulip-icon-stop-circle"></i>
<span class="popover-menu-label">{{t 'Go invisible' }}</span>
</a>
</li>
{{/if}}
</ul>
{{#if invisible_mode}}
<li role="none" class="link-item hidden-for-spectators popover-menu-list-item">
<a role="menuitem" tabindex="0" class="invisible_mode_turn_off popover-menu-link">
<i class="popover-menu-icon zulip-icon zulip-icon-play-circle"></i>
<span class="popover-menu-label">{{t 'Turn off invisible mode' }}</span>
</a>
</li>
<li class="popover-menu-outer-list-item">
<ul class="popover-menu-inner-list">
<li class="popover-menu-inner-list-item">
<div id="theme-switcher" class="tab-picker">
<input type="radio" id="select-automatic-theme" class="tab-option" name="theme-select" data-theme-code="{{color_scheme_values.automatic.code}}" {{#if (eq user_color_scheme color_scheme_values.automatic.code)}}checked{{/if}} />
<label class="tab-option-content tippy-zulip-delayed-tooltip" for="select-automatic-theme" aria-label="{{t 'Select automatic theme' }}" data-tooltip-template-id="automatic-theme-template" tabindex="0">
<i class="zulip-icon zulip-icon-monitor" aria-hidden="true"></i>
</label>
<input type="radio" id="select-light-theme" class="tab-option" name="theme-select" data-theme-code="{{color_scheme_values.day.code}}" {{#if (eq user_color_scheme color_scheme_values.day.code)}}checked{{/if}} />
<label class="tab-option-content tippy-zulip-delayed-tooltip" for="select-light-theme" aria-label="{{t 'Select light theme' }}" data-tippy-content="{{t 'Light theme' }}" tabindex="0">
<i class="zulip-icon zulip-icon-sun" aria-hidden="true"></i>
</label>
<input type="radio" id="select-dark-theme" class="tab-option" name="theme-select" data-theme-code="{{color_scheme_values.night.code}}" {{#if (eq user_color_scheme color_scheme_values.night.code)}}checked{{/if}} />
<label class="tab-option-content tippy-zulip-delayed-tooltip" for="select-dark-theme" aria-label="{{t 'Select dark theme' }}" data-tippy-content="{{t 'Dark theme' }}" tabindex="0">
<i class="zulip-icon zulip-icon-moon" aria-hidden="true"></i>
</label>
<span class="slider"></span>
</div>
</li>
</ul>
{{else}}
<li role="none" class="link-item hidden-for-spectators popover-menu-list-item">
<a role="menuitem" tabindex="0" class="invisible_mode_turn_on popover-menu-link">
<i class="popover-menu-icon zulip-icon zulip-icon-stop-circle"></i>
<span class="popover-menu-label">{{t 'Go invisible' }}</span>
</a>
</li>
<li class="popover-menu-outer-list-item">
<ul class="popover-menu-inner-list">
<li class="link-item popover-menu-inner-list-item">
<a href="#user/{{user_id}}" tabindex="0" class="view_full_user_profile popover-menu-link">
<i class="popover-menu-icon zulip-icon zulip-icon-account"></i>
<span class="popover-menu-label">{{t 'View your profile' }}</span>
</a>
</li>
<li class="link-item popover-menu-inner-list-item">
<a tabindex="0" class="narrow-self-direct-message popover-menu-link">
<i class="popover-menu-icon zulip-icon zulip-icon-users"></i>
<span class="popover-menu-label">{{t 'View messages with yourself' }}</span>
</a>
</li>
<li class="link-item popover-menu-inner-list-item">
<a tabindex="0" class="narrow-messages-sent popover-menu-link">
<i class="popover-menu-icon zulip-icon zulip-icon-message-square"></i>
<span class="popover-menu-label">{{t 'View messages sent' }}</span>
</a>
</li>
</ul>
{{/if}}
{{!-- Group 2 --}}
<li role="separator" class="popover-menu-separator"></li>
<li role="none" class="popover-menu-list-item">
<div role="group" id="theme-switcher" class="tab-picker" aria-label="{{t 'App theme' }}">
<input type="radio" id="select-automatic-theme" class="tab-option" name="theme-select" data-theme-code="{{color_scheme_values.automatic.code}}" {{#if (eq user_color_scheme color_scheme_values.automatic.code)}}checked{{/if}} />
<label role="menuitemradio" class="tab-option-content tippy-zulip-delayed-tooltip" for="select-automatic-theme" aria-label="{{t 'Select automatic theme' }}" data-tooltip-template-id="automatic-theme-template" tabindex="0">
<i class="zulip-icon zulip-icon-monitor" aria-hidden="true"></i>
</label>
<input type="radio" id="select-light-theme" class="tab-option" name="theme-select" data-theme-code="{{color_scheme_values.day.code}}" {{#if (eq user_color_scheme color_scheme_values.day.code)}}checked{{/if}} />
<label role="menuitemradio" class="tab-option-content tippy-zulip-delayed-tooltip" for="select-light-theme" aria-label="{{t 'Select light theme' }}" data-tippy-content="{{t 'Light theme' }}" tabindex="0">
<i class="zulip-icon zulip-icon-sun" aria-hidden="true"></i>
</label>
<input type="radio" id="select-dark-theme" class="tab-option" name="theme-select" data-theme-code="{{color_scheme_values.night.code}}" {{#if (eq user_color_scheme color_scheme_values.night.code)}}checked{{/if}} />
<label role="menuitemradio" class="tab-option-content tippy-zulip-delayed-tooltip" for="select-dark-theme" aria-label="{{t 'Select dark theme' }}" data-tippy-content="{{t 'Dark theme' }}" tabindex="0">
<i class="zulip-icon zulip-icon-moon" aria-hidden="true"></i>
</label>
<span class="slider"></span>
</div>
</li>
<li class="popover-menu-outer-list-item">
<ul class="popover-menu-inner-list">
<li class="link-item popover-menu-inner-list-item">
<a href="#settings/profile" class="open-profile-settings popover-menu-link">
<i class="popover-menu-icon zulip-icon zulip-icon-tool"></i>
<span class="popover-menu-label">{{t 'Settings' }}</span>
</a>
</li>
</ul>
{{!-- Group 3 --}}
<li role="separator" class="popover-menu-separator"></li>
<li role="none" class="link-item popover-menu-list-item">
<a role="menuitem" href="#user/{{user_id}}" tabindex="0" class="view_full_user_profile popover-menu-link">
<i class="popover-menu-icon zulip-icon zulip-icon-account"></i>
<span class="popover-menu-label">{{t 'View your profile' }}</span>
</a>
</li>
<li class="popover-menu-outer-list-item">
<ul class="popover-menu-inner-list">
<li class="link-item popover-menu-inner-list-item">
<a class="logout_button hidden-for-spectators popover-menu-link" tabindex="0">
<i class="popover-menu-icon zulip-icon zulip-icon-log-out" aria-hidden="true"></i>
<span class="popover-menu-label">{{t 'Log out' }}</span>
</a>
</li>
</ul>
<li role="none" class="link-item popover-menu-list-item">
<a role="menuitem" tabindex="0" class="narrow-self-direct-message popover-menu-link">
<i class="popover-menu-icon zulip-icon zulip-icon-users"></i>
<span class="popover-menu-label">{{t 'View messages with yourself' }}</span>
</a>
</li>
<li role="none" class="link-item popover-menu-list-item">
<a role="menuitem" tabindex="0" class="narrow-messages-sent popover-menu-link">
<i class="popover-menu-icon zulip-icon zulip-icon-message-square"></i>
<span class="popover-menu-label">{{t 'View messages sent' }}</span>
</a>
</li>
{{!-- Group 4 --}}
<li role="separator" class="popover-menu-separator"></li>
<li role="none" class="link-item popover-menu-list-item">
<a role="menuitem" href="#settings/profile" class="open-profile-settings popover-menu-link">
<i class="popover-menu-icon zulip-icon zulip-icon-tool"></i>
<span class="popover-menu-label">{{t 'Settings' }}</span>
</a>
</li>
{{!-- Group 5 --}}
<li role="separator" class="popover-menu-separator"></li>
<li role="none" class="link-item popover-menu-list-item">
<a role="menuitem" class="logout_button hidden-for-spectators popover-menu-link" tabindex="0">
<i class="popover-menu-icon zulip-icon zulip-icon-log-out" aria-hidden="true"></i>
<span class="popover-menu-label">{{t 'Log out' }}</span>
</a>
</li>
</ul>
</section>