Improved navigation significantly on mobile

Affects issues:
- Close #2228
This commit is contained in:
Aurora Lahtela 2023-02-03 20:29:03 +02:00
parent 12d22f945f
commit 413e087c4d
7 changed files with 112 additions and 43 deletions

View File

@ -1,6 +1,7 @@
import './style/main.sass';
import './style/sb-admin-2.css'
import './style/style.css';
import './style/mobile.css';
import {BrowserRouter, Navigate, Route, Routes} from "react-router-dom";
import React from "react";

View File

@ -30,7 +30,7 @@ const Visualizer = ({option, groups, colors, name}) => {
const VisualizerSelector = ({onClick, icon}) => {
return (
<button className="btn float-end" onClick={onClick}>
<button className="btn float-end visualizer-button" onClick={onClick}>
<FontAwesomeIcon icon={icon} className="col-gray"/>
</button>
)

View File

@ -60,7 +60,7 @@ const Contributor = ({contributor}) => {
const icons = contributor.contributed.map(
(type, i) => <Fa key={i} icon={["fa", getContributionIcon(type)]}/>);
return (
<li className="col-4">{contributor.name} {icons} </li>
<li className="contributor">{contributor.name} {icons} </li>
)
}

View File

@ -42,7 +42,7 @@ const Header = ({page, tab, hideUpdater}) => {
const headImageUrl = user ? getPlayerHeadImageUrl(user.playerName, user.linkedToUuid) : undefined
// TODO Remove .replace('<', '') after locale replacement
return (
<nav className="nav mt-3 align-items-center justify-content-between container-fluid">
<nav className="nav-header nav mt-3 align-items-center justify-content-between container-fluid">
<div className="d-sm-flex">
<h1 className="h3 mb-0 text-gray-800">
<button onClick={toggleSidebar}>

View File

@ -24,7 +24,7 @@ const Divider = ({showMargin}) => (
<hr className={"sidebar-divider" + (showMargin ? '' : " my-0")}/>
)
const InnerItem = ({href, icon, name, nameShort, color, external}) => {
const InnerItem = ({href, icon, name, nameShort, color, external, collapseSidebar}) => {
if (!href) {
return (<hr className={"nav-servers dropdown-divider mx-3 my-2"}/>)
}
@ -38,14 +38,14 @@ const InnerItem = ({href, icon, name, nameShort, color, external}) => {
)
}
return <NavLink to={href} className={({isActive}) => {
return <NavLink to={href} onClick={collapseSidebar} className={({isActive}) => {
return isActive ? "collapse-item nav-button active" : "collapse-item nav-button"
}}>
<Fa icon={icon} className={color ? "col-" + color : undefined}/> <span>{nameShort ? nameShort : name}</span>
</NavLink>
}
export const Item = ({item, inner}) => {
export const Item = ({item, inner, collapseSidebar}) => {
const {setCurrentTab} = useNavigation();
const {pathname} = useLocation();
const {t} = useTranslation();
@ -58,7 +58,7 @@ export const Item = ({item, inner}) => {
if (inner) {
return (<InnerItem href={href} icon={icon} name={t(name)} nameShort={t(nameShort)} color={color}
external={external}/>)
external={external} collapseSidebar={collapseSidebar}/>)
}
if (external) {
@ -74,7 +74,7 @@ export const Item = ({item, inner}) => {
return (
<li className={"nav-item nav-button"}>
<NavLink to={href} className={({isActive}) => {
<NavLink to={href} onClick={collapseSidebar} className={({isActive}) => {
return isActive ? "nav-link active" : "nav-link"
}}>
<Fa icon={icon} className={color ? "col-" + color : undefined}/> <span>{t(name)}</span>
@ -95,36 +95,19 @@ const VersionButton = ({toggleVersionModal, versionInfo}) => {
</button>;
}
const FooterButtons = () => {
const FooterButtons = ({collapseSidebar, toggleInfoModal, toggleVersionModal, versionInfo}) => {
const {t} = useTranslation();
const {toggleColorChooser} = useTheme();
const openColorChooser = useCallback(() => {
toggleColorChooser();
collapseSidebar();
}, [toggleColorChooser, collapseSidebar]);
const {authRequired} = useAuth();
const [infoModalOpen, setInfoModalOpen] = useState(false);
const toggleInfoModal = () => setInfoModalOpen(!infoModalOpen);
const [versionModalOpen, setVersionModalOpen] = useState(false);
const toggleVersionModal = () => setVersionModalOpen(!versionModalOpen);
const [versionInfo, setVersionInfo] = useState({currentVersion: 'Loading..', updateAvailable: false});
const loadVersion = async () => {
const {data, error} = await fetchPlanVersion();
if (data) {
setVersionInfo(data);
} else if (error) {
setVersionInfo({currentVersion: "Error getting version", updateAvailable: false})
}
}
useEffect(() => {
loadVersion();
}, [])
return (
<>
<div className={"footer-buttons"}>
<div className="mt-2 ms-md-3 text-center text-md-start">
<button className="btn bg-transparent-light" onClick={toggleColorChooser}
<button className="btn bg-transparent-light" onClick={openColorChooser}
title={t('html.label.themeSelect')}>
<Fa icon={faPalette}/>
</button>
@ -140,13 +123,11 @@ const FooterButtons = () => {
<div className="ms-md-3 text-center text-md-start">
<VersionButton toggleVersionModal={toggleVersionModal} versionInfo={versionInfo}/>
</div>
<PluginInformationModal open={infoModalOpen} toggle={toggleInfoModal}/>
<VersionInformationModal open={versionModalOpen} toggle={toggleVersionModal} versionInfo={versionInfo}/>
</>
</div>
)
}
const SidebarCollapse = ({item, open, setOpen}) => {
const SidebarCollapse = ({item, open, setOpen, collapseSidebar}) => {
const {t} = useTranslation();
const toggle = event => {
event.preventDefault();
@ -174,6 +155,7 @@ const SidebarCollapse = ({item, open, setOpen}) => {
inner
active={false}
item={content}
collapseSidebar={collapseSidebar}
/>)}
</div>
</div>
@ -182,18 +164,20 @@ const SidebarCollapse = ({item, open, setOpen}) => {
)
}
const renderItem = (item, i, openCollapse, setOpenCollapse, t) => {
const renderItem = (item, i, openCollapse, setOpenCollapse, t, windowWidth, collapseSidebar) => {
if (item.contents) {
return <SidebarCollapse key={i}
item={item}
open={openCollapse && openCollapse === i}
setOpen={() => setOpenCollapse(i)}/>
open={windowWidth < 660 || (openCollapse && openCollapse === i)}
setOpen={() => setOpenCollapse(i)}
collapseSidebar={collapseSidebar}/>
}
if (item.href !== undefined) {
return <Item key={i}
active={false}
item={item}
collapseSidebar={collapseSidebar}
/>
}
@ -220,8 +204,41 @@ const Sidebar = ({page, items}) => {
return () => window.removeEventListener('resize', updateWidth);
}, [updateWidth]);
const collapseSidebar = () => setSidebarExpanded(windowWidth > 1350);
useEffect(collapseSidebar, [windowWidth, currentTab, setSidebarExpanded]);
const collapseSidebar = useCallback(() => {
setSidebarExpanded(windowWidth > 1350);
if (windowWidth < 660) {
window.scrollTo({top: 0});
}
}, [setSidebarExpanded, windowWidth]);
const collapseConditionallyOnItemClick = useCallback(() => {
if (windowWidth < 660) {
setTimeout(collapseSidebar, 10);
}
}, [collapseSidebar, windowWidth]);
useEffect(collapseSidebar, [windowWidth, currentTab, setSidebarExpanded, collapseSidebar]);
const [infoModalOpen, setInfoModalOpen] = useState(false);
const toggleInfoModal = useCallback(() => {
setInfoModalOpen(!infoModalOpen);
collapseConditionallyOnItemClick();
}, [setInfoModalOpen, infoModalOpen, collapseConditionallyOnItemClick]);
const [versionModalOpen, setVersionModalOpen] = useState(false);
const toggleVersionModal = useCallback(() => {
setVersionModalOpen(!versionModalOpen);
collapseConditionallyOnItemClick();
}, [setVersionModalOpen, versionModalOpen, collapseConditionallyOnItemClick]);
const [versionInfo, setVersionInfo] = useState({currentVersion: 'Loading..', updateAvailable: false});
const loadVersion = async () => {
const {data, error} = await fetchPlanVersion();
if (data) {
setVersionInfo(data);
} else if (error) {
setVersionInfo({currentVersion: "Error getting version", updateAvailable: false})
}
}
useEffect(() => loadVersion(), []);
return (
<>
@ -230,10 +247,17 @@ const Sidebar = ({page, items}) => {
<Logo/>
<PageNavigationItem page={page}/>
<Divider showMargin={items.length && !items[0].contents && items[0].href === undefined}/>
{items.length ? items.filter(item => item !== undefined).map((item, i) => renderItem(item, i, openCollapse, toggleCollapse, t)) : ''}
{items.length ? items.filter(item => item !== undefined).map((item, i) => renderItem(item, i, openCollapse, toggleCollapse, t, windowWidth, collapseConditionallyOnItemClick)) : ''}
<Divider/>
<FooterButtons/>
<FooterButtons
collapseSidebar={collapseConditionallyOnItemClick}
toggleInfoModal={toggleInfoModal}
toggleVersionModal={toggleVersionModal}
versionInfo={versionInfo}
/>
</ul>}
<PluginInformationModal open={infoModalOpen} toggle={toggleInfoModal}/>
<VersionInformationModal open={versionModalOpen} toggle={toggleVersionModal} versionInfo={versionInfo}/>
</>
)
}

View File

@ -0,0 +1,40 @@
@media (max-width: 660px) {
.w-22 {
width: unset !important;
height: 4rem;
}
#wrapper {
font-size: small;
background-image: var(--color-theme);
}
.sidebar {
position: absolute;
padding-top: 1rem;
width: calc(100vw - 1rem) !important;
padding-right: 0.15rem;
z-index: 9999;
height: 100%;
}
.sidebar .nav-item .nav-link {
width: 100%;
}
.nav-header {
margin-top: 0.75rem !important;
}
.nav-header > * {
margin-top: 0.5rem;
}
.visualizer-button {
padding: 0.25rem;
}
.contributor {
width: 50%;
}
}

View File

@ -1424,4 +1424,8 @@ ul.filters {
display: flex;
min-height: 100vh;
background-image: linear-gradient(to right, var(--color-theme) 0%, var(--color-theme) 14rem, #f8f9fc 14.01rem, #f8f9fc 100%);
}
.contributor {
width: 33%;
}