diff options
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', () => { |