Light/dark theme toggle in top navbar

This commit is contained in:
Sean King 2020-07-10 22:35:02 -06:00
parent 06c4f88802
commit 697291e6f5
3 changed files with 35 additions and 13 deletions

View file

@ -79,8 +79,6 @@ const languages = {
const messages = defineMessages({
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 => ({
@ -114,15 +112,6 @@ class Preferences extends ImmutablePureComponent {
return (
<Column icon='cog' heading={intl.formatMessage(messages.heading)} backBtnSlim>
<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>
<SelectDropdown
label={<FormattedMessage id='preferences.fields.language_label' defaultMessage='Language' />}

View file

@ -13,9 +13,12 @@ import ActionBar from 'soapbox/features/compose/components/action_bar';
import { openModal } from '../../../actions/modal';
import { openSidebar } from '../../../actions/sidebar';
import Icon from '../../../components/icon';
import { changeSetting } from 'soapbox/actions/settings';
const messages = defineMessages({
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
@ -26,12 +29,15 @@ class TabsBar extends React.PureComponent {
history: PropTypes.object.isRequired,
onOpenCompose: PropTypes.func,
onOpenSidebar: PropTypes.func.isRequired,
toggleTheme: PropTypes.func,
logo: PropTypes.string,
account: ImmutablePropTypes.map,
settings: ImmutablePropTypes.map,
}
state = {
collapsed: false,
isLight: this.props.settings.get('themeMode') === 'light' ? true : false,
}
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(() => {
if (this.window) {
const { pageYOffset, innerWidth } = this.window;
@ -125,7 +143,7 @@ class TabsBar extends React.PureComponent {
render() {
const { account, onOpenCompose, onOpenSidebar, intl } = this.props;
const { collapsed } = this.state;
const { collapsed, isLight } = this.state;
const classes = classNames('tabs-bar', {
'tabs-bar--collapsed': collapsed,
@ -143,6 +161,9 @@ class TabsBar extends React.PureComponent {
</div>
{ account &&
<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'>
<Avatar account={account} />
<button className='tabs-bar__sidebar-btn' onClick={onOpenSidebar} />
@ -177,6 +198,7 @@ const mapStateToProps = state => {
return {
account: state.getIn(['accounts', me]),
logo: state.getIn(['soapbox', 'logo']),
settings: state.get('settings'),
};
};
@ -187,6 +209,9 @@ const mapDispatchToProps = (dispatch) => ({
onOpenSidebar() {
dispatch(openSidebar());
},
toggleTheme(setting) {
dispatch(changeSetting(['themeMode'], setting));
},
});
export default injectIntl(

View file

@ -55,7 +55,7 @@
&__profile {
position: relative;
overflow: hidden;
margin: 0 0 0 20px;
margin: 0 0 0 10px;
height: 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 {
display: block;
@media screen and (max-width: $nav-breakpoint-3) {display: none;}