diff --git a/src/components/languageSwitcher/LanguageSwitcher.js b/src/components/languageSwitcher/LanguageSwitcher.js index 807bc34..ab465d0 100644 --- a/src/components/languageSwitcher/LanguageSwitcher.js +++ b/src/components/languageSwitcher/LanguageSwitcher.js @@ -1,8 +1,9 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; +import { TransitionMotion, spring, presets } from 'react-motion'; +import { FormattedMessage as Message, intlShape } from 'react-intl'; import classNames from 'classnames'; -import { FormattedMessage as Message, intlShape } from 'react-intl'; import { requireLocaleFlag } from 'functions'; import LANGS from 'i18n/index.json'; @@ -14,6 +15,7 @@ import styles from './languageSwitcher.scss'; import messages from './languageSwitcher.intl.json'; const improveTranslationUrl = 'http://ely.by/erickskrauch/posts/174943'; +const itemHeight = 51; class LanguageSwitcher extends Component { static displayName = 'LanguageSwitcher'; @@ -22,6 +24,7 @@ class LanguageSwitcher extends Component { onClose: PropTypes.func, userLang: PropTypes.string, changeLang: PropTypes.func, + langs: PropTypes.objectOf(PropTypes.object).isRequired, }; static contextTypes = { @@ -29,21 +32,18 @@ class LanguageSwitcher extends Component { }; state = { - items: [], filter: '', + filteredLangs: this.props.langs, }; static defaultProps = { - onClose() {} + langs: LANGS, + onClose() {}, }; - componentWillMount() { - this.setState({items: LANGS}); - } - render() { const {userLang, onClose} = this.props; - const {items} = this.state; + const firstLocale = Object.keys(this.state.filteredLangs)[0] || null; return (
@@ -60,26 +60,40 @@ class LanguageSwitcher extends Component {
-
- {Object.keys(items).map((locale) => ( -
  • - {this.renderLanguageItem(locale, items[locale])} -
  • - ))} -
    + + {(items) => ( +
    + {items.map(({key: locale, data: definition, style}) => ( +
  • + {this.renderLanguageItem(locale, definition)} +
  • + ))} +
    + )} +
    @@ -93,7 +107,7 @@ class LanguageSwitcher extends Component { - ) + ), }} />
    @@ -122,7 +136,7 @@ class LanguageSwitcher extends Component { return (
    @@ -149,28 +163,26 @@ class LanguageSwitcher extends Component { setTimeout(this.props.onClose, 300); } - onFilterUpdate() { - return (event) => { - const value = event.target.value.trim().toLowerCase(); - let items = LANGS; - if (value.length !== 0) { - items = Object.keys(items).reduce((prev, next) => { - if (items[next].englishName.toLowerCase().search(value) !== -1 - || items[next].name.toLowerCase().search(value) !== -1 - ) { - prev[next] = items[next]; - } - - return prev; - }, {}); + onFilterUpdate = (event) => { + const filter = event.target.value.trim().toLowerCase(); + const { langs } = this.props; + const result = Object.keys(langs).reduce((previous, key) => { + if (langs[key].englishName.toLowerCase().search(filter) === -1 + && langs[key].name.toLowerCase().search(filter) === -1 + ) { + return previous; } - this.setState({ - items, - filter: value, - }); - }; - } + previous[key] = langs[key]; + + return previous; + }, {}); + + this.setState({ + filter, + filteredLangs: result, + }); + }; onFilterKeyPress() { return (event) => { @@ -178,7 +190,7 @@ class LanguageSwitcher extends Component { return; } - const locales = Object.keys(this.state.items); + const locales = Object.keys(this.props.langs); if (locales.length === 0) { return; } @@ -186,13 +198,53 @@ class LanguageSwitcher extends Component { this.changeLang(locales[0]); }; } + + getItemsWithDefaultStyles = () => Object.keys(this.props.langs).reduce((previous, key) => { + return [ + ...previous, + { + key, + data: this.props.langs[key], + style: { + height: itemHeight, + opacity: 1, + }, + }, + ]; + }, {}); + + getItemsWithStyles = () => Object.keys({...this.state.filteredLangs}).reduce((previous, key) => [ + ...previous, + { + key, + data: this.props.langs[key], + style: { + height: spring(itemHeight, presets.gentle), + opacity: spring(1, presets.gentle), + }, + }, + ], []); + + willEnter() { + return { + height: 0, + opacity: 1, + }; + } + + willLeave() { + return { + height: spring(0), + opacity: spring(0), + }; + } } import { connect } from 'react-redux'; import { changeLang } from 'components/user/actions'; export default connect((state) => ({ - userLang: state.user.lang + userLang: state.user.lang, }), { - changeLang + changeLang, })(LanguageSwitcher); diff --git a/src/components/languageSwitcher/languageSwitcher.scss b/src/components/languageSwitcher/languageSwitcher.scss index 0246940..f28808c 100644 --- a/src/components/languageSwitcher/languageSwitcher.scss +++ b/src/components/languageSwitcher/languageSwitcher.scss @@ -2,6 +2,12 @@ @import '~components/ui/fonts.scss'; @import '~components/ui/popup/popup.scss'; +@mixin hideFooter { + @media (max-height: 455px) { + @content; + } +} + .languageSwitcher { composes: popupWrapper from 'components/ui/popup/popup.scss'; @@ -36,7 +42,8 @@ pointer-events: none; // Иконка чисто декоративная, так что клик должен проходить сквозь неё } -$languageListBorderStyle: 1px solid #eee; +$languageListBorderColor: #eee; +$languageListBorderStyle: 1px solid $languageListBorderColor; .languagesList { flex-grow: 1; @@ -44,28 +51,35 @@ $languageListBorderStyle: 1px solid #eee; border-top: $languageListBorderStyle; border-bottom: $languageListBorderStyle; margin-bottom: 20px; + + @include hideFooter { + & { + margin-bottom: 0; + } + } } .languageItem { - padding: 10px; - border-top: $languageListBorderStyle; font-family: $font-family-title; - transition: .25s; + transition: background-color .25s; cursor: pointer; overflow: hidden; - &:first-child { - border-top: none; - } - &:hover { - background: $whiteButtonLight; + background-color: $whiteButtonLight; } } .languageFlex { + box-sizing: border-box; display: flex; align-items: center; + padding: 10px; + border-top: $languageListBorderStyle; + + .firstLanguageItem & { + border-top: none; + } } .languageIco { @@ -140,7 +154,7 @@ $languageListBorderStyle: 1px solid #eee; display: flex; flex-shrink: 0; - @media screen and (max-height: 455px) { + @include hideFooter { & { display: none; }