refactor(welcome): Improve readability of sections

This commit is contained in:
alexsparkes 2024-02-19 19:51:12 +00:00
parent fc9d1c3f65
commit ffb1c513c9
13 changed files with 209 additions and 140 deletions

View File

@ -3,11 +3,11 @@ import { MdOutlineOpenInNew } from 'react-icons/md';
import languages from '@/i18n/languages.json';
import { Radio } from 'components/Form/Settings';
import { Header } from '../components/Layout';
import { Header, Content } from '../components/Layout';
function ChooseLanguage() {
return (
<>
<Content>
<Header
title={variables.getMessage('modals.welcome.sections.language.title')}
subtitle={variables.getMessage('modals.welcome.sections.language.description')}
@ -33,7 +33,7 @@ function ChooseLanguage() {
<div className="languageSettings">
<Radio name="language" options={languages} category="welcomeLanguage" />
</div>
</>
</Content>
);
}

View File

@ -1,10 +1,10 @@
import variables from 'config/variables';
import languages from '@/i18n/languages.json';
import { Header } from '../components/Layout';
import { Header, Content } from '../components/Layout';
function Final(props) {
return (
<>
<Content>
<Header
title={variables.getMessage('modals.welcome.sections.final.title')}
subtitle={variables.getMessage('modals.welcome.sections.final.description')}
@ -38,7 +38,7 @@ function Final(props) {
</div>
)}*/}
</div>
</>
</Content>
);
}

View File

@ -3,7 +3,7 @@ import { useState } from 'react';
import { FileUpload } from 'components/Form/Settings';
import { MdCloudUpload } from 'react-icons/md';
import { importSettings as importSettingsFunction } from 'utils/settings';
import { Header } from '../components/Layout';
import { Header, Content } from '../components/Layout';
import default_settings from 'utils/data/default_settings.json';
function ImportSettings(props) {
@ -43,7 +43,7 @@ function ImportSettings(props) {
props.switchTab(5);
};
return (
<>
<Content>
<Header
title={variables.getMessage('modals.welcome.sections.settings.title')}
subtitle={variables.getMessage('modals.welcome.sections.settings.description')}
@ -62,7 +62,7 @@ function ImportSettings(props) {
<span className="subtitle">
{variables.getMessage('modals.welcome.sections.settings.tip')}
</span>
</>
</Content>
);
}

View File

@ -1,7 +1,7 @@
import variables from 'config/variables';
import { useState, useEffect } from 'react';
import { Header } from '../components/Layout';
import { Header, Content } from '../components/Layout';
import { MdOutlineWavingHand, MdOpenInNew } from 'react-icons/md';
import { FaDiscord, FaGithub } from 'react-icons/fa';
@ -18,7 +18,7 @@ useEffect(() => {
}, [welcomeImage]);
return (
<>
<Content>
<Header title={variables.getMessage('modals.welcome.sections.intro.title')} />
<div className="examples">
<img
@ -75,7 +75,7 @@ useEffect(() => {
{variables.getMessage('modals.welcome.sections.intro.notices.github_open')}
</a>
</div>
</>
</Content>
);
}

View File

@ -1,15 +1,11 @@
import variables from 'config/variables';
import { MdOutlineOpenInNew } from 'react-icons/md';
import { Checkbox } from 'components/Form/Settings';
import { Header } from '../components/Layout';
import { Header, Content } from '../components/Layout';
function PrivacyOptions() {
function OfflineMode() {
return (
<>
<Header
title={variables.getMessage('modals.welcome.sections.privacy.title')}
subtitle={variables.getMessage('modals.welcome.sections.privacy.description')}
/>
<Checkbox
name="offlineMode"
text={variables.getMessage('modals.main.settings.sections.advanced.offline_mode')}
@ -18,18 +14,27 @@ function PrivacyOptions() {
<span className="subtitle">
{variables.getMessage('modals.welcome.sections.privacy.offline_mode_description')}
</span>
</>
);
}
function DuckDuckGoProxy() {
return (
<>
<Checkbox
name="ddgProxy"
text={
variables.getMessage('modals.main.settings.sections.background.ddg_image_proxy') +
' (' +
variables.getMessage('modals.main.settings.sections.background.title') +
')'
}
text={`${variables.getMessage('modals.main.settings.sections.background.ddg_image_proxy')} (${variables.getMessage('modals.main.settings.sections.background.title')})`}
/>
<span className="subtitle">
{variables.getMessage('modals.welcome.sections.privacy.ddg_proxy_description')}
</span>
</>
);
}
function Links() {
return (
<>
<span className="title">
{variables.getMessage('modals.welcome.sections.privacy.links.title')}
</span>
@ -45,7 +50,7 @@ function PrivacyOptions() {
<a
className="link"
href={'https://github.com/' + variables.constants.ORG_NAME}
href={`https://github.com/${variables.constants.ORG_NAME}`}
target="_blank"
rel="noopener noreferrer"
>
@ -56,4 +61,18 @@ function PrivacyOptions() {
);
}
export { PrivacyOptions as default, PrivacyOptions };
function PrivacyOptions() {
return (
<Content>
<Header
title={variables.getMessage('modals.welcome.sections.privacy.title')}
subtitle={variables.getMessage('modals.welcome.sections.privacy.description')}
/>
<OfflineMode />
<DuckDuckGoProxy />
<Links />
</Content>
);
}
export { PrivacyOptions as default, PrivacyOptions };

View File

@ -1,41 +1,53 @@
import variables from 'config/variables';
import { MdArchive, MdOutlineWhatshot } from 'react-icons/md';
import { useState } from 'react';
import { Header } from '../components/Layout';
import { Header, Content } from '../components/Layout';
function StyleSelection() {
const widgetStyle = localStorage.getItem('widgetStyle');
const [style, setStyle] = useState({
newStyle: widgetStyle === 'legacy' ? 'toggle newStyle' : 'toggle newStyle active',
legacyStyle: widgetStyle === 'legacy' ? 'toggle legacyStyle active' : 'toggle legacyStyle',
});
const changeStyle = (type) => {
setStyle({
newStyle: type === 'new' ? 'toggle newStyle active' : 'toggle newStyle',
legacyStyle: type === 'legacy' ? 'toggle legacyStyle active' : 'toggle legacyStyle',
});
localStorage.setItem('widgetStyle', type);
};
const STYLES = {
NEW: 'new',
LEGACY: 'legacy',
};
return (
<>
<Header title={variables.getMessage('modals.welcome.sections.style.title')} subtitle={variables.getMessage('modals.welcome.sections.style.description')} />
<div className="themesToggleArea">
<div className="options">
<div className={style.legacyStyle} onClick={() => changeStyle('legacy')}>
<MdArchive />
<span>{variables.getMessage('modals.welcome.sections.style.legacy')}</span>
const StyleSelection = () => {
const widgetStyle = localStorage.getItem('widgetStyle') || STYLES.NEW;
const [style, setStyle] = useState(widgetStyle);
const changeStyle = (type) => {
setStyle(type);
localStorage.setItem('widgetStyle', type);
};
const styleMapping = {
[STYLES.LEGACY]: {
className: style === STYLES.LEGACY ? 'toggle legacyStyle active' : 'toggle legacyStyle',
icon: <MdArchive />,
text: variables.getMessage('modals.welcome.sections.style.legacy'),
},
[STYLES.NEW]: {
className: style === STYLES.NEW ? 'toggle newStyle active' : 'toggle newStyle',
icon: <MdOutlineWhatshot />,
text: variables.getMessage('modals.welcome.sections.style.modern'),
},
};
return (
<Content>
<Header
title={variables.getMessage('modals.welcome.sections.style.title')}
subtitle={variables.getMessage('modals.welcome.sections.style.description')}
/>
<div className="themesToggleArea">
<div className="options">
{Object.entries(styleMapping).map(([type, { className, icon, text }]) => (
<div className={className} onClick={() => changeStyle(type)} key={type}>
{icon}
<span>{text}</span>
</div>
<div className={style.newStyle} onClick={() => changeStyle('new')}>
<MdOutlineWhatshot />
<span>{variables.getMessage('modals.welcome.sections.style.modern')}</span>
</div>
</div>
))}
</div>
</>
)
}
</div>
</Content>
);
};
export { StyleSelection as default, StyleSelection };

View File

@ -2,55 +2,69 @@ import variables from 'config/variables';
import { useState } from 'react';
import { MdAutoAwesome, MdLightMode, MdDarkMode } from 'react-icons/md';
import { loadSettings } from 'utils/settings';
import { Header } from '../components/Layout';
import { Header, Content } from '../components/Layout';
const THEMES = {
AUTO: 'auto',
LIGHT: 'light',
DARK: 'dark',
};
function ThemeSelection() {
const [theme, setTheme] = useState({
autoClass: 'toggle auto active',
lightClass: 'toggle lightTheme',
darkClass: 'toggle darkTheme',
});
const currentTheme = localStorage.getItem('theme') || THEMES.AUTO;
const [theme, setTheme] = useState(currentTheme);
const changeTheme = (type) => {
setTheme({
autoClass: type === 'auto' ? 'toggle auto active' : 'toggle auto',
lightClass: type === 'light' ? 'toggle lightTheme active' : 'toggle lightTheme',
darkClass: type === 'dark' ? 'toggle darkTheme active' : 'toggle darkTheme',
});
setTheme(type);
localStorage.setItem('theme', type);
loadSettings(true);
};
const themeMapping = {
[THEMES.AUTO]: {
className: theme === THEMES.AUTO ? 'toggle auto active' : 'toggle auto',
icon: <MdAutoAwesome />,
text: variables.getMessage('modals.main.settings.sections.appearance.theme.auto'),
},
[THEMES.LIGHT]: {
className: theme === THEMES.LIGHT ? 'toggle lightTheme active' : 'toggle lightTheme',
icon: <MdLightMode />,
text: variables.getMessage('modals.main.settings.sections.appearance.theme.light'),
},
[THEMES.DARK]: {
className: theme === THEMES.DARK ? 'toggle darkTheme active' : 'toggle darkTheme',
icon: <MdDarkMode />,
text: variables.getMessage('modals.main.settings.sections.appearance.theme.dark'),
},
};
return (
<>
<Content>
<Header
title={variables.getMessage('modals.welcome.sections.theme.title')}
subtitle={variables.getMessage('modals.welcome.sections.theme.description')}
/>
<div className="themesToggleArea">
<div className={theme.autoClass} onClick={() => changeTheme('auto')}>
<MdAutoAwesome />
<span>{variables.getMessage('modals.main.settings.sections.appearance.theme.auto')}</span>
<div className={themeMapping[THEMES.AUTO].className} onClick={() => changeTheme(THEMES.AUTO)}>
{themeMapping[THEMES.AUTO].icon}
<span>{themeMapping[THEMES.AUTO].text}</span>
</div>
<div className="options">
<div className={theme.lightClass} onClick={() => changeTheme('light')}>
<MdLightMode />
<span>
{variables.getMessage('modals.main.settings.sections.appearance.theme.light')}
</span>
</div>
<div className={theme.darkClass} onClick={() => changeTheme('dark')}>
<MdDarkMode />
<span>
{variables.getMessage('modals.main.settings.sections.appearance.theme.dark')}
</span>
</div>
{Object.entries(themeMapping)
.filter(([type]) => type !== THEMES.AUTO)
.map(([type, { className, icon, text }]) => (
<div className={className} onClick={() => changeTheme(type)} key={type}>
{icon}
<span>{text}</span>
</div>
))}
</div>
</div>
<span className="title">{variables.getMessage('modals.welcome.tip')}</span>
<span className="subtitle">{variables.getMessage('modals.welcome.sections.theme.tip')}</span>
</>
</Content>
);
}
export { ThemeSelection as default, ThemeSelection };
export { ThemeSelection as default, ThemeSelection };

View File

@ -37,7 +37,6 @@ class WelcomeModal extends PureComponent {
if (minus) {
return this.setState({
currentTab: this.state.currentTab - 1,
image: this.images[this.state.currentTab - 1],
buttonText: variables.getMessage('modals.welcome.buttons.next'),
});
}
@ -48,7 +47,7 @@ class WelcomeModal extends PureComponent {
this.setState({
currentTab: this.state.currentTab + 1,
image: this.images[this.state.currentTab + 1],
image: [this.state.currentTab + 1],
buttonText:
this.state.currentTab !== this.state.finalTab
? variables.getMessage('modals.welcome.buttons.next')
@ -60,7 +59,6 @@ class WelcomeModal extends PureComponent {
switchTab(tab) {
this.setState({
currentTab: tab,
image: this.images[tab],
buttonText:
tab !== this.state.finalTab + 1
? variables.getMessage('modals.welcome.buttons.next')
@ -76,7 +74,6 @@ class WelcomeModal extends PureComponent {
if (welcomeTab) {
this.setState({
currentTab: Number(welcomeTab),
image: this.images[Number(welcomeTab)],
buttonText:
Number(welcomeTab) !== this.state.finalTab + 1
? variables.getMessage('modals.welcome.buttons.next')
@ -97,6 +94,38 @@ class WelcomeModal extends PureComponent {
EventBus.off('refresh');
}
renderButtons() {
const { currentTab, buttonText } = this.state;
const { modalSkip } = this.props;
return (
<div className="welcomeButtons">
{currentTab !== 0 ? (
<Button
type="settings"
onClick={() => this.changeTab(true)}
icon={<MdArrowBackIosNew />}
label={variables.getMessage('modals.welcome.buttons.previous')}
/>
) : (
<Button
type="settings"
onClick={() => modalSkip()}
icon={<MdOutlinePreview />}
label={variables.getMessage('modals.welcome.buttons.preview')}
/>
)}
<Button
type="settings"
onClick={() => this.changeTab()}
icon={<MdArrowForwardIos />}
label={buttonText}
iconPlacement={'right'}
/>
</div>
);
}
render() {
const tabComponents = {
0: <Intro />,
@ -114,37 +143,14 @@ class WelcomeModal extends PureComponent {
<Panel type="aside">
<AsideImage currentTab={this.state.currentTab} />
<ProgressBar
count={this.images}
numberOfTabs={this.state.finalTab + 2}
currentTab={this.state.currentTab}
switchTab={(tab) => this.switchTab(tab)}
/>
</Panel>
<Panel type="content">
{CurrentSection}
<div className="welcomeButtons">
{this.state.currentTab !== 0 ? (
<Button
type="settings"
onClick={() => this.changeTab(true)}
icon={<MdArrowBackIosNew />}
label={variables.getMessage('modals.welcome.buttons.previous')}
/>
) : (
<Button
type="settings"
onClick={() => this.props.modalSkip()}
icon={<MdOutlinePreview />}
label={variables.getMessage('modals.welcome.buttons.preview')}
/>
)}
<Button
type="settings"
onClick={() => this.changeTab()}
icon={<MdArrowForwardIos />}
label={this.state.buttonText}
iconPlacement={'right'}
/>
</div>
{this.renderButtons()}
</Panel>
</Wrapper>
);

View File

@ -1,22 +1,26 @@
import { memo } from 'react';
function ProgressBar({ count, currentTab, switchTab }) {
const Step = memo(({ isActive, index, onClick }) => {
const className = isActive ? 'step active' : 'step';
return (
<div className={className} onClick={onClick}>
<span>{index + 1}</span>
</div>
);
});
function ProgressBar({ numberOfTabs, currentTab, switchTab }) {
return (
<div className="progressbar">
{count.map((num) => {
let className = 'step';
const index = count.indexOf(num);
if (index === currentTab) {
className = 'step active';
}
return (
<div className={className} key={index} onClick={() => switchTab(index)}>
<span>{index + 1}</span>
</div>
);
})}
{Array.from({ length: numberOfTabs }, (_, index) => (
<Step
key={index}
isActive={index === currentTab}
index={index}
onClick={() => switchTab(index)}
/>
))}
</div>
);
}

View File

@ -0,0 +1,7 @@
const Content = ({ children }) => {
return (
<div className="content">{children}</div>
)
}
export { Content as default, Content };

View File

@ -1,12 +1,6 @@
const Panel = ({ children, type }) => (
<section className={type}>
{type === 'content' ? (
<div className="content">{children}</div>
) : type === 'aside' ? (
<>{children}</>
) : (
children
)}
{children}
</section>
);

View File

@ -1,3 +1,4 @@
export * from './Wrapper';
export * from './Panel';
export * from './Header';
export * from './Header';
export * from './Content';

View File

@ -89,6 +89,16 @@
}
.themesToggleArea {
display: grid;
grid-template-columns: 1fr;
grid-template-rows: auto auto;
div:nth-child(1) {
grid-column: span 1 / span 1 !important;
}
div:nth-child(2),
div:nth-child(3) {
grid-column: span 1 / span 1 !important;
}
@include themed {
.active {
background: t($modal-sidebarActive);
@ -199,6 +209,7 @@ a.privacy {
flex-flow: column;
.shareYourMue {
width: -moz-fit-content;
width: fit-content;
}
@ -305,6 +316,7 @@ a.privacy {
.welcomeButtons {
z-index: 999;
-webkit-backdrop-filter: blur(2px);
backdrop-filter: blur(2px);
position: sticky;
bottom: 0;