diff options
19 files changed, 626 insertions, 782 deletions
diff --git a/app/javascript/flavours/glitch/actions/compose.js b/app/javascript/flavours/glitch/actions/compose.js index d87786008..31866d223 100644 --- a/app/javascript/flavours/glitch/actions/compose.js +++ b/app/javascript/flavours/glitch/actions/compose.js @@ -38,7 +38,6 @@ export const COMPOSE_SPOILERNESS_CHANGE = 'COMPOSE_SPOILERNESS_CHANGE'; export const COMPOSE_SPOILER_TEXT_CHANGE = 'COMPOSE_SPOILER_TEXT_CHANGE'; export const COMPOSE_VISIBILITY_CHANGE = 'COMPOSE_VISIBILITY_CHANGE'; export const COMPOSE_LISTABILITY_CHANGE = 'COMPOSE_LISTABILITY_CHANGE'; -export const COMPOSE_COMPOSING_CHANGE = 'COMPOSE_COMPOSING_CHANGE'; export const COMPOSE_EMOJI_INSERT = 'COMPOSE_EMOJI_INSERT'; @@ -382,10 +381,3 @@ export function insertEmojiCompose(position, emoji) { emoji, }; }; - -export function changeComposing(value) { - return { - type: COMPOSE_COMPOSING_CHANGE, - value, - }; -} diff --git a/app/javascript/flavours/glitch/components/avatar.js b/app/javascript/flavours/glitch/components/avatar.js index 82ab0f45a..c5e9072c4 100644 --- a/app/javascript/flavours/glitch/components/avatar.js +++ b/app/javascript/flavours/glitch/components/avatar.js @@ -1,3 +1,4 @@ +import classNames from 'classnames'; import React from 'react'; import PropTypes from 'prop-types'; import ImmutablePropTypes from 'react-immutable-proptypes'; @@ -7,6 +8,7 @@ export default class Avatar extends React.PureComponent { static propTypes = { account: ImmutablePropTypes.map.isRequired, + className: PropTypes.string, size: PropTypes.number.isRequired, style: PropTypes.object, inline: PropTypes.bool, @@ -34,17 +36,19 @@ export default class Avatar extends React.PureComponent { } render () { - const { account, size, animate, inline } = this.props; + const { + account, + animate, + className, + inline, + size, + } = this.props; const { hovering } = this.state; const src = account.get('avatar'); const staticSrc = account.get('avatar_static'); - let className = 'account__avatar'; - - if (inline) { - className = className + ' account__avatar-inline'; - } + const computedClass = classNames('account__avatar', { 'account__avatar-inline': inline }, className); const style = { ...this.props.style, @@ -61,7 +65,7 @@ export default class Avatar extends React.PureComponent { return ( <div - className={className} + className={computedClass} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave} style={style} diff --git a/app/javascript/flavours/glitch/components/display_name.js b/app/javascript/flavours/glitch/components/display_name.js index 2cf84f8f4..ad1c3a534 100644 --- a/app/javascript/flavours/glitch/components/display_name.js +++ b/app/javascript/flavours/glitch/components/display_name.js @@ -1,3 +1,5 @@ +import classNames from 'classnames'; +import PropTypes from 'prop-types'; import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; @@ -5,13 +7,19 @@ export default class DisplayName extends React.PureComponent { static propTypes = { account: ImmutablePropTypes.map.isRequired, + className: PropTypes.string, }; render () { - const displayNameHtml = { __html: this.props.account.get('display_name_html') }; + const { + account, + className, + } = this.props; + const computedClass = classNames('display-name', className); + const displayNameHtml = { __html: account.get('display_name_html') }; return ( - <span className='display-name'> + <span className={computedClass}> <strong className='display-name__html' dangerouslySetInnerHTML={displayNameHtml} /> <span className='display-name__account'>@{this.props.account.get('acct')}</span> </span> ); diff --git a/app/javascript/flavours/glitch/features/composer/options/index.js b/app/javascript/flavours/glitch/features/composer/options/index.js index ee633e865..ea998a421 100644 --- a/app/javascript/flavours/glitch/features/composer/options/index.js +++ b/app/javascript/flavours/glitch/features/composer/options/index.js @@ -236,7 +236,12 @@ export default class ComposerOptions extends React.PureComponent { }} > {({ scale }) => ( - <div style={{ transform: `scale(${scale})` }}> + <div + style={{ + display: hasMedia ? null : 'none', + transform: `scale(${scale})`, + }} + > <IconButton active={sensitive} className='sensitive' diff --git a/app/javascript/flavours/glitch/features/composer/publisher/index.js b/app/javascript/flavours/glitch/features/composer/publisher/index.js index 85de80a9f..79337100f 100644 --- a/app/javascript/flavours/glitch/features/composer/publisher/index.js +++ b/app/javascript/flavours/glitch/features/composer/publisher/index.js @@ -49,6 +49,7 @@ export default function ComposerPublisher ({ <span class='count'>{diff}</span> {sideArm && sideArm !== 'none' ? ( <Button + className='side_arm' text={ <span> <Icon @@ -67,7 +68,7 @@ export default function ComposerPublisher ({ /> ) : null} <Button - className='compose-form__publish__primary' + className='primary' text={function () { switch (true) { case !!sideArm && sideArm !== 'none': diff --git a/app/javascript/flavours/glitch/features/composer/reply/index.js b/app/javascript/flavours/glitch/features/composer/reply/index.js index 2823415d2..4a52cddb4 100644 --- a/app/javascript/flavours/glitch/features/composer/reply/index.js +++ b/app/javascript/flavours/glitch/features/composer/reply/index.js @@ -70,24 +70,31 @@ export default class ComposerReply extends React.PureComponent { <article className='composer--reply'> <header> <IconButton + className='cancel' icon='times' onClick={click} title={intl.formatMessage(messages.cancel)} /> {account ? ( <a + className='account' href={account.get('url')} onClick={clickAccount} > <Avatar account={account} + className='avatar' size={24} /> - <DisplayName account={account} /> + <DisplayName + account={account} + className='display_name' + /> </a> ) : null} </header> <div + className='content' dangerouslySetInnerHTML={{ __html: content || '' }} style={{ direction: isRtl(content) ? 'rtl' : 'ltr' }} /> diff --git a/app/javascript/flavours/glitch/features/composer/textarea/index.js b/app/javascript/flavours/glitch/features/composer/textarea/index.js index ad0a35d7f..2299757df 100644 --- a/app/javascript/flavours/glitch/features/composer/textarea/index.js +++ b/app/javascript/flavours/glitch/features/composer/textarea/index.js @@ -246,12 +246,13 @@ export default class ComposerTextarea extends React.Component { // The result. return ( - <div className='autosuggest-textarea'> + <div className='composer--textarea'> <label> <span {...hiddenComponent}><FormattedMessage {...messages.placeholder} /></span> <Textarea aria-autocomplete='list' autoFocus={autoFocus} + className='textarea' disabled={disabled} inputRef={refTextarea} onBlur={blur} diff --git a/app/javascript/flavours/glitch/features/composer/textarea/suggestions/index.js b/app/javascript/flavours/glitch/features/composer/textarea/suggestions/index.js index b90696910..65ed2c18a 100644 --- a/app/javascript/flavours/glitch/features/composer/textarea/suggestions/index.js +++ b/app/javascript/flavours/glitch/features/composer/textarea/suggestions/index.js @@ -1,5 +1,4 @@ // Package imports. -import classNames from 'classnames'; import PropTypes from 'prop-types'; import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; @@ -14,10 +13,13 @@ export default function ComposerTextareaSuggestions ({ suggestions, value, }) { - const computedClass = classNames('comoser--textarea--suggestions', { hidden: hidden || suggestions.isEmpty() }); + // The result. return ( - <div className={computedClass}> + <div + className='composer--textarea--suggestions' + hidden={hidden || suggestions.isEmpty()} + > {!hidden ? suggestions.map( (suggestion, index) => ( <ComposerTextareaSuggestionsItem diff --git a/app/javascript/flavours/glitch/features/composer/textarea/suggestions/item/index.js b/app/javascript/flavours/glitch/features/composer/textarea/suggestions/item/index.js index 08c99ed0e..b78f99ee9 100644 --- a/app/javascript/flavours/glitch/features/composer/textarea/suggestions/item/index.js +++ b/app/javascript/flavours/glitch/features/composer/textarea/suggestions/item/index.js @@ -50,10 +50,10 @@ export default class ComposerTextareaSuggestionsItem extends React.Component { // The result. return ( <div - role='button' - tabIndex='0' className={computedClass} onMouseDown={click} + role='button' + tabIndex='0' > { // If the suggestion is an object, then we render an emoji. // Otherwise, we render an account. diff --git a/app/javascript/flavours/glitch/features/composer/upload_form/item/index.js b/app/javascript/flavours/glitch/features/composer/upload_form/item/index.js index bd67e7227..cbec5ecd9 100644 --- a/app/javascript/flavours/glitch/features/composer/upload_form/item/index.js +++ b/app/javascript/flavours/glitch/features/composer/upload_form/item/index.js @@ -139,6 +139,7 @@ export default class ComposerUploadFormItem extends React.PureComponent { }} > <IconButton + className='close' icon='times' onClick={remove} size={36} diff --git a/app/javascript/flavours/glitch/features/drawer/pager/account/index.js b/app/javascript/flavours/glitch/features/drawer/account/index.js index 2ee95d5b9..9afe8ba3e 100644 --- a/app/javascript/flavours/glitch/features/drawer/pager/account/index.js +++ b/app/javascript/flavours/glitch/features/drawer/account/index.js @@ -22,7 +22,7 @@ const messages = defineMessages({ }); // The component. -export default function DrawerPagerAccount ({ account }) { +export default function DrawerAccount ({ account }) { // We need an account to render. if (!account) { @@ -67,4 +67,4 @@ export default function DrawerPagerAccount ({ account }) { ); } -DrawerPagerAccount.propTypes = { account: ImmutablePropTypes.map }; +DrawerAccount.propTypes = { account: ImmutablePropTypes.map }; diff --git a/app/javascript/flavours/glitch/features/drawer/index.js b/app/javascript/flavours/glitch/features/drawer/index.js index 1b7a8a0b5..d184dfd9b 100644 --- a/app/javascript/flavours/glitch/features/drawer/index.js +++ b/app/javascript/flavours/glitch/features/drawer/index.js @@ -4,7 +4,6 @@ import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; // Actions. -import { changeComposing } from 'flavours/glitch/actions/compose'; import { openModal } from 'flavours/glitch/actions/modal'; import { changeSearch, @@ -14,8 +13,9 @@ import { } from 'flavours/glitch/actions/search'; // Components. +import Composer from 'flavours/glitch/features/composer'; +import DrawerAccount from './account'; import DrawerHeader from './header'; -import DrawerPager from './pager'; import DrawerResults from './results'; import DrawerSearch from './search'; @@ -27,7 +27,6 @@ import { wrap } from 'flavours/glitch/util/redux_helpers'; const mapStateToProps = state => ({ account: state.getIn(['accounts', me]), columns: state.getIn(['settings', 'columns']), - isComposing: state.getIn(['compose', 'is_composing']), results: state.getIn(['search', 'results']), searchHidden: state.getIn(['search', 'hidden']), searchValue: state.getIn(['search', 'value']), @@ -39,12 +38,6 @@ const mapDispatchToProps = dispatch => ({ change (value) { dispatch(changeSearch(value)); }, - changeComposingOff () { - dispatch(changeComposing(false)); - }, - changeComposingOn () { - dispatch(changeComposing(true)); - }, clear () { dispatch(clearSearch()); }, @@ -72,8 +65,6 @@ class Drawer extends React.Component { const { dispatch: { change, - changeComposingOff, - changeComposingOn, clear, openSettings, show, @@ -84,7 +75,6 @@ class Drawer extends React.Component { state: { account, columns, - isComposing, results, searchHidden, searchValue, @@ -111,16 +101,14 @@ class Drawer extends React.Component { submitted={submitted} value={searchValue} /> - <DrawerPager - account={account} - active={isComposing} - onBlur={changeComposingOff} - onFocus={changeComposingOn} - /> - <DrawerResults - results={results} - visible={submitted && !searchHidden} - /> + <div className='contents'> + <DrawerAccount account={account} /> + <Composer /> + <DrawerResults + results={results} + visible={submitted && !searchHidden} + /> + </div> </div> ); } @@ -135,7 +123,6 @@ Drawer.propTypes = { state: PropTypes.shape({ account: ImmutablePropTypes.map, columns: ImmutablePropTypes.list, - isComposing: PropTypes.bool, results: ImmutablePropTypes.map, searchHidden: PropTypes.bool, searchValue: PropTypes.string, diff --git a/app/javascript/flavours/glitch/features/drawer/pager/index.js b/app/javascript/flavours/glitch/features/drawer/pager/index.js deleted file mode 100644 index 8dc2d3ee9..000000000 --- a/app/javascript/flavours/glitch/features/drawer/pager/index.js +++ /dev/null @@ -1,43 +0,0 @@ -// Package imports. -import classNames from 'classnames'; -import PropTypes from 'prop-types'; -import React from 'react'; -import ImmutablePropTypes from 'react-immutable-proptypes'; - -// Components. -import IconButton from 'flavours/glitch/components/icon_button'; -import Composer from 'flavours/glitch/features/composer'; -import DrawerPagerAccount from './account'; - -// The component. -export default function DrawerPager ({ - account, - active, - onClose, - onFocus, -}) { - const computedClass = classNames('drawer--pager', { active }); - - // The result. - return ( - <div - className={computedClass} - onFocus={onFocus} - > - <DrawerPagerAccount account={account} /> - <IconButton - icon='close' - onClick={onClose} - title='' - /> - <Composer /> - </div> - ); -} - -DrawerPager.propTypes = { - account: ImmutablePropTypes.map, - active: PropTypes.bool, - onClose: PropTypes.func, - onFocus: PropTypes.func, -}; diff --git a/app/javascript/flavours/glitch/features/ui/components/onboarding_modal.js b/app/javascript/flavours/glitch/features/ui/components/onboarding_modal.js index 749bbbd86..91a83f330 100644 --- a/app/javascript/flavours/glitch/features/ui/components/onboarding_modal.js +++ b/app/javascript/flavours/glitch/features/ui/components/onboarding_modal.js @@ -7,13 +7,11 @@ import ReactSwipeableViews from 'react-swipeable-views'; import classNames from 'classnames'; import Permalink from 'flavours/glitch/components/permalink'; import { WrappedComponent as RawComposer } from 'flavours/glitch/features/composer'; -import DrawerPagerAccount from 'flavours/glitch/features/drawer/pager/account'; +import DrawerAccount from 'flavours/glitch/features/drawer/account'; import DrawerSearch from 'flavours/glitch/features/drawer/search'; import ColumnHeader from './column_header'; import { me } from 'flavours/glitch/util/initial_state'; -const noop = () => { }; - const messages = defineMessages({ home_title: { id: 'column.home', defaultMessage: 'Home' }, notifications_title: { id: 'column.notifications', defaultMessage: 'Notifications' }, @@ -49,7 +47,7 @@ const PageTwo = ({ intl, myAccount }) => ( <div className='onboarding-modal__page onboarding-modal__page-two'> <div className='figure non-interactive'> <div className='pseudo-drawer'> - <DrawerPagerAccount account={myAccount} /> + <DrawerAccount account={myAccount} /> <RawComposer intl={intl} state={composerState} @@ -72,7 +70,7 @@ const PageThree = ({ intl, myAccount }) => ( <DrawerSearch intl={intl} /> <div className='pseudo-drawer'> - <DrawerPagerAccount account={myAccount} /> + <DrawerAccount account={myAccount} /> </div> </div> diff --git a/app/javascript/flavours/glitch/reducers/compose.js b/app/javascript/flavours/glitch/reducers/compose.js index 52a8ab5ec..17c5e3a3a 100644 --- a/app/javascript/flavours/glitch/reducers/compose.js +++ b/app/javascript/flavours/glitch/reducers/compose.js @@ -21,7 +21,6 @@ import { COMPOSE_SPOILERNESS_CHANGE, COMPOSE_SPOILER_TEXT_CHANGE, COMPOSE_VISIBILITY_CHANGE, - COMPOSE_COMPOSING_CHANGE, COMPOSE_EMOJI_INSERT, COMPOSE_UPLOAD_CHANGE_REQUEST, COMPOSE_UPLOAD_CHANGE_SUCCESS, @@ -219,8 +218,6 @@ export default function compose(state = initialState, action) { return state .set('text', action.text) .set('idempotencyKey', uuid()); - case COMPOSE_COMPOSING_CHANGE: - return state.set('is_composing', action.value); case COMPOSE_REPLY: return state.withMutations(map => { map.set('in_reply_to', action.status.get('id')); diff --git a/app/javascript/flavours/glitch/styles/components/compose.scss b/app/javascript/flavours/glitch/styles/components/compose.scss deleted file mode 100644 index e69de29bb..000000000 --- a/app/javascript/flavours/glitch/styles/components/compose.scss +++ /dev/null diff --git a/app/javascript/flavours/glitch/styles/components/composer.scss b/app/javascript/flavours/glitch/styles/components/composer.scss new file mode 100644 index 000000000..a8d688ea5 --- /dev/null +++ b/app/javascript/flavours/glitch/styles/components/composer.scss @@ -0,0 +1,315 @@ +.composer { + padding: 10px; + + .composer--spoiler { + display: block; + box-sizing: border-box; + margin: 0; + border: none; + border-radius: 4px; + padding: 10px; + width: 100%; + outline: 0; + color: $ui-base-color; + background: $simple-background-color; + font-size: 14px; + font-family: inherit; + resize: vertical; + + &:focus { outline: 0 } + @include single-column('screen and (max-width: 630px)') { font-size: 16px } + } + + .composer--warning { + color: darken($ui-secondary-color, 65%); + margin-bottom: 15px; + background: $ui-primary-color; + box-shadow: 0 2px 6px rgba($base-shadow-color, 0.3); + padding: 8px 10px; + border-radius: 4px; + font-size: 13px; + font-weight: 400; + + a { + color: darken($ui-primary-color, 33%); + font-weight: 500; + text-decoration: underline; + + &:active, + &:focus, + &:hover { text-decoration: none } + } + } + + .composer--reply { + margin: 0 0 -2px; + border-radius: 4px 4px 0 0; + padding: 10px; + background: $ui-primary-color; + + & > header { + margin-bottom: 5px; + overflow: hidden; + + & > .account { + & > .avatar { + float: left; + margin-right: 5px; + } + + & > .display_name { + color: $ui-base-color; + display: block; + padding-right: 25px; + max-width: 100%; + line-height: 24px; + text-decoration: none; + overflow: hidden; + } + } + + & > .cancel { + float: right; + line-height: 24px; + } + } + + & > .content { + position: relative; + margin: 10px 0; + padding: 0 12px; + font-size: 14px; + line-height: 20px; + color: $ui-base-color; + word-wrap: break-word; + font-weight: 400; + overflow: visible; + white-space: pre-wrap; + padding-top: 5px; + } + + .emojione { + width: 20px; + height: 20px; + margin: -5px 0 0; + } + + p { + margin-bottom: 20px; + + &:last-child { margin-bottom: 0 } + } + + a { + color: lighten($ui-base-color, 20%); + text-decoration: none; + + &:hover { text-decoration: underline } + + &.mention { + &:hover { + text-decoration: none; + + span { text-decoration: underline } + } + } + } + } + + .composer--textarea { + background: $simple-background-color; + position: relative; + + &:disabled { background: $ui-secondary-color } + + & > .textarea { + display: block; + box-sizing: border-box; + margin: 0; + border: none; + border-radius: 4px 4px 0 0; + padding: 10px 32px 0 10px; + width: 100%; + min-height: 100px; + outline: 0; + color: $ui-base-color; + background: $simple-background-color; + font-size: 14px; + font-family: inherit; + resize: none; + + &:focus { outline: 0 } + @include single-column('screen and (max-width: 630px)') { font-size: 16px } + + @include limited-single-column('screen and (max-width: 600px)') { + height: 100px !important; // prevent auto-resize textarea + resize: vertical; + } + } + + .composer--textarea--suggestions { + display: block; + position: absolute; + box-sizing: border-box; + top: 100%; + border-radius: 0 0 4px 4px; + padding: 6px; + width: 100%; + color: $ui-base-color; + background: $ui-secondary-color; + box-shadow: 4px 4px 6px rgba($base-shadow-color, 0.4); + font-size: 14px; + z-index: 99; + + &[hidden] { display: none } + + .composer--textarea--suggestions--item { + display: flex; + flex-direction: row; + align-items: center; + justify-content: flex-start; + border-radius: 4px; + padding: 10px; + font-size: 14px; + line-height: 18px; + cursor: pointer; + + &:hover, + &:focus, + &:active, + &.active { background: darken($ui-secondary-color, 10%) } + + & > .emoji { + img { + display: block; + float: left; + margin-right: 8px; + width: 16px; + height: 16px; + } + } + } + } + } + + .composer--upload_form { + display: flex; + flex-direction: row; + flex-wrap: wrap; + padding: 5px; + color: $ui-base-color; + background: $simple-background-color; + font-size: 14px; + font-family: inherit; + overflow: hidden; + + .composer--upload_form--item { + flex: 1 1 0; + margin: 5px; + min-width: 40%; + + & > div { + position: relative; + border-radius: 4px; + height: 100px; + width: 100%; + background-position: center; + background-size: cover; + background-repeat: no-repeat; + + input { + display: block; + position: absolute; + box-sizing: border-box; + bottom: 0; + left: 0; + margin: 0; + border: 0; + padding: 10px; + width: 100%; + color: $ui-secondary-color; + background: linear-gradient(0deg, rgba($base-shadow-color, 0.8) 0, rgba($base-shadow-color, 0.35) 80%, transparent); + font-size: 14px; + font-family: inherit; + font-weight: 500; + opacity: 0; + z-index: 2; + transition: opacity .1s ease; + + &:focus { color: $white } + + &::placeholder { + opacity: 0.54; + color: $ui-secondary-color; + } + } + + & > .close { mix-blend-mode: difference } + } + + &.active { + & > div { + input { opacity: 1 } + } + } + } + } + + .composer--options { + padding: 10px; + background: darken($simple-background-color, 8%); + box-shadow: inset 0 5px 5px rgba($base-shadow-color, 0.05); + border-radius: 0 0 4px 4px; + + & > * { + display: inline-block; + box-sizing: content-box; + padding: 0 3px; + line-height: 27px; + } + + & > hr { + display: inline-block; + margin: 0 3px; + border-width: 0 0 0 1px; + border-style: none none none solid; + border-color: transparent transparent transparent darken($simple-background-color, 24%); + padding: 0; + background: transparent; + } + } + + .composer--publisher { + padding-top: 10px; + text-align: right; + white-space: nowrap; + overflow: hidden; + + & > .count { + display: inline-block; + margin: 0 16px 0 8px; + padding-top: 10px; + font-size: 16px; + line-height: 36px; + } + + & > .primary { + display: inline-block; + margin: 0; + padding: 0 10px; + text-align: center; + } + + & > .side_arm { + display: inline-block; + margin: 0 2px 0 0; + padding: 0; + width: 36px; + text-align: center; + } + + &.over { + & > .count { color: $warning-red } + } + } +} diff --git a/app/javascript/flavours/glitch/styles/components/drawer.scss b/app/javascript/flavours/glitch/styles/components/drawer.scss index e69de29bb..8ad55c79b 100644 --- a/app/javascript/flavours/glitch/styles/components/drawer.scss +++ b/app/javascript/flavours/glitch/styles/components/drawer.scss @@ -0,0 +1,234 @@ +.drawer { + display: flex; + flex-direction: column; + box-sizing: border-box; + padding: 10px 5px; + width: 300px; + flex: 1 1 100%; + contain: strict; + + &:first-child { + padding-left: 10px; + } + + &:last-child { + padding-right: 10px; + } + + @include multi-columns('screen and (max-width: 630px)') { + &, &:first-child, &:last-child { + padding: 0; + } + } + + .wide & { + min-width: 300px; + max-width: 400px; + flex: 1 1 200px; + } + + .react-swipeable-view-container & { + height: 100%; + } + + .drawer--header { + display: flex; + flex-direction: row; + margin-bottom: 10px; + flex: none; + background: lighten($ui-base-color, 8%); + font-size: 16px; + + & > * { + display: block; + box-sizing: border-box; + border-bottom: 2px solid transparent; + padding: 15px 5px 13px; + height: 48px; + flex: 1 1 auto; + color: $ui-primary-color; + text-align: center; + text-decoration: none; + cursor: pointer; + } + + a { + transition: background 100ms ease-in; + + &:focus, + &:hover { + outline: none; + background: lighten($ui-base-color, 3%); + transition: background 200ms ease-out; + } + } + } + + .drawer--search { + position: relative; + margin-bottom: 10px; + flex: none; + + @include limited-single-column('screen and (max-width: 360px)') { + margin-bottom: 0; + } + + input { + display: block; + box-sizing: border-box; + margin: 0; + border: none; + padding: 10px 30px 10px 10px; + width: 100%; + height: 36px; + outline: 0; + color: $ui-primary-color; + background: $ui-base-color; + font-size: 14px; + font-family: inherit; + line-height: 16px; + + &:focus { + outline: 0; + background: lighten($ui-base-color, 4%); + } + } + + & > .icon { + .fa { + display: inline-block; + position: absolute; + top: 10px; + right: 10px; + width: 18px; + height: 18px; + color: $ui-secondary-color; + font-size: 18px; + opacity: 0; + cursor: default; + pointer-events: none; + z-index: 2; + transition: all 100ms linear; + } + + .fa-search { + opacity: 0.3; + transform: rotate(0deg); + } + + .fa-times-circle { + top: 11px; + transform: rotate(-90deg); + cursor: pointer; + + &:hover { + color: $primary-text-color; + } + } + + &.active { + .fa-search { + opacity: 0; + transform: rotate(90deg); + } + + .fa-times-circle { + opacity: 0.3; + pointer-events: auto; + transform: rotate(0deg); + } + } + } + } + + & > .contents { + position: relative; + padding: 0; + width: 100%; + height: 100%; + background: lighten($ui-base-color, 13%); + overflow-x: hidden; + overflow-y: auto; + contain: strict; + + .drawer--account { + padding: 10px; + color: $ui-primary-color; + + & > a { + color: inherit; + text-decoration: none; + } + + & > .avatar { + float: left; + margin-right: 10px; + } + + & > .acct { + display: block; + color: $primary-text-color; + font-weight: 500; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + } + + .drawer--results { + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + padding: 0; + background: $ui-base-color; + overflow-x: hidden; + overflow-y: auto; + contain: strict; + + & > header { + border-bottom: 1px solid darken($ui-base-color, 4%); + padding: 15px 10px; + color: $ui-base-lighter-color; + background: lighten($ui-base-color, 2%); + font-size: 14px; + font-weight: 500; + } + + & > section { + background: $ui-base-color; + + & > .hashtag { + display: block; + padding: 10px; + color: $ui-secondary-color; + text-decoration: none; + + &:hover, + &:active, + &:focus { + color: lighten($ui-secondary-color, 4%); + text-decoration: underline; + } + } + } + } + } +} + +:root { // Overrides .wide stylings for mobile view + @include single-column('screen and (max-width: 630px)', $parent: null) { + .drawer { + flex: auto; + width: 100%; + min-width: 0; + max-width: none; + padding: 0; + + .drawer--search input { + font-size: 16px; + } + } + } +} diff --git a/app/javascript/flavours/glitch/styles/components/index.scss b/app/javascript/flavours/glitch/styles/components/index.scss index b947c082d..e9127affc 100644 --- a/app/javascript/flavours/glitch/styles/components/index.scss +++ b/app/javascript/flavours/glitch/styles/components/index.scss @@ -264,172 +264,6 @@ color: $ui-base-color; } -.compose-form { - padding: 10px; -} - -.compose-form__warning { - color: darken($ui-secondary-color, 65%); - margin-bottom: 15px; - background: $ui-primary-color; - box-shadow: 0 2px 6px rgba($base-shadow-color, 0.3); - padding: 8px 10px; - border-radius: 4px; - font-size: 13px; - font-weight: 400; - - strong { - color: darken($ui-secondary-color, 65%); - font-weight: 500; - } - - a { - color: darken($ui-primary-color, 33%); - font-weight: 500; - text-decoration: underline; - - &:hover, - &:active, - &:focus { - text-decoration: none; - } - } -} - -.compose-form__modifiers { - color: $ui-base-color; - font-family: inherit; - font-size: 14px; - background: $simple-background-color; -} - -.compose-form__buttons-wrapper { - display: flex; - justify-content: space-between; -} - -.compose-form__buttons { - padding: 10px; - background: darken($simple-background-color, 8%); - box-shadow: inset 0 5px 5px rgba($base-shadow-color, 0.05); - border-radius: 0 0 4px 4px; - display: flex; - - .icon-button { - box-sizing: content-box; - padding: 0 3px; - } -} - -.compose-form__buttons-separator { - border-left: 1px solid #c3c3c3; - margin: 0 3px; -} - -.compose-form__upload-button-icon { - line-height: 27px; -} - -.compose-form__sensitive-button { - display: none; - - &.compose-form__sensitive-button--visible { - display: block; - } - - .compose-form__sensitive-button__icon { - line-height: 27px; - } -} - -.compose-form__upload-wrapper { - overflow: hidden; -} - -.compose-form__uploads-wrapper { - display: flex; - flex-direction: row; - padding: 5px; - flex-wrap: wrap; -} - -.compose-form__upload { - flex: 1 1 0; - min-width: 40%; - margin: 5px; - - &-description { - position: absolute; - z-index: 2; - bottom: 0; - left: 0; - right: 0; - box-sizing: border-box; - background: linear-gradient(0deg, rgba($base-shadow-color, 0.8) 0, rgba($base-shadow-color, 0.35) 80%, transparent); - padding: 10px; - opacity: 0; - transition: opacity .1s ease; - - input { - background: transparent; - color: $ui-secondary-color; - border: 0; - padding: 0; - margin: 0; - width: 100%; - font-family: inherit; - font-size: 14px; - font-weight: 500; - - &:focus { - color: $white; - } - - &::placeholder { - opacity: 0.54; - color: $ui-secondary-color; - } - } - - &.active { - opacity: 1; - } - } - - .icon-button { - mix-blend-mode: difference; - } -} - -.compose-form__upload-thumbnail { - border-radius: 4px; - background-position: center; - background-size: cover; - background-repeat: no-repeat; - height: 100px; - width: 100%; -} - -.compose-form__label { - display: block; - line-height: 24px; - vertical-align: middle; - - &.with-border { - border-top: 1px solid $ui-base-color; - padding-top: 10px; - } - - .compose-form__label__text { - display: inline-block; - vertical-align: middle; - margin-bottom: 14px; - margin-left: 8px; - color: $ui-primary-color; - } -} - -.compose-form__textarea, .follow-form__input { background: $simple-background-color; @@ -438,49 +272,17 @@ } } -.compose-form__autosuggest-wrapper { - position: relative; - - .emoji-picker-dropdown { - position: absolute; - right: 5px; - top: 5px; - - ::-webkit-scrollbar-track:hover, - ::-webkit-scrollbar-track:active { - background-color: rgba($base-overlay-background, 0.3); - } - } -} - -.compose-form__publish { - display: flex; - justify-content: flex-end; - min-width: 0; -} - -.compose-form__publish-button-wrapper { - overflow: hidden; - padding-top: 10px; - white-space: nowrap; - display: flex; +.emoji-picker-dropdown { + position: absolute; + right: 5px; + top: 5px; - button { - text-overflow: unset; + ::-webkit-scrollbar-track:hover, + ::-webkit-scrollbar-track:active { + background-color: rgba($base-overlay-background, 0.3); } } -.compose-form__publish__side-arm { - padding: 0 !important; - width: 36px; - text-align: center; - margin-right: 2px; -} - -.compose-form__publish__primary { - padding: 0 10px !important; -} - .emojione { display: inline-block; font-size: inherit; @@ -495,46 +297,12 @@ } } -.reply-indicator { - border-radius: 4px 4px 0 0; - position: relative; - bottom: -2px; - background: $ui-primary-color; - padding: 10px; -} - -.reply-indicator__header { - margin-bottom: 5px; - overflow: hidden; -} - -.reply-indicator__cancel { - float: right; - line-height: 24px; -} - -.reply-indicator__display-name { - color: $ui-base-color; - display: block; - max-width: 100%; - line-height: 24px; - overflow: hidden; - padding-right: 25px; - text-decoration: none; -} - -.reply-indicator__display-avatar { - float: left; - margin-right: 5px; -} - .status__content--with-action { cursor: pointer; } .status-check-box { - .status__content, - .reply-indicator__content { + .status__content { color: #3a3a3a; a { color: #005aa9; @@ -542,8 +310,7 @@ } } -.status__content, -.reply-indicator__content { +.status__content { position: relative; margin: 10px 0; padding: 0 12px; @@ -975,15 +742,6 @@ margin-left: 6px; } -.reply-indicator__content { - color: $ui-base-color; - font-size: 14px; - - a { - color: lighten($ui-base-color, 20%); - } -} - .account { padding: 10px; border-bottom: 1px solid lighten($ui-base-color, 8%); @@ -1497,45 +1255,6 @@ } } -.navigation-bar { - padding: 10px; - display: flex; - flex-shrink: 0; - cursor: default; - color: $ui-primary-color; - - strong { - color: $primary-text-color; - } - - .permalink { - text-decoration: none; - } - - .icon-button { - pointer-events: none; - opacity: 0; - } -} - -.navigation-bar__profile { - flex: 1 1 auto; - margin-left: 8px; - overflow: hidden; -} - -.navigation-bar__profile-account { - display: block; - font-weight: 500; - overflow: hidden; - text-overflow: ellipsis; -} - -.navigation-bar__profile-edit { - color: inherit; - text-decoration: none; -} - .dropdown { display: inline-block; } @@ -1718,7 +1437,6 @@ .react-swipeable-view-container { &, .columns-area, - .drawer, .column { height: 100%; } @@ -1759,36 +1477,7 @@ background: darken($ui-base-color, 7%); } -.drawer { - width: 300px; - box-sizing: border-box; - display: flex; - flex-direction: column; - overflow-y: auto; - - .wide & { - flex: 1 1 200px; - min-width: 300px; - max-width: 400px; - } -} - -.drawer__tab { - display: block; - flex: 1 1 auto; - padding: 15px 5px 13px; - color: $ui-primary-color; - text-decoration: none; - text-align: center; - font-size: 16px; - border-bottom: 2px solid transparent; - outline: none; - cursor: pointer; -} - -.column, -.drawer { - flex: 1 1 100%; +.column { overflow: hidden; } @@ -1796,16 +1485,11 @@ .tabs-bar { margin: 0; } - - .search { - margin-bottom: 0; - } } :root { // Overrides .wide stylings for mobile view @include single-column('screen and (max-width: 630px)', $parent: null) { - .column, - .drawer { + .column { flex: auto; width: 100%; min-width: 0; @@ -1816,11 +1500,6 @@ .columns-area { flex-direction: column; } - - .search__input, - .autosuggest-textarea__textarea { - font-size: 16px; - } } } @@ -1829,8 +1508,7 @@ padding: 0; } - .column, - .drawer { + .column { padding: 10px; padding-left: 5px; padding-right: 5px; @@ -1845,63 +1523,19 @@ } .columns-area > div { - .column, - .drawer { + .column { padding-left: 5px; padding-right: 5px; } } } -.drawer__pager { - box-sizing: border-box; - padding: 0; - flex: 1 1 auto; - position: relative; -} - -.drawer__inner { - background: lighten($ui-base-color, 13%); - box-sizing: border-box; - padding: 0; - position: absolute; - height: 100%; - width: 100%; - - &.darker { - position: absolute; - top: 0; - left: 0; - background: $ui-base-color; - width: 100%; - height: 100%; - } -} - .pseudo-drawer { background: lighten($ui-base-color, 13%); font-size: 13px; text-align: left; } -.drawer__header { - flex: 0 0 auto; - font-size: 16px; - background: lighten($ui-base-color, 8%); - margin-bottom: 10px; - display: flex; - flex-direction: row; - - a { - transition: background 100ms ease-in; - - &:hover { - background: lighten($ui-base-color, 3%); - transition: background 200ms ease-out; - } - } -} - .tabs-bar { display: flex; background: lighten($ui-base-color, 8%); @@ -2176,121 +1810,6 @@ cursor: default; } -.autosuggest-textarea, -.spoiler-input { - position: relative; -} - -.autosuggest-textarea__textarea, -.spoiler-input__input { - display: block; - box-sizing: border-box; - width: 100%; - margin: 0; - color: $ui-base-color; - background: $simple-background-color; - padding: 10px; - font-family: inherit; - font-size: 14px; - resize: vertical; - border: 0; - outline: 0; - - &:focus { - outline: 0; - } - - @include limited-single-column('screen and (max-width: 600px)') { - font-size: 16px; - } -} - -.spoiler-input__input { - border-radius: 4px; -} - -.autosuggest-textarea__textarea { - min-height: 100px; - border-radius: 4px 4px 0 0; - padding-bottom: 0; - padding-right: 10px + 22px; - resize: none; - - @include limited-single-column('screen and (max-width: 600px)') { - height: 100px !important; // prevent auto-resize textarea - resize: vertical; - } -} - -.autosuggest-textarea__suggestions { - box-sizing: border-box; - display: none; - position: absolute; - top: 100%; - width: 100%; - z-index: 99; - box-shadow: 4px 4px 6px rgba($base-shadow-color, 0.4); - background: $ui-secondary-color; - border-radius: 0 0 4px 4px; - color: $ui-base-color; - font-size: 14px; - padding: 6px; - - &.autosuggest-textarea__suggestions--visible { - display: block; - } -} - -.autosuggest-textarea__suggestions__item { - padding: 10px; - cursor: pointer; - border-radius: 4px; - - &:hover, - &:focus, - &:active, - &.selected { - background: darken($ui-secondary-color, 10%); - } -} - -.autosuggest-account, -.autosuggest-emoji { - display: flex; - flex-direction: row; - align-items: center; - justify-content: flex-start; - line-height: 18px; - font-size: 14px; -} - -.autosuggest-account-icon, -.autosuggest-emoji img { - display: block; - margin-right: 8px; - width: 16px; - height: 16px; -} - -.autosuggest-account .display-name__account { - color: lighten($ui-base-color, 36%); -} - -.character-counter__wrapper { - line-height: 36px; - margin: 0 16px 0 8px; - padding-top: 10px; -} - -.character-counter { - cursor: default; - font-size: 16px; -} - -.character-counter--over { - color: $warning-red; -} - .getting-started__wrapper { position: relative; overflow-y: auto; @@ -3415,118 +2934,6 @@ } } - -.search { - position: relative; - margin-bottom: 10px; -} - -.search__input { - outline: 0; - box-sizing: border-box; - display: block; - width: 100%; - border: none; - padding: 10px; - padding-right: 30px; - font-family: inherit; - background: $ui-base-color; - color: $ui-primary-color; - font-size: 14px; - margin: 0; - - &::-moz-focus-inner { - border: 0; - } - - &::-moz-focus-inner, - &:focus, - &:active { - outline: 0 !important; - } - - &:focus { - background: lighten($ui-base-color, 4%); - } - - @include limited-single-column('screen and (max-width: 600px)') { - font-size: 16px; - } -} - -.search__icon { - .fa { - position: absolute; - top: 10px; - right: 10px; - z-index: 2; - display: inline-block; - opacity: 0; - transition: all 100ms linear; - font-size: 18px; - width: 18px; - height: 18px; - color: $ui-secondary-color; - cursor: default; - pointer-events: none; - - &.active { - pointer-events: auto; - opacity: 0.3; - } - } - - .fa-search { - transform: rotate(90deg); - - &.active { - pointer-events: none; - transform: rotate(0deg); - } - } - - .fa-times-circle { - top: 11px; - transform: rotate(0deg); - cursor: pointer; - - &.active { - transform: rotate(90deg); - } - - &:hover { - color: $primary-text-color; - } - } -} - -.search-results__header { - color: $ui-base-lighter-color; - background: lighten($ui-base-color, 2%); - border-bottom: 1px solid darken($ui-base-color, 4%); - padding: 15px 10px; - font-size: 14px; - font-weight: 500; -} - -.search-results__section { - background: $ui-base-color; -} - -.search-results__hashtag { - display: block; - padding: 10px; - color: $ui-secondary-color; - text-decoration: none; - - &:hover, - &:active, - &:focus { - color: lighten($ui-secondary-color, 4%); - text-decoration: underline; - } -} - .modal-root { transition: opacity 0.3s linear; will-change: opacity; @@ -4732,80 +4139,6 @@ noscript { 100% { opacity: 1; } } -@media screen and (max-width: 630px) and (max-height: 400px) { - $duration: 400ms; - $delay: 100ms; - - .tabs-bar, - .search { - will-change: margin-top; - transition: margin-top $duration $delay; - } - - .navigation-bar { - will-change: padding-bottom; - transition: padding-bottom $duration $delay; - } - - .navigation-bar { - & > a:first-child { - will-change: margin-top, margin-left, width; - transition: margin-top $duration $delay, margin-left $duration ($duration + $delay); - } - - & > .navigation-bar__profile-edit { - will-change: margin-top; - transition: margin-top $duration $delay; - } - - & > .icon-button { - will-change: opacity; - transition: opacity $duration $delay; - } - } - - .is-composing { - .tabs-bar, - .search { - margin-top: -50px; - } - - .navigation-bar { - padding-bottom: 0; - - & > a:first-child { - margin-top: -50px; - margin-left: -40px; - } - - .navigation-bar__profile { - padding-top: 2px; - } - - .navigation-bar__profile-edit { - position: absolute; - margin-top: -50px; - } - - .icon-button { - pointer-events: auto; - opacity: 1; - } - } - } - - // fixes for the navbar-under mode - .is-composing.navbar-under { - .search { - margin-top: -20px; - margin-bottom: -20px; - .search__icon { - display: none; - } - } - } -} - // more fixes for the navbar-under mode @mixin fix-margins-for-navbar-under { .tabs-bar { @@ -4984,6 +4317,8 @@ noscript { } } +@import 'composer'; @import 'doodle'; +@import 'drawer'; @import 'emoji_picker'; @import 'local_settings'; |