gab-social/app/javascript/gabsocial/components/navigation_bar.js

309 lines
9.5 KiB
JavaScript
Raw Normal View History

2020-04-29 03:24:35 +01:00
import ImmutablePropTypes from 'react-immutable-proptypes'
import ImmutablePureComponent from 'react-immutable-pure-component'
2020-05-14 07:03:22 +01:00
import { openSidebar } from '../actions/sidebar'
2020-05-15 04:17:31 +01:00
import { openPopover } from '../actions/popover'
2020-04-29 03:24:35 +01:00
import { BREAKPOINT_EXTRA_SMALL } from '../constants'
import { me } from '../initial_state'
import { makeGetAccount } from '../selectors'
import Responsive from '../features/ui/util/responsive_component'
2020-05-15 04:17:31 +01:00
import {
CX,
POPOVER_NAV_SETTINGS,
} from '../constants'
2020-04-29 23:32:49 +01:00
import Avatar from './avatar'
2020-05-10 04:26:58 +01:00
import BackButton from './back_button'
2020-04-30 05:34:50 +01:00
import Button from './button'
2020-05-06 05:33:54 +01:00
import Heading from './heading'
2020-04-29 03:24:35 +01:00
import Icon from './icon'
2020-04-30 05:34:50 +01:00
import Search from './search'
import Text from './text'
2020-04-29 03:24:35 +01:00
const mapStateToProps = (state) => ({
account: makeGetAccount()(state, me),
})
2020-05-14 07:03:22 +01:00
const mapDispatchToProps = (dispatch) => ({
onOpenSidebar() {
dispatch(openSidebar())
2020-05-15 03:31:24 +01:00
},
2020-05-15 04:17:31 +01:00
onOpenNavSettingsPopover(targetRef) {
dispatch(openPopover(POPOVER_NAV_SETTINGS, {
targetRef,
position: 'top',
}))
2020-05-14 07:03:22 +01:00
}
})
2020-04-29 03:24:35 +01:00
export default
2020-05-14 07:03:22 +01:00
@connect(mapStateToProps, mapDispatchToProps)
2020-04-29 03:24:35 +01:00
class NavigationBar extends ImmutablePureComponent {
static propTypes = {
account: ImmutablePropTypes.map,
actions: PropTypes.array,
tabs: PropTypes.array,
title: PropTypes.string,
showBackBtn: PropTypes.bool,
2020-05-14 07:03:22 +01:00
onOpenSidebar: PropTypes.func.isRequired,
2020-05-15 03:31:24 +01:00
onOpenNavSettingsPopover: PropTypes.func.isRequired,
noActions: PropTypes.bool,
noSearch: PropTypes.bool,
2020-04-29 23:32:49 +01:00
}
2020-05-15 04:17:31 +01:00
handleOnOpenNavSettingsPopover = () => {
this.props.onOpenNavSettingsPopover(this.avatarNode)
}
setAvatarNode = (c) => {
this.avatarNode = c
2020-05-14 21:45:39 +01:00
}
2020-04-29 03:24:35 +01:00
render() {
const {
title,
showBackBtn,
actions,
tabs,
account,
2020-05-14 07:03:22 +01:00
onOpenSidebar,
noActions,
noSearch,
2020-04-29 03:24:35 +01:00
} = this.props
return (
<div className={[_s.default, _s.z4, _s.heightMin53PX, _s.width100PC].join(' ')}>
<div className={[_s.default, _s.heightMin53PX, _s.bgNavigation, _s.alignItemsCenter, _s.z3, _s.top0, _s.right0, _s.left0, _s.posFixed].join(' ')} >
2020-04-29 23:32:49 +01:00
<div className={[_s.default, _s.saveAreaInsetPT, _s.saveAreaInsetPL, _s.saveAreaInsetPR, _s.flexRow, _s.width1255PX].join(' ')}>
2020-04-29 23:32:49 +01:00
2020-05-06 07:24:16 +01:00
{ /** Default */}
<Responsive min={BREAKPOINT_EXTRA_SMALL}>
2020-04-29 23:32:49 +01:00
2020-05-06 07:24:16 +01:00
<div className={[_s.default, _s.flexRow].join(' ')}>
2020-05-06 05:33:54 +01:00
<h1 className={[_s.default, _s.mr15].join(' ')}>
2020-05-07 06:55:24 +01:00
<Button
to='/'
isText
title='Gab'
aria-label='Gab'
color='none'
backgroundColor='none'
className={[_s.default, _s.justifyContentCenter, _s.noSelect, _s.noUnderline, _s.height53PX, _s.cursorPointer, _s.px10, _s.mr15].join(' ')}
>
2020-05-09 03:17:19 +01:00
<Icon id='logo' className={_s.fillNavigationBrand} />
2020-05-06 05:33:54 +01:00
</Button>
</h1>
2020-04-29 23:32:49 +01:00
{
!noSearch &&
<div className={[_s.default, _s.width340PX, _s.mr10].join(' ')}>
<Search isInNav />
</div>
}
2020-04-29 23:32:49 +01:00
2020-05-06 07:24:16 +01:00
</div>
2020-04-29 23:32:49 +01:00
2020-05-06 07:24:16 +01:00
<div className={[_s.default, _s.mlAuto].join(' ')}>
{
!noActions &&
<div className={[_s.default, _s.height53PX, _s.pl15, _s.flexRow, _s.alignItemsCenter, _s.justifyContentSpaceBetween].join(' ')}>
<NavigationBarButton title='Home' icon='home' to='/home' />
<NavigationBarButton title='Explore' icon='explore' to='/explore' />
<NavigationBarButtonDivider />
<NavigationBarButton attrTitle='Notifications' icon='notifications' to='/notifications' />
<NavigationBarButton attrTitle='Settings' icon='cog' href='/settings/preferences' />
<NavigationBarButtonDivider />
{
!!account &&
<button
ref={this.setAvatarNode}
title={account.get('display_name')}
onClick={this.handleOnOpenNavSettingsPopover}
className={[_s.height53PX, _s.bgTransparent, _s.outlineNone, _s.cursorPointer, _s.default, _s.justifyContentCenter, _s.ml15].join(' ')}
>
<Avatar account={account} size={32} noHover />
</button>
}
</div>
}
2020-05-06 07:24:16 +01:00
</div>
</Responsive>
{ /** Mobile */}
<Responsive max={BREAKPOINT_EXTRA_SMALL}>
2020-05-10 04:26:58 +01:00
<div className={[_s.default, _s.width84PX, _s.alignItemsStart, _s.pl10].join(' ')}>
2020-05-06 07:24:16 +01:00
{
!!account && !showBackBtn && !noActions &&
2020-05-06 07:24:16 +01:00
<button
title={account.get('display_name')}
2020-05-14 07:03:22 +01:00
onClick={onOpenSidebar}
2020-05-06 07:24:16 +01:00
className={[_s.height53PX, _s.bgTransparent, _s.outlineNone, _s.cursorPointer, _s.default, _s.justifyContentCenter].join(' ')}
>
<Avatar account={account} size={32} noHover />
</button>
}
{
showBackBtn &&
2020-05-10 04:26:58 +01:00
<BackButton
className={_s.height53PX}
icon='angle-left'
iconSize='18px'
2020-05-07 06:55:24 +01:00
iconClassName={[_s.mr5, _s.fillNavigation].join(' ')}
2020-05-06 07:24:16 +01:00
/>
}
{
noActions &&
<h1 className={[_s.default, _s.mr15].join(' ')}>
<Button
to='/'
isText
title='Gab'
aria-label='Gab'
color='none'
backgroundColor='none'
className={[_s.default, _s.justifyContentCenter, _s.noSelect, _s.noUnderline, _s.height53PX, _s.cursorPointer, _s.px10, _s.mr15].join(' ')}
>
<Icon id='logo' className={_s.fillNavigationBrand} />
</Button>
</h1>
}
2020-05-06 07:24:16 +01:00
</div>
<div className={[_s.default, _s.height53PX, _s.justifyContentCenter, _s.mlAuto, _s.mrAuto].join(' ')}>
<Heading size='h1'>
2020-05-07 06:55:24 +01:00
<span className={_s.colorNavigation}>
{title}
</span>
2020-05-06 07:24:16 +01:00
</Heading>
</div>
<div className={[_s.default, _s.width84PX, _s.pr15].join(' ')}>
2020-05-14 07:03:22 +01:00
<div className={[_s.default, _s.bgTransparent, _s.flexRow, _s.alignItemsCenter, _s.justifyContentCenter, _s.mlAuto].join(' ')}>
{
actions && actions.map((action, i) => (
<Button
isNarrow
backgroundColor='none'
color='primary'
onClick={() => action.onClick()}
key={`action-btn-${i}`}
className={[_s.ml5, _s.height53PX, _s.justifyContentCenter, _s.px5].join(' ')}
icon={action.icon}
iconClassName={_s.fillNavigation}
iconSize='18px'
/>
))
}
{
!noSearch &&
<Button
isNarrow
backgroundColor='none'
color='primary'
to='/search'
key={`action-btn-search`}
className={[_s.ml5, _s.height53PX, _s.justifyContentCenter, _s.px5].join(' ')}
icon='search'
iconClassName={_s.fillNavigation}
iconSize='18px'
/>
}
2020-05-14 07:03:22 +01:00
</div>
2020-04-29 03:24:35 +01:00
</div>
2020-05-06 07:24:16 +01:00
</Responsive>
2020-04-29 23:32:49 +01:00
2020-04-29 03:24:35 +01:00
</div>
2020-04-29 23:32:49 +01:00
2020-04-29 03:24:35 +01:00
</div>
</div>
)
}
2020-04-29 23:32:49 +01:00
}
class NavigationBarButtonDivider extends PureComponent {
render() {
return (
2020-05-07 06:55:24 +01:00
<div className={[_s.default, _s.height20PX, _s.width1PX, _s.mr10, _s.ml10, _s.bgNavigationBlend].join(' ')} />
2020-04-29 23:32:49 +01:00
)
}
}
class NavigationBarButton extends PureComponent {
static propTypes = {
title: PropTypes.string,
icon: PropTypes.string,
to: PropTypes.string,
2020-04-30 05:34:50 +01:00
href: PropTypes.string,
2020-05-01 06:50:27 +01:00
attrTitle: PropTypes.string,
2020-04-29 23:32:49 +01:00
}
render() {
const {
title,
icon,
to,
2020-04-30 05:34:50 +01:00
href,
2020-05-01 06:50:27 +01:00
attrTitle,
2020-04-29 23:32:49 +01:00
} = this.props
const active = false
const classes = CX({
default: 1,
height53PX: 1,
flexRow: 1,
alignItemsCenter: 1,
justifyContentCenter: 1,
outlineNone: 1,
cursorPointer: 1,
bgTransparent: 1,
2020-05-01 06:50:27 +01:00
noUnderline: 1,
2020-05-07 06:55:24 +01:00
colorNavigation: 1,
2020-05-01 06:50:27 +01:00
px10: !!title,
px5: !title,
2020-04-29 23:32:49 +01:00
colorWhite: !!title,
fs13PX: !!title,
fontWeightNormal: !!title,
})
const iconClasses = CX({
2020-05-07 06:55:24 +01:00
fillNavigation: !!title || active,
fillNavigationBlend: !title,
2020-04-29 23:32:49 +01:00
mr10: !!title,
})
2020-05-01 06:50:27 +01:00
const iconSize = !!title ? '16px' : '18px'
2020-04-29 23:32:49 +01:00
return (
2020-04-30 05:34:50 +01:00
<Button
to={to}
href={href}
title={attrTitle}
2020-04-29 23:32:49 +01:00
className={classes}
2020-04-30 05:34:50 +01:00
noClasses
2020-04-29 23:32:49 +01:00
>
<Icon className={iconClasses} id={icon} size={iconSize} />
2020-04-30 05:34:50 +01:00
{
!!title &&
<Text color='white'>
{title}
</Text>
}
</Button>
2020-04-29 23:32:49 +01:00
)
}
2020-04-29 03:24:35 +01:00
}