Make navigation panel retractable on mobile and tablet
This commit is contained in:
parent
6231d4b7ee
commit
2d6a98a43b
|
@ -1,6 +1,7 @@
|
|||
import React from 'react';
|
||||
import ComposeFormContainer from './containers/compose_form_container';
|
||||
import NavigationContainer from './containers/navigation_container';
|
||||
import ColumnHeader from 'mastodon/components/column_header';
|
||||
import PropTypes from 'prop-types';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import { connect } from 'react-redux';
|
||||
|
@ -37,25 +38,6 @@ const mapStateToProps = (state, ownProps) => ({
|
|||
showSearch: ownProps.multiColumn ? state.getIn(['search', 'submitted']) && !state.getIn(['search', 'hidden']) : false,
|
||||
});
|
||||
|
||||
let instanceMascot;
|
||||
if (mascot) {
|
||||
instanceMascot = <img alt='' draggable='false' src={mascot} />;
|
||||
} else {
|
||||
instanceMascot = <svg id='hometownlogo' width="2400" height="460" viewBox="0 0 2400 460" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid meet">
|
||||
<g>
|
||||
<g>
|
||||
<path d="m326.20431,287.85649l-302.73044,0c-10.28698,0 -19.10436,8.81738 -19.10436,19.10436s8.81738,19.10436 19.10436,19.10436l302.73044,0c10.28698,0 19.10436,-8.81738 19.10436,-19.10436s-8.81738,-19.10436 -19.10436,-19.10436z"/>
|
||||
<path d="m326.20431,351.04783l-302.73044,0c-10.28698,0 -19.10436,8.81738 -19.10436,19.10436s8.81738,19.10436 19.10436,19.10436l302.73044,0c10.28698,0 19.10436,-8.81738 19.10436,-19.10436s-8.81738,-19.10436 -19.10436,-19.10436z"/>
|
||||
<path d="m326.20431,415.70867l-302.73044,0c-10.28698,0 -19.10436,8.81738 -19.10436,19.10436s8.81738,19.10436 19.10436,19.10436l302.73044,0c10.28698,0 19.10436,-8.81738 19.10436,-19.10436s-8.81738,-19.10436 -19.10436,-19.10436z"/>
|
||||
<path d="m456.99565,287.85649c-10.28698,0 -19.10436,8.81738 -19.10436,19.10436l0,129.32173c0,10.28698 8.81738,19.10436 19.10436,19.10436s19.10436,-8.81738 19.10436,-19.10436l0,-129.32173c-1.46955,-11.75653 -10.28698,-19.10436 -19.10436,-19.10436z"/>
|
||||
<path d="m392.33476,287.85649c-10.28698,0 -19.10436,8.81738 -19.10436,19.10436l0,129.32173c0,10.28698 8.81738,19.10436 19.10436,19.10436s19.10436,-8.81738 19.10436,-19.10436l0,-129.32173c-1.46955,-11.75653 -8.81738,-19.10436 -19.10436,-19.10436z"/>
|
||||
<path d="m440.83045,205.56085c19.10436,-10.28698 29.39129,-36.73911 29.39129,-82.29564c0,-52.90436 -13.22609,-114.62609 -48.49564,-114.62609s-48.49564,61.72173 -48.49564,114.62609c0,45.55653 10.28698,72.00871 29.39129,82.29564l0,35.26955c0,10.28698 8.81738,19.10436 19.10436,19.10436s19.10436,-8.81738 19.10436,-19.10436l0,-35.26955l-0.00002,0zm-19.10436,-154.30436c5.87827,11.75653 11.75653,36.73911 11.75653,72.00871c0,36.73911 -7.34782,49.9652 -11.75653,49.9652s-11.75653,-13.22609 -11.75653,-49.9652c1.46955,-35.26955 7.34782,-60.25218 11.75653,-72.00871z"/>
|
||||
<path d="m342.36956,123.26521c0,-1.46955 -1.46955,-1.46955 -1.46955,-2.93911l-47.02609,-60.25218c-2.93911,-4.40871 -8.81738,-7.34782 -14.69564,-7.34782l-23.51307,0l0,-27.92173c0,-10.28698 -8.81738,-19.10436 -19.10436,-19.10436s-19.10436,8.81738 -19.10436,19.10436l0,29.39129l-57.31307,0l-16.1652,0l-76.41738,0c-5.87827,0 -10.28698,2.93911 -14.69564,7.34782l-47.02609,60.25218c0,1.46955 -1.46955,1.46955 -1.46955,2.93911c0,0 -1.46955,1.46955 -1.46955,1.46955c1.46955,1.46955 1.46955,4.40871 1.46955,5.87827l0,108.74782c0,10.28698 8.81738,19.10436 19.10436,19.10436l76.41738,0l108.74782,0l117.56525,0c10.28698,0 19.10436,-8.81738 19.10436,-19.10436l0,-108.74782c0,-2.93911 0,-4.40871 -1.46955,-5.87827c-1.46955,-1.46955 -1.46955,-1.46955 -1.46955,-2.93911l-0.00005,0l-0.00002,0zm-224.84351,99.93045l-76.41738,0l0,-72.00871l149.89564,0l0,72.00871l-73.47827,0l0.00001,0zm99.93045,-108.74782l-17.6348,-23.51307l70.53916,0l17.6348,23.51307l-70.53916,0zm-64.66089,-23.51307l17.6348,23.51307l-110.21738,0l17.6348,-23.51307l74.94782,0l-0.00005,0l0.00001,0zm74.94782,60.25218l80.82609,0l0,72.00871l-80.82609,0l0,-72.00871z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>;
|
||||
}
|
||||
|
||||
export default @connect(mapStateToProps)
|
||||
@injectIntl
|
||||
class Compose extends React.PureComponent {
|
||||
|
@ -155,6 +137,12 @@ class Compose extends React.PureComponent {
|
|||
|
||||
return (
|
||||
<Column onFocus={this.onFocus}>
|
||||
<ColumnHeader
|
||||
icon='pencil'
|
||||
title={intl.formatMessage(messages.compose)}
|
||||
onClick={this.handleHeaderClick}
|
||||
multiColumn={multiColumn}
|
||||
/>
|
||||
<NavigationContainer onClose={this.onBlur} />
|
||||
<ComposeFormContainer />
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ class Explore extends React.PureComponent {
|
|||
return (
|
||||
<Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.title)}>
|
||||
<ColumnHeader
|
||||
icon={isSearching ? 'search' : 'hashtag'}
|
||||
icon='search'
|
||||
title={intl.formatMessage(isSearching ? messages.searchResults : messages.title)}
|
||||
onClick={this.handleHeaderClick}
|
||||
multiColumn={multiColumn}
|
||||
|
|
|
@ -4,8 +4,8 @@ import { NavLink } from 'react-router-dom';
|
|||
import Icon from 'mastodon/components/icon';
|
||||
import classNames from 'classnames';
|
||||
|
||||
const ColumnLink = ({ icon, text, to, href, method, badge, transparent, ...other }) => {
|
||||
const className = classNames('column-link', { 'column-link--transparent': transparent });
|
||||
const ColumnLink = ({ icon, text, to, href, method, badge, transparent, button, onClick, ...other }) => {
|
||||
const className = classNames('column-link', { 'column-link--transparent': transparent, 'column-link--button': button });
|
||||
const badgeElement = typeof badge !== 'undefined' ? <span className='column-link__badge'>{badge}</span> : null;
|
||||
const iconElement = typeof icon === 'string' ? <Icon id={icon} fixedWidth className='column-link__icon' /> : icon;
|
||||
|
||||
|
@ -17,6 +17,14 @@ const ColumnLink = ({ icon, text, to, href, method, badge, transparent, ...other
|
|||
{badgeElement}
|
||||
</a>
|
||||
);
|
||||
} else if (button) {
|
||||
return (
|
||||
<button className={className} onClick={onClick} title={text} {...other}>
|
||||
{iconElement}
|
||||
<span>{text}</span>
|
||||
{badgeElement}
|
||||
</button>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<NavLink to={to} className={className} title={text} {...other}>
|
||||
|
@ -36,6 +44,8 @@ ColumnLink.propTypes = {
|
|||
method: PropTypes.string,
|
||||
badge: PropTypes.node,
|
||||
transparent: PropTypes.bool,
|
||||
button: PropTypes.bool,
|
||||
onClick: PropTypes.function,
|
||||
};
|
||||
|
||||
export default ColumnLink;
|
||||
|
|
|
@ -151,12 +151,10 @@ export default class ColumnsArea extends ImmutablePureComponent {
|
|||
<div className='columns-area columns-area--mobile'>{children}</div>
|
||||
</div>
|
||||
|
||||
<div className='columns-area__panels__pane columns-area__panels__pane--start columns-area__panels__pane--navigational'>
|
||||
<div className='columns-area__panels__pane__inner'>
|
||||
<div className='columns-area__panels__pane columns-area__panels__pane--start columns-area__panels__pane--navigational columns-area__panels__pane__inner'>
|
||||
<NavigationPanel />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ const messages = defineMessages({
|
|||
explore: { id: 'explore.title', defaultMessage: 'Explore' },
|
||||
local: { id: 'tabs_bar.local_timeline', defaultMessage: 'Local' },
|
||||
federated: { id: 'tabs_bar.federated_timeline', defaultMessage: 'Federated' },
|
||||
menu: { id: 'navigation_bar.menu', defaultMessage: 'Menu' },
|
||||
direct: { id: 'navigation_bar.direct', defaultMessage: 'Direct messages' },
|
||||
favourites: { id: 'navigation_bar.favourites', defaultMessage: 'Favourites' },
|
||||
bookmarks: { id: 'navigation_bar.bookmarks', defaultMessage: 'Bookmarks' },
|
||||
|
@ -33,14 +34,20 @@ const messages = defineMessages({
|
|||
const Account = connect(state => ({
|
||||
account: state.getIn(['accounts', me]),
|
||||
}))(({ account }) => (
|
||||
<Permalink className='column-link column-link--transparent' href={account.get('url')} to={`/@${account.get('acct')}`} title={account.get('acct')}>
|
||||
<Avatar account={account} size={24} />
|
||||
<Permalink className='column-link column-link--transparent navigation-panel--profile' href={account.get('url')} to={`/@${account.get('acct')}`} title={account.get('acct')}>
|
||||
<Avatar account={account} size={32} inline />
|
||||
<span>Profile</span>
|
||||
</Permalink>
|
||||
));
|
||||
|
||||
export default @injectIntl
|
||||
class NavigationPanel extends React.Component {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.handleMenuToggle = this.handleMenuToggle.bind(this);
|
||||
}
|
||||
|
||||
static contextTypes = {
|
||||
router: PropTypes.object.isRequired,
|
||||
identity: PropTypes.object.isRequired,
|
||||
|
@ -50,13 +57,35 @@ class NavigationPanel extends React.Component {
|
|||
intl: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
state = {
|
||||
retracted: false,
|
||||
};
|
||||
|
||||
handleMenuToggle() {
|
||||
this.setState({
|
||||
retracted: !this.state.retracted,
|
||||
});
|
||||
const mainContent = document.querySelector('.columns-area--mobile');
|
||||
if (!this.state.retracted) {
|
||||
mainContent.classList.add('navigation-panel--retracted');
|
||||
mainContent.classList.remove('navigation-panel--extended');
|
||||
} else {
|
||||
mainContent.classList.add('navigation-panel--extended');
|
||||
mainContent.classList.remove('navigation-panel--retracted');
|
||||
}
|
||||
};
|
||||
|
||||
render () {
|
||||
const { intl } = this.props;
|
||||
const { signedIn, disabledAccountId } = this.context.identity;
|
||||
|
||||
const isWideSingleColumnLayout = document.querySelector('.columns-area__panels__pane--compositional') && window.getComputedStyle(document.querySelector('.columns-area__panels__pane--compositional')).display !== 'none';
|
||||
|
||||
return (
|
||||
<div className='navigation-panel'>
|
||||
<ColumnLink transparent button onClick={this.handleMenuToggle} icon='bars' text={intl.formatMessage(messages.menu)} />
|
||||
|
||||
{ (isWideSingleColumnLayout || !this.state.retracted) && <div id='navigation-retractable'>
|
||||
{signedIn && (
|
||||
<React.Fragment>
|
||||
<Account />
|
||||
|
@ -106,6 +135,8 @@ class NavigationPanel extends React.Component {
|
|||
<hr />
|
||||
<ColumnLink transparent href='/about' icon='ellipsis-h' text={intl.formatMessage(messages.about)} />
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<NavigationPortal />
|
||||
</div>
|
||||
|
|
|
@ -386,6 +386,7 @@
|
|||
"navigation_bar.follows_and_followers": "Follows and followers",
|
||||
"navigation_bar.lists": "Lists",
|
||||
"navigation_bar.logout": "Logout",
|
||||
"navigation_bar.menu": "Menu",
|
||||
"navigation_bar.mutes": "Muted users",
|
||||
"navigation_bar.personal": "Personal",
|
||||
"navigation_bar.pins": "Pinned posts",
|
||||
|
|
|
@ -1181,3 +1181,35 @@ button.icon-button.disabled i.fa-retweet {
|
|||
color: darken($ui-highlight-color, 30%);
|
||||
}
|
||||
}
|
||||
|
||||
// Tablet layout
|
||||
@media screen and (max-width: $no-gap-breakpoint - 1px) {
|
||||
.tabs-bar__wrapper {
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.columns-area--mobile {
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.column-header {
|
||||
box-sizing: border-box;
|
||||
height: 48px;
|
||||
}
|
||||
}
|
||||
|
||||
// Mobile layout
|
||||
@media screen and (max-width: $no-gap-breakpoint - 285px - 1px) {
|
||||
.tabs-bar__wrapper {
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.columns-area--mobile {
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.column-header {
|
||||
box-sizing: border-box;
|
||||
height: 48px;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2626,30 +2626,6 @@ $ui-header-height: 0px;
|
|||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: $no-gap-breakpoint - 285px - 1px) {
|
||||
$sidebar-width: 55px;
|
||||
|
||||
.columns-area__panels__main {
|
||||
width: calc(100% - $sidebar-width);
|
||||
}
|
||||
|
||||
.columns-area__panels__pane--navigational {
|
||||
min-width: $sidebar-width;
|
||||
|
||||
.columns-area__panels__pane__inner {
|
||||
width: $sidebar-width;
|
||||
}
|
||||
|
||||
.column-link span {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.list-panel {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.explore__search-header {
|
||||
display: none;
|
||||
}
|
||||
|
@ -8787,6 +8763,8 @@ div.status__content--with-spoiler {
|
|||
padding: 8px 6px;
|
||||
border-radius: 4px;
|
||||
color: $primary-text-color;
|
||||
font-size: 16px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8796,3 +8774,173 @@ div.status__content--with-spoiler {
|
|||
color: lighten($ui-highlight-color, 30%);
|
||||
}
|
||||
}
|
||||
|
||||
.navigation-panel--profile {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.column-link--button {
|
||||
border: 0;
|
||||
border-bottom: 1px solid lighten($ui-base-color, 8%);
|
||||
box-sizing: border-box;
|
||||
height: 48px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
@media screen and (min-width: $no-gap-breakpoint) {
|
||||
$sidebar-width: 100%;
|
||||
|
||||
.columns-area__panels__pane--compositional {
|
||||
.columns-area__panels__pane__inner {
|
||||
position: fixed;
|
||||
}
|
||||
}
|
||||
|
||||
.columns-area__panels__pane__inner {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.navigation-panel {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.navigation-panel--profile {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#navigation-panel__publish {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.column-link--button {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: $no-gap-breakpoint - 1px) {
|
||||
$sidebar-width: 285px;
|
||||
|
||||
.tabs-bar__wrapper {
|
||||
z-index: 1;
|
||||
width: calc(100% - $sidebar-width);
|
||||
}
|
||||
|
||||
.columns-area__panels__main {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.columns-area--mobile {
|
||||
// z-index: -1;
|
||||
}
|
||||
|
||||
.columns-area--mobile.navigation-panel--retracted {
|
||||
width: 100%;
|
||||
margin: 0 auto auto 0;
|
||||
}
|
||||
|
||||
.columns-area--mobile.navigation-panel--extended {
|
||||
// z-index: -1;
|
||||
width: calc(100% - $sidebar-width);
|
||||
margin: 0;
|
||||
color: red !important;
|
||||
}
|
||||
|
||||
.columns-area__panels__pane__inner {
|
||||
width: 0;
|
||||
height: 0;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.column-header__collapsible {
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
.navigation-panel {
|
||||
width: $sidebar-width;
|
||||
z-index: 1000;
|
||||
position: fixed;
|
||||
right: 0;
|
||||
height: auto !important;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.column-link__icon {
|
||||
margin-right: 13px;
|
||||
}
|
||||
|
||||
.account__avatar-inline {
|
||||
margin-right: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: $no-gap-breakpoint - 285px - 1px) {
|
||||
$sidebar-width: 55px;
|
||||
|
||||
.tabs-bar__wrapper {
|
||||
z-index: 1;
|
||||
width: calc(100% - $sidebar-width);
|
||||
}
|
||||
|
||||
.columns-area__panels__main {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.columns-area--mobile {
|
||||
// z-index: -1;
|
||||
}
|
||||
|
||||
.columns-area--mobile.navigation-panel--extended {
|
||||
// z-index: -1;
|
||||
width: calc(100% - $sidebar-width);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.columns-area--mobile.navigation-panel--retracted {
|
||||
width: 100%;
|
||||
margin: 0 auto auto 0;
|
||||
}
|
||||
|
||||
.columns-area__panels__pane__inner {
|
||||
width: 0;
|
||||
height: 0;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.column-header__collapsible {
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
.navigation-panel {
|
||||
width: $sidebar-width;
|
||||
z-index: 1000;
|
||||
position: fixed;
|
||||
right: 0;
|
||||
height: auto !important;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.columns-area__panels__pane--navigational {
|
||||
min-width: $sidebar-width;
|
||||
|
||||
.columns-area__panels__pane__inner {
|
||||
width: $sidebar-width;
|
||||
}
|
||||
|
||||
.column-link span {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.list-panel {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#navigation-retractable {
|
||||
position: relative;
|
||||
overflow-y: auto;
|
||||
bottom: 0;
|
||||
height: 100vh;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue