about summary refs log tree commit diff
path: root/app/assets/javascripts/components/features
diff options
context:
space:
mode:
authorZac Anger <zac@zacanger.com>2017-04-15 05:27:27 -0600
committerEugen <eugen@zeonfederated.com>2017-04-15 13:27:27 +0200
commitf4045ba3d962105ae4a7c0ee785a83c678ca2f8a (patch)
tree89eedfbe31105593e77a78014e3dd94c658f0156 /app/assets/javascripts/components/features
parentdf4ff9a8e13d776e1670c232655db0275a353a0f (diff)
Add eslint-plugin-jsx-a11y (#1651)
* Add eslint-plugin-jsx-a11y.

* Fix npm script.

* Adjust npm scripts so test also runs lint.

* Fix existing lint errors.

* Don't break on a11y issues.

* Add role and tabIndex.

* Add vim and Mac files to .gitignore and .dockerignore.

* Handle htmlFor (partially), a that's actually a button.

* Fix missing tabIndex.

* Add cursor:pointer to load-more

* Revert change to load_more.

* Fixes based on review.

* Update yarn.lock.

* Don't try to install fsevents on Linux (hides warning noise).
Diffstat (limited to 'app/assets/javascripts/components/features')
-rw-r--r--app/assets/javascripts/components/features/account/components/header.jsx11
-rw-r--r--app/assets/javascripts/components/features/compose/components/privacy_dropdown.jsx2
-rw-r--r--app/assets/javascripts/components/features/compose/components/search.jsx8
-rw-r--r--app/assets/javascripts/components/features/notifications/components/clear_column_button.jsx2
-rw-r--r--app/assets/javascripts/components/features/notifications/components/column_settings.jsx4
-rw-r--r--app/assets/javascripts/components/features/notifications/components/notification.jsx2
-rw-r--r--app/assets/javascripts/components/features/notifications/components/setting_toggle.jsx7
-rw-r--r--app/assets/javascripts/components/features/ui/components/column_header.jsx2
-rw-r--r--app/assets/javascripts/components/features/ui/components/column_link.jsx3
-rw-r--r--app/assets/javascripts/components/features/ui/components/media_modal.jsx4
-rw-r--r--app/assets/javascripts/components/features/ui/components/modal_root.jsx2
11 files changed, 32 insertions, 15 deletions
diff --git a/app/assets/javascripts/components/features/account/components/header.jsx b/app/assets/javascripts/components/features/account/components/header.jsx
index a359963c4..c4619a3c7 100644
--- a/app/assets/javascripts/components/features/account/components/header.jsx
+++ b/app/assets/javascripts/components/features/account/components/header.jsx
@@ -43,7 +43,16 @@ const Avatar = React.createClass({
     return (
       <Motion defaultStyle={{ radius: 90 }} style={{ radius: spring(isHovered ? 30 : 90, { stiffness: 180, damping: 12 }) }}>
         {({ radius }) =>
-          <a href={account.get('url')} className='account__header__avatar' target='_blank' rel='noopener' style={{ display: 'block', width: '90px', height: '90px', margin: '0 auto', marginBottom: '10px', borderRadius: `${radius}px`, overflow: 'hidden' }} onMouseOver={this.handleMouseOver} onMouseOut={this.handleMouseOut}>
+          <a
+            href={account.get('url')}
+            className='account__header__avatar'
+            target='_blank'
+            rel='noopener'
+            style={{ display: 'block', width: '90px', height: '90px', margin: '0 auto', marginBottom: '10px', borderRadius: `${radius}px`, overflow: 'hidden' }}
+            onMouseOver={this.handleMouseOver}
+            onMouseOut={this.handleMouseOut}
+            onFocus={this.handleMouseOver}
+            onBlur={this.handleMouseOut}>
             <img src={account.get('avatar')} alt={account.get('acct')} style={{ display: 'block', width: '90px', height: '90px' }} />
           </a>
         }
diff --git a/app/assets/javascripts/components/features/compose/components/privacy_dropdown.jsx b/app/assets/javascripts/components/features/compose/components/privacy_dropdown.jsx
index e54fa4d28..de8942d4d 100644
--- a/app/assets/javascripts/components/features/compose/components/privacy_dropdown.jsx
+++ b/app/assets/javascripts/components/features/compose/components/privacy_dropdown.jsx
@@ -83,7 +83,7 @@ const PrivacyDropdown = React.createClass({
         <div className='privacy-dropdown__value'><IconButton icon={valueOption.icon} title={intl.formatMessage(messages.change_privacy)} size={18} active={open} inverted onClick={this.handleToggle} style={iconStyle} /></div>
         <div className='privacy-dropdown__dropdown'>
           {options.map(item =>
-            <div key={item.value} onClick={this.handleClick.bind(this, item.value)} className={`privacy-dropdown__option ${item.value === value ? 'active' : ''}`}>
+            <div role='button' tabIndex='0' key={item.value} onClick={this.handleClick.bind(this, item.value)} className={`privacy-dropdown__option ${item.value === value ? 'active' : ''}`}>
               <div className='privacy-dropdown__option__icon'><i className={`fa fa-fw fa-${item.icon}`} /></div>
               <div className='privacy-dropdown__option__content'>
                 <strong>{item.shortText}</strong>
diff --git a/app/assets/javascripts/components/features/compose/components/search.jsx b/app/assets/javascripts/components/features/compose/components/search.jsx
index 936e003f2..9ca1f5dc5 100644
--- a/app/assets/javascripts/components/features/compose/components/search.jsx
+++ b/app/assets/javascripts/components/features/compose/components/search.jsx
@@ -36,6 +36,10 @@ const Search = React.createClass({
     }
   },
 
+  noop () {
+
+  },
+
   handleFocus () {
     this.props.onShow();
   },
@@ -56,9 +60,9 @@ const Search = React.createClass({
           onFocus={this.handleFocus}
         />
 
-        <div className='search__icon'>
+        <div role='button' tabIndex='0' className='search__icon' onClick={hasValue ? this.handleClear : this.noop}>
           <i className={`fa fa-search ${hasValue ? '' : 'active'}`} />
-          <i className={`fa fa-times-circle ${hasValue ? 'active' : ''}`} onClick={this.handleClear} />
+          <i aria-label="Clear search" className={`fa fa-times-circle ${hasValue ? 'active' : ''}`} />
         </div>
       </div>
     );
diff --git a/app/assets/javascripts/components/features/notifications/components/clear_column_button.jsx b/app/assets/javascripts/components/features/notifications/components/clear_column_button.jsx
index debbfd01f..63fe86af6 100644
--- a/app/assets/javascripts/components/features/notifications/components/clear_column_button.jsx
+++ b/app/assets/javascripts/components/features/notifications/components/clear_column_button.jsx
@@ -15,7 +15,7 @@ const ClearColumnButton = React.createClass({
     const { intl } = this.props;
 
     return (
-      <div title={intl.formatMessage(messages.clear)} className='column-icon column-icon-clear' tabIndex='0' onClick={this.props.onClick}>
+      <div role='button' title={intl.formatMessage(messages.clear)} className='column-icon column-icon-clear' tabIndex='0' onClick={this.props.onClick}>
         <i className='fa fa-eraser' />
       </div>
     );
diff --git a/app/assets/javascripts/components/features/notifications/components/column_settings.jsx b/app/assets/javascripts/components/features/notifications/components/column_settings.jsx
index 2edf98292..03bfaa653 100644
--- a/app/assets/javascripts/components/features/notifications/components/column_settings.jsx
+++ b/app/assets/javascripts/components/features/notifications/components/column_settings.jsx
@@ -27,9 +27,11 @@ const ColumnSettings = React.createClass({
 
   propTypes: {
     settings: ImmutablePropTypes.map.isRequired,
-    intl: React.PropTypes.object.isRequired,
     onChange: React.PropTypes.func.isRequired,
     onSave: React.PropTypes.func.isRequired,
+    intl: React.PropTypes.shape({
+      formatMessage: React.PropTypes.func.isRequired
+    }).isRequired
   },
 
   mixins: [PureRenderMixin],
diff --git a/app/assets/javascripts/components/features/notifications/components/notification.jsx b/app/assets/javascripts/components/features/notifications/components/notification.jsx
index fdebe4bb5..2a9f2d076 100644
--- a/app/assets/javascripts/components/features/notifications/components/notification.jsx
+++ b/app/assets/javascripts/components/features/notifications/components/notification.jsx
@@ -71,7 +71,7 @@ const Notification = React.createClass({
     );
   },
 
-  render () {
+  render () { // eslint-disable-line consistent-return
     const { notification } = this.props;
     const account          = notification.get('account');
     const displayName      = account.get('display_name').length > 0 ? account.get('display_name') : account.get('username');
diff --git a/app/assets/javascripts/components/features/notifications/components/setting_toggle.jsx b/app/assets/javascripts/components/features/notifications/components/setting_toggle.jsx
index eae3c2be2..c4bfad5cd 100644
--- a/app/assets/javascripts/components/features/notifications/components/setting_toggle.jsx
+++ b/app/assets/javascripts/components/features/notifications/components/setting_toggle.jsx
@@ -14,8 +14,8 @@ const labelSpanStyle = {
   marginLeft: '8px'
 };
 
-const SettingToggle = ({ settings, settingKey, label, onChange }) => (
-  <label style={labelStyle}>
+const SettingToggle = ({ settings, settingKey, label, onChange, htmlFor = '' }) => (
+  <label htmlFor={htmlFor} style={labelStyle}>
     <Toggle checked={settings.getIn(settingKey)} onChange={(e) => onChange(settingKey, e.target.checked)} />
     <span className='setting-toggle' style={labelSpanStyle}>{label}</span>
   </label>
@@ -25,7 +25,8 @@ SettingToggle.propTypes = {
   settings: ImmutablePropTypes.map.isRequired,
   settingKey: React.PropTypes.array.isRequired,
   label: React.PropTypes.node.isRequired,
-  onChange: React.PropTypes.func.isRequired
+  onChange: React.PropTypes.func.isRequired,
+  htmlFor: React.PropTypes.string
 };
 
 export default SettingToggle;
diff --git a/app/assets/javascripts/components/features/ui/components/column_header.jsx b/app/assets/javascripts/components/features/ui/components/column_header.jsx
index b7052ffaf..1df0b3da9 100644
--- a/app/assets/javascripts/components/features/ui/components/column_header.jsx
+++ b/app/assets/javascripts/components/features/ui/components/column_header.jsx
@@ -25,7 +25,7 @@ const ColumnHeader = React.createClass({
     }
 
     return (
-      <div aria-label={type} className={`column-header ${active ? 'active' : ''}`} onClick={this.handleClick}>
+      <div role='button' tabIndex='0' aria-label={type} className={`column-header ${active ? 'active' : ''}`} onClick={this.handleClick}>
         {icon}
         {type}
       </div>
diff --git a/app/assets/javascripts/components/features/ui/components/column_link.jsx b/app/assets/javascripts/components/features/ui/components/column_link.jsx
index 2bd1e1017..fb253bbbd 100644
--- a/app/assets/javascripts/components/features/ui/components/column_link.jsx
+++ b/app/assets/javascripts/components/features/ui/components/column_link.jsx
@@ -34,7 +34,8 @@ ColumnLink.propTypes = {
   icon: React.PropTypes.string.isRequired,
   text: React.PropTypes.string.isRequired,
   to: React.PropTypes.string,
-  href: React.PropTypes.string
+  href: React.PropTypes.string,
+  method: React.PropTypes.string
 };
 
 export default ColumnLink;
diff --git a/app/assets/javascripts/components/features/ui/components/media_modal.jsx b/app/assets/javascripts/components/features/ui/components/media_modal.jsx
index 130f48b46..786b08152 100644
--- a/app/assets/javascripts/components/features/ui/components/media_modal.jsx
+++ b/app/assets/javascripts/components/features/ui/components/media_modal.jsx
@@ -104,8 +104,8 @@ const MediaModal = React.createClass({
     leftNav = rightNav = content = '';
 
     if (media.size > 1) {
-      leftNav  = <div style={leftNavStyle} className='modal-container__nav' onClick={this.handlePrevClick}><i className='fa fa-fw fa-chevron-left' /></div>;
-      rightNav = <div style={rightNavStyle} className='modal-container__nav' onClick={this.handleNextClick}><i className='fa fa-fw fa-chevron-right' /></div>;
+      leftNav  = <div role='button' tabIndex='0' style={leftNavStyle} className='modal-container__nav' onClick={this.handlePrevClick}><i className='fa fa-fw fa-chevron-left' /></div>;
+      rightNav = <div role='button' tabIndex='0' style={rightNavStyle} className='modal-container__nav' onClick={this.handleNextClick}><i className='fa fa-fw fa-chevron-right' /></div>;
     }
 
     if (attachment.get('type') === 'image') {
diff --git a/app/assets/javascripts/components/features/ui/components/modal_root.jsx b/app/assets/javascripts/components/features/ui/components/modal_root.jsx
index 74eb50039..a1ed8fd88 100644
--- a/app/assets/javascripts/components/features/ui/components/modal_root.jsx
+++ b/app/assets/javascripts/components/features/ui/components/modal_root.jsx
@@ -66,7 +66,7 @@ const ModalRoot = React.createClass({
 
               return (
                 <div key={key}>
-                  <div className='modal-root__overlay' style={{ opacity: style.opacity, transform: `translateZ(0px)` }} onClick={onClose} />
+                  <div role='presentation' className='modal-root__overlay' style={{ opacity: style.opacity, transform: `translateZ(0px)` }} onClick={onClose} />
                   <div className='modal-root__container' style={{ opacity: style.opacity, transform: `translateZ(0px) scale(${style.scale})` }}>
                     <SpecificComponent {...props} onClose={onClose} />
                   </div>