about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--app/javascript/mastodon/components/autosuggest_textarea.js3
-rw-r--r--app/javascript/mastodon/components/button.js12
-rw-r--r--app/javascript/mastodon/components/column_collapsable.js2
-rw-r--r--app/javascript/mastodon/components/icon_button.js9
-rw-r--r--app/javascript/mastodon/components/media_gallery.js2
-rw-r--r--app/javascript/mastodon/components/status_content.js14
-rw-r--r--app/javascript/mastodon/components/video_player.js4
-rw-r--r--app/javascript/mastodon/features/account/components/header.js14
-rw-r--r--app/javascript/mastodon/features/compose/components/emoji_picker_dropdown.js18
-rw-r--r--app/javascript/mastodon/features/getting_started/index.js2
-rw-r--r--app/javascript/mastodon/features/ui/index.js2
-rw-r--r--app/javascript/styles/components.scss89
-rw-r--r--spec/javascript/components/button.test.jsx6
13 files changed, 122 insertions, 55 deletions
diff --git a/app/javascript/mastodon/components/autosuggest_textarea.js b/app/javascript/mastodon/components/autosuggest_textarea.js
index 869ecad6b..b3d62ec3a 100644
--- a/app/javascript/mastodon/components/autosuggest_textarea.js
+++ b/app/javascript/mastodon/components/autosuggest_textarea.js
@@ -79,6 +79,7 @@ class AutosuggestTextarea extends ImmutablePureComponent {
     }
 
     // auto-resize textarea
+    e.target.style.height = 'auto';
     e.target.style.height = `${e.target.scrollHeight}px`;
 
     this.props.onChange(e);
@@ -197,7 +198,7 @@ class AutosuggestTextarea extends ImmutablePureComponent {
           style={style}
         />
 
-        <div style={{ display: (suggestions.size > 0 && !suggestionsHidden) ? 'block' : 'none' }} className='autosuggest-textarea__suggestions'>
+        <div className={`autosuggest-textarea__suggestions ${suggestionsHidden || suggestions.isEmpty() ? '' : 'autosuggest-textarea__suggestions--visible'}`}>
           {suggestions.map((suggestion, i) => (
             <div
               role='button'
diff --git a/app/javascript/mastodon/components/button.js b/app/javascript/mastodon/components/button.js
index 40a17f92e..7612bd233 100644
--- a/app/javascript/mastodon/components/button.js
+++ b/app/javascript/mastodon/components/button.js
@@ -26,15 +26,19 @@ class Button extends React.PureComponent {
 
   render () {
     const style = {
-      display: this.props.block ? 'block' : 'inline-block',
-      width: this.props.block ? '100%' : 'auto',
       padding: `0 ${this.props.size / 2.25}px`,
       height: `${this.props.size}px`,
-      lineHeight: `${this.props.size}px`
+      lineHeight: `${this.props.size}px`,
+      ...this.props.style
     };
 
     return (
-      <button className={`button ${this.props.secondary ? 'button-secondary' : ''}`} disabled={this.props.disabled} onClick={this.handleClick} style={{ ...style, ...this.props.style }}>
+      <button
+        className={`button ${this.props.secondary ? 'button-secondary' : ''} ${this.props.block ? 'button--block' : ''}`}
+        disabled={this.props.disabled}
+        onClick={this.handleClick}
+        style={style}
+      >
         {this.props.text || this.props.children}
       </button>
     );
diff --git a/app/javascript/mastodon/components/column_collapsable.js b/app/javascript/mastodon/components/column_collapsable.js
index a54f76932..44ec63af8 100644
--- a/app/javascript/mastodon/components/column_collapsable.js
+++ b/app/javascript/mastodon/components/column_collapsable.js
@@ -35,7 +35,7 @@ class ColumnCollapsable extends React.PureComponent {
           <i className={`fa fa-${icon}`} />
         </div>
 
-        <div className='column-collapsable__content' style={{ height: `${fullHeight}px`, maxHeight: '70vh' }}>
+        <div className='column-collapsable__content' style={{ height: `${fullHeight}px` }}>
           {children}
         </div>
       </div>
diff --git a/app/javascript/mastodon/components/icon_button.js b/app/javascript/mastodon/components/icon_button.js
index b229e5748..c2fbbd4b9 100644
--- a/app/javascript/mastodon/components/icon_button.js
+++ b/app/javascript/mastodon/components/icon_button.js
@@ -36,18 +36,15 @@ class IconButton extends React.PureComponent {
   }
 
   render () {
-    let style = {
+    const style = {
       fontSize: `${this.props.size}px`,
       width: `${this.props.size * 1.28571429}px`,
       height: `${this.props.size * 1.28571429}px`,
       lineHeight: `${this.props.size}px`,
-      ...this.props.style
+      ...this.props.style,
+      ...(this.props.active ? this.props.activeStyle : {})
     };
 
-    if (this.props.active) {
-      style = { ...style, ...this.props.activeStyle };
-    }
-
     const classes = ['icon-button'];
 
     if (this.props.active) {
diff --git a/app/javascript/mastodon/components/media_gallery.js b/app/javascript/mastodon/components/media_gallery.js
index 439588735..10389751e 100644
--- a/app/javascript/mastodon/components/media_gallery.js
+++ b/app/javascript/mastodon/components/media_gallery.js
@@ -173,7 +173,7 @@ class MediaGallery extends React.PureComponent {
 
     return (
       <div className='media-gallery' style={{ height: `${this.props.height}px` }}>
-        <div className='spoiler-button' style={{ display: !this.state.visible ? 'none' : 'block' }}>
+        <div className={`spoiler-button ${this.state.visible ? 'spoiler-button--visible' : ''}`}>
           <IconButton title={intl.formatMessage(messages.toggle_visible)} icon={this.state.visible ? 'eye' : 'eye-slash'} overlay onClick={this.handleOpen} />
         </div>
 
diff --git a/app/javascript/mastodon/components/status_content.js b/app/javascript/mastodon/components/status_content.js
index fd12cc78a..4d002607d 100644
--- a/app/javascript/mastodon/components/status_content.js
+++ b/app/javascript/mastodon/components/status_content.js
@@ -117,15 +117,15 @@ class StatusContent extends React.PureComponent {
 
       return (
         <div className='status__content' ref={this.setRef} onMouseDown={this.handleMouseDown} onMouseUp={this.handleMouseUp}>
-          <p style={{ marginBottom: hidden && status.get('mentions').size === 0 ? '0px' : '' }} >
-            <span dangerouslySetInnerHTML={spoilerContent} /> <button tabIndex='0' className='status__content__spoiler-link' onClick={this.handleSpoilerClick}>{toggleText}</button>
-
+          <p style={{ marginBottom: hidden && status.get('mentions').isEmpty() ? '0px' : null }}>
+            <span dangerouslySetInnerHTML={spoilerContent} />
+            {' '}
+            <button tabIndex='0' className='status__content__spoiler-link' onClick={this.handleSpoilerClick}>{toggleText}</button>
           </p>
 
           {mentionsPlaceholder}
 
-          <div style={{ display: hidden ? 'none' : 'block', ...directionStyle }} dangerouslySetInnerHTML={content} />
-
+          <div className={`status__content__text ${!hidden ? 'status__content__text--visible' : ''}`} style={directionStyle} dangerouslySetInnerHTML={content} />
         </div>
       );
     } else if (this.props.onClick) {
@@ -133,7 +133,7 @@ class StatusContent extends React.PureComponent {
         <div
           ref={this.setRef}
           className='status__content'
-          style={{ ...directionStyle }}
+          style={directionStyle}
           onMouseDown={this.handleMouseDown}
           onMouseUp={this.handleMouseUp}
           dangerouslySetInnerHTML={content}
@@ -144,7 +144,7 @@ class StatusContent extends React.PureComponent {
         <div
           ref={this.setRef}
           className='status__content status__content--no-action'
-          style={{ ...directionStyle }}
+          style={directionStyle}
           dangerouslySetInnerHTML={content}
         />
       );
diff --git a/app/javascript/mastodon/components/video_player.js b/app/javascript/mastodon/components/video_player.js
index ba6d97c84..cd4b69659 100644
--- a/app/javascript/mastodon/components/video_player.js
+++ b/app/javascript/mastodon/components/video_player.js
@@ -113,7 +113,7 @@ class VideoPlayer extends React.PureComponent {
     const { media, intl, width, height, sensitive, autoplay } = this.props;
 
     let spoilerButton = (
-      <div className='status__video-player-spoiler' style={{ display: !this.state.visible ? 'none' : 'block' }} >
+      <div className={`status__video-player-spoiler ${this.state.visible ? 'status__video-player-spoiler--visible' : ''}`}>
         <IconButton overlay title={intl.formatMessage(messages.toggle_visible)} icon={this.state.visible ? 'eye' : 'eye-slash'} onClick={this.handleVisibility} />
       </div>
     );
@@ -156,7 +156,7 @@ class VideoPlayer extends React.PureComponent {
 
     if (this.state.preview && !autoplay) {
       return (
-        <div role='button' tabIndex='0' className='media-spoiler-video' style={{ width: `${width}px`, height: `${height}px`, background: `url(${media.get('preview_url')}) no-repeat center` }} onClick={this.handleOpen}>
+        <div role='button' tabIndex='0' className='media-spoiler-video' style={{ width: `${width}px`, height: `${height}px`, backgroundImage: `url(${media.get('preview_url')})` }} onClick={this.handleOpen}>
           {spoilerButton}
           <div className='media-spoiler-video-play-icon'><i className='fa fa-play' /></div>
         </div>
diff --git a/app/javascript/mastodon/features/account/components/header.js b/app/javascript/mastodon/features/account/components/header.js
index e65f70595..5d2586f4d 100644
--- a/app/javascript/mastodon/features/account/components/header.js
+++ b/app/javascript/mastodon/features/account/components/header.js
@@ -96,19 +96,19 @@ class Header extends ImmutablePureComponent {
     }
 
     if (me !== account.get('id') && account.getIn(['relationship', 'followed_by'])) {
-      info = <span className='account--follows-info' style={{ position: 'absolute', top: '10px', right: '10px', opacity: '0.7', display: 'inline-block', verticalAlign: 'top', background: 'rgba(0, 0, 0, 0.4)', textTransform: 'uppercase', fontSize: '11px', fontWeight: '500', padding: '4px', borderRadius: '4px' }}><FormattedMessage id='account.follows_you' defaultMessage='Follows you' /></span>
+      info = <span className='account--follows-info'><FormattedMessage id='account.follows_you' defaultMessage='Follows you' /></span>
     }
 
     if (me !== account.get('id')) {
       if (account.getIn(['relationship', 'requested'])) {
         actionBtn = (
-          <div style={{ position: 'absolute', top: '10px', left: '20px' }}>
+          <div className='account--action-button'>
             <IconButton size={26} disabled={true} icon='hourglass' title={intl.formatMessage(messages.requested)} />
           </div>
         );
       } else if (!account.getIn(['relationship', 'blocking'])) {
         actionBtn = (
-          <div style={{ position: 'absolute', top: '10px', left: '20px' }}>
+          <div className='account--action-button'>
             <IconButton size={26} icon={account.getIn(['relationship', 'following']) ? 'user-times' : 'user-plus'} active={account.getIn(['relationship', 'following'])} title={intl.formatMessage(account.getIn(['relationship', 'following']) ? messages.unfollow : messages.follow)} onClick={this.props.onFollow} />
           </div>
         );
@@ -124,12 +124,12 @@ class Header extends ImmutablePureComponent {
 
     return (
       <div className='account__header' style={{ backgroundImage: `url(${account.get('header')})` }}>
-        <div style={{ padding: '20px 10px' }}>
+        <div>
           <Avatar account={account} autoPlayGif={this.props.autoPlayGif} />
 
-          <span style={{ display: 'inline-block', fontSize: '20px', lineHeight: '27px', fontWeight: '500' }} className='account__header__display-name' dangerouslySetInnerHTML={displayNameHTML} />
-          <span className='account__header__username' style={{ fontSize: '14px', fontWeight: '400', display: 'block', marginBottom: '10px' }}>@{account.get('acct')} {lockedIcon}</span>
-          <div style={{ fontSize: '14px' }} className='account__header__content' dangerouslySetInnerHTML={content} />
+          <span className='account__header__display-name' dangerouslySetInnerHTML={displayNameHTML} />
+          <span className='account__header__username'>@{account.get('acct')} {lockedIcon}</span>
+          <div className='account__header__content' dangerouslySetInnerHTML={content} />
 
           {info}
           {actionBtn}
diff --git a/app/javascript/mastodon/features/compose/components/emoji_picker_dropdown.js b/app/javascript/mastodon/features/compose/components/emoji_picker_dropdown.js
index 9ad0ae296..50b8ef37e 100644
--- a/app/javascript/mastodon/features/compose/components/emoji_picker_dropdown.js
+++ b/app/javascript/mastodon/features/compose/components/emoji_picker_dropdown.js
@@ -22,20 +22,6 @@ const settings = {
   imagePathPNG: '/emoji/'
 };
 
-const dropdownStyle = {
-  position: 'absolute',
-  right: '5px',
-  top: '5px'
-};
-
-const dropdownTriggerStyle = {
-  display: 'block',
-  fontSize: '24px',
-  lineHeight: '24px',
-  marginLeft: '2px',
-  width: '24px'
-}
-
 let EmojiPicker; // load asynchronously
 
 class EmojiPickerDropdown extends React.PureComponent {
@@ -118,8 +104,8 @@ class EmojiPickerDropdown extends React.PureComponent {
     const { active, loading } = this.state;
 
     return (
-      <Dropdown ref={this.setRef} style={dropdownStyle} onShow={this.onShowDropdown} onHide={this.onHideDropdown}>
-        <DropdownTrigger className='emoji-button' title={intl.formatMessage(messages.emoji)} style={dropdownTriggerStyle}>
+      <Dropdown ref={this.setRef} className='emoji-picker__dropdown' onShow={this.onShowDropdown} onHide={this.onHideDropdown}>
+        <DropdownTrigger className='emoji-button' title={intl.formatMessage(messages.emoji)}>
           <img draggable="false"
                className={`emojione ${active && loading ? "pulse-loading" : ''}`}
                alt="🙂" src="/emoji/1f602.svg" />
diff --git a/app/javascript/mastodon/features/getting_started/index.js b/app/javascript/mastodon/features/getting_started/index.js
index bbde15c65..5e72a5612 100644
--- a/app/javascript/mastodon/features/getting_started/index.js
+++ b/app/javascript/mastodon/features/getting_started/index.js
@@ -60,7 +60,7 @@ class GettingStarted extends ImmutablePureComponent {
           <ColumnLink icon='sign-out' text={intl.formatMessage(messages.sign_out)} href='/auth/sign_out' method='delete' />
         </div>
 
-        <div className='scrollable optionally-scrollable' style={{ display: 'flex', flexDirection: 'column' }}>
+        <div className='getting-started__footer scrollable optionally-scrollable'>
           <div className='static-content getting-started'>
             <p>
               <FormattedMessage
diff --git a/app/javascript/mastodon/features/ui/index.js b/app/javascript/mastodon/features/ui/index.js
index 355bca5dc..bc465aa5a 100644
--- a/app/javascript/mastodon/features/ui/index.js
+++ b/app/javascript/mastodon/features/ui/index.js
@@ -133,7 +133,7 @@ class UI extends React.PureComponent {
           <Compose withHeader={true} />
           <HomeTimeline shouldUpdateScroll={noOp} />
           <Notifications shouldUpdateScroll={noOp} />
-          <div style={{display: 'flex', flex: '1 1 auto', position: 'relative'}}>{children}</div>
+          <div className="column__wrapper">{children}</div>
         </ColumnsArea>
       );
     }
diff --git a/app/javascript/styles/components.scss b/app/javascript/styles/components.scss
index 3c90ae728..f639ca8d4 100644
--- a/app/javascript/styles/components.scss
+++ b/app/javascript/styles/components.scss
@@ -28,6 +28,7 @@
   text-overflow: ellipsis;
   transition: all 100ms ease-in;
   white-space: nowrap;
+  width: auto;
 
   &:active,
   &:focus,
@@ -44,6 +45,17 @@
   &.button-secondary {
     //
   }
+
+  &.button--block {
+    display: block;
+    width: 100%;
+  }
+}
+
+.column__wrapper {
+  display: flex;
+  flex: 1 1 auto;
+  position: relative;
 }
 
 .column-collapsable {
@@ -53,6 +65,7 @@
     overflow: auto;
     transition: 300ms ease;
     opacity: 1;
+    max-height: 70vh;
   }
 
   &.collapsed .column-collapsable__content {
@@ -370,10 +383,16 @@
 .compose-form__autosuggest-wrapper {
   position: relative;
 
-  .dropdown--active::after {
-    border-color: transparent transparent $base-border-color;
-    bottom: -1px;
-    right: 8px;
+  .emoji-picker__dropdown {
+    position: absolute;
+    right: 5px;
+    top: 5px;
+
+    &.dropdown--active::after {
+      border-color: transparent transparent $base-border-color;
+      bottom: -1px;
+      right: 8px;
+    }
   }
 }
 
@@ -498,6 +517,14 @@
       text-decoration: none;
     }
   }
+
+  .status__content__text {
+    display: none;
+
+    &.status__content__text--visible {
+      display: block;
+    }
+  }
 }
 
 .status__content__spoiler-link {
@@ -800,6 +827,7 @@
 
   & > div {
     background: rgba(lighten($ui-base-color, 4%), 0.9);
+    padding: 20px 10px;
   }
 
   .account__header__content {
@@ -808,10 +836,18 @@
 
   .account__header__display-name {
     color: $primary-text-color;
+    display: inline-block;
+    font-size: 20px;
+    line-height: 27px;
+    font-weight: 500;
   }
 
   .account__header__username {
     color: $ui-highlight-color;
+    font-size: 14px;
+    font-weight: 400;
+    display: block;
+    margin-bottom: 10px;
   }
 }
 
@@ -1716,6 +1752,7 @@
 }
 
 .autosuggest-textarea__suggestions {
+  display: none;
   position: absolute;
   top: 100%;
   width: 100%;
@@ -1724,6 +1761,10 @@
   background: $ui-secondary-color;
   color: $ui-base-color;
   font-size: 14px;
+
+  &.autosuggest-textarea__suggestions--visible {
+    display: block;
+  }
 }
 
 .autosuggest-textarea__suggestions__item {
@@ -1778,6 +1819,11 @@
   position: relative;
 }
 
+.getting-started__footer {
+  display: flex;
+  flex-direction: column;
+}
+
 .getting-started {
   box-sizing: border-box;
   padding-bottom: 235px;
@@ -2051,11 +2097,16 @@ button.icon-button.active i.fa-retweet {
 }
 
 .spoiler-button {
+  display: none;
   left: 4px;
   position: absolute;
   text-shadow: 0 1px 1px $base-shadow-color, 1px 0 1px $base-shadow-color;
   top: 4px;
   z-index: 100;
+
+  &.spoiler-button--visible {
+    display: block;
+  }
 }
 
 .modal-container--preloader {
@@ -2114,6 +2165,24 @@ button.icon-button.active i.fa-retweet {
 
 .account--follows-info {
   color: $primary-text-color;
+  position: absolute;
+  top: 10px;
+  right: 10px;
+  opacity: 0.7;
+  display: inline-block;
+  vertical-align: top;
+  background-color: rgba($base-overlay-background, 0.4);
+  text-transform: uppercase;
+  font-size: 11px;
+  font-weight: 500;
+  padding: 4px;
+  border-radius: 4px;
+}
+
+.account--action-button {
+  position: absolute;
+  top: 10px;
+  left: 20px;
 }
 
 .setting-toggle__label {
@@ -2531,6 +2600,11 @@ button.icon-button.active i.fa-retweet {
 }
 
 .emoji-button {
+  display: block;
+  font-size: 24px;
+  line-height: 24px;
+  margin-left: 2px;
+  width: 24px;
   outline: 0;
 
   &:active,
@@ -3345,12 +3419,17 @@ button.icon-button.active i.fa-retweet {
 }
 
 .status__video-player-spoiler {
+  display: none;
   color: $primary-text-color;
   left: 4px;
   position: absolute;
   text-shadow: 0 1px 1px $base-shadow-color, 1px 0 1px $base-shadow-color;
   top: 4px;
   z-index: 100;
+
+  &.status__video-player-spoiler--visible {
+    display: block;
+  }
 }
 
 .status__video-player-expand {
@@ -3365,6 +3444,8 @@ button.icon-button.active i.fa-retweet {
 
 .media-spoiler-video {
   background-size: cover;
+  background-repeat: no-repeat;
+  background-position: center;
   cursor: pointer;
   margin-top: 8px;
   position: relative;
diff --git a/spec/javascript/components/button.test.jsx b/spec/javascript/components/button.test.jsx
index c32fae32a..e08671c01 100644
--- a/spec/javascript/components/button.test.jsx
+++ b/spec/javascript/components/button.test.jsx
@@ -51,14 +51,12 @@ describe('<Button />', () => {
 
   it('renders style="display: block; width: 100%;" if props.block given', () => {
     const wrapper = shallow(<Button block />);
-    expect(wrapper.find('button')).to.have.style('display', 'block');
-    expect(wrapper.find('button')).to.have.style('width', '100%');
+    expect(wrapper.find('button')).to.have.className('button--block');
   });
 
   it('renders style="display: inline-block; width: auto;" by default', () => {
     const wrapper = shallow(<Button />);
-    expect(wrapper.find('button')).to.have.style('display', 'inline-block');
-    expect(wrapper.find('button')).to.have.style('width', 'auto');
+    expect(wrapper.find('button')).to.not.have.className('button--block');
   });
 
   it('adds class "button-secondary" if props.secondary given', () => {