The code powering m.abunchtell.com https://m.abunchtell.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

77 lines
3.2 KiB

  1. import React from 'react';
  2. import PropTypes from 'prop-types';
  3. import NavLink from 'react-router-dom/NavLink';
  4. import { FormattedMessage, injectIntl } from 'react-intl';
  5. import { debounce } from 'lodash';
  6. export const links = [
  7. <NavLink className='tabs-bar__link primary' to='/statuses/new' data-preview-title-id='tabs_bar.compose' data-preview-icon='pencil' ><i className='fa fa-fw fa-pencil' /><FormattedMessage id='tabs_bar.compose' defaultMessage='Compose' /></NavLink>,
  8. <NavLink className='tabs-bar__link primary' to='/timelines/home' data-preview-title-id='column.home' data-preview-icon='home' ><i className='fa fa-fw fa-home' /><FormattedMessage id='tabs_bar.home' defaultMessage='Home' /></NavLink>,
  9. <NavLink className='tabs-bar__link primary' to='/notifications' data-preview-title-id='column.notifications' data-preview-icon='bell' ><i className='fa fa-fw fa-bell' /><FormattedMessage id='tabs_bar.notifications' defaultMessage='Notifications' /></NavLink>,
  10. <NavLink className='tabs-bar__link secondary' to='/timelines/public/local' data-preview-title-id='column.community' data-preview-icon='users' ><i className='fa fa-fw fa-users' /><FormattedMessage id='tabs_bar.local_timeline' defaultMessage='Local' /></NavLink>,
  11. <NavLink className='tabs-bar__link secondary' exact to='/timelines/public' data-preview-title-id='column.public' data-preview-icon='globe' ><i className='fa fa-fw fa-globe' /><FormattedMessage id='tabs_bar.federated_timeline' defaultMessage='Federated' /></NavLink>,
  12. <NavLink className='tabs-bar__link primary' style={{ flexGrow: '0', flexBasis: '30px' }} to='/getting-started' data-preview-title-id='getting_started.heading' data-preview-icon='asterisk' ><i className='fa fa-fw fa-asterisk' /></NavLink>,
  13. ];
  14. export function getIndex (path) {
  15. return links.findIndex(link => link.props.to === path);
  16. }
  17. export function getLink (index) {
  18. return links[index].props.to;
  19. }
  20. @injectIntl
  21. export default class TabsBar extends React.Component {
  22. static contextTypes = {
  23. router: PropTypes.object.isRequired,
  24. }
  25. static propTypes = {
  26. intl: PropTypes.object.isRequired,
  27. }
  28. setRef = ref => {
  29. this.node = ref;
  30. }
  31. handleClick = (e) => {
  32. e.preventDefault();
  33. e.persist();
  34. requestAnimationFrame(() => {
  35. const tabs = Array(...this.node.querySelectorAll('.tabs-bar__link'));
  36. const currentTab = tabs.find(tab => tab.classList.contains('active'));
  37. const nextTab = tabs.find(tab => tab.contains(e.target));
  38. const { props: { to } } = links[Array(...this.node.childNodes).indexOf(nextTab)];
  39. if (currentTab) {
  40. currentTab.classList.remove('active');
  41. }
  42. const listener = debounce(() => {
  43. nextTab.removeEventListener('transitionend', listener);
  44. this.context.router.history.push(to);
  45. }, 50);
  46. nextTab.addEventListener('transitionend', listener);
  47. nextTab.classList.add('active');
  48. });
  49. }
  50. render () {
  51. const { intl: { formatMessage } } = this.props;
  52. return (
  53. <nav className='tabs-bar' ref={this.setRef}>
  54. {links.map(link => React.cloneElement(link, { key: link.props.to, onClick: this.handleClick, 'aria-label': formatMessage({ id: link.props['data-preview-title-id'] }) }))}
  55. </nav>
  56. );
  57. }
  58. }