[Glitch] Accessibility: Add landmark regions to Web UI

Port e1aa4e3a8c7401d9fd2ab0371e550dde0458c961 to glitch-soc

Signed-off-by: Claire <claire.github-309c@sitedethib.com>
This commit is contained in:
diondiondion 2026-05-26 12:22:22 +02:00 committed by Claire
parent 526034d996
commit 392f8e43f9
8 changed files with 49 additions and 20 deletions

View File

@ -270,7 +270,15 @@ class ComposeForm extends ImmutablePureComponent {
const { intl, onPaste, onDrop, autoFocus, withoutNavigation, maxChars, isSubmitting } = this.props; const { intl, onPaste, onDrop, autoFocus, withoutNavigation, maxChars, isSubmitting } = this.props;
return ( 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 /> <ReplyIndicator />
{!withoutNavigation && <NavigationBar />} {!withoutNavigation && <NavigationBar />}
<Warning /> <Warning />

View File

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

View File

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

View File

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

View File

@ -65,7 +65,7 @@ import { MoreLink } from './components/more_link';
import { SignInBanner } from './components/sign_in_banner'; import { SignInBanner } from './components/sign_in_banner';
import { Trends } from './components/trends'; import { Trends } from './components/trends';
const messages = defineMessages({ export const messages = defineMessages({
home: { id: 'tabs_bar.home', defaultMessage: 'Home' }, home: { id: 'tabs_bar.home', defaultMessage: 'Home' },
notifications: { notifications: {
id: 'tabs_bar.notifications', id: 'tabs_bar.notifications',
@ -77,6 +77,12 @@ const messages = defineMessages({
id: 'column.firehose_singular', id: 'column.firehose_singular',
defaultMessage: 'Live feed', 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' }, direct: { id: 'navigation_bar.direct', defaultMessage: 'Private mentions' },
favourites: { id: 'navigation_bar.favourites', defaultMessage: 'Favorites' }, favourites: { id: 'navigation_bar.favourites', defaultMessage: 'Favorites' },
bookmarks: { id: 'navigation_bar.bookmarks', defaultMessage: 'Bookmarks' }, bookmarks: { id: 'navigation_bar.bookmarks', defaultMessage: 'Bookmarks' },
@ -455,6 +461,7 @@ export const NavigationPanel: React.FC<{ multiColumn?: boolean }> = ({
}; };
export const CollapsibleNavigationPanel: React.FC = () => { export const CollapsibleNavigationPanel: React.FC = () => {
const intl = useIntl();
const open = useAppSelector((state) => state.navigation.open); const open = useAppSelector((state) => state.navigation.open);
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const openable = useBreakpoint('openable'); const openable = useBreakpoint('openable');
@ -563,7 +570,8 @@ export const CollapsibleNavigationPanel: React.FC = () => {
const showOverlay = openable && open; const showOverlay = openable && open;
return ( return (
<div <nav
aria-label={intl.formatMessage(messages.main)}
className={classNames( className={classNames(
'columns-area__panels__pane columns-area__panels__pane--start columns-area__panels__pane--navigational', 'columns-area__panels__pane columns-area__panels__pane--start columns-area__panels__pane--navigational',
{ 'columns-area__panels__pane--overlay': showOverlay }, { 'columns-area__panels__pane--overlay': showOverlay },
@ -577,6 +585,6 @@ export const CollapsibleNavigationPanel: React.FC = () => {
> >
<NavigationPanel /> <NavigationPanel />
</animated.div> </animated.div>
</div> </nav>
); );
}; };

View File

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

View File

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

View File

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