Light/dark theme toggle in top navbar
This commit is contained in:
parent
06c4f88802
commit
697291e6f5
3 changed files with 35 additions and 13 deletions
|
@ -79,8 +79,6 @@ const languages = {
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
heading: { id: 'column.preferences', defaultMessage: 'Preferences' },
|
heading: { id: 'column.preferences', defaultMessage: 'Preferences' },
|
||||||
themeLight: { id: 'preferences.options.theme_light', defaultMessage: 'Light' },
|
|
||||||
themeDark: { id: 'preferences.options.theme_dark', defaultMessage: 'Dark' },
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = state => ({
|
||||||
|
@ -114,15 +112,6 @@ class Preferences extends ImmutablePureComponent {
|
||||||
return (
|
return (
|
||||||
<Column icon='cog' heading={intl.formatMessage(messages.heading)} backBtnSlim>
|
<Column icon='cog' heading={intl.formatMessage(messages.heading)} backBtnSlim>
|
||||||
<SimpleForm>
|
<SimpleForm>
|
||||||
<FieldsGroup>
|
|
||||||
<SelectDropdown
|
|
||||||
label={<FormattedMessage id='preferences.fields.theme_label' defaultMessage='Theme' />}
|
|
||||||
items={{ light: intl.formatMessage(messages.themeLight), dark: intl.formatMessage(messages.themeDark) }}
|
|
||||||
defaultValue={settings.get('themeMode')}
|
|
||||||
onChange={this.onSelectChange(['themeMode'])}
|
|
||||||
/>
|
|
||||||
</FieldsGroup>
|
|
||||||
|
|
||||||
<FieldsGroup>
|
<FieldsGroup>
|
||||||
<SelectDropdown
|
<SelectDropdown
|
||||||
label={<FormattedMessage id='preferences.fields.language_label' defaultMessage='Language' />}
|
label={<FormattedMessage id='preferences.fields.language_label' defaultMessage='Language' />}
|
||||||
|
|
|
@ -13,9 +13,12 @@ import ActionBar from 'soapbox/features/compose/components/action_bar';
|
||||||
import { openModal } from '../../../actions/modal';
|
import { openModal } from '../../../actions/modal';
|
||||||
import { openSidebar } from '../../../actions/sidebar';
|
import { openSidebar } from '../../../actions/sidebar';
|
||||||
import Icon from '../../../components/icon';
|
import Icon from '../../../components/icon';
|
||||||
|
import { changeSetting } from 'soapbox/actions/settings';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
post: { id: 'tabs_bar.post', defaultMessage: 'Post' },
|
post: { id: 'tabs_bar.post', defaultMessage: 'Post' },
|
||||||
|
switchToLight: { id: 'tabs_bar.theme_toggle_light', defaultMessage: 'Switch to light theme' },
|
||||||
|
switchToDark: { id: 'tabs_bar.theme_toggle_dark', defaultMessage: 'Switch to dark theme' },
|
||||||
});
|
});
|
||||||
|
|
||||||
@withRouter
|
@withRouter
|
||||||
|
@ -26,12 +29,15 @@ class TabsBar extends React.PureComponent {
|
||||||
history: PropTypes.object.isRequired,
|
history: PropTypes.object.isRequired,
|
||||||
onOpenCompose: PropTypes.func,
|
onOpenCompose: PropTypes.func,
|
||||||
onOpenSidebar: PropTypes.func.isRequired,
|
onOpenSidebar: PropTypes.func.isRequired,
|
||||||
|
toggleTheme: PropTypes.func,
|
||||||
logo: PropTypes.string,
|
logo: PropTypes.string,
|
||||||
account: ImmutablePropTypes.map,
|
account: ImmutablePropTypes.map,
|
||||||
|
settings: ImmutablePropTypes.map,
|
||||||
}
|
}
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
collapsed: false,
|
collapsed: false,
|
||||||
|
isLight: this.props.settings.get('themeMode') === 'light' ? true : false,
|
||||||
}
|
}
|
||||||
|
|
||||||
static contextTypes = {
|
static contextTypes = {
|
||||||
|
@ -102,6 +108,18 @@ class TabsBar extends React.PureComponent {
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getNewThemeValue() {
|
||||||
|
if (this.props.settings.get('themeMode') === 'light') return 'dark';
|
||||||
|
|
||||||
|
return 'light';
|
||||||
|
}
|
||||||
|
|
||||||
|
handleToggleTheme = () => {
|
||||||
|
this.props.toggleTheme(this.getNewThemeValue());
|
||||||
|
|
||||||
|
this.setState({ isLight: !this.state.isLight });
|
||||||
|
}
|
||||||
|
|
||||||
handleScroll = throttle(() => {
|
handleScroll = throttle(() => {
|
||||||
if (this.window) {
|
if (this.window) {
|
||||||
const { pageYOffset, innerWidth } = this.window;
|
const { pageYOffset, innerWidth } = this.window;
|
||||||
|
@ -125,7 +143,7 @@ class TabsBar extends React.PureComponent {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { account, onOpenCompose, onOpenSidebar, intl } = this.props;
|
const { account, onOpenCompose, onOpenSidebar, intl } = this.props;
|
||||||
const { collapsed } = this.state;
|
const { collapsed, isLight } = this.state;
|
||||||
|
|
||||||
const classes = classNames('tabs-bar', {
|
const classes = classNames('tabs-bar', {
|
||||||
'tabs-bar--collapsed': collapsed,
|
'tabs-bar--collapsed': collapsed,
|
||||||
|
@ -143,6 +161,9 @@ class TabsBar extends React.PureComponent {
|
||||||
</div>
|
</div>
|
||||||
{ account &&
|
{ account &&
|
||||||
<div className='flex'>
|
<div className='flex'>
|
||||||
|
<button className='tabs-bar__button-theme-toggle button' onClick={this.handleToggleTheme} aria-label={isLight ? intl.formatMessage(messages.switchToDark) : intl.formatMessage(messages.switchToLight)}>
|
||||||
|
<Icon id={isLight ? 'moon' : 'sun'} />
|
||||||
|
</button>
|
||||||
<div className='tabs-bar__profile'>
|
<div className='tabs-bar__profile'>
|
||||||
<Avatar account={account} />
|
<Avatar account={account} />
|
||||||
<button className='tabs-bar__sidebar-btn' onClick={onOpenSidebar} />
|
<button className='tabs-bar__sidebar-btn' onClick={onOpenSidebar} />
|
||||||
|
@ -177,6 +198,7 @@ const mapStateToProps = state => {
|
||||||
return {
|
return {
|
||||||
account: state.getIn(['accounts', me]),
|
account: state.getIn(['accounts', me]),
|
||||||
logo: state.getIn(['soapbox', 'logo']),
|
logo: state.getIn(['soapbox', 'logo']),
|
||||||
|
settings: state.get('settings'),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -187,6 +209,9 @@ const mapDispatchToProps = (dispatch) => ({
|
||||||
onOpenSidebar() {
|
onOpenSidebar() {
|
||||||
dispatch(openSidebar());
|
dispatch(openSidebar());
|
||||||
},
|
},
|
||||||
|
toggleTheme(setting) {
|
||||||
|
dispatch(changeSetting(['themeMode'], setting));
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export default injectIntl(
|
export default injectIntl(
|
||||||
|
|
|
@ -55,7 +55,7 @@
|
||||||
&__profile {
|
&__profile {
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
margin: 0 0 0 20px;
|
margin: 0 0 0 10px;
|
||||||
height: 34px;
|
height: 34px;
|
||||||
width: 34px;
|
width: 34px;
|
||||||
|
|
||||||
|
@ -111,6 +111,14 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__button-theme-toggle {
|
||||||
|
margin-left: 10px;
|
||||||
|
padding: 0 10px;
|
||||||
|
font-size: 20px;
|
||||||
|
|
||||||
|
.fa { margin-right: 0; }
|
||||||
|
}
|
||||||
|
|
||||||
&__button-compose {
|
&__button-compose {
|
||||||
display: block;
|
display: block;
|
||||||
@media screen and (max-width: $nav-breakpoint-3) {display: none;}
|
@media screen and (max-width: $nav-breakpoint-3) {display: none;}
|
||||||
|
|
Loading…
Reference in a new issue