Merge pull request #174 from LemmyNet/more_accessibility

More accessibility
This commit is contained in:
Dessalines 2021-02-11 15:55:39 -05:00 committed by GitHub
commit 01152eccbb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 169 additions and 19 deletions

18
accessibility_tests.sh Executable file
View file

@ -0,0 +1,18 @@
#!/bin/bash
ignores="WCAG2AA.Principle1.Guideline1_4.1_4_3.G18.Fail"
base_url="http://192.168.50.60:1234"
test_urls=(
$base_url
$base_url/communities
$base_url/login
$base_url/search
$base_url/c/announcements
$base_url/u/dessalines
$base_url/post/34286
)
for i in "${test_urls[@]}"; do
pa11y --ignore="$ignores" "$i"
done

View file

@ -205,7 +205,14 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
onClick={linkEvent(node, this.handleCommentUpvote)} onClick={linkEvent(node, this.handleCommentUpvote)}
data-tippy-content={this.pointsTippy} data-tippy-content={this.pointsTippy}
> >
<span class="mr-1 font-weight-bold">{this.state.score}</span> <span
class="mr-1 font-weight-bold"
aria-label={i18n.t('number_of_points', {
count: this.state.score,
})}
>
{this.state.score}
</span>
</a> </a>
<span className="mr-1"></span> <span className="mr-1"></span>
<span> <span>
@ -409,6 +416,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
this, this,
this.handleModRemoveShow this.handleModRemoveShow
)} )}
aria-label={i18n.t('remove')}
> >
{i18n.t('remove')} {i18n.t('remove')}
</button> </button>
@ -419,6 +427,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
this, this,
this.handleModRemoveSubmit this.handleModRemoveSubmit
)} )}
aria-label={i18n.t('restore')}
> >
{i18n.t('restore')} {i18n.t('restore')}
</button> </button>
@ -436,6 +445,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
this, this,
this.handleModBanFromCommunityShow this.handleModBanFromCommunityShow
)} )}
aria-label={i18n.t('ban')}
> >
{i18n.t('ban')} {i18n.t('ban')}
</button> </button>
@ -446,6 +456,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
this, this,
this.handleModBanFromCommunitySubmit this.handleModBanFromCommunitySubmit
)} )}
aria-label={i18n.t('unban')}
> >
{i18n.t('unban')} {i18n.t('unban')}
</button> </button>
@ -459,6 +470,11 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
this, this,
this.handleShowConfirmAppointAsMod this.handleShowConfirmAppointAsMod
)} )}
aria-label={
this.isMod
? i18n.t('remove_as_mod')
: i18n.t('appoint_as_mod')
}
> >
{this.isMod {this.isMod
? i18n.t('remove_as_mod') ? i18n.t('remove_as_mod')
@ -466,7 +482,10 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
</button> </button>
) : ( ) : (
<> <>
<button class="btn btn-link btn-animate text-muted"> <button
class="btn btn-link btn-animate text-muted"
aria-label={i18n.t('are_you_sure')}
>
{i18n.t('are_you_sure')} {i18n.t('are_you_sure')}
</button> </button>
<button <button
@ -475,6 +494,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
this, this,
this.handleAddModToCommunity this.handleAddModToCommunity
)} )}
aria-label={i18n.t('yes')}
> >
{i18n.t('yes')} {i18n.t('yes')}
</button> </button>
@ -484,6 +504,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
this, this,
this.handleCancelConfirmAppointAsMod this.handleCancelConfirmAppointAsMod
)} )}
aria-label={i18n.t('no')}
> >
{i18n.t('no')} {i18n.t('no')}
</button> </button>
@ -502,12 +523,16 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
this, this,
this.handleShowConfirmTransferCommunity this.handleShowConfirmTransferCommunity
)} )}
aria-label={i18n.t('transfer_community')}
> >
{i18n.t('transfer_community')} {i18n.t('transfer_community')}
</button> </button>
) : ( ) : (
<> <>
<button class="btn btn-link btn-animate text-muted"> <button
class="btn btn-link btn-animate text-muted"
aria-label={i18n.t('are_you_sure')}
>
{i18n.t('are_you_sure')} {i18n.t('are_you_sure')}
</button> </button>
<button <button
@ -516,6 +541,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
this, this,
this.handleTransferCommunity this.handleTransferCommunity
)} )}
aria-label={i18n.t('yes')}
> >
{i18n.t('yes')} {i18n.t('yes')}
</button> </button>
@ -526,6 +552,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
this this
.handleCancelShowConfirmTransferCommunity .handleCancelShowConfirmTransferCommunity
)} )}
aria-label={i18n.t('no')}
> >
{i18n.t('no')} {i18n.t('no')}
</button> </button>
@ -542,6 +569,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
this, this,
this.handleModBanShow this.handleModBanShow
)} )}
aria-label={i18n.t('ban_from_site')}
> >
{i18n.t('ban_from_site')} {i18n.t('ban_from_site')}
</button> </button>
@ -552,6 +580,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
this, this,
this.handleModBanSubmit this.handleModBanSubmit
)} )}
aria-label={i18n.t('unban_from_site')}
> >
{i18n.t('unban_from_site')} {i18n.t('unban_from_site')}
</button> </button>
@ -565,6 +594,11 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
this, this,
this.handleShowConfirmAppointAsAdmin this.handleShowConfirmAppointAsAdmin
)} )}
aria-label={
this.isAdmin
? i18n.t('remove_as_admin')
: i18n.t('appoint_as_admin')
}
> >
{this.isAdmin {this.isAdmin
? i18n.t('remove_as_admin') ? i18n.t('remove_as_admin')
@ -581,6 +615,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
this, this,
this.handleAddAdmin this.handleAddAdmin
)} )}
aria-label={i18n.t('yes')}
> >
{i18n.t('yes')} {i18n.t('yes')}
</button> </button>
@ -590,6 +625,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
this, this,
this.handleCancelConfirmAppointAsAdmin this.handleCancelConfirmAppointAsAdmin
)} )}
aria-label={i18n.t('no')}
> >
{i18n.t('no')} {i18n.t('no')}
</button> </button>
@ -608,12 +644,16 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
this, this,
this.handleShowConfirmTransferSite this.handleShowConfirmTransferSite
)} )}
aria-label={i18n.t('transfer_site')}
> >
{i18n.t('transfer_site')} {i18n.t('transfer_site')}
</button> </button>
) : ( ) : (
<> <>
<button class="btn btn-link btn-animate text-muted"> <button
class="btn btn-link btn-animate text-muted"
aria-label={i18n.t('are_you_sure')}
>
{i18n.t('are_you_sure')} {i18n.t('are_you_sure')}
</button> </button>
<button <button
@ -622,6 +662,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
this, this,
this.handleTransferSite this.handleTransferSite
)} )}
aria-label={i18n.t('yes')}
> >
{i18n.t('yes')} {i18n.t('yes')}
</button> </button>
@ -631,6 +672,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
this, this,
this.handleCancelShowConfirmTransferSite this.handleCancelShowConfirmTransferSite
)} )}
aria-label={i18n.t('no')}
> >
{i18n.t('no')} {i18n.t('no')}
</button> </button>
@ -652,14 +694,25 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
class="form-inline" class="form-inline"
onSubmit={linkEvent(this, this.handleModRemoveSubmit)} onSubmit={linkEvent(this, this.handleModRemoveSubmit)}
> >
<label
class="sr-only"
htmlFor={`mod-remove-reason-${cv.comment.id}`}
>
{i18n.t('reason')}
</label>
<input <input
type="text" type="text"
id={`mod-remove-reason-${cv.comment.id}`}
class="form-control mr-2" class="form-control mr-2"
placeholder={i18n.t('reason')} placeholder={i18n.t('reason')}
value={this.state.removeReason} value={this.state.removeReason}
onInput={linkEvent(this, this.handleModRemoveReasonChange)} onInput={linkEvent(this, this.handleModRemoveReasonChange)}
/> />
<button type="submit" class="btn btn-secondary"> <button
type="submit"
class="btn btn-secondary"
aria-label={i18n.t('remove_comment')}
>
{i18n.t('remove_comment')} {i18n.t('remove_comment')}
</button> </button>
</form> </form>
@ -702,7 +755,11 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
{/* <input type="date" class="form-control mr-2" placeholder={i18n.t('expires')} value={this.state.banExpires} onInput={linkEvent(this, this.handleModBanExpiresChange)} /> */} {/* <input type="date" class="form-control mr-2" placeholder={i18n.t('expires')} value={this.state.banExpires} onInput={linkEvent(this, this.handleModBanExpiresChange)} /> */}
{/* </div> */} {/* </div> */}
<div class="form-group row"> <div class="form-group row">
<button type="submit" class="btn btn-secondary"> <button
type="submit"
class="btn btn-secondary"
aria-label={i18n.t('ban')}
>
{i18n.t('ban')} {cv.creator.name} {i18n.t('ban')} {cv.creator.name}
</button> </button>
</div> </div>

View file

@ -198,6 +198,7 @@ export class Communities extends Component<any, CommunitiesState> {
> >
<input <input
type="text" type="text"
id="communities-search"
class="form-control mr-2 mb-2" class="form-control mr-2 mb-2"
value={this.state.searchText} value={this.state.searchText}
placeholder={`${i18n.t('search')}...`} placeholder={`${i18n.t('search')}...`}
@ -205,6 +206,9 @@ export class Communities extends Component<any, CommunitiesState> {
required required
minLength={3} minLength={3}
/> />
<label class="sr-only" htmlFor="communities-search">
{i18n.t('search')}
</label>
<button type="submit" class="btn btn-secondary mr-2 mb-2"> <button type="submit" class="btn btn-secondary mr-2 mb-2">
<span>{i18n.t('search')}</span> <span>{i18n.t('search')}</span>
</button> </button>

View file

@ -253,6 +253,7 @@ export class Login extends Component<any, State> {
type="button" type="button"
class="btn btn-secondary" class="btn btn-secondary"
onClick={linkEvent(this, this.handleRegenCaptcha)} onClick={linkEvent(this, this.handleRegenCaptcha)}
aria-label={i18n.t('captcha')}
> >
<Icon icon="refresh-cw" classes="icon-refresh-cw" /> <Icon icon="refresh-cw" classes="icon-refresh-cw" />
</button> </button>

View file

@ -139,6 +139,9 @@ export class MarkdownTextArea extends Component<
/> />
)} )}
</div> </div>
<label class="sr-only" htmlFor={this.id}>
{i18n.t('body')}
</label>
</div> </div>
<div class="row"> <div class="row">
<div class="col-sm-12 d-flex flex-wrap"> <div class="col-sm-12 d-flex flex-wrap">
@ -179,6 +182,7 @@ export class MarkdownTextArea extends Component<
<button <button
class="btn btn-sm text-muted" class="btn btn-sm text-muted"
data-tippy-content={i18n.t('bold')} data-tippy-content={i18n.t('bold')}
aria-label={i18n.t('bold')}
onClick={linkEvent(this, this.handleInsertBold)} onClick={linkEvent(this, this.handleInsertBold)}
> >
<Icon icon="bold" classes="icon-inline" /> <Icon icon="bold" classes="icon-inline" />
@ -186,6 +190,7 @@ export class MarkdownTextArea extends Component<
<button <button
class="btn btn-sm text-muted" class="btn btn-sm text-muted"
data-tippy-content={i18n.t('italic')} data-tippy-content={i18n.t('italic')}
aria-label={i18n.t('italic')}
onClick={linkEvent(this, this.handleInsertItalic)} onClick={linkEvent(this, this.handleInsertItalic)}
> >
<Icon icon="italic" classes="icon-inline" /> <Icon icon="italic" classes="icon-inline" />
@ -193,6 +198,7 @@ export class MarkdownTextArea extends Component<
<button <button
class="btn btn-sm text-muted" class="btn btn-sm text-muted"
data-tippy-content={i18n.t('link')} data-tippy-content={i18n.t('link')}
aria-label={i18n.t('link')}
onClick={linkEvent(this, this.handleInsertLink)} onClick={linkEvent(this, this.handleInsertLink)}
> >
<Icon icon="link" classes="icon-inline" /> <Icon icon="link" classes="icon-inline" />

View file

@ -201,7 +201,12 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
> >
<Icon icon="bell" /> <Icon icon="bell" />
{this.state.unreadCount > 0 && ( {this.state.unreadCount > 0 && (
<span class="mx-1 badge badge-light"> <span
class="mx-1 badge badge-light"
aria-label={`${this.state.unreadCount} ${i18n.t(
'unread_messages'
)}`}
>
{this.state.unreadCount} {this.state.unreadCount}
</span> </span>
)} )}
@ -281,6 +286,7 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
onSubmit={linkEvent(this, this.handleSearchSubmit)} onSubmit={linkEvent(this, this.handleSearchSubmit)}
> >
<input <input
id="search-input"
class={`form-control mr-0 search-input ${ class={`form-control mr-0 search-input ${
this.state.toggleSearch ? 'show-input' : 'hide-input' this.state.toggleSearch ? 'show-input' : 'hide-input'
}`} }`}
@ -291,11 +297,15 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
placeholder={i18n.t('search')} placeholder={i18n.t('search')}
onBlur={linkEvent(this, this.handleSearchBlur)} onBlur={linkEvent(this, this.handleSearchBlur)}
></input> ></input>
<label class="sr-only" htmlFor="search-input">
{i18n.t('search')}
</label>
<button <button
name="search-btn" name="search-btn"
onClick={linkEvent(this, this.handleSearchBtn)} onClick={linkEvent(this, this.handleSearchBtn)}
class="px-1 btn btn-link" class="px-1 btn btn-link"
style="color: var(--gray)" style="color: var(--gray)"
aria-label={i18n.t('search')}
> >
<Icon icon="search" /> <Icon icon="search" />
</button> </button>
@ -312,7 +322,12 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
> >
<Icon icon="bell" /> <Icon icon="bell" />
{this.state.unreadCount > 0 && ( {this.state.unreadCount > 0 && (
<span class="ml-1 badge badge-light"> <span
class="ml-1 badge badge-light"
aria-label={`${this.state.unreadCount} ${i18n.t(
'unread_messages'
)}`}
>
{this.state.unreadCount} {this.state.unreadCount}
</span> </span>
)} )}

View file

@ -27,7 +27,6 @@ import {
debounce, debounce,
isImage, isImage,
toast, toast,
randomStr,
setupTippy, setupTippy,
hostname, hostname,
pictrsDeleteToast, pictrsDeleteToast,
@ -72,7 +71,6 @@ interface PostFormState {
} }
export class PostForm extends Component<PostFormProps, PostFormState> { export class PostForm extends Component<PostFormProps, PostFormState> {
private id = `post-form-${randomStr()}`;
private subscription: Subscription; private subscription: Subscription;
private choices: any; private choices: any;
private emptyState: PostFormState = { private emptyState: PostFormState = {
@ -278,9 +276,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-2 col-form-label" htmlFor={this.id}> <label class="col-sm-2 col-form-label">{i18n.t('body')}</label>
{i18n.t('body')}
</label>
<div class="col-sm-10"> <div class="col-sm-10">
<MarkdownTextArea <MarkdownTextArea
initialContent={this.state.postForm.body} initialContent={this.state.postForm.body}

View file

@ -639,6 +639,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
class="btn btn-link btn-animate text-muted py-0" class="btn btn-link btn-animate text-muted py-0"
onClick={linkEvent(this, this.handleEditClick)} onClick={linkEvent(this, this.handleEditClick)}
data-tippy-content={i18n.t('edit')} data-tippy-content={i18n.t('edit')}
aria-label={i18n.t('edit')}
> >
<Icon icon="edit" classes="icon-inline" /> <Icon icon="edit" classes="icon-inline" />
</button> </button>
@ -648,6 +649,9 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
data-tippy-content={ data-tippy-content={
!post_view.post.deleted ? i18n.t('delete') : i18n.t('restore') !post_view.post.deleted ? i18n.t('delete') : i18n.t('restore')
} }
aria-label={
!post_view.post.deleted ? i18n.t('delete') : i18n.t('restore')
}
> >
<Icon <Icon
icon="trash" icon="trash"
@ -675,6 +679,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
class="btn btn-link btn-animate text-muted py-0" class="btn btn-link btn-animate text-muted py-0"
onClick={linkEvent(this, this.handleViewSource)} onClick={linkEvent(this, this.handleViewSource)}
data-tippy-content={i18n.t('view_source')} data-tippy-content={i18n.t('view_source')}
aria-label={i18n.t('view_source')}
> >
<Icon <Icon
icon="file-text" icon="file-text"
@ -692,6 +697,9 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
data-tippy-content={ data-tippy-content={
post_view.post.locked ? i18n.t('unlock') : i18n.t('lock') post_view.post.locked ? i18n.t('unlock') : i18n.t('lock')
} }
aria-label={
post_view.post.locked ? i18n.t('unlock') : i18n.t('lock')
}
> >
<Icon <Icon
icon="lock" icon="lock"
@ -708,6 +716,11 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
? i18n.t('unsticky') ? i18n.t('unsticky')
: i18n.t('sticky') : i18n.t('sticky')
} }
aria-label={
post_view.post.stickied
? i18n.t('unsticky')
: i18n.t('sticky')
}
> >
<Icon <Icon
icon="pin" icon="pin"
@ -724,6 +737,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
<button <button
class="btn btn-link btn-animate text-muted py-0" class="btn btn-link btn-animate text-muted py-0"
onClick={linkEvent(this, this.handleModRemoveShow)} onClick={linkEvent(this, this.handleModRemoveShow)}
aria-label={i18n.t('remove')}
> >
{i18n.t('remove')} {i18n.t('remove')}
</button> </button>
@ -731,6 +745,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
<button <button
class="btn btn-link btn-animate text-muted py-0" class="btn btn-link btn-animate text-muted py-0"
onClick={linkEvent(this, this.handleModRemoveSubmit)} onClick={linkEvent(this, this.handleModRemoveSubmit)}
aria-label={i18n.t('restore')}
> >
{i18n.t('restore')} {i18n.t('restore')}
</button> </button>
@ -745,6 +760,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
this, this,
this.handleModBanFromCommunityShow this.handleModBanFromCommunityShow
)} )}
aria-label={i18n.t('ban')}
> >
{i18n.t('ban')} {i18n.t('ban')}
</button> </button>
@ -755,6 +771,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
this, this,
this.handleModBanFromCommunitySubmit this.handleModBanFromCommunitySubmit
)} )}
aria-label={i18n.t('unban')}
> >
{i18n.t('unban')} {i18n.t('unban')}
</button> </button>
@ -764,6 +781,11 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
<button <button
class="btn btn-link btn-animate text-muted py-0" class="btn btn-link btn-animate text-muted py-0"
onClick={linkEvent(this, this.handleAddModToCommunity)} onClick={linkEvent(this, this.handleAddModToCommunity)}
aria-label={
this.isMod
? i18n.t('remove_as_mod')
: i18n.t('appoint_as_mod')
}
> >
{this.isMod {this.isMod
? i18n.t('remove_as_mod') ? i18n.t('remove_as_mod')
@ -783,16 +805,21 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
this, this,
this.handleShowConfirmTransferCommunity this.handleShowConfirmTransferCommunity
)} )}
aria-label={i18n.t('transfer_community')}
> >
{i18n.t('transfer_community')} {i18n.t('transfer_community')}
</button> </button>
) : ( ) : (
<> <>
<button class="d-inline-block mr-1 btn btn-link btn-animate text-muted py-0"> <button
class="d-inline-block mr-1 btn btn-link btn-animate text-muted py-0"
aria-label={i18n.t('are_you_sure')}
>
{i18n.t('are_you_sure')} {i18n.t('are_you_sure')}
</button> </button>
<button <button
class="btn btn-link btn-animate text-muted py-0 d-inline-block mr-1" class="btn btn-link btn-animate text-muted py-0 d-inline-block mr-1"
aria-label={i18n.t('yes')}
onClick={linkEvent(this, this.handleTransferCommunity)} onClick={linkEvent(this, this.handleTransferCommunity)}
> >
{i18n.t('yes')} {i18n.t('yes')}
@ -803,6 +830,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
this, this,
this.handleCancelShowConfirmTransferCommunity this.handleCancelShowConfirmTransferCommunity
)} )}
aria-label={i18n.t('no')}
> >
{i18n.t('no')} {i18n.t('no')}
</button> </button>
@ -816,6 +844,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
<button <button
class="btn btn-link btn-animate text-muted py-0" class="btn btn-link btn-animate text-muted py-0"
onClick={linkEvent(this, this.handleModBanShow)} onClick={linkEvent(this, this.handleModBanShow)}
aria-label={i18n.t('ban_from_site')}
> >
{i18n.t('ban_from_site')} {i18n.t('ban_from_site')}
</button> </button>
@ -823,6 +852,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
<button <button
class="btn btn-link btn-animate text-muted py-0" class="btn btn-link btn-animate text-muted py-0"
onClick={linkEvent(this, this.handleModBanSubmit)} onClick={linkEvent(this, this.handleModBanSubmit)}
aria-label={i18n.t('unban_from_site')}
> >
{i18n.t('unban_from_site')} {i18n.t('unban_from_site')}
</button> </button>
@ -831,6 +861,11 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
<button <button
class="btn btn-link btn-animate text-muted py-0" class="btn btn-link btn-animate text-muted py-0"
onClick={linkEvent(this, this.handleAddAdmin)} onClick={linkEvent(this, this.handleAddAdmin)}
aria-label={
this.isAdmin
? i18n.t('remove_as_admin')
: i18n.t('appoint_as_admin')
}
> >
{this.isAdmin {this.isAdmin
? i18n.t('remove_as_admin') ? i18n.t('remove_as_admin')
@ -849,17 +884,22 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
this, this,
this.handleShowConfirmTransferSite this.handleShowConfirmTransferSite
)} )}
aria-label={i18n.t('transfer_site')}
> >
{i18n.t('transfer_site')} {i18n.t('transfer_site')}
</button> </button>
) : ( ) : (
<> <>
<button class="btn btn-link btn-animate text-muted py-0 d-inline-block mr-1"> <button
class="btn btn-link btn-animate text-muted py-0 d-inline-block mr-1"
aria-label={i18n.t('are_you_sure')}
>
{i18n.t('are_you_sure')} {i18n.t('are_you_sure')}
</button> </button>
<button <button
class="btn btn-link btn-animate text-muted py-0 d-inline-block mr-1" class="btn btn-link btn-animate text-muted py-0 d-inline-block mr-1"
onClick={linkEvent(this, this.handleTransferSite)} onClick={linkEvent(this, this.handleTransferSite)}
aria-label={i18n.t('yes')}
> >
{i18n.t('yes')} {i18n.t('yes')}
</button> </button>
@ -869,6 +909,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
this, this,
this.handleCancelShowConfirmTransferSite this.handleCancelShowConfirmTransferSite
)} )}
aria-label={i18n.t('no')}
> >
{i18n.t('no')} {i18n.t('no')}
</button> </button>
@ -890,14 +931,22 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
class="form-inline" class="form-inline"
onSubmit={linkEvent(this, this.handleModRemoveSubmit)} onSubmit={linkEvent(this, this.handleModRemoveSubmit)}
> >
<label class="sr-only" htmlFor="post-listing-remove-reason">
{i18n.t('reason')}
</label>
<input <input
type="text" type="text"
id="post-listing-remove-reason"
class="form-control mr-2" class="form-control mr-2"
placeholder={i18n.t('reason')} placeholder={i18n.t('reason')}
value={this.state.removeReason} value={this.state.removeReason}
onInput={linkEvent(this, this.handleModRemoveReasonChange)} onInput={linkEvent(this, this.handleModRemoveReasonChange)}
/> />
<button type="submit" class="btn btn-secondary"> <button
type="submit"
class="btn btn-secondary"
aria-label={i18n.t('remove_post')}
>
{i18n.t('remove_post')} {i18n.t('remove_post')}
</button> </button>
</form> </form>
@ -905,12 +954,12 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
{this.state.showBanDialog && ( {this.state.showBanDialog && (
<form onSubmit={linkEvent(this, this.handleModBanBothSubmit)}> <form onSubmit={linkEvent(this, this.handleModBanBothSubmit)}>
<div class="form-group row"> <div class="form-group row">
<label class="col-form-label" htmlFor="post-listing-reason"> <label class="col-form-label" htmlFor="post-listing-ban-reason">
{i18n.t('reason')} {i18n.t('reason')}
</label> </label>
<input <input
type="text" type="text"
id="post-listing-reason" id="post-listing-ban-reason"
class="form-control mr-2" class="form-control mr-2"
placeholder={i18n.t('reason')} placeholder={i18n.t('reason')}
value={this.state.banReason} value={this.state.banReason}
@ -937,7 +986,11 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
{/* <input type="date" class="form-control mr-2" placeholder={i18n.t('expires')} value={this.state.banExpires} onInput={linkEvent(this, this.handleModBanExpiresChange)} /> */} {/* <input type="date" class="form-control mr-2" placeholder={i18n.t('expires')} value={this.state.banExpires} onInput={linkEvent(this, this.handleModBanExpiresChange)} /> */}
{/* </div> */} {/* </div> */}
<div class="form-group row"> <div class="form-group row">
<button type="submit" class="btn btn-secondary"> <button
type="submit"
class="btn btn-secondary"
aria-label={i18n.t('ban')}
>
{i18n.t('ban')} {post.creator.name} {i18n.t('ban')} {post.creator.name}
</button> </button>
</div> </div>