mirror of
https://github.com/mue/mue.git
synced 2026-07-09 13:35:35 +02:00
Refactor MainModal and Tab components to integrate Library and Discover tabs
This commit is contained in:
@@ -1,22 +1,20 @@
|
||||
import variables from 'config/variables';
|
||||
import { Suspense, lazy, useState, memo, useEffect } from 'react';
|
||||
import { MdClose } from 'react-icons/md';
|
||||
|
||||
import './scss/index.scss';
|
||||
import { Tooltip } from 'components/Elements';
|
||||
import ModalLoader from './components/ModalLoader';
|
||||
import ModalTopBar from './components/ModalTopBar';
|
||||
import { TAB_TYPES } from './constants/tabConfig';
|
||||
import { updateHash, onHashChange } from 'utils/deepLinking';
|
||||
|
||||
const Settings = lazy(() => import('../../../features/misc/views/Settings'));
|
||||
const Addons = lazy(() => import('../../../features/misc/views/Addons'));
|
||||
const Marketplace = lazy(() => import('../../../features/misc/views/Marketplace'));
|
||||
const Library = lazy(() => import('../../../features/misc/views/Library'));
|
||||
const Discover = lazy(() => import('../../../features/misc/views/Discover'));
|
||||
|
||||
// Map tab types to their corresponding components
|
||||
const TAB_COMPONENTS = {
|
||||
[TAB_TYPES.SETTINGS]: Settings,
|
||||
[TAB_TYPES.ADDONS]: Addons,
|
||||
[TAB_TYPES.MARKETPLACE]: Marketplace,
|
||||
[TAB_TYPES.LIBRARY]: Library,
|
||||
[TAB_TYPES.DISCOVER]: Discover,
|
||||
};
|
||||
|
||||
function MainModal({ modalClose, deepLinkData }) {
|
||||
@@ -45,17 +43,13 @@ function MainModal({ modalClose, deepLinkData }) {
|
||||
|
||||
return (
|
||||
<div className="frame">
|
||||
<Tooltip
|
||||
style={{ position: 'absolute', top: '1rem', right: '1rem' }}
|
||||
title={variables.getMessage('modals.welcome.buttons.close')}
|
||||
key="closeTooltip"
|
||||
>
|
||||
<span className="closeModal" onClick={modalClose}>
|
||||
<MdClose />
|
||||
</span>
|
||||
</Tooltip>
|
||||
<ModalTopBar currentTab={currentTab} onTabChange={handleChangeTab} onClose={modalClose} />
|
||||
<Suspense fallback={<ModalLoader />}>
|
||||
<TabComponent changeTab={handleChangeTab} deepLinkData={deepLinkData} />
|
||||
<TabComponent
|
||||
changeTab={handleChangeTab}
|
||||
deepLinkData={deepLinkData}
|
||||
currentTab={currentTab}
|
||||
/>
|
||||
</Suspense>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import variables from 'config/variables';
|
||||
import { memo, useState, useEffect } from 'react';
|
||||
import { getIconComponent, DIVIDER_LABELS, MUE_TITLE_LABELS } from '../constants/tabConfig';
|
||||
import { getIconComponent, DIVIDER_LABELS } from '../constants/tabConfig';
|
||||
|
||||
function Tab({ label, currentTab, onClick, navbarTab }) {
|
||||
const [isExperimental, setIsExperimental] = useState(true);
|
||||
@@ -15,9 +15,6 @@ function Tab({ label, currentTab, onClick, navbarTab }) {
|
||||
// Determine if this label should have a divider after it
|
||||
const hasDivider = DIVIDER_LABELS.some((key) => variables.getMessage(key) === label);
|
||||
|
||||
// Determine if this label should have "Mue" title before it
|
||||
const hasMueTitle = MUE_TITLE_LABELS.some((key) => variables.getMessage(key) === label);
|
||||
|
||||
// Build className
|
||||
const baseClass = navbarTab ? 'navbar-item' : 'tab-list-item';
|
||||
const activeClass = navbarTab ? 'navbar-item-active' : 'tab-list-active';
|
||||
@@ -32,7 +29,6 @@ function Tab({ label, currentTab, onClick, navbarTab }) {
|
||||
|
||||
return (
|
||||
<>
|
||||
{hasMueTitle && <span className="mainTitle">Mue</span>}
|
||||
<button className={className} onClick={() => onClick(label)}>
|
||||
{IconComponent && <IconComponent />} <span>{label}</span>
|
||||
</button>
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import variables from 'config/variables';
|
||||
import { useState } from 'react';
|
||||
import Tab from './Tab';
|
||||
import ModalNavbar from '../components/ModalNavbar';
|
||||
import ReminderInfo from '../components/ReminderInfo';
|
||||
import ErrorBoundary from '../../../../features/misc/modals/ErrorBoundary';
|
||||
import { TAB_TYPES } from '../constants/tabConfig';
|
||||
|
||||
const Tabs = ({ children, changeTab, current, navbar = false }) => {
|
||||
const Tabs = ({ children, navbar = false, currentTab: activeTab }) => {
|
||||
const [currentTab, setCurrentTab] = useState(children[0]?.props.label);
|
||||
const [currentName, setCurrentName] = useState(children[0]?.props.name);
|
||||
const [showReminder, setShowReminder] = useState(localStorage.getItem('showReminder') === 'true');
|
||||
@@ -24,22 +24,26 @@ const Tabs = ({ children, changeTab, current, navbar = false }) => {
|
||||
setShowReminder(false);
|
||||
};
|
||||
|
||||
// Only show sidebar for Settings tab
|
||||
const showSidebar = activeTab === TAB_TYPES.SETTINGS;
|
||||
|
||||
return (
|
||||
<div style={{ display: 'flex', width: '100%', minHeight: '100%' }}>
|
||||
<div className="modalSidebar">
|
||||
{children.map((tab, index) => (
|
||||
<Tab
|
||||
key={index}
|
||||
currentTab={currentTab}
|
||||
label={tab.props.label}
|
||||
onClick={(nextTab) => handleTabClick(nextTab, tab.props.name)}
|
||||
navbarTab={navbar}
|
||||
/>
|
||||
))}
|
||||
<ReminderInfo isVisible={showReminder} onHide={handleHideReminder} />
|
||||
</div>
|
||||
{showSidebar && (
|
||||
<div className="modalSidebar">
|
||||
{children.map((tab, index) => (
|
||||
<Tab
|
||||
key={index}
|
||||
currentTab={currentTab}
|
||||
label={tab.props.label}
|
||||
onClick={(nextTab) => handleTabClick(nextTab, tab.props.name)}
|
||||
navbarTab={navbar}
|
||||
/>
|
||||
))}
|
||||
<ReminderInfo isVisible={showReminder} onHide={handleHideReminder} />
|
||||
</div>
|
||||
)}
|
||||
<div className="modalTabContent">
|
||||
<ModalNavbar currentTab={current} onChangeTab={changeTab} />
|
||||
{children.map((tab, index) => {
|
||||
if (tab.props.label !== currentTab) {
|
||||
return null;
|
||||
|
||||
40
src/components/Elements/MainModal/components/ModalTopBar.jsx
Normal file
40
src/components/Elements/MainModal/components/ModalTopBar.jsx
Normal file
@@ -0,0 +1,40 @@
|
||||
import variables from 'config/variables';
|
||||
import { MdClose } from 'react-icons/md';
|
||||
import { Tooltip, Button } from 'components/Elements';
|
||||
import { NAVBAR_BUTTONS } from '../constants/tabConfig';
|
||||
|
||||
function ModalTopBar({ currentTab, onTabChange, onClose }) {
|
||||
return (
|
||||
<div className="modalTopBar">
|
||||
<div className="topBarLeft">
|
||||
<img
|
||||
src="src/assets/icons/mue_about.png"
|
||||
alt="Mue"
|
||||
className="topBarLogo"
|
||||
draggable={false}
|
||||
/>
|
||||
</div>
|
||||
<div className="topBarRight">
|
||||
<div className="topBarNavigation">
|
||||
{NAVBAR_BUTTONS.map(({ tab, icon: Icon, messageKey }) => (
|
||||
<Button
|
||||
key={tab}
|
||||
type="navigation"
|
||||
onClick={() => onTabChange(tab)}
|
||||
active={currentTab === tab}
|
||||
icon={<Icon />}
|
||||
label={variables.getMessage(messageKey)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<Tooltip title={variables.getMessage('modals.welcome.buttons.close')} key="closeTooltip">
|
||||
<span className="closeModal" onClick={onClose}>
|
||||
<MdClose />
|
||||
</span>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default ModalTopBar;
|
||||
@@ -28,15 +28,15 @@ import {
|
||||
// Tab type constants
|
||||
export const TAB_TYPES = {
|
||||
SETTINGS: 'settings',
|
||||
ADDONS: 'addons',
|
||||
MARKETPLACE: 'marketplace',
|
||||
LIBRARY: 'library',
|
||||
DISCOVER: 'discover',
|
||||
};
|
||||
|
||||
// Icon component mapping - using component references instead of elements
|
||||
export const ICON_COMPONENTS = {
|
||||
SETTINGS: MdSettings,
|
||||
ADDONS: MdWidgets,
|
||||
MARKETPLACE: MdShoppingBasket,
|
||||
LIBRARY: MdWidgets,
|
||||
DISCOVER: MdShoppingBasket,
|
||||
NAVBAR: MdMenu,
|
||||
GREETING: MdEmojiPeople,
|
||||
TIME: MdAccessAlarm,
|
||||
@@ -64,8 +64,8 @@ export const ICON_COMPONENTS = {
|
||||
export const MESSAGE_KEYS = {
|
||||
OVERVIEW: 'modals.main.marketplace.product.overview',
|
||||
SETTINGS: 'modals.main.navbar.settings',
|
||||
ADDONS: 'modals.main.navbar.addons',
|
||||
MARKETPLACE: 'modals.main.navbar.marketplace',
|
||||
LIBRARY: 'modals.main.navbar.library',
|
||||
DISCOVER: 'modals.main.navbar.discover',
|
||||
NAVBAR: 'modals.main.settings.sections.appearance.navbar.title',
|
||||
GREETING: 'modals.main.settings.sections.greeting.title',
|
||||
TIME: 'modals.main.settings.sections.time.title',
|
||||
@@ -98,8 +98,8 @@ export const getIconComponent = (label, variables) => {
|
||||
const iconMap = {
|
||||
[variables.getMessage(MESSAGE_KEYS.OVERVIEW)]: ICON_COMPONENTS.OVERVIEW,
|
||||
[variables.getMessage(MESSAGE_KEYS.SETTINGS)]: ICON_COMPONENTS.SETTINGS,
|
||||
[variables.getMessage(MESSAGE_KEYS.ADDONS)]: ICON_COMPONENTS.ADDONS,
|
||||
[variables.getMessage(MESSAGE_KEYS.MARKETPLACE)]: ICON_COMPONENTS.MARKETPLACE,
|
||||
[variables.getMessage(MESSAGE_KEYS.LIBRARY)]: ICON_COMPONENTS.LIBRARY,
|
||||
[variables.getMessage(MESSAGE_KEYS.DISCOVER)]: ICON_COMPONENTS.DISCOVER,
|
||||
[variables.getMessage(MESSAGE_KEYS.NAVBAR)]: ICON_COMPONENTS.NAVBAR,
|
||||
[variables.getMessage(MESSAGE_KEYS.GREETING)]: ICON_COMPONENTS.GREETING,
|
||||
[variables.getMessage(MESSAGE_KEYS.TIME)]: ICON_COMPONENTS.TIME,
|
||||
@@ -119,7 +119,7 @@ export const getIconComponent = (label, variables) => {
|
||||
[variables.getMessage(MESSAGE_KEYS.ABOUT)]: ICON_COMPONENTS.ABOUT,
|
||||
[variables.getMessage(MESSAGE_KEYS.ADDED)]: ICON_COMPONENTS.ADDED,
|
||||
[variables.getMessage(MESSAGE_KEYS.CREATE)]: ICON_COMPONENTS.CREATE,
|
||||
[variables.getMessage(MESSAGE_KEYS.ALL_MARKETPLACE)]: ICON_COMPONENTS.ADDONS,
|
||||
[variables.getMessage(MESSAGE_KEYS.ALL_MARKETPLACE)]: ICON_COMPONENTS.LIBRARY,
|
||||
[variables.getMessage(MESSAGE_KEYS.PHOTO_PACKS)]: ICON_COMPONENTS.BACKGROUND,
|
||||
[variables.getMessage(MESSAGE_KEYS.QUOTE_PACKS)]: ICON_COMPONENTS.QUOTE,
|
||||
[variables.getMessage(MESSAGE_KEYS.PRESET_SETTINGS)]: ICON_COMPONENTS.ADVANCED,
|
||||
@@ -137,14 +137,14 @@ export const NAVBAR_BUTTONS = [
|
||||
messageKey: 'modals.main.navbar.settings',
|
||||
},
|
||||
{
|
||||
tab: TAB_TYPES.ADDONS,
|
||||
icon: ICON_COMPONENTS.ADDONS,
|
||||
messageKey: 'modals.main.navbar.addons',
|
||||
tab: TAB_TYPES.LIBRARY,
|
||||
icon: ICON_COMPONENTS.LIBRARY,
|
||||
messageKey: 'modals.main.navbar.library',
|
||||
},
|
||||
{
|
||||
tab: TAB_TYPES.MARKETPLACE,
|
||||
icon: ICON_COMPONENTS.MARKETPLACE,
|
||||
messageKey: 'modals.main.navbar.marketplace',
|
||||
tab: TAB_TYPES.DISCOVER,
|
||||
icon: ICON_COMPONENTS.DISCOVER,
|
||||
messageKey: 'modals.main.navbar.discover',
|
||||
},
|
||||
];
|
||||
|
||||
@@ -155,10 +155,3 @@ export const DIVIDER_LABELS = [
|
||||
'modals.main.marketplace.all',
|
||||
'modals.main.settings.sections.experimental.title',
|
||||
];
|
||||
|
||||
// Labels that should have "Mue" title before them
|
||||
export const MUE_TITLE_LABELS = [
|
||||
'modals.main.marketplace.product.overview',
|
||||
'modals.main.addons.added',
|
||||
'modals.main.marketplace.all',
|
||||
];
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
@use 'sass:map';
|
||||
@use 'scss/variables' as *;
|
||||
@use 'modules/topBar' as *;
|
||||
@use 'modules/sidebar' as *;
|
||||
@use 'modules/navbar' as *;
|
||||
@use 'modules/modalTabContent' as *;
|
||||
|
||||
@@ -13,14 +13,6 @@
|
||||
height: 80vh;
|
||||
min-width: 250px;
|
||||
|
||||
.mainTitle {
|
||||
text-align: center;
|
||||
font-size: 35px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 25px;
|
||||
}
|
||||
|
||||
svg {
|
||||
margin-left: 20px;
|
||||
margin-right: 20px;
|
||||
|
||||
53
src/components/Elements/MainModal/scss/modules/_topBar.scss
Normal file
53
src/components/Elements/MainModal/scss/modules/_topBar.scss
Normal file
@@ -0,0 +1,53 @@
|
||||
@use 'scss/variables' as *;
|
||||
|
||||
.modalTopBar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 1.5rem 1.5rem;
|
||||
// width: 100%;
|
||||
|
||||
.topBarLeft {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
|
||||
.topBarLogo {
|
||||
height: 32px;
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.topBarRight {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
flex-shrink: 0;
|
||||
|
||||
.topBarNavigation {
|
||||
display: flex;
|
||||
flex-flow: row;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.closeModal {
|
||||
display: grid;
|
||||
place-items: center;
|
||||
padding: 0.4em;
|
||||
border-radius: 12px;
|
||||
cursor: pointer;
|
||||
transition: 0.5s;
|
||||
flex-shrink: 0;
|
||||
|
||||
svg {
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
@include themed {
|
||||
background: t($modal-sidebarActive);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user