Commit 5b5631f2 authored by Eugen Rochko's avatar Eugen Rochko

Add language picker

parent 0dbca54e
...@@ -4,12 +4,12 @@ ...@@ -4,12 +4,12 @@
"private": true, "private": true,
"dependencies": { "dependencies": {
"axios": "^0.16.2", "axios": "^0.16.2",
"classnames": "^2.2.5",
"fuzzysearch": "^1.0.3", "fuzzysearch": "^1.0.3",
"gh-pages": "^0.12.0", "gh-pages": "^0.12.0",
"react": "^15.5.3", "react": "^15.5.3",
"react-custom-scrollbars": "^4.1.2", "react-custom-scrollbars": "^4.1.2",
"react-dom": "^15.5.3", "react-dom": "^15.5.3",
"react-dropdown": "^1.3.0",
"react-intl": "^2.4.0", "react-intl": "^2.4.0",
"react-motion": "^0.4.7", "react-motion": "^0.4.7",
"react-redux": "^5.0.5", "react-redux": "^5.0.5",
......
import React from 'react'; import React, { PureComponent } from 'react';
import Dropdown from 'react-dropdown'; import classNames from 'classnames';
import flagEn from 'twemoji/2/svg/1f1ec-1f1e7.svg'; import flagEn from 'twemoji/2/svg/1f1ec-1f1e7.svg';
import flagJa from 'twemoji/2/svg/1f1ef-1f1f5.svg'; import flagFr from 'twemoji/2/svg/1f1eb-1f1f7.svg';
import flagPl from 'twemoji/2/svg/1f1f5-1f1f1.svg';
import flagEs from 'twemoji/2/svg/1f1ea-1f1f8.svg';
const options = [ const options = [
{ value: 'en', label: <span><img src={flagEn} className='emoji' alt='' /> English</span> }, { value: 'en', label: <span><img src={flagEn} className='emoji' alt='' /> English</span> },
{ value: 'ja', label: <span><img src={flagJa} className='emoji' alt='' /> 日本語</span> } { value: 'fr', label: <span><img src={flagFr} className='emoji' alt='' /> Français</span> },
{ value: 'es', label: <span><img src={flagEs} className='emoji' alt='' /> Español</span> },
{ value: 'pl', label: <span><img src={flagPl} className='emoji' alt='' /> Polszczyzna</span> }
]; ];
const LanguageSelect = ({ value, onChange }) => ( export default class LanguageSelect extends PureComponent {
<Dropdown state = {
options={options} opened: false
value={{ value, label: '文A' }} };
onChange={onChange}
/> renderMenu () {
); const { value } = this.props;
return (
<div className='dropdown__menu'>
{options.map(option => (
<div key={option.value} className={classNames('dropdown__option', { active: option.value === value })} onClick={this.handleOptionClick.bind(this, option.value)}>
{option.label}
</div>
))}
</div>
);
}
handleOptionClick = (value) => {
this.props.onChange(value);
this.setState({ opened: false });
}
handleClick = () => {
this.setState({ opened: !this.state.opened });
}
handleDocumentClick = e => {
if (this.node && !this.node.contains(e.target)) {
this.setState({ opened: false });
}
}
componentDidMount () {
document.addEventListener('click', this.handleDocumentClick, false);
document.addEventListener('touchend', this.handleDocumentClick, false);
}
componentWillUnmount () {
document.removeEventListener('click', this.handleDocumentClick, false);
document.removeEventListener('touchend', this.handleDocumentClick, false);
}
setRef = c => {
this.node = c;
}
render () {
const { opened } = this.state;
export default LanguageSelect; return (
<div className={classNames('dropdown', { active: opened })} ref={this.setRef}>
<div className='dropdown__control' tabIndex='0' role='button' onClick={this.handleClick}>A <i className='dropdown__arrow ion-ios-arrow-down' /></div>
{opened && this.renderMenu()}
</div>
);
}
}
...@@ -7,7 +7,7 @@ const mapStateToProps = state => ({ ...@@ -7,7 +7,7 @@ const mapStateToProps = state => ({
}); });
const mapDispatchToProps = dispatch => ({ const mapDispatchToProps = dispatch => ({
onChange: option => dispatch(changeLocale(option.value)) onChange: value => dispatch(changeLocale(value))
}); });
export default connect(mapStateToProps, mapDispatchToProps)(LanguageSelect); export default connect(mapStateToProps, mapDispatchToProps)(LanguageSelect);
...@@ -2,6 +2,8 @@ import React from 'react'; ...@@ -2,6 +2,8 @@ import React from 'react';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { FormattedMessage } from 'react-intl'; import { FormattedMessage } from 'react-intl';
import LanguageSelectContainer from './LanguageSelectContainer';
import mastodonLogo from './assets/logo_full.svg'; import mastodonLogo from './assets/logo_full.svg';
const Navigation = () => ( const Navigation = () => (
...@@ -19,6 +21,7 @@ const Navigation = () => ( ...@@ -19,6 +21,7 @@ const Navigation = () => (
<li className='optional-link-2'><a href='https://github.com/tootsuite/documentation'><FormattedMessage id='nav.docs' defaultMessage='Documentation' /></a></li> <li className='optional-link-2'><a href='https://github.com/tootsuite/documentation'><FormattedMessage id='nav.docs' defaultMessage='Documentation' /></a></li>
<li><Link to='/sponsors'><FormattedMessage id='nav.sponsors' defaultMessage='Sponsors' /></Link></li> <li><Link to='/sponsors'><FormattedMessage id='nav.sponsors' defaultMessage='Sponsors' /></Link></li>
<li><a href='https://github.com/tootsuite/mastodon'><FormattedMessage id='nav.code' defaultMessage='Source code' /></a></li> <li><a href='https://github.com/tootsuite/mastodon'><FormattedMessage id='nav.code' defaultMessage='Source code' /></a></li>
<li><LanguageSelectContainer /></li>
</ul> </ul>
</div> </div>
); );
......
...@@ -38,7 +38,7 @@ $phi: 1.6180339887498948482; ...@@ -38,7 +38,7 @@ $phi: 1.6180339887498948482;
color: $lighter; color: $lighter;
text-decoration: none; text-decoration: none;
padding: 12px 16px; padding: 12px 14px;
line-height: 32px; line-height: 32px;
transition: color $transition-out; transition: color $transition-out;
font-family: 'Montserrat', sans-serif; font-family: 'Montserrat', sans-serif;
...@@ -304,6 +304,7 @@ $phi: 1.6180339887498948482; ...@@ -304,6 +304,7 @@ $phi: 1.6180339887498948482;
z-index: -1; z-index: -1;
top: -21px; top: -21px;
left: -28px; left: -28px;
pointer-events: none;
} }
&:hover { &:hover {
......
...@@ -3,91 +3,73 @@ ...@@ -3,91 +3,73 @@
$transition-in: 100ms linear; $transition-in: 100ms linear;
$transition-out: 250ms linear; $transition-out: 250ms linear;
.Dropdown-root { .dropdown {
position: relative; position: relative;
.emoji { .emoji {
vertical-align: -0.15em; vertical-align: -0.15em;
margin-right: 0.1em; margin-right: 0.1em;
} }
}
.Dropdown-control { &__control {
position: relative; position: relative;
overflow: hidden; overflow: hidden;
box-sizing: border-box; box-sizing: border-box;
color: $lighter; color: $lighter;
font-family: 'Montserrat', sans-serif; font-family: 'Montserrat', sans-serif;
font-weight: 500; font-weight: 500;
font-size: 14px; font-size: 14px;
cursor: pointer; cursor: pointer;
outline: none; outline: none;
padding: 12px 16px; padding: 12px 16px;
transition: color $transition-out; transition: color $transition-out;
&:hover { &:hover {
color: $lightest; color: $lightest;
transition: color $transition-in; transition: color $transition-in;
}
} }
}
.Dropdown-arrow {
border-color: lighten($darkest, 30%) transparent transparent;
border-style: solid;
border-width: 5px 5px 0;
content: ' ';
display: block;
height: 0;
margin-top: -ceil(2.5);
position: absolute;
right: 0;
top: 24px;
width: 0
}
.is-open { &__menu {
.Dropdown-control { background-color: $lightest;
color: $lightest; box-shadow: 0 1px 3px rgba($black, 0.1);
box-sizing: border-box;
border-radius: 4px;
margin-top: -1px;
max-height: 200px;
width: 140px;
overflow-y: auto;
position: absolute;
top: 100%;
z-index: 1000;
-webkit-overflow-scrolling: touch;
} }
.Dropdown-arrow { &__option {
border-color: $lightest transparent transparent; box-sizing: border-box;
} color: $darkest;
} cursor: pointer;
display: block;
.Dropdown-menu { padding: 4px 16px;
background-color: $lightest; font-family: 'Montserrat', sans-serif;
box-shadow: 0 1px 3px rgba($black, 0.1); font-weight: 500;
box-sizing: border-box; font-size: 14px;
border-radius: 4px; text-align: left;
margin-top: -1px;
max-height: 200px;
width: 140px;
overflow-y: auto;
position: absolute;
top: 100%;
z-index: 1000;
-webkit-overflow-scrolling: touch;
}
.Dropdown-option { &:last-child {
box-sizing: border-box; border-bottom-right-radius: 2px;
color: $darkest; border-bottom-left-radius: 2px;
cursor: pointer; }
display: block;
padding: 4px 16px;
font-family: 'Montserrat', sans-serif;
font-weight: 500;
font-size: 14px;
text-align: left;
&:last-child { &:hover,
border-bottom-right-radius: 2px; &.active {
border-bottom-left-radius: 2px; background-color: $lighter;
}
} }
&:hover, &.active {
&.is-selected { .dropdown__control {
background-color: $lighter; color: $lightest;
}
} }
} }
...@@ -1485,7 +1485,7 @@ clap@^1.0.9: ...@@ -1485,7 +1485,7 @@ clap@^1.0.9:
dependencies: dependencies:
chalk "^1.1.3" chalk "^1.1.3"
classnames@^2.2.3: classnames@^2.2.5:
version "2.2.5" version "2.2.5"
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.5.tgz#fb3801d453467649ef3603c7d61a02bd129bde6d" resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.5.tgz#fb3801d453467649ef3603c7d61a02bd129bde6d"
...@@ -4997,12 +4997,6 @@ react-dom@^15.3.0, react-dom@^15.5.3: ...@@ -4997,12 +4997,6 @@ react-dom@^15.3.0, react-dom@^15.5.3:
object-assign "^4.1.0" object-assign "^4.1.0"
prop-types "~15.5.0" prop-types "~15.5.0"
react-dropdown@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/react-dropdown/-/react-dropdown-1.3.0.tgz#11cfce8e2e936b1a8ba2d4a700b1fe19f64c4792"
dependencies:
classnames "^2.2.3"
react-intl-translations-manager@^5.0.0: react-intl-translations-manager@^5.0.0:
version "5.0.0" version "5.0.0"
resolved "https://registry.yarnpkg.com/react-intl-translations-manager/-/react-intl-translations-manager-5.0.0.tgz#3c78d3e3e44c5804d7a15c60e89c3aefd9d06615" resolved "https://registry.yarnpkg.com/react-intl-translations-manager/-/react-intl-translations-manager-5.0.0.tgz#3c78d3e3e44c5804d7a15c60e89c3aefd9d06615"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment