Accessibility: Add landmark regions to Web UI (#39133)

This commit is contained in:
diondiondion 2026-05-26 12:22:22 +02:00 committed by GitHub
parent 9fe97e1ad6
commit e1aa4e3a8c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 55 additions and 23 deletions

View File

@ -248,7 +248,15 @@ class ComposeForm extends ImmutablePureComponent {
const { intl, onPaste, onDrop, autoFocus, withoutNavigation, maxChars, isSubmitting } = this.props;
return (
<form className='compose-form' onSubmit={this.handleSubmit}>
<form
className='compose-form'
role='region'
aria-label={intl.formatMessage({
id: 'tabs_bar.publish',
defaultMessage: 'New Post'
})}
onSubmit={this.handleSubmit}
>
<ReplyIndicator />
{!withoutNavigation && <NavigationBar />}
<Warning />

View File

@ -547,11 +547,15 @@ export const Search: React.FC<{
const searchOptionsHeading = useId();
return (
<form ref={formRef} className={classNames('search', { active: expanded })}>
<form
role='search'
ref={formRef}
className={classNames('search', { active: expanded })}
>
<input
ref={searchInputRef}
className='search__input'
type='text'
type='search'
placeholder={intl.formatMessage(
signedIn ? messages.placeholderSignedIn : messages.placeholder,
)}

View File

@ -87,12 +87,11 @@ const Compose: React.FC<{ multiColumn: boolean }> = ({ multiColumn }) => {
if (multiColumn) {
return (
<div
className='drawer'
role='region'
aria-label={intl.formatMessage(navbarMessages.publish)}
>
<nav className='drawer__header'>
<div className='drawer'>
<nav
className='drawer__header'
aria-label={intl.formatMessage(navbarMessages.advancedUiQuickLinks)}
>
<Link
to='/getting-started'
className='drawer__tab'
@ -163,7 +162,11 @@ const Compose: React.FC<{ multiColumn: boolean }> = ({ multiColumn }) => {
<Search singleColumn={false} />
<div className='drawer__pager'>
<div
className='drawer__pager'
role='region'
aria-label={intl.formatMessage(navbarMessages.publish)}
>
<div className='drawer__inner'>
<ComposeFormContainer />

View File

@ -4,14 +4,16 @@ import { Helmet } from '@unhead/react/helmet';
import { Column } from 'mastodon/components/column';
import { NavigationPanel } from '../navigation_panel';
import { NavigationPanel, messages } from '../navigation_panel';
import { LinkFooter } from '../ui/components/link_footer';
const GettingStarted: React.FC = () => {
const intl = useIntl();
return (
<Column>
<NavigationPanel multiColumn />
<nav aria-label={intl.formatMessage(messages.main)}>
<NavigationPanel multiColumn />
</nav>
<LinkFooter context='multi-column' />

View File

@ -60,7 +60,7 @@ import { MoreLink } from './components/more_link';
import { SignInBanner } from './components/sign_in_banner';
import { Trends } from './components/trends';
const messages = defineMessages({
export const messages = defineMessages({
home: { id: 'tabs_bar.home', defaultMessage: 'Home' },
notifications: {
id: 'tabs_bar.notifications',
@ -72,6 +72,12 @@ const messages = defineMessages({
id: 'column.firehose_singular',
defaultMessage: 'Live feed',
},
main: {
id: 'navigation_bar.main',
defaultMessage: 'Main',
description:
'Label for the main navigation; should not contain the word "navigation".',
},
direct: { id: 'navigation_bar.direct', defaultMessage: 'Private mentions' },
favourites: { id: 'navigation_bar.favourites', defaultMessage: 'Favorites' },
bookmarks: { id: 'navigation_bar.bookmarks', defaultMessage: 'Bookmarks' },
@ -419,6 +425,7 @@ export const NavigationPanel: React.FC<{ multiColumn?: boolean }> = ({
};
export const CollapsibleNavigationPanel: React.FC = () => {
const intl = useIntl();
const open = useAppSelector((state) => state.navigation.open);
const dispatch = useAppDispatch();
const openable = useBreakpoint('openable');
@ -527,7 +534,8 @@ export const CollapsibleNavigationPanel: React.FC = () => {
const showOverlay = openable && open;
return (
<div
<nav
aria-label={intl.formatMessage(messages.main)}
className={classNames(
'columns-area__panels__pane columns-area__panels__pane--start columns-area__panels__pane--navigational',
{ 'columns-area__panels__pane--overlay': showOverlay },
@ -541,6 +549,6 @@ export const CollapsibleNavigationPanel: React.FC = () => {
>
<NavigationPanel />
</animated.div>
</div>
</nav>
);
};

View File

@ -108,12 +108,12 @@ export const ColumnsArea = forwardRef<
</div>
</div>
<div className='columns-area__panels__main'>
<main className='columns-area__panels__main'>
<div className='tabs-bar__wrapper'>
<TabsBarPortal />
</div>
<div className='columns-area columns-area--mobile'>{children}</div>
</div>
</main>
<CollapsibleNavigationPanel />
</div>
@ -121,7 +121,7 @@ export const ColumnsArea = forwardRef<
}
return (
<div
<main
className={classNames('columns-area', { unscrollable: isModalOpen })}
ref={ref}
tabIndex={isModalOpen ? undefined : 0}
@ -160,7 +160,7 @@ export const ColumnsArea = forwardRef<
cloneElement(child, { multiColumn: true }),
)}
</ColumnIndexContext.Provider>
</div>
</main>
);
});

View File

@ -31,6 +31,10 @@ export const messages = defineMessages({
defaultMessage: 'Notifications',
},
menu: { id: 'tabs_bar.menu', defaultMessage: 'Menu' },
advancedUiQuickLinks: {
id: 'tabs_bar.quick_links',
defaultMessage: 'Quick links',
},
});
const IconLabelButton: React.FC<{

View File

@ -908,6 +908,7 @@
"navigation_bar.live_feed_local": "Live feed (local)",
"navigation_bar.live_feed_public": "Live feed (public)",
"navigation_bar.logout": "Logout",
"navigation_bar.main": "Main",
"navigation_bar.moderation": "Moderation",
"navigation_bar.more": "More",
"navigation_bar.mutes": "Muted users",
@ -1305,6 +1306,7 @@
"tabs_bar.menu": "Menu",
"tabs_bar.notifications": "Notifications",
"tabs_bar.publish": "New Post",
"tabs_bar.quick_links": "Quick links",
"tabs_bar.search": "Search",
"tag.remove": "Remove",
"terms_of_service.effective_as_of": "Effective as of {date}",

View File

@ -411,7 +411,7 @@ $content-width: 840px;
display: flex;
}
& > ul {
& > nav > ul {
display: none;
&.visible {

View File

@ -8,7 +8,7 @@
- content_for :content do
%a.navigation-skip-link{ href: '#content' }= t('admin.skip_to_content')
.admin-wrapper
%nav.sidebar-wrapper
%header.sidebar-wrapper
.sidebar-wrapper__inner
.sidebar
= link_to root_path do
@ -23,7 +23,8 @@
= material_symbol 'menu'
= material_symbol 'close'
= render_navigation
%nav
= render_navigation
%main.content-wrapper#content
.content

View File

@ -12,6 +12,6 @@ RSpec.describe 'UnloggedBrowsing', :js, :streaming do
it 'loads the home page' do
expect(subject).to have_css('div.app-holder')
expect(subject).to have_css('div.columns-area__panels__main')
expect(subject).to have_css('main.columns-area__panels__main')
end
end