mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
fix(react): address Doctor findings (#1143)
Accessibility/semantics pass aligned with React Doctor: role-based spans/divs become real buttons, role=status becomes <output>, modals use native <dialog>, author/peer flags render as <img>, and embed/challenge iframes are sandboxed. Includes review follow-ups: correct button chrome/centering/themed dialog colors and focus rings, the missing aria-label i18n keys (all languages), the Yandex image-search URL, clearer .bso setup steps, a keyboard-accessible image-search dropdown, and removal of the post-edit ('comment edited') display (mod edits unchanged).
This commit is contained in:
@@ -220,7 +220,7 @@ describe('BoardsBar', () => {
|
||||
await renderBoardsBar('/mu');
|
||||
|
||||
await act(async () => {
|
||||
findExactText('search')?.dispatchEvent(new MouseEvent('click', { bubbles: true }));
|
||||
findExactText('Search')?.dispatchEvent(new MouseEvent('click', { bubbles: true }));
|
||||
});
|
||||
|
||||
const inputs = container.querySelectorAll<HTMLInputElement>('input[type="text"]');
|
||||
|
||||
@@ -5,13 +5,30 @@
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.boardNavDesktop button, .boardNavMobile button {
|
||||
appearance: none;
|
||||
background: transparent;
|
||||
border: 0;
|
||||
color: inherit;
|
||||
display: inline;
|
||||
font: inherit;
|
||||
line-height: inherit;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.boardNavDesktop button:focus-visible, .boardNavMobile button:focus-visible {
|
||||
outline: 1px dotted currentcolor;
|
||||
outline-offset: 1px;
|
||||
}
|
||||
|
||||
.checkingSubscriptions {
|
||||
font-size: var(--boardsbar-font-size);
|
||||
color: var(--boardsbar-desktop-link-text-color);
|
||||
text-transform: lowercase;
|
||||
}
|
||||
|
||||
.boardNavDesktop a, .navTopRight span {
|
||||
.boardNavDesktop a, .navTopRight span, .navTopRight button {
|
||||
color: var(--boardsbar-desktop-link-text-color);
|
||||
text-decoration: var(--boardsbar-desktop-link-text-decoration);
|
||||
}
|
||||
@@ -20,13 +37,13 @@
|
||||
padding: 0 1px;
|
||||
}
|
||||
|
||||
.boardNavDesktop a:hover, .navTopRight span:hover {
|
||||
.boardNavDesktop a:hover, .navTopRight span:hover, .navTopRight button:hover {
|
||||
color: var(--boardsbar-desktop-link-text-color-hover);
|
||||
text-decoration: var(--boardsbar-desktop-link-text-decoration-hover);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.placeholder {
|
||||
.boardNavDesktop .placeholder {
|
||||
color: var(--boardsbar-separator-color);
|
||||
}
|
||||
|
||||
@@ -45,13 +62,17 @@
|
||||
margin-right: -7px;
|
||||
}
|
||||
|
||||
.temporaryButton {
|
||||
.boardNavDesktop .temporaryButton {
|
||||
color: var(--boardsbar-desktop-link-text-color);
|
||||
text-decoration: var(--boardsbar-desktop-link-text-decoration);
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
.temporaryButton:hover {
|
||||
.navTopRight button {
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
.boardNavDesktop .temporaryButton:hover {
|
||||
color: var(--boardsbar-desktop-link-text-color-hover);
|
||||
text-decoration: var(--boardsbar-desktop-link-text-decoration-hover);
|
||||
cursor: pointer;
|
||||
@@ -80,7 +101,7 @@
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
.boardNavMobile .pageJump a, .boardNavMobile .pageJump span {
|
||||
.boardNavMobile .pageJump a, .boardNavMobile .pageJump span, .boardNavMobile .pageJump button {
|
||||
color: var(--boardsbar-mobile-button-text-color);
|
||||
text-decoration: var(--button-text-decoration-mobile);
|
||||
}
|
||||
@@ -108,7 +129,7 @@
|
||||
padding: 3px 5px 0 0;
|
||||
}
|
||||
|
||||
.pageJump a, .pageJump span {
|
||||
.pageJump a, .pageJump span, .pageJump button {
|
||||
padding-right: 5px;
|
||||
text-decoration: var(--homepage-box-link-text-decoration);
|
||||
cursor: pointer;
|
||||
|
||||
@@ -70,7 +70,16 @@ const SearchBar = ({ setShowSearchBar }: { setShowSearchBar: (show: boolean) =>
|
||||
return (
|
||||
<div className={styles.searchBar} ref={searchBarRef}>
|
||||
<form onSubmit={handleSearchSubmit}>
|
||||
<input type='text' autoCorrect='off' autoComplete='off' spellCheck='false' autoCapitalize='off' placeholder={placeholder} ref={searchInputRef} />
|
||||
<input
|
||||
type='text'
|
||||
aria-label={placeholder}
|
||||
autoCorrect='off'
|
||||
autoComplete='off'
|
||||
spellCheck='false'
|
||||
autoCapitalize='off'
|
||||
placeholder={placeholder}
|
||||
ref={searchInputRef}
|
||||
/>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
@@ -154,9 +163,9 @@ const BoardsBarDesktop = () => {
|
||||
const linkContent = (
|
||||
<>
|
||||
{isPlaceholder ? (
|
||||
<span
|
||||
<button
|
||||
type='button'
|
||||
className={styles.placeholder}
|
||||
role='button'
|
||||
tabIndex={0}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
@@ -168,7 +177,7 @@ const BoardsBarDesktop = () => {
|
||||
style={{ cursor: 'pointer' }}
|
||||
>
|
||||
{code}
|
||||
</span>
|
||||
</button>
|
||||
) : (
|
||||
<Link to={`/${code}${catalogSuffix}`} onClick={openDirectoryForPlaceholder}>
|
||||
{code}
|
||||
@@ -209,19 +218,19 @@ const BoardsBarDesktop = () => {
|
||||
</>
|
||||
)}
|
||||
]{' '}
|
||||
{BOARD_CODE_GROUPS.map((group, groupIndex) => {
|
||||
{BOARD_CODE_GROUPS.map((group) => {
|
||||
const visibleCodes = group.filter((code) => directoriesToShow.has(code));
|
||||
if (visibleCodes.length === 0) return null;
|
||||
|
||||
return <span key={groupIndex}>[{visibleCodes.map((code, codeIndex) => renderBoardCode(code, codeIndex === visibleCodes.length - 1))}] </span>;
|
||||
return <span key={group.join('|')}>[{visibleCodes.map((code, codeIndex) => renderBoardCode(code, codeIndex === visibleCodes.length - 1))}] </span>;
|
||||
})}
|
||||
{hasHiddenDirectories && !showAllTemporarily && (
|
||||
<>
|
||||
{' '}
|
||||
[
|
||||
<span
|
||||
<button
|
||||
type='button'
|
||||
className={styles.temporaryButton}
|
||||
role='button'
|
||||
tabIndex={0}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
@@ -234,7 +243,7 @@ const BoardsBarDesktop = () => {
|
||||
title='Show all'
|
||||
>
|
||||
...
|
||||
</span>
|
||||
</button>
|
||||
]{' '}
|
||||
</>
|
||||
)}
|
||||
@@ -242,9 +251,9 @@ const BoardsBarDesktop = () => {
|
||||
<>[{visibleSubscriptionAddresses.map((address: string, index: number) => renderSubscription(address, index, visibleSubscriptionAddresses.length))}] </>
|
||||
)}
|
||||
[
|
||||
<span
|
||||
<button
|
||||
type='button'
|
||||
className={styles.temporaryButton}
|
||||
role='button'
|
||||
tabIndex={0}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
@@ -256,11 +265,11 @@ const BoardsBarDesktop = () => {
|
||||
style={{ cursor: 'pointer' }}
|
||||
>
|
||||
{capitalize(t('edit'))}
|
||||
</span>
|
||||
</button>
|
||||
] [
|
||||
<span
|
||||
<button
|
||||
type='button'
|
||||
className={styles.temporaryButton}
|
||||
role='button'
|
||||
tabIndex={0}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
@@ -272,13 +281,13 @@ const BoardsBarDesktop = () => {
|
||||
style={{ cursor: 'pointer' }}
|
||||
>
|
||||
{t('create_board')}
|
||||
</span>
|
||||
</button>
|
||||
]
|
||||
</span>
|
||||
<span className={styles.navTopRight}>
|
||||
[<Link to={!location.pathname.endsWith('settings') ? location.pathname.replace(/\/$/, '') + '/settings' : location.pathname}>{t('settings')}</Link>] [
|
||||
<span
|
||||
role='button'
|
||||
<button
|
||||
type='button'
|
||||
tabIndex={0}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
@@ -288,8 +297,8 @@ const BoardsBarDesktop = () => {
|
||||
}}
|
||||
onClick={() => setShowSearchBar(!showSearchBar)}
|
||||
>
|
||||
{t('search')}
|
||||
</span>
|
||||
{capitalize(t('search'))}
|
||||
</button>
|
||||
] [<Link to='/'>{t('home')}</Link>]
|
||||
</span>
|
||||
{showSearchBar && <SearchBar setShowSearchBar={setShowSearchBar} />}
|
||||
@@ -387,8 +396,8 @@ const BoardsBarMobile = ({ communityAddress }: { communityAddress?: string }) =>
|
||||
</div>
|
||||
<div className={styles.pageJump}>
|
||||
<Link to={location.pathname.replace(/\/$/, '') + '/settings'}>{t('settings')}</Link>
|
||||
<span
|
||||
role='button'
|
||||
<button
|
||||
type='button'
|
||||
tabIndex={0}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
@@ -399,7 +408,7 @@ const BoardsBarMobile = ({ communityAddress }: { communityAddress?: string }) =>
|
||||
onClick={() => setShowSearchBar(!showSearchBar)}
|
||||
>
|
||||
{capitalize(t('search'))}
|
||||
</span>
|
||||
</button>
|
||||
<Link to='/'>{t('home')}</Link>
|
||||
{showSearchBar && <SearchBar setShowSearchBar={setShowSearchBar} />}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user