Add forceSingleColumn
prop to <UI />
(#10807)
* Move TabsBar rendering logic from CSS to the ColumnsArea component * Add forceSingleColumn mode * Add unread notifications counter to tabs bar * Add toggle to control `forceSingleColumn` * Increase paddings in mobile layout responsively at large sizes
This commit is contained in:
parent
ca6c93a2f5
commit
9ddeb30f90
9 changed files with 309 additions and 131 deletions
|
@ -5,7 +5,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
|
|||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
|
||||
import ReactSwipeableViews from 'react-swipeable-views';
|
||||
import { links, getIndex, getLink } from './tabs_bar';
|
||||
import TabsBar, { links, getIndex, getLink } from './tabs_bar';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import BundleContainer from '../containers/bundle_container';
|
||||
|
@ -139,7 +139,7 @@ class ColumnsArea extends ImmutablePureComponent {
|
|||
<ColumnLoading title={title} icon={icon} />;
|
||||
|
||||
return (
|
||||
<div className='columns-area' key={index}>
|
||||
<div className='columns-area columns-area--mobile' key={index}>
|
||||
{view}
|
||||
</div>
|
||||
);
|
||||
|
@ -164,13 +164,17 @@ class ColumnsArea extends ImmutablePureComponent {
|
|||
const floatingActionButton = shouldHideFAB(this.context.router.history.location.pathname) ? null : <Link key='floating-action-button' to='/statuses/new' className='floating-action-button' aria-label={intl.formatMessage(messages.publish)}><Icon id='pencil' /></Link>;
|
||||
|
||||
return columnIndex !== -1 ? [
|
||||
<TabsBar key='tabs' />,
|
||||
|
||||
<ReactSwipeableViews key='content' index={columnIndex} onChangeIndex={this.handleSwipe} onTransitionEnd={this.handleAnimationEnd} animateTransitions={shouldAnimate} springConfig={{ duration: '400ms', delay: '0s', easeFunction: 'ease' }} style={{ height: '100%' }}>
|
||||
{links.map(this.renderView)}
|
||||
</ReactSwipeableViews>,
|
||||
|
||||
floatingActionButton,
|
||||
] : [
|
||||
<div className='columns-area'>{children}</div>,
|
||||
<TabsBar key='tabs' />,
|
||||
|
||||
<div key='content' className='columns-area columns-area--mobile'>{children}</div>,
|
||||
|
||||
floatingActionButton,
|
||||
];
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { connect } from 'react-redux';
|
||||
import Icon from 'mastodon/components/icon';
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
count: state.getIn(['notifications', 'unread']),
|
||||
});
|
||||
|
||||
const formatNumber = num => num > 99 ? '99+' : num;
|
||||
|
||||
const NotificationsCounterIcon = ({ count }) => (
|
||||
<i className='icon-with-badge'>
|
||||
<Icon id='bell' fixedWidth />
|
||||
{count > 0 && <i className='icon-with-badge__badge'>{formatNumber(count)}</i>}
|
||||
</i>
|
||||
);
|
||||
|
||||
NotificationsCounterIcon.propTypes = {
|
||||
count: PropTypes.number.isRequired,
|
||||
};
|
||||
|
||||
export default connect(mapStateToProps)(NotificationsCounterIcon);
|
|
@ -5,10 +5,11 @@ import { FormattedMessage, injectIntl } from 'react-intl';
|
|||
import { debounce } from 'lodash';
|
||||
import { isUserTouching } from '../../../is_mobile';
|
||||
import Icon from 'mastodon/components/icon';
|
||||
import NotificationsCounterIcon from './notifications_counter_icon';
|
||||
|
||||
export const links = [
|
||||
<NavLink className='tabs-bar__link primary' to='/timelines/home' data-preview-title-id='column.home' data-preview-icon='home' ><Icon id='home' fixedWidth /><FormattedMessage id='tabs_bar.home' defaultMessage='Home' /></NavLink>,
|
||||
<NavLink className='tabs-bar__link primary' to='/notifications' data-preview-title-id='column.notifications' data-preview-icon='bell' ><Icon id='bell' fixedWidth /><FormattedMessage id='tabs_bar.notifications' defaultMessage='Notifications' /></NavLink>,
|
||||
<NavLink className='tabs-bar__link primary' to='/notifications' data-preview-title-id='column.notifications' data-preview-icon='bell' ><NotificationsCounterIcon /><FormattedMessage id='tabs_bar.notifications' defaultMessage='Notifications' /></NavLink>,
|
||||
|
||||
<NavLink className='tabs-bar__link secondary' to='/timelines/public/local' data-preview-title-id='column.community' data-preview-icon='users' ><Icon id='users' fixedWidth /><FormattedMessage id='tabs_bar.local_timeline' defaultMessage='Local' /></NavLink>,
|
||||
<NavLink className='tabs-bar__link secondary' exact to='/timelines/public' data-preview-title-id='column.public' data-preview-icon='globe' ><Icon id='globe' fixedWidth /><FormattedMessage id='tabs_bar.federated_timeline' defaultMessage='Federated' /></NavLink>,
|
||||
|
|
|
@ -7,7 +7,6 @@ import { Redirect, withRouter } from 'react-router-dom';
|
|||
import PropTypes from 'prop-types';
|
||||
import NotificationsContainer from './containers/notifications_container';
|
||||
import LoadingBarContainer from './containers/loading_bar_container';
|
||||
import TabsBar from './components/tabs_bar';
|
||||
import ModalContainer from './containers/modal_container';
|
||||
import { isMobile } from '../../is_mobile';
|
||||
import { debounce } from 'lodash';
|
||||
|
@ -63,6 +62,7 @@ const mapStateToProps = state => ({
|
|||
hasComposingText: state.getIn(['compose', 'text']).trim().length !== 0,
|
||||
hasMediaAttachments: state.getIn(['compose', 'media_attachments']).size > 0,
|
||||
dropdownMenuIsOpen: state.getIn(['dropdown_menu', 'openId']) !== null,
|
||||
forceSingleColumn: state.getIn(['settings', 'forceSingleColumn'], false),
|
||||
});
|
||||
|
||||
const keyMap = {
|
||||
|
@ -101,6 +101,7 @@ class SwitchingColumnsArea extends React.PureComponent {
|
|||
children: PropTypes.node,
|
||||
location: PropTypes.object,
|
||||
onLayoutChange: PropTypes.func.isRequired,
|
||||
forceSingleColumn: PropTypes.bool,
|
||||
};
|
||||
|
||||
state = {
|
||||
|
@ -139,12 +140,13 @@ class SwitchingColumnsArea extends React.PureComponent {
|
|||
}
|
||||
|
||||
render () {
|
||||
const { children } = this.props;
|
||||
const { children, forceSingleColumn } = this.props;
|
||||
const { mobile } = this.state;
|
||||
const redirect = mobile ? <Redirect from='/' to='/timelines/home' exact /> : <Redirect from='/' to='/getting-started' exact />;
|
||||
const singleColumn = forceSingleColumn || mobile;
|
||||
const redirect = singleColumn ? <Redirect from='/' to='/timelines/home' exact /> : <Redirect from='/' to='/getting-started' exact />;
|
||||
|
||||
return (
|
||||
<ColumnsAreaContainer ref={this.setRef} singleColumn={mobile}>
|
||||
<ColumnsAreaContainer ref={this.setRef} singleColumn={singleColumn}>
|
||||
<WrappedSwitch>
|
||||
{redirect}
|
||||
<WrappedRoute path='/getting-started' component={GettingStarted} content={children} />
|
||||
|
@ -205,6 +207,7 @@ class UI extends React.PureComponent {
|
|||
location: PropTypes.object,
|
||||
intl: PropTypes.object.isRequired,
|
||||
dropdownMenuIsOpen: PropTypes.bool,
|
||||
forceSingleColumn: PropTypes.bool,
|
||||
};
|
||||
|
||||
state = {
|
||||
|
@ -453,7 +456,7 @@ class UI extends React.PureComponent {
|
|||
|
||||
render () {
|
||||
const { draggingOver } = this.state;
|
||||
const { children, isComposing, location, dropdownMenuIsOpen } = this.props;
|
||||
const { children, isComposing, location, dropdownMenuIsOpen, forceSingleColumn } = this.props;
|
||||
|
||||
const handlers = {
|
||||
help: this.handleHotkeyToggleHelp,
|
||||
|
@ -479,9 +482,7 @@ class UI extends React.PureComponent {
|
|||
return (
|
||||
<HotKeys keyMap={keyMap} handlers={handlers} ref={this.setHotkeysRef} attach={window} focused>
|
||||
<div className={classNames('ui', { 'is-composing': isComposing })} ref={this.setRef} style={{ pointerEvents: dropdownMenuIsOpen ? 'none' : null }}>
|
||||
<TabsBar />
|
||||
|
||||
<SwitchingColumnsArea location={location} onLayoutChange={this.handleLayoutChange}>
|
||||
<SwitchingColumnsArea location={location} onLayoutChange={this.handleLayoutChange} forceSingleColumn={forceSingleColumn}>
|
||||
{children}
|
||||
</SwitchingColumnsArea>
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue