Skip to content

Commit

Permalink
perf: Memo menu components
Browse files Browse the repository at this point in the history
  • Loading branch information
RabbitDoge committed Mar 2, 2021
1 parent 9a3b5c8 commit ba47f13
Show file tree
Hide file tree
Showing 12 changed files with 177 additions and 106 deletions.
24 changes: 12 additions & 12 deletions src/__tests__/widgets/menu.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ it("renders correctly", () => {
class="sc-kEjbxe fnkFQx"
>
<div
class="sc-fubCfw hswJXu"
class="sc-fubCfw ivOlsg"
role="button"
>
<a
Expand Down Expand Up @@ -239,7 +239,7 @@ it("renders correctly", () => {
class="sc-pFZIQ kJqcph"
>
<div
class="sc-fubCfw duwseR"
class="sc-fubCfw bRGoVr"
role="button"
>
<svg
Expand Down Expand Up @@ -277,7 +277,7 @@ it("renders correctly", () => {
/>
</div>
<div
class="sc-fubCfw duwseR"
class="sc-fubCfw bRGoVr"
role="button"
>
<a
Expand Down Expand Up @@ -315,7 +315,7 @@ it("renders correctly", () => {
</a>
</div>
<div
class="sc-fubCfw duwseR"
class="sc-fubCfw bRGoVr"
role="button"
>
<a
Expand Down Expand Up @@ -345,7 +345,7 @@ it("renders correctly", () => {
</a>
</div>
<div
class="sc-fubCfw duwseR"
class="sc-fubCfw bRGoVr"
role="button"
>
<a
Expand All @@ -372,7 +372,7 @@ it("renders correctly", () => {
</a>
</div>
<div
class="sc-fubCfw duwseR"
class="sc-fubCfw bRGoVr"
role="button"
>
<a
Expand Down Expand Up @@ -400,7 +400,7 @@ it("renders correctly", () => {
class="sc-pFZIQ kJqcph"
>
<div
class="sc-fubCfw duwseR rainbow"
class="sc-fubCfw bRGoVr rainbow"
role="button"
>
<svg
Expand Down Expand Up @@ -439,7 +439,7 @@ it("renders correctly", () => {
class="sc-pFZIQ kJqcph"
>
<div
class="sc-fubCfw duwseR"
class="sc-fubCfw bRGoVr"
role="button"
>
<svg
Expand Down Expand Up @@ -483,7 +483,7 @@ it("renders correctly", () => {
class="sc-pFZIQ kJqcph"
>
<div
class="sc-fubCfw duwseR"
class="sc-fubCfw bRGoVr"
role="button"
>
<svg
Expand Down Expand Up @@ -522,7 +522,7 @@ it("renders correctly", () => {
class="sc-pFZIQ kJqcph"
>
<div
class="sc-fubCfw duwseR"
class="sc-fubCfw bRGoVr"
role="button"
>
<svg
Expand Down Expand Up @@ -559,10 +559,10 @@ it("renders correctly", () => {
</div>
</div>
<div
class="sc-bkzZxe jfJWEE"
class="sc-idOhPF bXwMqE"
>
<button
class="sc-eCssSg bcQvse sc-fFubgz gudwLA"
class="sc-eCssSg bcQvse sc-iqHYGH iOsNjo"
scale="md"
>
<svg
Expand Down
5 changes: 3 additions & 2 deletions src/widgets/Menu/components/Accordion.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState } from "react";
import React, { ReactNode, useState } from "react";
import styled from "styled-components";
import { MENU_ENTRY_HEIGHT } from "../config";
import { MenuEntry, LinkLabel } from "./MenuEntry";
Expand All @@ -10,6 +10,7 @@ interface Props extends PushedProps {
icon: React.ReactElement;
initialOpenState?: boolean;
className?: string;
children: ReactNode;
}

const Container = styled.div`
Expand Down Expand Up @@ -66,4 +67,4 @@ const Accordion: React.FC<Props> = ({
);
};

export default Accordion;
export default React.memo(Accordion, (prev, next) => prev.isPushed === next.isPushed);
35 changes: 35 additions & 0 deletions src/widgets/Menu/components/CakePrice.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import React from "react";
import styled from "styled-components";
import { PancakeRoundIcon } from "../../../components/Svg";
import Text from "../../../components/Text/Text";
import Skeleton from "../../../components/Skeleton/Skeleton";

interface Props {
cakePriceUsd?: number;
}

const PriceLink = styled.a`
display: flex;
align-items: center;
svg {
transition: transform 0.3s;
}
:hover {
svg {
transform: scale(1.2);
}
}
`;

const CakePrice: React.FC<Props> = ({ cakePriceUsd }) => {
return cakePriceUsd ? (
<PriceLink href="https://pancakeswap.info/token/0x0e09fabb73bd3ade0a17ecc321fd13a19e81ce82" target="_blank">
<PancakeRoundIcon width="24px" mr="8px" />
<Text color="textSubtle" bold>{`$${cakePriceUsd.toFixed(3)}`}</Text>
</PriceLink>
) : (
<Skeleton width={80} height={24} />
);
};

export default React.memo(CakePrice);
42 changes: 42 additions & 0 deletions src/widgets/Menu/components/LangSelector.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import React from "react";
import { SvgProps } from "../../../components/Svg";
import Text from "../../../components/Text/Text";
import Dropdown from "../../../components/Dropdown/Dropdown";
import Button from "../../../components/Button/Button";
import * as IconModule from "../icons";
import { LangType } from "../types";
import MenuButton from "./MenuButton";

const Icons = (IconModule as unknown) as { [key: string]: React.FC<SvgProps> };
const { LanguageIcon } = Icons;

interface Props {
currentLang: string;
langs: LangType[];
setLang: (lang: LangType) => void;
}

const LangSelector: React.FC<Props> = ({ currentLang, langs, setLang }) => (
<Dropdown
position="top-right"
target={
<Button variant="text" startIcon={<LanguageIcon color="textSubtle" width="24px" />}>
<Text color="textSubtle">{currentLang?.toUpperCase()}</Text>
</Button>
}
>
{langs.map((lang) => (
<MenuButton
key={lang.code}
fullWidth
onClick={() => setLang(lang)}
// Safari fix
style={{ minHeight: "32px", height: "auto" }}
>
{lang.language}
</MenuButton>
))}
</Dropdown>
);

export default React.memo(LangSelector, (prev, next) => prev.currentLang === next.currentLang);
2 changes: 1 addition & 1 deletion src/widgets/Menu/components/Logo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,4 @@ const Logo: React.FC<Props> = ({ isPushed, togglePush, isDark, href }) => {
);
};

export default Logo;
export default React.memo(Logo, (prev, next) => prev.isPushed === next.isPushed && prev.isDark === next.isDark);
6 changes: 5 additions & 1 deletion src/widgets/Menu/components/MenuEntry.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import React from "react";
import styled, { keyframes, DefaultTheme } from "styled-components";
import { MENU_ENTRY_HEIGHT } from "../config";

Expand Down Expand Up @@ -65,4 +66,7 @@ MenuEntry.defaultProps = {
role: "button",
};

export { MenuEntry, LinkLabel };
const MenuEntryMemo = React.memo(MenuEntry, () => true);
const LinkLabelMemo = React.memo(LinkLabel, () => true);

export { MenuEntryMemo as MenuEntry, LinkLabelMemo as LinkLabel };
2 changes: 1 addition & 1 deletion src/widgets/Menu/components/MenuLink.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ const MenuLink: React.FC<AnchorHTMLAttributes<HTMLAnchorElement>> = ({ href, ...
return <Tag {...props} {...otherProps} />;
};

export default MenuLink;
export default React.memo(MenuLink, () => true);
97 changes: 10 additions & 87 deletions src/widgets/Menu/components/PanelFooter.tsx
Original file line number Diff line number Diff line change
@@ -1,43 +1,23 @@
import React from "react";
import styled from "styled-components";
import { PancakeRoundIcon, CogIcon, SvgProps } from "../../../components/Svg";
import Text from "../../../components/Text/Text";
import Flex from "../../../components/Box/Flex";
import Dropdown from "../../../components/Dropdown/Dropdown";
import Link from "../../../components/Link/Link";
import Skeleton from "../../../components/Skeleton/Skeleton";
import Button from "../../../components/Button/Button";
import { CogIcon } from "../../../components/Svg";
import IconButton from "../../../components/Button/IconButton";
import MenuButton from "./MenuButton";
import * as IconModule from "../icons";
import { socials, MENU_ENTRY_HEIGHT } from "../config";
import { MENU_ENTRY_HEIGHT } from "../config";
import { PanelProps, PushedProps } from "../types";
import CakePrice from "./CakePrice";
import ThemeSwitcher from "./ThemeSwitcher";
import SocialLinks from "./SocialLinks";
import LangSelector from "./LangSelector";

interface Props extends PanelProps, PushedProps {}

const Icons = (IconModule as unknown) as { [key: string]: React.FC<SvgProps> };
const { MoonIcon, SunIcon, LanguageIcon } = Icons;

const Container = styled.div`
flex: none;
padding: 8px 4px;
background-color: ${({ theme }) => theme.nav.background};
border-top: solid 2px rgba(133, 133, 133, 0.1);
`;

const PriceLink = styled.a`
display: flex;
align-items: center;
svg {
transition: transform 0.3s;
}
:hover {
svg {
transform: scale(1.2);
}
}
`;

const SettingsEntry = styled.div`
display: flex;
align-items: center;
Expand Down Expand Up @@ -77,69 +57,12 @@ const PanelFooter: React.FC<Props> = ({
return (
<Container>
<SocialEntry>
{cakePriceUsd ? (
<PriceLink href="https://pancakeswap.info/token/0x0e09fabb73bd3ade0a17ecc321fd13a19e81ce82" target="_blank">
<PancakeRoundIcon width="24px" mr="8px" />
<Text color="textSubtle" bold>{`$${cakePriceUsd.toFixed(3)}`}</Text>
</PriceLink>
) : (
<Skeleton width={80} height={24} />
)}
<Flex>
{socials.map((social, index) => {
const Icon = Icons[social.icon];
const iconProps = { width: "24px", color: "textSubtle", style: { cursor: "pointer" } };
const mr = index < socials.length - 1 ? "24px" : 0;
if (social.items) {
return (
<Dropdown key={social.label} position="top" target={<Icon {...iconProps} mr={mr} />}>
{social.items.map((item) => (
<Link external key={item.label} href={item.href} aria-label={item.label} color="textSubtle">
{item.label}
</Link>
))}
</Dropdown>
);
}
return (
<Link external key={social.label} href={social.href} aria-label={social.label} mr={mr}>
<Icon {...iconProps} />
</Link>
);
})}
</Flex>
<CakePrice cakePriceUsd={cakePriceUsd} />
<SocialLinks />
</SocialEntry>
<SettingsEntry>
<Button variant="text" onClick={() => toggleTheme(!isDark)}>
{/* alignItems center is a Safari fix */}
<Flex alignItems="center">
<SunIcon color={isDark ? "textDisabled" : "text"} width="24px" />
<Text color="textDisabled" mx="4px">
/
</Text>
<MoonIcon color={isDark ? "text" : "textDisabled"} width="24px" />
</Flex>
</Button>
<Dropdown
position="top-right"
target={
<Button variant="text" startIcon={<LanguageIcon color="textSubtle" width="24px" />}>
<Text color="textSubtle">{currentLang?.toUpperCase()}</Text>
</Button>
}
>
{langs.map((lang) => (
<MenuButton
key={lang.code}
fullWidth
onClick={() => setLang(lang)}
// Safari fix
style={{ minHeight: "32px", height: "auto" }}
>
{lang.language}
</MenuButton>
))}
</Dropdown>
<ThemeSwitcher isDark={isDark} toggleTheme={toggleTheme} />
<LangSelector currentLang={currentLang} langs={langs} setLang={setLang} />
</SettingsEntry>
</Container>
);
Expand Down
37 changes: 37 additions & 0 deletions src/widgets/Menu/components/SocialLinks.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React from "react";
import { SvgProps } from "../../../components/Svg";
import Flex from "../../../components/Box/Flex";
import Dropdown from "../../../components/Dropdown/Dropdown";
import Link from "../../../components/Link/Link";
import * as IconModule from "../icons";
import { socials } from "../config";

const Icons = (IconModule as unknown) as { [key: string]: React.FC<SvgProps> };

const SocialLinks: React.FC = () => (
<Flex>
{socials.map((social, index) => {
const Icon = Icons[social.icon];
const iconProps = { width: "24px", color: "textSubtle", style: { cursor: "pointer" } };
const mr = index < socials.length - 1 ? "24px" : 0;
if (social.items) {
return (
<Dropdown key={social.label} position="top" target={<Icon {...iconProps} mr={mr} />}>
{social.items.map((item) => (
<Link external key={item.label} href={item.href} aria-label={item.label} color="textSubtle">
{item.label}
</Link>
))}
</Dropdown>
);
}
return (
<Link external key={social.label} href={social.href} aria-label={social.label} mr={mr}>
<Icon {...iconProps} />
</Link>
);
})}
</Flex>
);

export default React.memo(SocialLinks, () => true);

0 comments on commit ba47f13

Please sign in to comment.