mirror of
https://github.com/LemmyNet/lemmy-ui.git
synced 2024-11-26 06:11:15 +00:00
Add aria attributes where possible (#156)
* Add aria attributes where possible * Bump submodule to get aria translations
This commit is contained in:
parent
ef19b9f6b8
commit
04955cc45e
19 changed files with 137 additions and 19 deletions
|
@ -1 +1 @@
|
|||
Subproject commit a47ae3f825f74ad7a6106b92e21d3c66b10d3fe8
|
||||
Subproject commit 084ce539fff5253317d6460598b10a6867999c20
|
|
@ -14,12 +14,13 @@ export class BannerIconHeader extends Component<BannerIconHeaderProps, any> {
|
|||
render() {
|
||||
return (
|
||||
<div class="position-relative mb-2">
|
||||
{this.props.banner && <PictrsImage src={this.props.banner} />}
|
||||
{this.props.banner && <PictrsImage src={this.props.banner} alt="" />}
|
||||
{this.props.icon && (
|
||||
<PictrsImage
|
||||
src={this.props.icon}
|
||||
iconOverlay
|
||||
pushup={!!this.props.banner}
|
||||
alt=""
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
@ -198,6 +198,9 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
|||
<button
|
||||
class="btn btn-sm text-muted"
|
||||
onClick={linkEvent(this, this.handleCommentCollapse)}
|
||||
aria-label={
|
||||
this.state.collapsed ? i18n.t('expand') : i18n.t('collapse')
|
||||
}
|
||||
>
|
||||
{this.state.collapsed ? '+' : '—'}
|
||||
</button>
|
||||
|
@ -248,6 +251,11 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
|||
? i18n.t('mark_as_unread')
|
||||
: i18n.t('mark_as_read')
|
||||
}
|
||||
aria-label={
|
||||
this.commentOrMentionRead
|
||||
? i18n.t('mark_as_unread')
|
||||
: i18n.t('mark_as_read')
|
||||
}
|
||||
>
|
||||
{this.state.readLoading ? (
|
||||
this.loadingIcon
|
||||
|
@ -270,6 +278,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
|||
}`}
|
||||
onClick={linkEvent(node, this.handleCommentUpvote)}
|
||||
data-tippy-content={i18n.t('upvote')}
|
||||
aria-label={i18n.t('upvote')}
|
||||
>
|
||||
<svg class="icon icon-inline">
|
||||
<use xlinkHref="#icon-arrow-up1"></use>
|
||||
|
@ -287,6 +296,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
|||
}`}
|
||||
onClick={linkEvent(node, this.handleCommentDownvote)}
|
||||
data-tippy-content={i18n.t('downvote')}
|
||||
aria-label={i18n.t('downvote')}
|
||||
>
|
||||
<svg class="icon icon-inline">
|
||||
<use xlinkHref="#icon-arrow-down1"></use>
|
||||
|
@ -300,6 +310,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
|||
class="btn btn-link btn-animate text-muted"
|
||||
onClick={linkEvent(this, this.handleReplyClick)}
|
||||
data-tippy-content={i18n.t('reply')}
|
||||
aria-label={i18n.t('reply')}
|
||||
>
|
||||
<svg class="icon icon-inline">
|
||||
<use xlinkHref="#icon-reply1"></use>
|
||||
|
@ -310,6 +321,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
|||
className="btn btn-link btn-animate text-muted"
|
||||
onClick={linkEvent(this, this.handleShowAdvanced)}
|
||||
data-tippy-content={i18n.t('more')}
|
||||
aria-label={i18n.t('more')}
|
||||
>
|
||||
<svg class="icon icon-inline">
|
||||
<use xlinkHref="#icon-more-vertical"></use>
|
||||
|
@ -340,6 +352,9 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
|||
data-tippy-content={
|
||||
cv.saved ? i18n.t('unsave') : i18n.t('save')
|
||||
}
|
||||
aria-label={
|
||||
cv.saved ? i18n.t('unsave') : i18n.t('save')
|
||||
}
|
||||
>
|
||||
{this.state.saveLoading ? (
|
||||
this.loadingIcon
|
||||
|
@ -357,6 +372,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
|||
className="btn btn-link btn-animate text-muted"
|
||||
onClick={linkEvent(this, this.handleViewSource)}
|
||||
data-tippy-content={i18n.t('view_source')}
|
||||
aria-label={i18n.t('view_source')}
|
||||
>
|
||||
<svg
|
||||
class={`icon icon-inline ${
|
||||
|
@ -372,6 +388,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
|||
class="btn btn-link btn-animate text-muted"
|
||||
onClick={linkEvent(this, this.handleEditClick)}
|
||||
data-tippy-content={i18n.t('edit')}
|
||||
aria-label={i18n.t('edit')}
|
||||
>
|
||||
<svg class="icon icon-inline">
|
||||
<use xlinkHref="#icon-edit"></use>
|
||||
|
@ -388,6 +405,11 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
|||
? i18n.t('delete')
|
||||
: i18n.t('restore')
|
||||
}
|
||||
aria-label={
|
||||
!cv.comment.deleted
|
||||
? i18n.t('delete')
|
||||
: i18n.t('restore')
|
||||
}
|
||||
>
|
||||
<svg
|
||||
class={`icon icon-inline ${
|
||||
|
@ -667,9 +689,15 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
|||
{this.state.showBanDialog && (
|
||||
<form onSubmit={linkEvent(this, this.handleModBanBothSubmit)}>
|
||||
<div class="form-group row">
|
||||
<label class="col-form-label">{i18n.t('reason')}</label>
|
||||
<label
|
||||
class="col-form-label"
|
||||
htmlFor={`mod-ban-reason-${cv.comment.id}`}
|
||||
>
|
||||
{i18n.t('reason')}
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
id={`mod-ban-reason-${cv.comment.id}`}
|
||||
class="form-control mr-2"
|
||||
placeholder={i18n.t('reason')}
|
||||
value={this.state.banReason}
|
||||
|
|
|
@ -158,6 +158,7 @@ export class Communities extends Component<any, CommunitiesState> {
|
|||
{cv.subscribed ? (
|
||||
<span
|
||||
class="pointer btn-link"
|
||||
role="button"
|
||||
onClick={linkEvent(
|
||||
cv.community.id,
|
||||
this.handleUnsubscribe
|
||||
|
@ -168,6 +169,7 @@ export class Communities extends Component<any, CommunitiesState> {
|
|||
) : (
|
||||
<span
|
||||
class="pointer btn-link"
|
||||
role="button"
|
||||
onClick={linkEvent(
|
||||
cv.community.id,
|
||||
this.handleSubscribe
|
||||
|
|
|
@ -2,6 +2,7 @@ import { Component, linkEvent } from 'inferno';
|
|||
import { pictrsUri } from '../env';
|
||||
import { UserService } from '../services';
|
||||
import { toast, randomStr } from '../utils';
|
||||
import { i18n } from '../i18next';
|
||||
|
||||
interface ImageUploadFormProps {
|
||||
uploadTitle: string;
|
||||
|
@ -48,7 +49,10 @@ export class ImageUploadForm extends Component<
|
|||
this.props.rounded ? 'rounded-circle' : ''
|
||||
}`}
|
||||
/>
|
||||
<a onClick={linkEvent(this, this.handleRemoveImage)}>
|
||||
<a
|
||||
onClick={linkEvent(this, this.handleRemoveImage)}
|
||||
aria-label={i18n.t('remove')}
|
||||
>
|
||||
<svg class="icon mini-overlay">
|
||||
<use xlinkHref="#icon-x"></use>
|
||||
</svg>
|
||||
|
|
|
@ -172,6 +172,7 @@ export class Inbox extends Component<any, InboxState> {
|
|||
<li className="list-inline-item">
|
||||
<span
|
||||
class="pointer"
|
||||
role="button"
|
||||
onClick={linkEvent(this, this.markAllAsRead)}
|
||||
>
|
||||
{i18n.t('mark_all_as_read')}
|
||||
|
|
|
@ -326,6 +326,7 @@ export class Login extends Component<any, State> {
|
|||
class="rounded-top img-fluid"
|
||||
src={this.captchaPngSrc()}
|
||||
style="border-bottom-right-radius: 0; border-bottom-left-radius: 0;"
|
||||
alt={i18n.t('captcha')}
|
||||
/>
|
||||
{this.state.captcha.ok.wav && (
|
||||
<button
|
||||
|
|
|
@ -508,7 +508,9 @@ export class Main extends Component<any, MainState> {
|
|||
<li className="list-inline-item-action">
|
||||
<span
|
||||
class="pointer"
|
||||
role="button"
|
||||
onClick={linkEvent(this, this.handleEditClick)}
|
||||
aria-label={i18n.t('edit')}
|
||||
data-tippy-content={i18n.t('edit')}
|
||||
>
|
||||
<svg class="icon icon-inline">
|
||||
|
|
|
@ -233,6 +233,7 @@ export class MarkdownTextArea extends Component<
|
|||
<button
|
||||
class="btn btn-sm text-muted"
|
||||
data-tippy-content={i18n.t('header')}
|
||||
aria-label={i18n.t('header')}
|
||||
onClick={linkEvent(this, this.handleInsertHeader)}
|
||||
>
|
||||
<svg class="icon icon-inline">
|
||||
|
@ -242,6 +243,7 @@ export class MarkdownTextArea extends Component<
|
|||
<button
|
||||
class="btn btn-sm text-muted"
|
||||
data-tippy-content={i18n.t('strikethrough')}
|
||||
aria-label={i18n.t('strikethrough')}
|
||||
onClick={linkEvent(this, this.handleInsertStrikethrough)}
|
||||
>
|
||||
<svg class="icon icon-inline">
|
||||
|
@ -251,6 +253,7 @@ export class MarkdownTextArea extends Component<
|
|||
<button
|
||||
class="btn btn-sm text-muted"
|
||||
data-tippy-content={i18n.t('quote')}
|
||||
aria-label={i18n.t('quote')}
|
||||
onClick={linkEvent(this, this.handleInsertQuote)}
|
||||
>
|
||||
<svg class="icon icon-inline">
|
||||
|
@ -260,6 +263,7 @@ export class MarkdownTextArea extends Component<
|
|||
<button
|
||||
class="btn btn-sm text-muted"
|
||||
data-tippy-content={i18n.t('list')}
|
||||
aria-label={i18n.t('list')}
|
||||
onClick={linkEvent(this, this.handleInsertList)}
|
||||
>
|
||||
<svg class="icon icon-inline">
|
||||
|
@ -269,6 +273,7 @@ export class MarkdownTextArea extends Component<
|
|||
<button
|
||||
class="btn btn-sm text-muted"
|
||||
data-tippy-content={i18n.t('code')}
|
||||
aria-label={i18n.t('code')}
|
||||
onClick={linkEvent(this, this.handleInsertCode)}
|
||||
>
|
||||
<svg class="icon icon-inline">
|
||||
|
@ -278,6 +283,7 @@ export class MarkdownTextArea extends Component<
|
|||
<button
|
||||
class="btn btn-sm text-muted"
|
||||
data-tippy-content={i18n.t('subscript')}
|
||||
aria-label={i18n.t('subscript')}
|
||||
onClick={linkEvent(this, this.handleInsertSubscript)}
|
||||
>
|
||||
<svg class="icon icon-inline">
|
||||
|
@ -287,6 +293,7 @@ export class MarkdownTextArea extends Component<
|
|||
<button
|
||||
class="btn btn-sm text-muted"
|
||||
data-tippy-content={i18n.t('superscript')}
|
||||
aria-label={i18n.t('superscript')}
|
||||
onClick={linkEvent(this, this.handleInsertSuperscript)}
|
||||
>
|
||||
<svg class="icon icon-inline">
|
||||
|
@ -296,6 +303,7 @@ export class MarkdownTextArea extends Component<
|
|||
<button
|
||||
class="btn btn-sm text-muted"
|
||||
data-tippy-content={i18n.t('spoiler')}
|
||||
aria-label={i18n.t('spoiler')}
|
||||
onClick={linkEvent(this, this.handleInsertSpoiler)}
|
||||
>
|
||||
<svg class="icon icon-inline">
|
||||
|
|
|
@ -80,11 +80,12 @@ export class PasswordChange extends Component<any, State> {
|
|||
return (
|
||||
<form onSubmit={linkEvent(this, this.handlePasswordChangeSubmit)}>
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-2 col-form-label">
|
||||
<label class="col-sm-2 col-form-label" htmlFor="new-password">
|
||||
{i18n.t('new_password')}
|
||||
</label>
|
||||
<div class="col-sm-10">
|
||||
<input
|
||||
id="new-password"
|
||||
type="password"
|
||||
value={this.state.passwordChangeForm.password}
|
||||
onInput={linkEvent(this, this.handlePasswordChange)}
|
||||
|
@ -94,11 +95,12 @@ export class PasswordChange extends Component<any, State> {
|
|||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-2 col-form-label">
|
||||
<label class="col-sm-2 col-form-label" htmlFor="verify-password">
|
||||
{i18n.t('verify_password')}
|
||||
</label>
|
||||
<div class="col-sm-10">
|
||||
<input
|
||||
id="verify-password"
|
||||
type="password"
|
||||
value={this.state.passwordChangeForm.password_verify}
|
||||
onInput={linkEvent(this, this.handleVerifyPasswordChange)}
|
||||
|
|
|
@ -6,6 +6,7 @@ const maxImageSize = 3000;
|
|||
|
||||
interface PictrsImageProps {
|
||||
src: string;
|
||||
alt?: string;
|
||||
icon?: boolean;
|
||||
thumbnail?: boolean;
|
||||
nsfw?: boolean;
|
||||
|
@ -25,6 +26,7 @@ export class PictrsImage extends Component<PictrsImageProps, any> {
|
|||
<source srcSet={this.src('jpg')} type="image/jpeg" />
|
||||
<img
|
||||
src={this.src('jpg')}
|
||||
alt={this.alt()}
|
||||
className={`
|
||||
${!this.props.icon && !this.props.iconOverlay && 'img-fluid '}
|
||||
${
|
||||
|
@ -71,4 +73,11 @@ export class PictrsImage extends Component<PictrsImageProps, any> {
|
|||
|
||||
return out;
|
||||
}
|
||||
|
||||
alt(): string {
|
||||
if (this.props.icon) {
|
||||
return '';
|
||||
}
|
||||
return this.props.alt || '';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -180,6 +180,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
|||
{this.state.suggestedTitle && (
|
||||
<div
|
||||
class="mt-1 text-muted small font-weight-bold pointer"
|
||||
role="button"
|
||||
onClick={linkEvent(this, this.copySuggestedTitle)}
|
||||
>
|
||||
{i18n.t('copy_suggested_title', {
|
||||
|
@ -227,7 +228,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
|||
</svg>
|
||||
)}
|
||||
{isImage(this.state.postForm.url) && (
|
||||
<img src={this.state.postForm.url} class="img-fluid" />
|
||||
<img src={this.state.postForm.url} class="img-fluid" alt="" />
|
||||
)}
|
||||
{this.state.crossPosts.length > 0 && (
|
||||
<>
|
||||
|
|
|
@ -169,6 +169,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
<PictrsImage
|
||||
src={src}
|
||||
thumbnail
|
||||
alt=""
|
||||
nsfw={post_view.post.nsfw || post_view.community.nsfw}
|
||||
/>
|
||||
);
|
||||
|
@ -200,6 +201,8 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
class="float-right text-body pointer d-inline-block position-relative mb-2"
|
||||
data-tippy-content={i18n.t('expand_here')}
|
||||
onClick={linkEvent(this, this.handleImageExpandClick)}
|
||||
role="button"
|
||||
aria-label={i18n.t('expand_here')}
|
||||
>
|
||||
{this.imgThumb(this.getImageSrc())}
|
||||
<svg class="icon mini-overlay">
|
||||
|
@ -328,6 +331,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
previewLines(post_view.post.body)
|
||||
)}
|
||||
data-tippy-allowHtml={true}
|
||||
aria-label={i18n.t('upvote')}
|
||||
to={`/post/${post_view.post.id}`}
|
||||
>
|
||||
<svg class="mr-1 icon icon-inline">
|
||||
|
@ -350,6 +354,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
}`}
|
||||
onClick={linkEvent(this, this.handlePostLike)}
|
||||
data-tippy-content={i18n.t('upvote')}
|
||||
aria-label={i18n.t('upvote')}
|
||||
>
|
||||
<svg class="icon upvote">
|
||||
<use xlinkHref="#icon-arrow-up1"></use>
|
||||
|
@ -368,6 +373,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
}`}
|
||||
onClick={linkEvent(this, this.handlePostDisLike)}
|
||||
data-tippy-content={i18n.t('downvote')}
|
||||
aria-label={i18n.t('downvote')}
|
||||
>
|
||||
<svg class="icon downvote">
|
||||
<use xlinkHref="#icon-arrow-down1"></use>
|
||||
|
@ -504,6 +510,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
<button
|
||||
class="btn text-muted py-0 pr-0"
|
||||
data-tippy-content={this.pointsTippy}
|
||||
aria-label={i18n.t('downvote')}
|
||||
>
|
||||
<small>
|
||||
<svg class="icon icon-inline mr-1">
|
||||
|
@ -520,6 +527,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
data-tippy-content={
|
||||
post_view.saved ? i18n.t('unsave') : i18n.t('save')
|
||||
}
|
||||
aria-label={post_view.saved ? i18n.t('unsave') : i18n.t('save')}
|
||||
>
|
||||
<small>
|
||||
<svg
|
||||
|
@ -545,6 +553,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
}`}
|
||||
data-tippy-content={this.pointsTippy}
|
||||
onClick={linkEvent(this, this.handlePostLike)}
|
||||
aria-label={i18n.t('upvote')}
|
||||
>
|
||||
<svg class="small icon icon-inline mr-2">
|
||||
<use xlinkHref="#icon-arrow-up1"></use>
|
||||
|
@ -558,6 +567,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
}`}
|
||||
onClick={linkEvent(this, this.handlePostDisLike)}
|
||||
data-tippy-content={this.pointsTippy}
|
||||
aria-label={i18n.t('downvote')}
|
||||
>
|
||||
<svg class="small icon icon-inline mr-2">
|
||||
<use xlinkHref="#icon-arrow-down1"></use>
|
||||
|
@ -571,6 +581,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
<button
|
||||
class="btn btn-link btn-animate text-muted py-0 pl-1 pr-0"
|
||||
onClick={linkEvent(this, this.handleSavePostClick)}
|
||||
aria-label={post_view.saved ? i18n.t('unsave') : i18n.t('save')}
|
||||
data-tippy-content={
|
||||
post_view.saved ? i18n.t('unsave') : i18n.t('save')
|
||||
}
|
||||
|
@ -586,6 +597,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
<button
|
||||
class="btn btn-link btn-animate text-muted py-0"
|
||||
onClick={linkEvent(this, this.handleShowMoreMobile)}
|
||||
aria-label={i18n.t('more')}
|
||||
data-tippy-content={i18n.t('more')}
|
||||
>
|
||||
<svg class="icon icon-inline">
|
||||
|
@ -639,6 +651,9 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
data-tippy-content={
|
||||
post_view.saved ? i18n.t('unsave') : i18n.t('save')
|
||||
}
|
||||
aria-label={
|
||||
post_view.saved ? i18n.t('unsave') : i18n.t('save')
|
||||
}
|
||||
>
|
||||
<svg
|
||||
class={`icon icon-inline ${
|
||||
|
@ -694,6 +709,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
class="btn btn-link btn-animate text-muted py-0"
|
||||
onClick={linkEvent(this, this.handleShowAdvanced)}
|
||||
data-tippy-content={i18n.t('more')}
|
||||
aria-label={i18n.t('more')}
|
||||
>
|
||||
<svg class="icon icon-inline">
|
||||
<use xlinkHref="#icon-more-vertical"></use>
|
||||
|
|
|
@ -116,8 +116,10 @@ export class PrivateMessageForm extends Component<
|
|||
{i18n.t('message')}
|
||||
<span
|
||||
onClick={linkEvent(this, this.handleShowDisclaimer)}
|
||||
role="button"
|
||||
class="ml-2 pointer text-danger"
|
||||
data-tippy-content={i18n.t('disclaimer')}
|
||||
aria-label={i18n.t('disclaimer')}
|
||||
>
|
||||
<svg class={`icon icon-inline`}>
|
||||
<use xlinkHref="#icon-alert-triangle"></use>
|
||||
|
|
|
@ -77,6 +77,7 @@ export class PrivateMessage extends Component<
|
|||
</li>
|
||||
<li className="list-inline-item">
|
||||
<div
|
||||
role="button"
|
||||
className="pointer text-monospace"
|
||||
onClick={linkEvent(this, this.handleMessageCollapse)}
|
||||
>
|
||||
|
@ -123,6 +124,11 @@ export class PrivateMessage extends Component<
|
|||
? i18n.t('mark_as_unread')
|
||||
: i18n.t('mark_as_read')
|
||||
}
|
||||
aria-label={
|
||||
message_view.private_message.read
|
||||
? i18n.t('mark_as_unread')
|
||||
: i18n.t('mark_as_read')
|
||||
}
|
||||
>
|
||||
<svg
|
||||
class={`icon icon-inline ${
|
||||
|
@ -138,6 +144,7 @@ export class PrivateMessage extends Component<
|
|||
class="btn btn-link btn-animate text-muted"
|
||||
onClick={linkEvent(this, this.handleReplyClick)}
|
||||
data-tippy-content={i18n.t('reply')}
|
||||
aria-label={i18n.t('reply')}
|
||||
>
|
||||
<svg class="icon icon-inline">
|
||||
<use xlinkHref="#icon-reply1"></use>
|
||||
|
@ -153,6 +160,7 @@ export class PrivateMessage extends Component<
|
|||
class="btn btn-link btn-animate text-muted"
|
||||
onClick={linkEvent(this, this.handleEditClick)}
|
||||
data-tippy-content={i18n.t('edit')}
|
||||
aria-label={i18n.t('edit')}
|
||||
>
|
||||
<svg class="icon icon-inline">
|
||||
<use xlinkHref="#icon-edit"></use>
|
||||
|
@ -168,6 +176,11 @@ export class PrivateMessage extends Component<
|
|||
? i18n.t('delete')
|
||||
: i18n.t('restore')
|
||||
}
|
||||
aria-label={
|
||||
!message_view.private_message.deleted
|
||||
? i18n.t('delete')
|
||||
: i18n.t('restore')
|
||||
}
|
||||
>
|
||||
<svg
|
||||
class={`icon icon-inline ${
|
||||
|
@ -186,6 +199,7 @@ export class PrivateMessage extends Component<
|
|||
class="btn btn-link btn-animate text-muted"
|
||||
onClick={linkEvent(this, this.handleViewSource)}
|
||||
data-tippy-content={i18n.t('view_source')}
|
||||
aria-label={i18n.t('view_source')}
|
||||
>
|
||||
<svg
|
||||
class={`icon icon-inline ${
|
||||
|
|
|
@ -209,6 +209,7 @@ export class Search extends Component<any, SearchState> {
|
|||
class="form-control mr-2 mb-2"
|
||||
value={this.state.searchText}
|
||||
placeholder={`${i18n.t('search')}...`}
|
||||
aria-label={i18n.t('search')}
|
||||
onInput={linkEvent(this, this.handleQChange)}
|
||||
required
|
||||
minLength={3}
|
||||
|
@ -233,8 +234,11 @@ export class Search extends Component<any, SearchState> {
|
|||
value={this.state.type_}
|
||||
onChange={linkEvent(this, this.handleTypeChange)}
|
||||
class="custom-select w-auto mb-2"
|
||||
aria-label={i18n.t('type')}
|
||||
>
|
||||
<option disabled>{i18n.t('type')}</option>
|
||||
<option disabled aria-hidden="true">
|
||||
{i18n.t('type')}
|
||||
</option>
|
||||
<option value={SearchType.All}>{i18n.t('all')}</option>
|
||||
<option value={SearchType.Comments}>{i18n.t('comments')}</option>
|
||||
<option value={SearchType.Posts}>{i18n.t('posts')}</option>
|
||||
|
|
|
@ -299,9 +299,11 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
|
|||
<>
|
||||
<li className="list-inline-item-action">
|
||||
<span
|
||||
role="button"
|
||||
class="pointer"
|
||||
onClick={linkEvent(this, this.handleEditClick)}
|
||||
data-tippy-content={i18n.t('edit')}
|
||||
aria-label={i18n.t('edit')}
|
||||
>
|
||||
<svg class="icon icon-inline">
|
||||
<use xlinkHref="#icon-edit"></use>
|
||||
|
@ -313,6 +315,7 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
|
|||
<li className="list-inline-item-action">
|
||||
<span
|
||||
class="pointer"
|
||||
role="button"
|
||||
onClick={linkEvent(
|
||||
this,
|
||||
this.handleShowConfirmLeaveModTeamClick
|
||||
|
@ -329,6 +332,7 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
|
|||
<li className="list-inline-item-action">
|
||||
<span
|
||||
class="pointer"
|
||||
role="button"
|
||||
onClick={linkEvent(this, this.handleLeaveModTeamClick)}
|
||||
>
|
||||
{i18n.t('yes')}
|
||||
|
@ -337,6 +341,7 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
|
|||
<li className="list-inline-item-action">
|
||||
<span
|
||||
class="pointer"
|
||||
role="button"
|
||||
onClick={linkEvent(
|
||||
this,
|
||||
this.handleCancelLeaveModTeamClick
|
||||
|
@ -357,6 +362,11 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
|
|||
? i18n.t('delete')
|
||||
: i18n.t('restore')
|
||||
}
|
||||
aria-label={
|
||||
!community_view.community.deleted
|
||||
? i18n.t('delete')
|
||||
: i18n.t('restore')
|
||||
}
|
||||
>
|
||||
<svg
|
||||
class={`icon icon-inline ${
|
||||
|
@ -375,6 +385,7 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
|
|||
{!this.props.community_view.community.removed ? (
|
||||
<span
|
||||
class="pointer"
|
||||
role="button"
|
||||
onClick={linkEvent(this, this.handleModRemoveShow)}
|
||||
>
|
||||
{i18n.t('remove')}
|
||||
|
@ -382,6 +393,7 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
|
|||
) : (
|
||||
<span
|
||||
class="pointer"
|
||||
role="button"
|
||||
onClick={linkEvent(this, this.handleModRemoveSubmit)}
|
||||
>
|
||||
{i18n.t('restore')}
|
||||
|
|
|
@ -40,8 +40,9 @@ export class SortSelect extends Component<SortSelectProps, SortSelectState> {
|
|||
value={this.state.sort}
|
||||
onChange={linkEvent(this, this.handleSortChange)}
|
||||
class="custom-select w-auto mr-2 mb-2"
|
||||
aria-label={i18n.t('sort_type')}
|
||||
>
|
||||
<option disabled>{i18n.t('sort_type')}</option>
|
||||
<option disabled aria-hidden="true">{i18n.t('sort_type')}</option>
|
||||
{!this.props.hideHot && [
|
||||
<option value={SortType.Hot}>{i18n.t('hot')}</option>,
|
||||
<option value={SortType.Active}>{i18n.t('active')}</option>,
|
||||
|
@ -52,7 +53,7 @@ export class SortSelect extends Component<SortSelectProps, SortSelectState> {
|
|||
{i18n.t('most_comments')}
|
||||
</option>
|
||||
)}
|
||||
<option disabled>─────</option>
|
||||
<option disabled aria-hidden="true">─────</option>
|
||||
<option value={SortType.TopDay}>{i18n.t('top_day')}</option>
|
||||
<option value={SortType.TopWeek}>{i18n.t('top_week')}</option>
|
||||
<option value={SortType.TopMonth}>{i18n.t('top_month')}</option>
|
||||
|
|
|
@ -526,28 +526,36 @@ export class User extends Component<any, UserState> {
|
|||
/>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>{i18n.t('language')}</label>
|
||||
<label htmlFor="user-language">{i18n.t('language')}</label>
|
||||
<select
|
||||
id="user-language"
|
||||
value={this.state.userSettingsForm.lang}
|
||||
onChange={linkEvent(this, this.handleUserSettingsLangChange)}
|
||||
class="ml-2 custom-select w-auto"
|
||||
>
|
||||
<option disabled>{i18n.t('language')}</option>
|
||||
<option disabled aria-hidden="true">
|
||||
{i18n.t('language')}
|
||||
</option>
|
||||
<option value="browser">{i18n.t('browser_default')}</option>
|
||||
<option disabled>──</option>
|
||||
<option disabled aria-hidden="true">
|
||||
──
|
||||
</option>
|
||||
{languages.map(lang => (
|
||||
<option value={lang.code}>{lang.name}</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>{i18n.t('theme')}</label>
|
||||
<label htmlFor="user-theme">{i18n.t('theme')}</label>
|
||||
<select
|
||||
id="user-theme"
|
||||
value={this.state.userSettingsForm.theme}
|
||||
onChange={linkEvent(this, this.handleUserSettingsThemeChange)}
|
||||
class="ml-2 custom-select w-auto"
|
||||
>
|
||||
<option disabled>{i18n.t('theme')}</option>
|
||||
<option disabled aria-hidden="true">
|
||||
{i18n.t('theme')}
|
||||
</option>
|
||||
<option value="browser">{i18n.t('browser_default')}</option>
|
||||
{themes.map(theme => (
|
||||
<option value={theme}>{theme}</option>
|
||||
|
@ -584,11 +592,12 @@ export class User extends Component<any, UserState> {
|
|||
/>
|
||||
</form>
|
||||
<div class="form-group row">
|
||||
<label class="col-lg-5 col-form-label">
|
||||
<label class="col-lg-5 col-form-label" htmlFor="display-name">
|
||||
{i18n.t('display_name')}
|
||||
</label>
|
||||
<div class="col-lg-7">
|
||||
<input
|
||||
id="display-name"
|
||||
type="text"
|
||||
class="form-control"
|
||||
placeholder={i18n.t('optional')}
|
||||
|
@ -636,13 +645,14 @@ export class User extends Component<any, UserState> {
|
|||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label class="col-lg-5 col-form-label">
|
||||
<label class="col-lg-5 col-form-label" htmlFor="matrix-user-id">
|
||||
<a href={elementUrl} target="_blank" rel="noopener">
|
||||
{i18n.t('matrix_user_id')}
|
||||
</a>
|
||||
</label>
|
||||
<div class="col-lg-7">
|
||||
<input
|
||||
id="matrix-user-id"
|
||||
type="text"
|
||||
class="form-control"
|
||||
placeholder="@user:example.com"
|
||||
|
|
Loading…
Reference in a new issue