feat: new welcome modal, refactor many things, various bug fixes, use material-ui v5 etc

Co-authored-by: Alex Sparkes <turbomarshmello@gmail.com>
This commit is contained in:
David Ralph
2021-07-02 21:29:33 +01:00
parent c6b65f943a
commit cf36ced2a7
61 changed files with 782 additions and 324 deletions

View File

@@ -1,5 +1,7 @@
import React from 'react';
import EventBus from '../../modules/helpers/eventbus';
import Main from './main/Main';
import Navbar from '../widgets/navbar/Navbar';
@@ -39,6 +41,8 @@ export default class Modals extends React.PureComponent {
this.setState({
welcomeModal: false
});
EventBus.dispatch('refresh', 'widgets');
EventBus.dispatch('refresh', 'backgroundwelcome');
}
toggleModal(type, action) {
@@ -59,7 +63,7 @@ export default class Modals extends React.PureComponent {
<Main modalClose={() => this.toggleModal('mainModal', false)}/>
</Modal>
<React.Suspense fallback={renderLoader()}>
<Modal closeTimeoutMS={300} onRequestClose={() => this.closeWelcome()} isOpen={this.state.welcomeModal} className='Modal welcomemodal mainModal' overlayClassName='Overlay' ariaHideApp={false}>
<Modal closeTimeoutMS={300} onRequestClose={() => this.closeWelcome()} isOpen={this.state.welcomeModal} className='Modal welcomemodal mainModal' overlayClassName='Overlay welcomeoverlay' shouldCloseOnOverlayClick={false} ariaHideApp={false}>
<Welcome modalClose={() => this.closeWelcome()}/>
</Modal>
<Modal closeTimeoutMS={300} onRequestClose={() => this.toggleModal('feedbackModal', false)} isOpen={this.state.feedbackModal} className='Modal mainModal' overlayClassName='Overlay' ariaHideApp={false}>

View File

@@ -29,17 +29,17 @@ export default function MainModal(props) {
<>
<span className='closeModal' onClick={props.modalClose}>&times;</span>
<Tabs navbar={true}>
<div label={language.settings}>
<div label={language.settings} name='settings'>
<React.Suspense fallback={renderLoader()}>
<Settings/>
</React.Suspense>
</div>
<div label={language.addons}>
<div label={language.addons} name='addons'>
<React.Suspense fallback={renderLoader()}>
<Addons/>
</React.Suspense>
</div>
<div label={language.marketplace}>
<div label={language.marketplace} name='marketplace'>
<React.Suspense fallback={renderLoader()}>
<Marketplace/>
</React.Suspense>

View File

@@ -34,7 +34,7 @@ export default class Item extends React.PureComponent {
}
// prevent console error
let iconsrc = window.constants.DDG_PROXY + this.props.data.icon;
let iconsrc = window.constants.DDG_IMAGE_PROXY + this.props.data.icon;
if (!this.props.data.icon) {
iconsrc = null;
}

View File

@@ -3,7 +3,7 @@ export default function Items(props) {
<div className='items'>
{props.items.map((item) => (
<div className='item' onClick={() => props.toggleFunction(item.name)} key={item.name}>
<img alt='icon' draggable='false' src={window.constants.DDG_PROXY + item.icon_url} />
<img alt='icon' draggable='false' src={window.constants.DDG_IMAGE_PROXY + item.icon_url} />
<div className='details'>
<h4>{item.display_name || item.name}</h4>
<p>{item.author}</p>

View File

@@ -410,3 +410,7 @@ h3 {
h5 {
font-size: 0.8rem;
}
.checkbox svg {
fill: var(--modal-text) !important;
}

View File

@@ -1,7 +1,6 @@
import React from 'react';
import EventBus from '../../../../modules/helpers/eventbus';
import SettingsFunctions from '../../../../modules/helpers/settings';
import CheckboxUI from '@material-ui/core/Checkbox';
import FormControlLabel from '@material-ui/core/FormControlLabel';
@@ -15,10 +14,11 @@ export default class Checkbox extends React.PureComponent {
}
handleChange = () => {
SettingsFunctions.setItem(this.props.name);
const value = (this.state.checked === true) ? false : true;
localStorage.setItem(this.props.name, value);
this.setState({
checked: (this.state.checked === true) ? false : true
checked: value
});
window.stats.postEvent('setting', `${this.props.name} ${(this.state.checked === true) ? 'enabled' : 'disabled'}`);
@@ -45,7 +45,7 @@ export default class Checkbox extends React.PureComponent {
return (
<>
<FormControlLabel
control={<CheckboxUI name={this.props.name} color='primary' checked={this.state.checked} onChange={this.handleChange} />}
control={<CheckboxUI name={this.props.name} color='primary' className='checkbox' checked={this.state.checked} onChange={this.handleChange} />}
label={text}
/>
<br/>

View File

@@ -1,7 +1,6 @@
import React from 'react';
import EventBus from '../../../../modules/helpers/eventbus';
import SettingsFunctions from '../../../../modules/helpers/settings';
import SwitchUI from '@material-ui/core/Switch';
import FormControlLabel from '@material-ui/core/FormControlLabel';
@@ -15,10 +14,11 @@ export default class Switch extends React.PureComponent {
}
handleChange = () => {
SettingsFunctions.setItem(this.props.name);
const value = (this.state.checked === true) ? false : true;
localStorage.setItem(this.props.name, value);
this.setState({
checked: (this.state.checked === true) ? false : true
checked: value
});
window.stats.postEvent('setting', `${this.props.name} ${(this.state.checked === true) ? 'enabled' : 'disabled'}`);

View File

@@ -3,7 +3,7 @@ import React from 'react';
import Tooltip from '../../../../helpers/tooltip/Tooltip';
import EmailIcon from '@material-ui/icons/Email';
import TwitterIcon from '@material-ui/icons/Twitter';
import ForumIcon from '@material-ui/icons/Forum';
import ChatIcon from '@material-ui/icons/Chat';
import InstagramIcon from '@material-ui/icons/Instagram';
import FacebookIcon from '@material-ui/icons/Facebook';
@@ -96,7 +96,7 @@ export default class About extends React.PureComponent {
<a href='https://twitter.com/getmue' className='aboutIcon' target='_blank' rel='noopener noreferrer'><TwitterIcon/></a>
<a href='https://instagram.com/mue.tab' className='aboutIcon' target='_blank' rel='noopener noreferrer'><InstagramIcon/></a>
<a href='https://facebook.com/muetab' className='aboutIcon' target='_blank' rel='noopener noreferrer'><FacebookIcon/></a>
<a href='https://discord.gg/zv8C9F8' className='aboutIcon' target='_blank' rel='noopener noreferrer'><ForumIcon/></a>
<a href='https://discord.gg/zv8C9F8' className='aboutIcon' target='_blank' rel='noopener noreferrer'><ChatIcon/></a>
<h3>{this.language.support_mue}</h3>
<p>

View File

@@ -6,9 +6,8 @@ import Text from '../Text';
import Switch from '../Switch';
import ResetModal from '../ResetModal';
import SettingsFunctions from '../../../../../modules/helpers/settings';
import SettingsFunctions from '../../../../../modules/helpers/settings/modals';
import { toast } from 'react-toastify';
import Modal from 'react-modal';
export default class AdvancedSettings extends React.PureComponent {
@@ -20,17 +19,6 @@ export default class AdvancedSettings extends React.PureComponent {
this.language = window.language.modals.main.settings;
}
settingsImport(e) {
const content = JSON.parse(e.target.result);
Object.keys(content).forEach((key) => {
localStorage.setItem(key, content[key]);
});
toast(window.language.toasts.imported);
window.stats.postEvent('tab', 'Settings imported');
}
render() {
const { advanced } = this.language.sections;
@@ -43,7 +31,7 @@ export default class AdvancedSettings extends React.PureComponent {
<button className='reset' onClick={() => this.setState({ resetModal: true })}>{this.language.buttons.reset}</button>
<button className='export' onClick={() => SettingsFunctions.exportSettings()}>{this.language.buttons.export}</button>
<button className='import' onClick={() => document.getElementById('file-input').click()}>{this.language.buttons.import}</button>
<FileUpload id='file-input' accept='application/json' type='settings' loadFunction={(e) => this.settingsImport(e)}/>
<FileUpload id='file-input' accept='application/json' type='settings' loadFunction={(e) => SettingsFunctions.importSettings(e)}/>
<h3>{advanced.customisation}</h3>
<Text title={advanced.tab_name} name='tabName' default={window.language.tabname} category='other'/>

View File

@@ -53,7 +53,7 @@ export default class Changelog extends React.PureComponent {
lightboxImg: img.src
});
};
}
};
for (let link = 0; link < links.length; link++) {
links[link].target = '_blank';

View File

@@ -52,7 +52,6 @@ export default class OrderSettings extends React.PureComponent {
}
const newArray = [...array];
const target = newArray[oldIndex];
const inc = newIndex < oldIndex ? -1 : 1;
@@ -61,7 +60,6 @@ export default class OrderSettings extends React.PureComponent {
}
newArray[newIndex] = target;
return newArray;
}

View File

@@ -8,7 +8,7 @@ export default function QuickLinks() {
<>
<h2>{language.title}</h2>
<Switch name='quicklinksenabled' text={window.language.modals.main.settings.enabled} category='quicklinks' element='.quicklinks-container' />
<Checkbox name='quicklinksddgProxy' text={window.language.modals.main.settings.sections.background.ddg_proxy} element='.other' />
<Checkbox name='quicklinksddgProxy' text={window.language.modals.main.settings.sections.background.ddg_image_proxy} element='.other' />
<Checkbox name='quicklinksnewtab' text={language.open_new} category='quicklinks' />
<Checkbox name='quicklinkstooltip' text={language.tooltip} category='quicklinks' />
</>

View File

@@ -85,7 +85,6 @@ export default class SearchSettings extends React.PureComponent {
))}
<option value='custom'>{search.custom.split(' ')[0]}</option>
</Dropdown>
<ul style={{ display: this.state.customDisplay }}>
<br/>
<p style={{ marginTop: '0px' }}>{search.custom} <span className='modalLink' onClick={() => this.resetSearch()}>{language.buttons.reset}</span></p>

View File

@@ -153,7 +153,7 @@ export default class BackgroundSettings extends React.PureComponent {
<>
<h2>{background.title}</h2>
<Switch name='background' text={this.language.enabled} category='background' />
<Checkbox name='ddgProxy' text={background.ddg_proxy} />
<Checkbox name='ddgProxy' text={background.ddg_image_proxy} />
<Checkbox name='bgtransition' text={background.transition} />
<Checkbox name='photoInformation' text={background.photo_information} category='background' element='.other' />

View File

@@ -55,7 +55,7 @@ export default class ColourSettings extends React.PureComponent {
try {
gradientSettings = JSON.parse(hex);
} catch (e) {
// Disregard exception.
// Disregard exception
}
}

View File

@@ -8,8 +8,8 @@ export default function Addons() {
return (
<Tabs>
<div label={addons.added}><Added/></div>
<div label={addons.sideload}><Sideload/></div>
<div label={addons.added} name='added'><Added/></div>
<div label={addons.sideload} name='sideload'><Sideload/></div>
</Tabs>
);
}

View File

@@ -7,9 +7,9 @@ export default function Marketplace() {
return (
<Tabs>
<div label={marketplace.photo_packs}><MarketplaceTab type='photo_packs'/></div>
<div label={marketplace.quote_packs}><MarketplaceTab type='quote_packs'/></div>
<div label={marketplace.preset_settings}><MarketplaceTab type='preset_settings'/></div>
<div label={marketplace.photo_packs} name='photo_packs'><MarketplaceTab type='photo_packs'/></div>
<div label={marketplace.quote_packs} name='quote_packs'><MarketplaceTab type='quote_packs'/></div>
<div label={marketplace.preset_settings} name='preset_settings'><MarketplaceTab type='preset_settings'/></div>
</Tabs>
);
}

View File

@@ -26,20 +26,20 @@ export default function Settings() {
return (
<>
<Tabs>
<div label={sections.time.title}><Time/></div>
<div label={sections.quote.title}><Quote/></div>
<div label={sections.greeting.title}><Greeting/></div>
<div label={sections.background.title}><Background/></div>
<div label={sections.search.title}><Search/></div>
<div label={sections.quicklinks.title}><QuickLinks/></div>
<div label={sections.weather.title}><Weather/></div>
<div label={sections.appearance.title}><Appearance/></div>
<div label={sections.order.title}><Order/></div>
<div label={sections.language.title}><Language/></div>
<div label={sections.advanced.title}><Advanced/></div>
<div label={sections.experimental.title}><Experimental/></div>
<div label={sections.changelog}><Changelog/></div>
<div label={sections.about.title}><About/></div>
<div label={sections.time.title} name='time'><Time/></div>
<div label={sections.quote.title} name='quote'><Quote/></div>
<div label={sections.greeting.title} name='greeting'><Greeting/></div>
<div label={sections.background.title} name='background'><Background/></div>
<div label={sections.search.title} name='search'><Search/></div>
<div label={sections.quicklinks.title} name='quicklinks'><QuickLinks/></div>
<div label={sections.weather.title} name='weather'><Weather/></div>
<div label={sections.appearance.title} name='appearance'><Appearance/></div>
<div label={sections.order.title} name='order'><Order/></div>
<div label={sections.language.title} name='language'><Language/></div>
<div label={sections.advanced.title} name='advanced'><Advanced/></div>
<div label={sections.experimental.title} name='experimental'><Experimental/></div>
<div label={sections.changelog} name='changelog'><Changelog/></div>
<div label={sections.about.title} name='about'><About/></div>
</Tabs>
<div className='reminder-info' style={{ display: display }}>
<h1>{reminder.title}</h1>

View File

@@ -8,17 +8,19 @@ export default class Tabs extends React.PureComponent {
super(props);
this.state = {
currentTab: this.props.children[0].props.label
currentTab: this.props.children[0].props.label,
currentName: this.props.children[0].props.name
};
}
onClick = (tab) => {
if (tab !== this.state.currentTab) {
window.stats.postEvent('tab', `Changed ${this.state.currentTab} to ${tab}`);
onClick = (tab, name) => {
if (name !== this.state.currentName) {
window.stats.postEvent('tab', `Changed ${this.state.currentName} to ${name}`);
}
this.setState({
currentTab: tab
currentTab: tab,
currentName: name
});
};
@@ -42,7 +44,7 @@ export default class Tabs extends React.PureComponent {
currentTab={this.state.currentTab}
key={tab.props.label || index}
label={tab.props.label}
onClick={this.onClick}
onClick={(nextTab) => this.onClick(nextTab, tab.props.name)}
navbar={this.props.navbar || false}
/>
))}

View File

@@ -0,0 +1,16 @@
export default function ProgressBar(props) {
return (
<div className='progressbar'>
{props.count.map((num) => {
let className = 'step';
const index = props.count.indexOf(num);
if (index === props.currentTab) {
className = 'step active';
}
return <div className={className} key={index} onClick={() => props.switchTab(index)}></div>
})}
</div>
);
}

View File

@@ -1,28 +1,69 @@
import EmailIcon from '@material-ui/icons/Email';
import TwitterIcon from '@material-ui/icons/Twitter';
import ForumIcon from '@material-ui/icons/Forum';
import React from 'react';
import WelcomeSections from './WelcomeSections';
import ProgressBar from './ProgressBar';
import './welcome.scss';
export default function WelcomeModal(props) {
const language = window.language.modals.welcome;
export default class WelcomeModal extends React.PureComponent {
constructor() {
super();
this.state = {
image: './././icons/undraw_celebration.svg',
currentTab: 0,
finalTab: 4,
buttonText: 'Next'
};
this.language = window.language.modals.welcome;
this.images = ['./././icons/undraw_celebration.svg', './././icons/undraw_around_the_world_modified.svg', './././icons/undraw_add_files_modified.svg', './././icons/undraw_dark_mode.svg', './././icons/undraw_private_data_modified.svg', './././icons/undraw_upgrade_modified.svg']
}
return (
<div className='welcomeContent'>
<span className='closeModal' onClick={props.modalClose}>&times;</span>
<div className='welcomeModalText'>
<h2 className='subtitle'>{language.title}</h2>
<h1 className='welcometitle'>Mue Tab</h1>
<img alt='celebration' style={{ height: '200px', width: 'auto' }} draggable={false} src='./././icons/undraw_celebration.svg' />
<h2 className='subtitle'>{language.information}</h2>
<p>{language.thankyoumessage1}<br/> {language.thankyoumessage2}</p>
<h2 className='subtitle'>{language.support}</h2>
<a href='mailto:hello@muetab.com' className='welcomeLink' target='_blank' rel='noopener noreferrer'><EmailIcon/></a>
<a href='https://twitter.com/getmue' className='welcomeLink' target='_blank' rel='noopener noreferrer'><TwitterIcon/></a>
<a href='https://discord.gg/zv8C9F8' className='welcomeLink' target='_blank' rel='noopener noreferrer'><ForumIcon/></a>
<br/>
<button className='close' onClick={props.modalClose}>{language.close}</button>
changeTab(minus) {
if (minus) {
return this.setState({
currentTab: this.state.currentTab - 1,
image: this.images[this.state.currentTab - 1],
buttonText: 'Next'
});
}
if (this.state.buttonText === 'Close') {
return this.props.modalClose();
}
this.setState({
currentTab: this.state.currentTab + 1,
image: this.images[this.state.currentTab + 1],
buttonText: (this.state.currentTab !== this.state.finalTab) ? 'Next' : 'Close'
});
}
// specific
switchTab(tab) {
this.setState({
currentTab: tab,
image: this.images[tab],
buttonText: 'Next'
});
}
render() {
return (
<div className='welcomeContent'>
<section>
<img alt='celebration' draggable={false} src={this.state.image} />
<ProgressBar count={this.images} currentTab={this.state.currentTab} switchTab={(tab) => this.switchTab(tab)}/>
</section>
<section>
<div className='content'>
<WelcomeSections currentTab={this.state.currentTab} switchTab={(tab) => this.switchTab(tab)}/>
</div>
<div className='buttons'>
{(this.state.currentTab !== 0) ? <button className='close' style={{ marginRight: '20px' }} onClick={() => this.changeTab(true)}>Previous</button> : null}
<button className='close' onClick={() => this.changeTab()}>{this.state.buttonText}</button>
</div>
</section>
</div>
</div>
);
);
}
}

View File

@@ -0,0 +1,156 @@
import React from 'react';
import Radio from '../main/settings/Radio';
//import Checkbox from '../main/settings/Checkbox';
import FileUpload from '../main/settings/FileUpload';
import UploadIcon from '@material-ui/icons/CloudUpload';
import AutoIcon from '@material-ui/icons/AutoAwesome';
import LightModeIcon from '@material-ui/icons/LightMode';
import DarkModeIcon from '@material-ui/icons/DarkMode';
import SettingsFunctions from '../../../modules/helpers/settings';
const languages = require('../../../modules/languages.json');
export default class WelcomeSections extends React.Component {
constructor() {
super();
this.state = {
autoClass: 'toggle auto active',
lightClass: 'toggle lightTheme',
darkClass: 'toggle darkTheme',
welcomeImage: 0
};
this.changeWelcomeImg = this.changeWelcomeImg.bind(this);
this.welcomeImages = ['https://external-content.duckduckgo.com/iu/?u=example.com/example.png'];
}
changeTheme(type) {
this.setState({
autoClass: (type === 'auto') ? 'toggle auto active' : 'toggle auto',
lightClass: (type === 'light') ? 'toggle lightTheme active' : 'toggle lightTheme',
darkClass: (type === 'dark') ? 'toggle darkTheme active': 'toggle darkTheme'
});
localStorage.setItem('theme', type);
SettingsFunctions.loadSettings(true);
}
getSetting(name) {
const value = localStorage.getItem(name).replace('false', 'Off').replace('true', 'On');
return value.charAt(0).toUpperCase() + value.slice(1);
}
importSettings(e) {
SettingsFunctions.importSettings(e);
this.props.switchTab(4);
}
changeWelcomeImg() {
let welcomeImage = this.state.welcomeImage;
this.setState({
welcomeImage: ++welcomeImage % this.welcomeImages.length
});
this.timeout = setTimeout(this.changeWelcomeImg, 3 * 1000);
}
componentDidMount() {
this.timeout = setTimeout(this.changeWelcomeImg, 3 * 1000);
}
render() {
const language = window.language.modals.welcome;
let tabContent;
const intro = (
<>
<h1>{language.title} Mue Tab</h1>
<p>{language.thankyoumessage1} {language.thankyoumessage2}</p>
<h3 className='quicktip'>to be added</h3>
<div className='examples'>
<img src={this.welcomeImages[this.state.welcomeImage]} alt='example mue setup' draggable={false}/>
</div>
</>
);
const chooseLanguage = (
<>
<h1>Choose your language</h1>
<p>to be added</p>
<Radio name='language' options={languages}/>
</>
);
const theme = (
<>
<h1>Select a theme</h1>
<p>Mue is available in both light and dark theme, or this can be automatically set depending on your system theme.</p>
<div className='themesToggleArea'>
<div className={this.state.autoClass} onClick={() => this.changeTheme('auto')}>
<AutoIcon/>
<span>Auto</span>
</div>
<div className='options'>
<div className={this.state.lightClass} onClick={() => this.changeTheme('light')}>
<LightModeIcon/>
<span>Light</span>
</div>
<div className={this.state.darkClass} onClick={() => this.changeTheme('dark')}>
<DarkModeIcon/>
<span>Dark</span>
</div>
</div>
<h3 className='quicktip'>Quick Tip</h3>
<p>Using the Auto settings will use the theme on your computer. This setting will impact the modals and some of the widgets displayed on the screen, such as weather and notes.</p>
</div>
</>
);
const settings = (
<>
<h1>Import Settings</h1>
<p>Installing Mue on a new device? Feel free to import your old settings!</p>
<button className='upload' onClick={() => document.getElementById('file-input').click()}>
<UploadIcon/>
<br/>
<span>{window.language.modals.main.settings.buttons.import}</span>
</button>
<FileUpload id='file-input' accept='application/json' type='settings' loadFunction={(e) => this.importSettings(e)}/>
<h3 className='quicktip'>Quick Tip</h3>
<p>You can export your old settings by navigating to the Advanced tab in your old Mue setup. Then you need to click the export button which will download the JSON file. You can upload this file here to carry across your settings and preferences from your previous Mue installation.</p>
</>
);
const privacy = (
<>
<h1>Privacy Options</h1>
<p>to be added</p>
</>
);
const final = (
<>
<h1>Final step</h1>
<p>Your Mue Tab experience is finally about to begin.</p>
<h3 className='quicktip'>Changes</h3>
<p>To change settings later click on the settings icon in the top right corner of your tab.</p>
<div className='themesToggleArea'>
<div className='toggle' onClick={() => this.props.switchTab(1)}>Language: {languages.find((i) => i.value === localStorage.getItem('language')).name}</div>
<div className='toggle' onClick={() => this.props.switchTab(3)}>Theme: {this.getSetting('theme')}</div>
</div>
</>
)
switch (this.props.currentTab) {
case 1: tabContent = chooseLanguage; break;
case 2: tabContent = settings; break;
case 3: tabContent = theme; break;
case 4: tabContent = privacy; break;
case 5: tabContent = final; break;
// 0
default: tabContent = intro;
}
return tabContent;
}
}

View File

@@ -1,59 +1,148 @@
@import '../main/scss/index.scss';
.welcomemodal {
margin-top: 40px;
}
position: absolute;
margin: auto;
top: 0;
right: 0;
bottom: 0;
left: 0;
height: 80%;
width: 60%;
padding: 0;
.welcomeModalText {
line-height: 2px;
h2.subtitle {
font-size: 24px;
color: var(--modal-text);
text-transform: uppercase;
section {
width: 50%;
display: inline;
height: 80vh;
}
h1.welcometitle {
font-size: 50px;
}
}
section:nth-child(1) {
float: left;
background: var(--sidebar);
display: flex;
justify-content: center;
align-items: center;
.welcomeContent {
margin-top: 2em;
text-align: center;
padding: 25px;
a {
text-decoration: none;
line-height: 20px !important;
color: var(--modal-link);
cursor: pointer;
}
img.icon,
svg {
margin-top: -12px;
padding: 10px;
cursor: pointer;
transition: ease 0.2s;
&:hover {
transform: scale(1.1);
img {
height: 300px;
width: 400px;
}
}
p {
margin-top: 0.7rem;
line-height: 1em;
}
section:nth-child(2) {
float: right;
img,
svg {
height: 24px;
width: auto;
.content {
padding: 20px;
}
.buttons {
position: absolute;
bottom: 2rem;
right: 2rem;
}
h1 {
font-size: 2.5em;
}
h3.quicktip {
text-transform: uppercase;
color: #5352ed;
}
}
}
.welcomeLink {
color: var(--modal-text) !important;
.welcomeoverlay {
background-color: rgba(0, 0, 0, 0.4);
}
.progressbar {
position: fixed;
bottom: 50px;
text-align: center;
display: inline;
overflow: hidden;
white-space: nowrap;
.step {
display: inline-block;
width: 50px;
background: #8395a7;
height: 4px;
margin: 10px;
transition: .2s ease;
cursor: pointer;
border-radius: 15px;
}
.active {
background: #5352ed;
}
}
.examples {
display: flex;
flex-wrap: wrap;
flex-direction: column;
align-items: center;
img {
width: 30rem;
height: auto;
display: block;
margin: 30px;
border-radius: 12px;
}
}
.themesToggleArea {
.active {
background: var(--tab-active) !important;
}
.toggle {
background: var(--sidebar);
text-align: center;
border-radius: 40px;
padding: 20px;
margin: 10px;
&:hover {
background: var(--tab-active);
cursor: pointer;
}
}
.auto {
svg {
font-size: 12px;
padding-right: 5px;
}
}
.options {
display: flex;
justify-content: space-between;
.lightTheme,
.darkTheme {
width: 40%;
padding: 50px;
span {
display: block;
}
}
}
}
a.privacy {
text-decoration: none;
color: var(--modal-text);
&:hover {
color: #5352ed;
}
}