about summary refs log tree commit diff
path: root/app/javascript/glitch
diff options
context:
space:
mode:
Diffstat (limited to 'app/javascript/glitch')
-rw-r--r--app/javascript/glitch/components/local_settings/container.js (renamed from app/javascript/glitch/components/settings/container.js)11
-rw-r--r--app/javascript/glitch/components/local_settings/index.js50
-rw-r--r--app/javascript/glitch/components/local_settings/navigation/index.js74
-rw-r--r--app/javascript/glitch/components/local_settings/navigation/item/index.js69
-rw-r--r--app/javascript/glitch/components/local_settings/navigation/item/style.scss27
-rw-r--r--app/javascript/glitch/components/local_settings/navigation/style.scss10
-rw-r--r--app/javascript/glitch/components/local_settings/page/index.js (renamed from app/javascript/glitch/components/settings/index.js)193
-rw-r--r--app/javascript/glitch/components/local_settings/page/item/index.js (renamed from app/javascript/glitch/components/settings/item.js)69
-rw-r--r--app/javascript/glitch/components/local_settings/page/item/style.scss7
-rw-r--r--app/javascript/glitch/components/local_settings/page/style.scss9
-rw-r--r--app/javascript/glitch/components/local_settings/style.scss34
-rw-r--r--app/javascript/glitch/components/settings/style.scss84
12 files changed, 396 insertions, 241 deletions
diff --git a/app/javascript/glitch/components/settings/container.js b/app/javascript/glitch/components/local_settings/container.js
index 5dfe228c0..6c202a4e7 100644
--- a/app/javascript/glitch/components/settings/container.js
+++ b/app/javascript/glitch/components/local_settings/container.js
@@ -6,22 +6,19 @@ import { closeModal } from 'mastodon/actions/modal';
 
 //  Our imports  //
 import { changeLocalSetting } from 'glitch/actions/local_settings';
-import Settings from 'glitch/components/settings';
+import LocalSettings from '.';
 
 const mapStateToProps = state => ({
   settings: state.get('local_settings'),
 });
 
 const mapDispatchToProps = dispatch => ({
-  toggleSetting (setting, e) {
-    dispatch(changeLocalSetting(setting, e.target.checked));
-  },
-  changeSetting (setting, e) {
-    dispatch(changeLocalSetting(setting, e.target.value));
+  onChange (setting, value) {
+    dispatch(changeLocalSetting(setting, value));
   },
   onClose () {
     dispatch(closeModal());
   },
 });
 
-export default connect(mapStateToProps, mapDispatchToProps)(Settings);
+export default connect(mapStateToProps, mapDispatchToProps)(LocalSettings);
diff --git a/app/javascript/glitch/components/local_settings/index.js b/app/javascript/glitch/components/local_settings/index.js
new file mode 100644
index 000000000..7f7b93de4
--- /dev/null
+++ b/app/javascript/glitch/components/local_settings/index.js
@@ -0,0 +1,50 @@
+//  Package imports
+import React from 'react';
+import PropTypes from 'prop-types';
+import ImmutablePropTypes from 'react-immutable-proptypes';
+
+//  Our imports
+import LocalSettingsPage from './page';
+import LocalSettingsNavigation from './navigation';
+
+//  Stylesheet imports
+import './style';
+
+export default class LocalSettings extends React.PureComponent {
+
+  static propTypes = {
+    onChange: PropTypes.func.isRequired,
+    onClose: PropTypes.func.isRequired,
+    settings: ImmutablePropTypes.map.isRequired,
+  };
+
+  state = {
+    currentIndex: 0,
+  };
+
+  navigateTo = (index) =>
+    this.setState({ currentIndex: +index });
+
+  render () {
+
+    const { navigateTo } = this;
+    const { onChange, onClose, settings } = this.props;
+    const { currentIndex } = this.state;
+
+    return (
+      <div className='glitch modal-root__modal local-settings'>
+        <LocalSettingsNavigation
+          index={currentIndex}
+          onClose={onClose}
+          onNavigate={navigateTo}
+        />
+        <LocalSettingsPage
+          index={currentIndex}
+          onChange={onChange}
+          settings={settings}
+        />
+      </div>
+    );
+  }
+
+}
diff --git a/app/javascript/glitch/components/local_settings/navigation/index.js b/app/javascript/glitch/components/local_settings/navigation/index.js
new file mode 100644
index 000000000..1f72cc824
--- /dev/null
+++ b/app/javascript/glitch/components/local_settings/navigation/index.js
@@ -0,0 +1,74 @@
+//  Package imports
+import React from 'react';
+import PropTypes from 'prop-types';
+import { injectIntl, defineMessages } from 'react-intl';
+
+//  Our imports
+import LocalSettingsNavigationItem from './item';
+
+//  Stylesheet imports
+import './style';
+
+//  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+const messages = defineMessages({
+  general: {  id: 'settings.general', defaultMessage: 'General' },
+  collapsed: { id: 'settings.collapsed_statuses', defaultMessage: 'Collapsed toots' },
+  media: { id: 'settings.media', defaultMessage: 'Media' },
+  preferences: { id: 'settings.preferences', defaultMessage: 'Preferences' },
+  close: { id: 'settings.close', defaultMessage: 'Close' },
+});
+
+@injectIntl
+export default class LocalSettingsNavigation extends React.PureComponent {
+
+  static propTypes = {
+    index      : PropTypes.number,
+    intl       : PropTypes.object.isRequired,
+    onClose    : PropTypes.func.isRequired,
+    onNavigate : PropTypes.func.isRequired,
+  };
+
+  render () {
+
+    const { index, intl, onClose, onNavigate } = this.props;
+
+    return (
+      <nav className='glitch local-settings__navigation'>
+        <LocalSettingsNavigationItem
+          active={index === 0}
+          index={0}
+          onNavigate={onNavigate}
+          title={intl.formatMessage(messages.general)}
+        />
+        <LocalSettingsNavigationItem
+          active={index === 1}
+          index={1}
+          onNavigate={onNavigate}
+          title={intl.formatMessage(messages.collapsed)}
+        />
+        <LocalSettingsNavigationItem
+          active={index === 2}
+          index={2}
+          onNavigate={onNavigate}
+          title={intl.formatMessage(messages.media)}
+        />
+        <LocalSettingsNavigationItem
+          active={index === 3}
+          href='/settings/preferences'
+          index={3}
+          icon='cog'
+          title={intl.formatMessage(messages.preferences)}
+        />
+        <LocalSettingsNavigationItem
+          active={index === 4}
+          className='close'
+          index={4}
+          onNavigate={onClose}
+          title={intl.formatMessage(messages.close)}
+        />
+      </nav>
+    );
+  }
+
+}
diff --git a/app/javascript/glitch/components/local_settings/navigation/item/index.js b/app/javascript/glitch/components/local_settings/navigation/item/index.js
new file mode 100644
index 000000000..1676aa404
--- /dev/null
+++ b/app/javascript/glitch/components/local_settings/navigation/item/index.js
@@ -0,0 +1,69 @@
+//  Package imports
+import React from 'react';
+import PropTypes from 'prop-types';
+import classNames from 'classnames';
+
+//  Stylesheet imports
+import './style';
+
+//  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+export default class LocalSettingsPage extends React.PureComponent {
+
+  static propTypes = {
+    active: PropTypes.bool,
+    className: PropTypes.string,
+    href: PropTypes.string,
+    icon: PropTypes.string,
+    index: PropTypes.number.isRequired,
+    onNavigate: PropTypes.func,
+    title: PropTypes.string,
+  };
+
+  handleClick = (e) => {
+    const { index, onNavigate } = this.props;
+    if (onNavigate) {
+      onNavigate(index);
+      e.preventDefault();
+    }
+  }
+
+  render () {
+    const { handleClick } = this;
+    const {
+      active,
+      className,
+      href,
+      icon,
+      onNavigate,
+      title,
+    } = this.props;
+
+    const finalClassName = classNames('glitch', 'local-settings__navigation__item', {
+      active,
+    }, className);
+
+    const iconElem = icon ? <i className={`fa fa-fw fa-${icon}`} /> : null;
+
+    if (href) return (
+      <a
+        href={href}
+        className={finalClassName}
+      >
+        {iconElem} {title}
+      </a>
+    );
+    else if (onNavigate) return (
+      <a
+        onClick={handleClick}
+        role='button'
+        tabIndex='0'
+        className={finalClassName}
+      >
+        {iconElem} {title}
+      </a>
+    );
+    else return null;
+  }
+
+}
diff --git a/app/javascript/glitch/components/local_settings/navigation/item/style.scss b/app/javascript/glitch/components/local_settings/navigation/item/style.scss
new file mode 100644
index 000000000..505c86912
--- /dev/null
+++ b/app/javascript/glitch/components/local_settings/navigation/item/style.scss
@@ -0,0 +1,27 @@
+@import 'variables';
+
+.glitch.local-settings__navigation__item {
+  display: block;
+  padding: 15px 20px;
+  color: inherit;
+  background: $primary-text-color;
+  border-bottom: 1px $ui-primary-color solid;
+  cursor: pointer;
+  text-decoration: none;
+  outline: none;
+  transition: background .3s;
+
+  &:hover {
+    background: $ui-secondary-color;
+  }
+
+  &.active {
+    background: $ui-highlight-color;
+    color: $primary-text-color;
+  }
+
+  &.close, &.close:hover {
+    background: $error-value-color;
+    color: $primary-text-color;
+  }
+}
diff --git a/app/javascript/glitch/components/local_settings/navigation/style.scss b/app/javascript/glitch/components/local_settings/navigation/style.scss
new file mode 100644
index 000000000..1cc39e3e9
--- /dev/null
+++ b/app/javascript/glitch/components/local_settings/navigation/style.scss
@@ -0,0 +1,10 @@
+@import 'variables';
+
+.glitch.local-settings__navigation {
+  background: $primary-text-color;
+  color: $ui-base-color;
+  width: 200px;
+  font-size: 15px;
+  line-height: 20px;
+  overflow-y: auto;
+}
diff --git a/app/javascript/glitch/components/settings/index.js b/app/javascript/glitch/components/local_settings/page/index.js
index ab2e0fb87..8635b604f 100644
--- a/app/javascript/glitch/components/settings/index.js
+++ b/app/javascript/glitch/components/local_settings/page/index.js
@@ -2,14 +2,16 @@
 import React from 'react';
 import PropTypes from 'prop-types';
 import ImmutablePropTypes from 'react-immutable-proptypes';
-import { injectIntl, defineMessages, FormattedMessage } from 'react-intl';
+import { defineMessages, FormattedMessage, injectIntl } from 'react-intl';
 
 //  Our imports
-import SettingsItem from './item';
+import LocalSettingsPageItem from './item';
 
 //  Stylesheet imports
 import './style';
 
+//  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
 const messages = defineMessages({
   layout_auto: {  id: 'layout.auto', defaultMessage: 'Auto' },
   layout_desktop: { id: 'layout.desktop', defaultMessage: 'Desktop' },
@@ -17,27 +19,21 @@ const messages = defineMessages({
 });
 
 @injectIntl
-export default class Settings extends React.PureComponent {
+export default class LocalSettingsPage extends React.PureComponent {
 
   static propTypes = {
-    settings: ImmutablePropTypes.map.isRequired,
-    toggleSetting: PropTypes.func.isRequired,
-    changeSetting: PropTypes.func.isRequired,
-    onClose: PropTypes.func.isRequired,
-    intl: PropTypes.object.isRequired,
-  };
-
-  state = {
-    currentIndex: 0,
+    index    : PropTypes.number,
+    intl     : PropTypes.object.isRequired,
+    onChange : PropTypes.func.isRequired,
+    settings : ImmutablePropTypes.map.isRequired,
   };
 
-  General = () => {
-    const { intl } = this.props;
-    return (
-      <div>
+  pages = [
+    ({ intl, onChange, settings }) => (
+      <div className='glitch local-settings__page general'>
         <h1><FormattedMessage id='settings.general' defaultMessage='General' /></h1>
-        <SettingsItem
-          settings={this.props.settings}
+        <LocalSettingsPageItem
+          settings={settings}
           item={['layout']}
           id='mastodon-settings--layout'
           options={[
@@ -45,180 +41,135 @@ export default class Settings extends React.PureComponent {
             { value: 'multiple', message: intl.formatMessage(messages.layout_desktop) },
             { value: 'single', message: intl.formatMessage(messages.layout_mobile) },
           ]}
-          onChange={this.props.changeSetting}
+          onChange={onChange}
         >
           <FormattedMessage id='settings.layout' defaultMessage='Layout:' />
-        </SettingsItem>
-
-        <SettingsItem
-          settings={this.props.settings}
+        </LocalSettingsPageItem>
+        <LocalSettingsPageItem
+          settings={settings}
           item={['stretch']}
           id='mastodon-settings--stretch'
-          onChange={this.props.toggleSetting}
+          onChange={onChange}
         >
           <FormattedMessage id='settings.wide_view' defaultMessage='Wide view (Desktop mode only)' />
-        </SettingsItem>
-
+        </LocalSettingsPageItem>
       </div>
-    );
-  }
-
-  CollapsedStatuses = () => {
-    return (
-      <div>
+    ),
+    ({ onChange, settings }) => (
+      <div className='glitch local-settings__page collapsed'>
         <h1><FormattedMessage id='settings.collapsed_statuses' defaultMessage='Collapsed toots' /></h1>
-        <SettingsItem
-          settings={this.props.settings}
+        <LocalSettingsPageItem
+          settings={settings}
           item={['collapsed', 'enabled']}
           id='mastodon-settings--collapsed-enabled'
-          onChange={this.props.toggleSetting}
+          onChange={onChange}
         >
           <FormattedMessage id='settings.enable_collapsed' defaultMessage='Enable collapsed toots' />
-        </SettingsItem>
+        </LocalSettingsPageItem>
         <section>
           <h2><FormattedMessage id='settings.auto_collapse' defaultMessage='Automatic collapsing' /></h2>
-          <SettingsItem
-            settings={this.props.settings}
+          <LocalSettingsPageItem
+            settings={settings}
             item={['collapsed', 'auto', 'all']}
             id='mastodon-settings--collapsed-auto-all'
-            onChange={this.props.toggleSetting}
+            onChange={onChange}
             dependsOn={[['collapsed', 'enabled']]}
           >
             <FormattedMessage id='settings.auto_collapse_all' defaultMessage='Everything' />
-          </SettingsItem>
-          <SettingsItem
-            settings={this.props.settings}
+          </LocalSettingsPageItem>
+          <LocalSettingsPageItem
+            settings={settings}
             item={['collapsed', 'auto', 'notifications']}
             id='mastodon-settings--collapsed-auto-notifications'
-            onChange={this.props.toggleSetting}
+            onChange={onChange}
             dependsOn={[['collapsed', 'enabled']]}
             dependsOnNot={[['collapsed', 'auto', 'all']]}
           >
             <FormattedMessage id='settings.auto_collapse_notifications' defaultMessage='Notifications' />
-          </SettingsItem>
-          <SettingsItem
-            settings={this.props.settings}
+          </LocalSettingsPageItem>
+          <LocalSettingsPageItem
+            settings={settings}
             item={['collapsed', 'auto', 'lengthy']}
             id='mastodon-settings--collapsed-auto-lengthy'
-            onChange={this.props.toggleSetting}
+            onChange={onChange}
             dependsOn={[['collapsed', 'enabled']]}
             dependsOnNot={[['collapsed', 'auto', 'all']]}
           >
             <FormattedMessage id='settings.auto_collapse_lengthy' defaultMessage='Lengthy toots' />
-          </SettingsItem>
-          <SettingsItem
-            settings={this.props.settings}
+          </LocalSettingsPageItem>
+          <LocalSettingsPageItem
+            settings={settings}
             item={['collapsed', 'auto', 'replies']}
             id='mastodon-settings--collapsed-auto-replies'
-            onChange={this.props.toggleSetting}
+            onChange={onChange}
             dependsOn={[['collapsed', 'enabled']]}
             dependsOnNot={[['collapsed', 'auto', 'all']]}
           >
             <FormattedMessage id='settings.auto_collapse_replies' defaultMessage='Replies' />
-          </SettingsItem>
-          <SettingsItem
-            settings={this.props.settings}
+          </LocalSettingsPageItem>
+          <LocalSettingsPageItem
+            settings={settings}
             item={['collapsed', 'auto', 'media']}
             id='mastodon-settings--collapsed-auto-media'
-            onChange={this.props.toggleSetting}
+            onChange={onChange}
             dependsOn={[['collapsed', 'enabled']]}
             dependsOnNot={[['collapsed', 'auto', 'all']]}
           >
             <FormattedMessage id='settings.auto_collapse_media' defaultMessage='Toots with media' />
-          </SettingsItem>
+          </LocalSettingsPageItem>
         </section>
         <section>
           <h2><FormattedMessage id='settings.image_backgrounds' defaultMessage='Image backgrounds' /></h2>
-          <SettingsItem
-            settings={this.props.settings}
+          <LocalSettingsPageItem
+            settings={settings}
             item={['collapsed', 'backgrounds', 'user_backgrounds']}
             id='mastodon-settings--collapsed-user-backgrouns'
-            onChange={this.props.toggleSetting}
+            onChange={onChange}
             dependsOn={[['collapsed', 'enabled']]}
           >
             <FormattedMessage id='settings.image_backgrounds_users' defaultMessage='Give collapsed toots an image background' />
-          </SettingsItem>
-          <SettingsItem
-            settings={this.props.settings}
+          </LocalSettingsPageItem>
+          <LocalSettingsPageItem
+            settings={settings}
             item={['collapsed', 'backgrounds', 'preview_images']}
             id='mastodon-settings--collapsed-preview-images'
-            onChange={this.props.toggleSetting}
+            onChange={onChange}
             dependsOn={[['collapsed', 'enabled']]}
           >
             <FormattedMessage id='settings.image_backgrounds_media' defaultMessage='Preview collapsed toot media' />
-          </SettingsItem>
+          </LocalSettingsPageItem>
         </section>
       </div>
-    );
-  }
-
-  Media = () => {
-    return (
-      <div>
+    ),
+    ({ onChange, settings }) => (
+      <div className='glitch local-settings__page media'>
         <h1><FormattedMessage id='settings.media' defaultMessage='Media' /></h1>
-        <SettingsItem
-          settings={this.props.settings}
+        <LocalSettingsPageItem
+          settings={settings}
           item={['media', 'letterbox']}
           id='mastodon-settings--media-letterbox'
-          onChange={this.props.toggleSetting}
+          onChange={onChange}
         >
           <FormattedMessage id='settings.media_letterbox' defaultMessage='Letterbox media' />
-        </SettingsItem>
-        <SettingsItem
-          settings={this.props.settings}
+        </LocalSettingsPageItem>
+        <LocalSettingsPageItem
+          settings={settings}
           item={['media', 'fullwidth']}
           id='mastodon-settings--media-fullwidth'
-          onChange={this.props.toggleSetting}
+          onChange={onChange}
         >
           <FormattedMessage id='settings.media_fullwidth' defaultMessage='Full-width media previews' />
-        </SettingsItem>
+        </LocalSettingsPageItem>
       </div>
-    );
-  }
-
-  navigateTo = (e) =>
-    this.setState({ currentIndex: +e.currentTarget.getAttribute('data-mastodon-navigation_index') });
+    ),
+  ];
 
   render () {
+    const { pages } = this;
+    const { index, intl, onChange, settings } = this.props;
+    const CurrentPage = pages[index] || pages[0];
 
-    const { General, CollapsedStatuses, Media, navigateTo } = this;
-    const { onClose } = this.props;
-    const { currentIndex } = this.state;
-
-    return (
-      <div className='modal-root__modal settings-modal'>
-
-        <nav className='settings-modal__navigation'>
-          <a onClick={navigateTo} role='button' data-mastodon-navigation_index='0' tabIndex='0' className={`settings-modal__navigation-item${currentIndex === 0 ? ' active' : ''}`}>
-            <FormattedMessage id='settings.general' defaultMessage='General' />
-          </a>
-          <a onClick={navigateTo} role='button' data-mastodon-navigation_index='1' tabIndex='0' className={`settings-modal__navigation-item${currentIndex === 1 ? ' active' : ''}`}>
-            <FormattedMessage id='settings.collapsed_statuses' defaultMessage='Collapsed toots' />
-          </a>
-          <a onClick={navigateTo} role='button' data-mastodon-navigation_index='2' tabIndex='0' className={`settings-modal__navigation-item${currentIndex === 2 ? ' active' : ''}`}>
-            <FormattedMessage id='settings.media' defaultMessage='Media' />
-          </a>
-          <a href='/settings/preferences' className='settings-modal__navigation-item'>
-            <i className='fa fa-fw fa-cog' /> <FormattedMessage id='settings.preferences' defaultMessage='User preferences' />
-          </a>
-          <a onClick={onClose} role='button' tabIndex='0' className='settings-modal__navigation-close'>
-            <FormattedMessage id='settings.close' defaultMessage='Close' />
-          </a>
-
-        </nav>
-
-        <div className='settings-modal__content'>
-          {
-            [
-              <General />,
-              <CollapsedStatuses />,
-              <Media />,
-            ][currentIndex] || <General />
-          }
-        </div>
-
-      </div>
-    );
+    return <CurrentPage intl={intl} onChange={onChange} settings={settings} />;
   }
 
 }
diff --git a/app/javascript/glitch/components/settings/item.js b/app/javascript/glitch/components/local_settings/page/item/index.js
index 4c67cc2ac..326c7eeb0 100644
--- a/app/javascript/glitch/components/settings/item.js
+++ b/app/javascript/glitch/components/local_settings/page/item/index.js
@@ -1,30 +1,38 @@
-//  Package imports  //
+//  Package imports
 import React from 'react';
 import PropTypes from 'prop-types';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 
-export default class SettingsItem extends React.PureComponent {
+//  Stylesheet imports
+import './style';
+
+//  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+export default class LocalSettingsPageItem extends React.PureComponent {
 
   static propTypes = {
-    settings: ImmutablePropTypes.map.isRequired,
-    item: PropTypes.array.isRequired,
+    children: PropTypes.element.isRequired,
+    dependsOn: PropTypes.array,
+    dependsOnNot: PropTypes.array,
     id: PropTypes.string.isRequired,
+    item: PropTypes.array.isRequired,
+    onChange: PropTypes.func.isRequired,
     options: PropTypes.arrayOf(PropTypes.shape({
       value: PropTypes.string.isRequired,
-      message: PropTypes.object.isRequired,
+      message: PropTypes.string.isRequired,
     })),
-    dependsOn: PropTypes.array,
-    dependsOnNot: PropTypes.array,
-    children: PropTypes.element.isRequired,
-    onChange: PropTypes.func.isRequired,
+    settings: ImmutablePropTypes.map.isRequired,
   };
 
-  handleChange = (e) => {
-    const { item, onChange } = this.props;
-    onChange(item, e);
+  handleChange = e => {
+    const { target } = e;
+    const { item, onChange, options } = this.props;
+    if (options && options.length > 0) onChange(item, target.value);
+    else onChange(item, target.checked);
   }
 
   render () {
+    const { handleChange } = this;
     const { settings, item, id, options, children, dependsOn, dependsOnNot } = this.props;
     let enabled = true;
 
@@ -42,38 +50,41 @@ export default class SettingsItem extends React.PureComponent {
     if (options && options.length > 0) {
       const currentValue = settings.getIn(item);
       const optionElems = options && options.length > 0 && options.map((opt) => (
-        <option key={opt.value} selected={currentValue === opt.value} value={opt.value} >
+        <option
+          key={opt.value}
+          value={opt.value}
+        >
           {opt.message}
         </option>
       ));
       return (
-        <label htmlFor={id}>
+        <label className='glitch local-settings__page__item' htmlFor={id}>
           <p>{children}</p>
           <p>
             <select
               id={id}
               disabled={!enabled}
-              onBlur={this.handleChange}
+              onBlur={handleChange}
+              onChange={handleChange}
+              value={currentValue}
             >
               {optionElems}
             </select>
           </p>
         </label>
       );
-    } else {
-      return (
-        <label htmlFor={id}>
-          <input
-            id={id}
-            type='checkbox'
-            checked={settings.getIn(item)}
-            onChange={this.handleChange}
-            disabled={!enabled}
-          />
-          {children}
-        </label>
-      );
-    }
+    } else return (
+      <label className='glitch local-settings__page__item' htmlFor={id}>
+        <input
+          id={id}
+          type='checkbox'
+          checked={settings.getIn(item)}
+          onChange={handleChange}
+          disabled={!enabled}
+        />
+        {children}
+      </label>
+    );
   }
 
 }
diff --git a/app/javascript/glitch/components/local_settings/page/item/style.scss b/app/javascript/glitch/components/local_settings/page/item/style.scss
new file mode 100644
index 000000000..e614030c0
--- /dev/null
+++ b/app/javascript/glitch/components/local_settings/page/item/style.scss
@@ -0,0 +1,7 @@
+@import 'variables';
+
+.glitch.local-settings__page__item {
+  select {
+    margin-bottom: 5px;
+  }
+}
diff --git a/app/javascript/glitch/components/local_settings/page/style.scss b/app/javascript/glitch/components/local_settings/page/style.scss
new file mode 100644
index 000000000..7269056c3
--- /dev/null
+++ b/app/javascript/glitch/components/local_settings/page/style.scss
@@ -0,0 +1,9 @@
+@import 'variables';
+
+.glitch.local-settings__page {
+  display: block;
+  flex: auto;
+  padding: 15px 20px 15px 20px;
+  width: 360px;
+  overflow-y: auto;
+}
diff --git a/app/javascript/glitch/components/local_settings/style.scss b/app/javascript/glitch/components/local_settings/style.scss
new file mode 100644
index 000000000..6f7fcbaa4
--- /dev/null
+++ b/app/javascript/glitch/components/local_settings/style.scss
@@ -0,0 +1,34 @@
+@import 'variables';
+
+.glitch.local-settings {
+  position: relative;
+  display: flex;
+  flex-direction: row;
+  background: $ui-secondary-color;
+  color: $ui-base-color;
+  border-radius: 8px;
+  height: 80vh;
+  width: 80vw;
+  max-width: 740px;
+  max-height: 450px;
+  overflow: hidden;
+
+  label {
+    display: block;
+  }
+
+  h1 {
+    font-size: 18px;
+    font-weight: 500;
+    line-height: 24px;
+    margin-bottom: 20px;
+  }
+
+  h2 {
+    font-size: 15px;
+    font-weight: 500;
+    line-height: 20px;
+    margin-top: 20px;
+    margin-bottom: 10px;
+  }
+}
diff --git a/app/javascript/glitch/components/settings/style.scss b/app/javascript/glitch/components/settings/style.scss
deleted file mode 100644
index 48cc37984..000000000
--- a/app/javascript/glitch/components/settings/style.scss
+++ /dev/null
@@ -1,84 +0,0 @@
-@import 'variables';
-
-.settings-modal {
-  position: relative;
-  display: flex;
-  flex-direction: row;
-  background: $ui-secondary-color;
-  color: $ui-base-color;
-  border-radius: 8px;
-  height: 80vh;
-  width: 80vw;
-  max-width: 740px;
-  max-height: 450px;
-  overflow: hidden;
-
-  label {
-    display: block;
-  }
-
-  h1 {
-    font-size: 18px;
-    font-weight: 500;
-    line-height: 24px;
-    margin-bottom: 20px;
-  }
-
-  h2 {
-    font-size: 15px;
-    font-weight: 500;
-    line-height: 20px;
-    margin-top: 20px;
-    margin-bottom: 10px;
-  }
-}
-
-.settings-modal__navigation {
-  background: $primary-text-color;
-  color: $ui-base-color;
-  width: 200px;
-  font-size: 15px;
-  line-height: 20px;
-  overflow-y: auto;
-
-  .settings-modal__navigation-item, .settings-modal__navigation-close {
-    display: block;
-    padding: 15px 20px;
-    cursor: pointer;
-    outline: none;
-    text-decoration: none;
-  }
-
-  .settings-modal__navigation-item {
-    background: $primary-text-color;
-    color: inherit;
-    border-bottom: 1px $ui-primary-color solid;
-    transition: background .3s;
-
-    &:hover {
-      background: $ui-secondary-color;
-    }
-
-    &.active {
-      background: $ui-highlight-color;
-      color: $primary-text-color;
-    }
-  }
-
-  .settings-modal__navigation-close {
-    background: $error-value-color;
-    color: $primary-text-color;
-  }
-}
-
-.settings-modal__content {
-  display: block;
-  flex: auto;
-  padding: 15px 20px 15px 20px;
-  width: 360px;
-  overflow-y: auto;
-
-  select {
-    margin-bottom: 5px;
-  }
-}
\ No newline at end of file