Commit cdde4549 authored by mgabdev's avatar mgabdev

Progress

parent 389b189d
......@@ -132,8 +132,8 @@ class Account extends ImmutablePureComponent {
</div>
<div className={[styles.default, styles.marginLeftAuto].join(' ')}>
<button className={[styles.default, styles.circle, styles.backgroundSubtle2, styles.paddingVertical5PX, styles.paddingHorizontal5PX, styles.cursorPointer].join(' ')}>
<Icon id='close' width='8px' height='8px' />
<button className={[styles.default, styles.circle, styles.backgroundTransparent, styles.paddingVertical5PX, styles.paddingHorizontal5PX, styles.cursorPointer].join(' ')}>
<Icon className={styles.fillColorSubtle} id='close' width='8px' height='8px' />
</button>
</div>
......
import { NavLink } from 'react-router-dom'
import classNames from 'classnames/bind'
export default class Button extends PureComponent {
static propTypes = {
children: PropTypes.node,
text: PropTypes.node,
to: PropTypes.string,
href: PropTypes.string,
onClick: PropTypes.func,
disabled: PropTypes.bool,
block: PropTypes.bool,
secondary: PropTypes.bool,
children: PropTypes.node,
className: PropTypes.string,
}
state = {
hovering: false,
}
handleOnMouseEnter = () => {
this.setState({
hovering: true,
})
}
handleOnMouseLeave = () => {
this.setState({
hovering: false,
})
}
handleClick = (e) => {
if (!this.props.disabled && this.props.onClick) {
......@@ -44,8 +31,7 @@ export default class Button extends PureComponent {
}
render () {
const { secondary, block, className, disabled, text, children, href } = this.props
const { hovering } = this.state
const { block, className, disabled, text, to, children, href } = this.props
const cx = classNames.bind(styles)
......@@ -60,21 +46,22 @@ export default class Button extends PureComponent {
paddingVertical10PX: 1,
paddingHorizontal15PX: 1,
width100PC: block,
backgroundColorBrand: !hovering,
backgroundColorBrandDark: hovering,
backgroundColorBrand: 1,
backgroundColorBrandDark_onHover: 1,
})
if (href) {
return (
<a
className={classes}
href={href}
onMouseEnter={() => this.handleOnMouseEnter()}
onMouseLeave={() => this.handleOnMouseLeave()}
>
<a className={classes} href={href}>
{text || children}
</a>
)
} else if (to) {
return (
<NavLink className={classes} to={to}>
{text || children}
</NavLink>
)
}
return (
......@@ -83,8 +70,6 @@ export default class Button extends PureComponent {
disabled={disabled}
onClick={this.handleClick}
className={classes}
onMouseEnter={() => this.handleOnMouseEnter()}
onMouseLeave={() => this.handleOnMouseLeave()}
>
{text || children}
</button>
......
......@@ -26,7 +26,7 @@ export default class Column extends PureComponent {
);
return (
<div role='region' aria-labelledby={columnHeaderId} className='column'>
<div role='region' aria-labelledby={columnHeaderId} className={[styles.default].join(' ')}>
{ backBtn && <ColumnBackButton slim={backBtn === 'slim'} />}
{children}
</div>
......
import { injectIntl, defineMessages } from 'react-intl'
import Icon from './icon'
const messages = defineMessages({
show: { id: 'column_header.show_settings', defaultMessage: 'Show settings' },
hide: { id: 'column_header.hide_settings', defaultMessage: 'Hide settings' },
})
export default @injectIntl
class ColumnHeader extends PureComponent {
static contextTypes = {
router: PropTypes.object,
}
static propTypes = {
intl: PropTypes.object.isRequired,
title: PropTypes.node,
icon: PropTypes.string,
active: PropTypes.bool,
children: PropTypes.node,
}
state = {
collapsed: true,
}
historyBack = () => {
if (window.history && window.history.length === 1) {
this.context.router.history.push('/home') // homehack
} else {
this.context.router.history.goBack()
}
}
handleToggleClick = (e) => {
e.stopPropagation()
this.setState({
collapsed: !this.state.collapsed,
})
}
handleBackClick = () => {
this.historyBack()
}
render () {
const { title, icon, active, children, intl: { formatMessage } } = this.props
const { collapsed } = this.state
return (
<div className={[styles.default, styles.height100PC, styles.flexRow].join(' ')}>
{ /* <button className={[styles.default, styles.cursorPointer, styles.backgroundTransparent, styles.alignItemsCenter, styles.marginRight10PX, styles.justifyContentCenter].join(' ')}>
<Icon className={[styles.marginRight5PX, styles.fillColorBrand].join(' ')} id='back' width='24px' height='24px' />
</button> */ }
<h1 className={[styles.default, styles.height100PC, styles.justifyContentCenter].join(' ')}>
<span className={[styles.default, styles.text, styles.fontSize24PX, styles.fontWeight500, styles.colorBlack].join(' ')}>
{title}
</span>
</h1>
<div className={[styles.default, styles.backgroundTransparent, styles.flexRow, styles.alignItemsCenter, styles.justifyContentCenter, styles.marginLeftAuto].join(' ')}>
<button className={[styles.default, styles.marginLeft5PX, styles.cursorPointer, styles.backgroundSubtle2, styles.paddingHorizontal10PX, styles.paddingVertical5PX, styles.radiusSmall].join(' ')}>
<Icon className={styles.fillColorSubtle} id='ellipsis' width='24px' height='24px' />
</button>
<button className={[styles.default, styles.marginLeft5PX, styles.cursorPointer, styles.backgroundSubtle2, styles.paddingHorizontal10PX, styles.paddingVertical5PX, styles.radiusSmall].join(' ')}>
<Icon className={styles.fillColorSubtle} id='ellipsis' width='24px' height='24px' />
</button>
<button className={[styles.default, styles.marginLeft5PX, styles.cursorPointer, styles.backgroundSubtle2, styles.paddingHorizontal10PX, styles.paddingVertical5PX, styles.radiusSmall].join(' ')}>
<Icon className={styles.fillColorSubtle} id='ellipsis' width='24px' height='24px' />
</button>
</div>
</div>
)
// const wrapperClassName = classNames('column-header__wrapper', {
// 'column-header__wrapper--active': active,
// })
// const buttonClassName = classNames('column-header', {
// 'column-header--active': active,
// })
// const btnTitle = formatMessage(collapsed ? messages.show : messages.hide)
// const hasTitle = icon && title
// const hasChildren = !!children
// if (!hasChildren && !hasTitle) {
// return null
// } else if (!hasChildren && hasTitle) {
// return (
// <div className={wrapperClassName}>
// <h1 className={buttonClassName}>
// <Icon id={icon} fixedWidth className='column-header__icon' />
// {title}
// </h1>
// </div>
// )
// }
// const collapsibleClassName = classNames('column-header__collapsible', {
// 'column-header__collapsible--collapsed': collapsed,
// })
// const collapsibleButtonClassName = classNames('column-header__button', {
// 'column-header__button--active': !collapsed,
// })
// return (
// <div className={wrapperClassName}>
// <h1 className={buttonClassName}>
// {
// hasTitle && (
// <Fragment>
// <Icon id={icon} fixedWidth className='column-header__icon' />
// {title}
// </Fragment>
// )
// }
// <button
// className={collapsibleButtonClassName}
// title={btnTitle}
// aria-label={btnTitle}
// aria-pressed={!collapsed}
// onClick={this.handleToggleClick}
// >
// <Icon id='sliders' />
// </button>
// </h1>
// <div className={collapsibleClassName} tabIndex={collapsed ? -1 : null}>
// <div className='column-header__collapsible-inner'>
// {
// !collapsed &&
// <div key='extra-content' className='column-header__collapsible__extra'>
// {children}
// </div>
// }
// </div>
// </div>
// </div>
// )
}
}
import { Fragment } from 'react';
import classNames from 'classnames';
import { injectIntl, defineMessages } from 'react-intl';
import Icon from '../icon';
const messages = defineMessages({
show: { id: 'column_header.show_settings', defaultMessage: 'Show settings' },
hide: { id: 'column_header.hide_settings', defaultMessage: 'Hide settings' },
});
export default @injectIntl
class ColumnHeader extends PureComponent {
static contextTypes = {
router: PropTypes.object,
};
static propTypes = {
intl: PropTypes.object.isRequired,
title: PropTypes.node,
icon: PropTypes.string,
active: PropTypes.bool,
children: PropTypes.node,
};
state = {
collapsed: true,
};
historyBack = () => {
if (window.history && window.history.length === 1) {
this.context.router.history.push('/home'); // homehack
} else {
this.context.router.history.goBack();
}
}
handleToggleClick = (e) => {
e.stopPropagation();
this.setState({
collapsed: !this.state.collapsed,
});
}
handleBackClick = () => {
this.historyBack();
}
render () {
const { title, icon, active, children, intl: { formatMessage } } = this.props;
const { collapsed } = this.state;
const wrapperClassName = classNames('column-header__wrapper', {
'column-header__wrapper--active': active,
});
const buttonClassName = classNames('column-header', {
'column-header--active': active,
});
const btnTitle = formatMessage(collapsed ? messages.show : messages.hide);
const hasTitle = icon && title;
const hasChildren = !!children;
if (!hasChildren && !hasTitle) {
return null;
} else if (!hasChildren && hasTitle) {
return (
<div className={wrapperClassName}>
<h1 className={buttonClassName}>
<Icon id={icon} fixedWidth className='column-header__icon' />
{title}
</h1>
</div>
);
}
const collapsibleClassName = classNames('column-header__collapsible', {
'column-header__collapsible--collapsed': collapsed,
});
const collapsibleButtonClassName = classNames('column-header__button', {
'column-header__button--active': !collapsed,
});
return (
<div className={wrapperClassName}>
<h1 className={buttonClassName}>
{
hasTitle && (
<Fragment>
<Icon id={icon} fixedWidth className='column-header__icon' />
{title}
</Fragment>
)
}
<button
className={collapsibleButtonClassName}
title={btnTitle}
aria-label={btnTitle}
aria-pressed={!collapsed}
onClick={this.handleToggleClick}
>
<Icon id='sliders' />
</button>
</h1>
<div className={collapsibleClassName} tabIndex={collapsed ? -1 : null}>
<div className='column-header__collapsible-inner'>
{
!collapsed &&
<div key='extra-content' className='column-header__collapsible__extra'>
{children}
</div>
}
</div>
</div>
</div>
);
}
}
.column-header {
display: flex;
font-size: 16px;
flex: 0 0 auto;
cursor: pointer;
position: relative;
z-index: 2;
outline: 0;
overflow: hidden;
background: $gab-background-container;
body.theme-gabsocial-light & {
background: $gab-background-container-light;
color: $gab-default-text-light;
}
&--active {
box-shadow: 0 1px 0 rgba($highlight-text-color, 0.3);
.column-header__icon {
color: $highlight-text-color;
text-shadow: 0 0 10px rgba($highlight-text-color, 0.4);
}
}
&:focus,
&:active {
outline: 0;
}
&__wrapper {
position: relative;
flex: 0 0 auto;
overflow: hidden;
&--active {
&::before {
pointer-events: none;
z-index: 1;
background: radial-gradient(ellipse, rgba($ui-highlight-color, 0.23) 0%, rgba($ui-highlight-color, 0) 60%);
@include pseudo;
@include size(60%, 28px);
@include abs-position(35px, 0, auto, 0, false);
@include margin-center;
}
}
}
&__icon {
display: inline-block;
margin-right: 5px;
}
&__expansion {
overflow-x: scroll;
overflow-y: hidden;
white-space: nowrap;
max-height: 0px;
&--open {
max-height: 55px;
}
}
&__button {
margin-left: auto;
cursor: pointer;
border: 0;
padding: 0 15px;
font-size: 16px;
color: #fff;
background: $gab-background-container;
body.theme-gabsocial-light & {
color: $gab-default-text-light;
background: $gab-background-container-light;
}
&:hover {
color: lighten($darker-text-color, 7%);
}
&--active {
color: $primary-text-color;
background: lighten($ui-base-color, 8%);
&:hover {
color: $primary-text-color;
background: lighten($ui-base-color, 8%);
}
}
}
&__collapsible-inner {
background: #3f3f3f;
padding: 15px;
body.theme-gabsocial-light & {
background: #e6e6e6;
}
}
&__collapsible {
max-height: 70vh;
overflow: hidden;
overflow-y: auto;
color: $darker-text-color;
transition: max-height 150ms linear;
&--collapsed {
max-height: 0;
}
hr {
height: 0;
background: transparent;
border: 0;
border-top: 1px solid lighten($ui-base-color, 12%);
margin: 10px 0;
}
}
}
.column-header-btn {
padding: 15px;
color: inherit;
text-decoration: none;
white-space: nowrap;
&--sub {
font-size: 14px;
padding: 6px s10px;
}
&--grouped {
margin: 6px;
}
&--active {
color: $primary-text-color;
border-radius: 10px;
background-color: rgba($highlight-text-color, .1);
}
}
\ No newline at end of file
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import classNames from 'classnames';
import { injectIntl, defineMessages } from 'react-intl';
import { Link } from 'react-router-dom';
import { createSelector } from 'reselect';
import { fetchLists } from '../../actions/lists';
import Icon from '../icon';
const messages = defineMessages({
show: { id: 'column_header.show_settings', defaultMessage: 'Show settings' },
hide: { id: 'column_header.hide_settings', defaultMessage: 'Hide settings' },
homeTitle: { id: 'home_column_header.home', defaultMessage: 'Home' },
allTitle: { id: 'home_column_header.all', defaultMessage: 'All' },
listTitle: { id: 'home_column.lists', defaultMessage: 'Lists' },
});
const getOrderedLists = createSelector([state => state.get('lists')], lists => {
if (!lists) {
return lists;
}
return lists.toList().filter(item => !!item).sort((a, b) => a.get('title').localeCompare(b.get('title')));
});
const mapStateToProps = state => {
return {
lists: getOrderedLists(state),
};
};
export default @connect(mapStateToProps)
@injectIntl
class HomeColumnHeader extends ImmutablePureComponent {
static contextTypes = {
router: PropTypes.object,
};
static propTypes = {
intl: PropTypes.object.isRequired,
dispatch: PropTypes.func.isRequired,
active: PropTypes.bool,
children: PropTypes.node,
activeItem: PropTypes.string,
activeSubItem: PropTypes.string,
lists: ImmutablePropTypes.list,
};
state = {
collapsed: true,
listsExpanded: false,
};
componentDidMount() {
this.props.dispatch(fetchLists());
}
handleToggleClick = (e) => {
e.stopPropagation();
this.setState({ collapsed: !this.state.collapsed });
}
expandLists = () => {
this.setState({ listsExpanded: !this.state.listsExpanded });
}
render () {
const { active, children, intl: { formatMessage }, activeItem, activeSubItem, lists } = this.props;
const { collapsed, listsExpanded } = this.state;
const wrapperClassName = classNames('column-header__wrapper', {
'column-header__wrapper--active': active,
});
const buttonClassName = classNames('column-header', {
'column-header--active': active,
});
const collapsibleClassName = classNames('column-header__collapsible', {
'column-header__collapsible--collapsed': collapsed,
});
const collapsibleButtonClassName = classNames('column-header__button', {
'column-header__button--active': !collapsed,
});
const expansionClassName = classNames('column-header column-header__expansion', {
'column-header__expansion--open': listsExpanded,
});
const btnTitle = formatMessage(collapsed ? messages.show : messages.hide);
let expandedContent = null;
if ((listsExpanded || activeItem === 'lists') && lists) {
expandedContent = lists.map((list) => {
const listId = list.get('id');
const linkUrl = `/list/${listId}`;
const classes = classNames('column-header-btn column-header-btn--sub column-header-btn--grouped', {
'column-header-btn--active': listId === activeSubItem,
});
return (
<Link key={listId} to={linkUrl} className={classes}>
{list.get('title')}
</Link>
);
});
}
return (
<div className={wrapperClassName}>
<h1 className={buttonClassName}>
<Link to='/home' className={classNames('column-header-btn column-header-btn--grouped', { 'column-header-btn--active': 'home' === activeItem })}>
<Icon id='home' fixedWidth className='column-header__icon' />
{formatMessage(messages.homeTitle)}
</Link>
<Link to='/timeline/all' className={classNames('column-header-btn column-header-btn--grouped', { 'column-header-btn--active': 'all' === activeItem })}>
<Icon id='globe' fixedWidth className='column-header__icon' />
{formatMessage(messages.allTitle)}
</Link>
{ lists.size > 0 &&
<a onClick={this.expandLists} className={classNames('column-header-btn column-header-btn--grouped', { 'column-header-btn--active': 'lists' === activeItem })}>
<Icon id='list' fixedWidth className='column-header__icon' />
{formatMessage(messages.listTitle)}
</a>
}
{ lists.size == 0 &&
<Link to='/lists' className='column-header-btn column-header-btn--grouped'>
<Icon id='list' fixedWidth className='column-header__icon' />
{formatMessage(messages.listTitle)}
</Link>
}
<div className='column-header__buttons'>
<button