Skip to content

Commit 7add72d

Browse files
authored
refactor(appmenu): small refactor (#1206)
2 parents b2cc2e0 + 61f5c6a commit 7add72d

File tree

21 files changed

+147
-185
lines changed

21 files changed

+147
-185
lines changed
Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
.circle {
22
position: fixed;
33
bottom: 0px;
4-
z-index: -1;
54
width: 220px;
65
height: 220px;
76
display: inline-flex;
87
border-radius: 50%;
8+
z-index: 4;
9+
pointer-events: none;
910
}
1011

1112
.menu {
@@ -20,34 +21,35 @@
2021

2122
.menu li {
2223
grid-area: 1/1;
23-
transform: rotate(calc(var(--r) + var(--delta))) translateX(var(--diameter))
24-
rotate(calc(-1 * (var(--r) + var(--delta))));
24+
transform: rotate(calc(var(--rotation-angle) + var(--delta)))
25+
translateX(var(--diameter))
26+
rotate(calc(-1 * (var(--rotation-angle) + var(--delta))));
2527
}
2628

2729
.menu li:nth-child(1) {
28-
--r: calc(-5 * var(--i));
30+
--rotation-angle: calc(-5 * var(--i));
2931
}
3032

3133
.menu li:nth-child(2) {
32-
--r: calc(-4 * var(--i));
34+
--rotation-angle: calc(-4 * var(--i));
3335
}
3436

3537
.menu li:nth-child(3) {
36-
--r: calc(-3 * var(--i));
38+
--rotation-angle: calc(-3 * var(--i));
3739
}
3840

3941
.menu li:nth-child(4) {
40-
--r: calc(-2 * var(--i));
42+
--rotation-angle: calc(-2 * var(--i));
4143
}
4244

4345
.menu li:nth-child(5) {
44-
--r: calc(-1 * var(--i));
46+
--rotation-angle: calc(-1 * var(--i));
4547
}
4648

4749
.menu li:nth-child(6) {
48-
--r: calc(0 * var(--i));
50+
--rotation-angle: calc(0 * var(--i));
4951
}
5052

5153
.menu li:nth-child(7) {
52-
--r: calc(1 * var(--i));
54+
--rotation-angle: calc(1 * var(--i));
5355
}

src/components/appMenu/CircularMenu.tsx renamed to src/components/appMenu/CircularMenu/CircularMenu.tsx

Lines changed: 7 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
1-
import { useState, useEffect } from 'react';
2-
import itemsMenu from 'src/utils/appsMenu';
1+
import getMenuItems from 'src/utils/appsMenu';
32
import styles from './CircularMenu.module.scss';
4-
import { MenuItem } from 'src/types/menu';
5-
import { useLocation } from 'react-router-dom';
63
import _ from 'lodash';
74
import CircularMenuItem from './CircularMenuItem';
5+
import { useActiveMenuItem } from 'src/hooks/useActiveMenuItem';
86

97
declare module 'react' {
108
interface CSSProperties {
@@ -15,43 +13,18 @@ declare module 'react' {
1513
}
1614

1715
function CircularMenu({ circleSize }) {
18-
const [activeItem, setActiveItem] = useState<MenuItem | null>(null);
1916
const chunkSize = 7;
20-
const linkChunks = _.chunk(itemsMenu(), chunkSize);
21-
const location = useLocation();
17+
const linkChunks = _.chunk(getMenuItems(), chunkSize);
18+
19+
const { isActiveItem, activeItem } = useActiveMenuItem(getMenuItems());
2220

2321
const calculateDiameter = (index, circleSize) => {
2422
const menuCircleDiameter = circleSize / 2 + 45 * (index + 1) - 10;
2523
const nextLevelMenuAngle = index === 1 ? -28 : 0; // decreases the angle of second menu layer
26-
const menuItemsAngle = index === 1 ? 16 : 23; // angle in wich menu items spreads around brain
24+
const menuItemsAngle = index === 1 ? 16 : 23; // angle in which menu items spread around the brain
2725
return { menuCircleDiameter, nextLevelMenuAngle, menuItemsAngle };
2826
};
2927

30-
const isActiveItem = (item: MenuItem) => {
31-
if (location.pathname === item.to) {
32-
return true;
33-
}
34-
if (
35-
item.to === '/robot' &&
36-
(location.pathname.includes('@') || location.pathname.includes('neuron/'))
37-
) {
38-
return true;
39-
}
40-
if (item.to === '/senate' && location.pathname.startsWith('/senate/')) {
41-
return true;
42-
}
43-
return item.subItems?.some((subItem) => location.pathname === subItem.to);
44-
};
45-
46-
useEffect(() => {
47-
const activeMenuItem = itemsMenu().find((item) => isActiveItem(item));
48-
setActiveItem(activeMenuItem || null);
49-
}, [location]);
50-
51-
const handleItemClick = (item: MenuItem) => {
52-
setActiveItem(item);
53-
};
54-
5528
return (
5629
<div>
5730
{linkChunks.map((chunk, index) => {
@@ -77,7 +50,7 @@ function CircularMenu({ circleSize }) {
7750
<li key={index}>
7851
<CircularMenuItem
7952
item={item}
80-
onClick={() => handleItemClick(item)}
53+
onClick={() => isActiveItem(item)}
8154
selected={isSelected}
8255
/>
8356
</li>

src/components/appMenu/CircularMenuItem.module.scss renamed to src/components/appMenu/CircularMenu/CircularMenuItem.module.scss

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
@import '../../style/mixins.scss';
1+
@import '../../../style/mixins.scss';
22

3-
.menu_item {
3+
.menuItem {
44
box-shadow: 0px 0px 13px #ffffff54;
55
opacity: 1;
66
background-color: #101010;
@@ -10,16 +10,17 @@
1010
justify-content: center;
1111
align-items: center;
1212
display: flex;
13+
pointer-events: auto;
1314
}
1415

15-
.menu_item.active {
16+
.menuItem.active {
1617
border: 1px solid #ffffff6b;
1718
box-shadow: 0px 0px 8px #ffffff98 inset, 0px 0px 13px #ffffff98;
1819
width: 100%;
1920
height: 100%;
2021
}
2122

22-
.menu_item:hover {
23+
.menuItem:hover {
2324
border: 1px solid #4ed6ae;
2425
box-shadow: 0px 0px 8px #4ed6ae inset, 0px 0px 13px #4ed6ae;
2526
}

src/components/appMenu/CircularMenuItem.tsx renamed to src/components/appMenu/CircularMenu/CircularMenuItem.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ function CircularMenuItem({ item, onClick, selected }: Props) {
1414
const isExternal = item.to.startsWith('http');
1515

1616
return (
17-
<div className={cx(styles.menu_item, { [styles.active]: selected })}>
17+
<div className={cx(styles.menuItem, { [styles.active]: selected })}>
1818
<AdviserHoverWrapper adviserContent={item.name}>
1919
<NavLink
2020
to={item.to}
@@ -26,7 +26,6 @@ function CircularMenuItem({ item, onClick, selected }: Props) {
2626
{isExternal && <span className={styles.external}></span>}
2727
</NavLink>
2828
</AdviserHoverWrapper>
29-
3029
</div>
3130
);
3231
}

src/components/appMenu/MobileMenu.tsx

Lines changed: 0 additions & 88 deletions
This file was deleted.

src/components/appMenu/MobileMenu.module.scss renamed to src/components/appMenu/MobileMenu/MobileMenu.module.scss

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
@import '../../style/mixins.scss';
1+
@import '../../../style/mixins.scss';
22

33
.mobileMenu {
44
position: fixed;
@@ -10,14 +10,7 @@
1010
justify-content: center;
1111
display: flex;
1212
justify-content: space-between;
13-
14-
&.closed {
15-
pointer-events: none;
16-
17-
.menuButton {
18-
pointer-events: auto;
19-
}
20-
}
13+
pointer-events: none;
2114

2215
&.open {
2316
pointer-events: auto;
@@ -40,6 +33,8 @@
4033
align-items: center;
4134
box-shadow: 0px 0px 13px #ffffff54;
4235

36+
pointer-events: auto;
37+
4338
&.active {
4439
border: 1px solid #ffffff6b;
4540
box-shadow: 0px 0px 8px #ffffff4d inset, 0px 0px 13px #ffffff4d;
@@ -59,6 +54,11 @@
5954
grid-template-rows: repeat(2, 1fr);
6055
grid-auto-flow: column;
6156
grid-gap: 20px;
57+
visibility: hidden;
58+
}
59+
60+
.visible {
61+
visibility: visible;
6262
}
6363

6464
.menuItem {
@@ -77,14 +77,6 @@
7777
}
7878
}
7979

80-
.visible {
81-
visibility: visible;
82-
}
83-
84-
.hidden {
85-
visibility: hidden;
86-
}
87-
8880
.external {
8981
display: block;
9082
position: absolute;
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import { useState, useRef } from 'react';
2+
import { NavLink } from 'react-router-dom';
3+
import getMenuItems from 'src/utils/appsMenu';
4+
import styles from './MobileMenu.module.scss';
5+
import cx from 'classnames';
6+
import useOnClickOutside from 'src/hooks/useOnClickOutside';
7+
import { useActiveMenuItem } from 'src/hooks/useActiveMenuItem';
8+
9+
const MobileMenu = () => {
10+
const [isOpen, setIsOpen] = useState(false);
11+
const menuRef = useRef<HTMLDivElement>(null);
12+
13+
const toggleMenu = () => setIsOpen(!isOpen);
14+
15+
const { isActiveItem, activeItem } = useActiveMenuItem(getMenuItems());
16+
17+
useOnClickOutside(menuRef, () => setIsOpen(false));
18+
19+
return (
20+
<div
21+
ref={menuRef}
22+
className={cx(styles.mobileMenu, { [styles.open]: isOpen })}
23+
>
24+
<div className={cx(styles.menuContent, { [styles.visible]: isOpen })}>
25+
<button
26+
className={cx(styles.menuButton, { [styles.active]: isOpen })}
27+
onClick={toggleMenu}
28+
>
29+
<img
30+
src={activeItem?.icon}
31+
className={styles.icon}
32+
alt={`${activeItem?.name} menu active icon`}
33+
/>
34+
</button>
35+
{getMenuItems().map((item, index) => {
36+
const isExternal = item.to.startsWith('http');
37+
return (
38+
!isActiveItem(item) && (
39+
<NavLink
40+
key={index}
41+
to={item.to}
42+
className={styles.menuItem}
43+
onClick={toggleMenu}
44+
{...(isExternal && {
45+
target: '_blank',
46+
rel: 'noreferrer noopener',
47+
})}
48+
>
49+
<img
50+
src={item.icon}
51+
className={styles.icon}
52+
alt={`${item.name} menu icon`}
53+
/>
54+
{isExternal && <span className={styles.external}></span>}
55+
</NavLink>
56+
)
57+
);
58+
})}
59+
</div>
60+
</div>
61+
);
62+
};
63+
64+
export default MobileMenu;

src/components/appMenu/SubMenu.module.scss renamed to src/components/appMenu/SubMenu/SubMenu.module.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,4 @@ $icon-size: 30px;
5151
@include active-el();
5252
}
5353
}
54-
}
54+
}

0 commit comments

Comments
 (0)