Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/overlay redesign #965

Merged
merged 3 commits into from
Oct 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion src/components/@widgets/SwapWidget/SwapWidget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -658,7 +658,6 @@ const SwapWidget: FC = () => {
</ButtonContainer>

<Overlay
hasDynamicHeight
isHidden={!showTokenSelectModalFor}
title={t("common.selectToken")}
onClose={() => setShowTokenSelectModalFor(null)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ const AvailableOrdersWidget = ({
});

const sortedOrders = useMemo(() => {
if (!bestRfqOrder) {
return [];
}

const ordersToSort: (FullOrderERC20 | OrderERC20)[] = [...orders];

if (
Expand Down Expand Up @@ -108,6 +112,10 @@ const AvailableOrdersWidget = ({
});
};

if (!senderToken || !signerToken) {
return <div />;
}

return (
<Container>
<AvailableOrdersList
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import styled from "styled-components/macro";
import { OverlayActionButton } from "../../../Overlay/Overlay.styles";

export const Container = styled.div`
padding-bottom: 2rem;
padding-bottom: 3rem;
`;

export const StyledCloseButton = styled(OverlayActionButton)`
margin-top: 1.5rem;
margin-top: 3rem;
`;
59 changes: 17 additions & 42 deletions src/components/Overlay/Overlay.styles.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { motion } from "framer-motion";
import { css } from "styled-components";
import styled from "styled-components/macro";

Expand All @@ -11,8 +10,9 @@ import { InfoSubHeading } from "../Typography/Typography";
import { StyledH3 } from "../Typography/Typography.styles";

type ContainerProps = {
hasOverflow: boolean;
isHidden: boolean;
hasDynamicHeight: boolean;
showScrollbar: boolean;
hasTitle: boolean;
};

Expand Down Expand Up @@ -41,46 +41,29 @@ export const ScrollContainer = styled.div<ScrollContainerProps>`
${ScrollBarStyle};
`;

export const ContentContainer = styled(motion.div)`
export const ContentContainer = styled.div<{ isHidden: boolean }>`
position: relative;
border: 1px solid ${(props) => props.theme.colors.borderGrey};
border-radius: 2rem;
margin-block-end: 2rem;
width: calc(100vw - 4rem);
max-width: 38.75rem;
height: fit-content;
max-height: 47.5rem;
min-height: 30rem;
padding: 0 ${sizes.tradeContainerPadding};
backdrop-filter: blur(25px);

background: rgba(57, 122, 255, 0.11);
transform: translateY(${(props) => (props.isHidden ? "100vh" : "0vh")});
pointer-events: ${(props) => (props.isHidden ? "none" : "visible")};
transition: transform ease-out 0.3s;
@media ${breakPoints.phoneOnly} {
padding: 0 ${sizes.tradeContainerMobilePadding};
}

&::before {
content: "";
display: block;
position: absolute;
top: 0;
left: 0;
border-radius: 2rem;
width: 100%;
height: 100%;
background: ${(props) => props.theme.colors.darkBlue};
filter: brightness(0.5);
opacity: 0.8;
pointer-events: none;
z-index: -1;
}
`;

export const TitleContainer = styled.div`
display: flex;
align-items: center;
flex-direction: row;
justify-content: space-between;
margin-block-end: 1rem;
margin-block-end: 2rem;
padding-block-start: ${sizes.tradeContainerPadding};
transition: background ease-in-out 0.3s;

Expand Down Expand Up @@ -131,32 +114,24 @@ export const OverlayActionButton = styled(Button)`
${OverlayActionButtonStyle};
`;

const containerDynamicHeightStyle = css`
padding-block-start: 0;

@media (max-height: 700px) {
padding-block-start: 2rem;
}

@media (min-height: 800px) {
margin-block-start: -2rem;
}
`;

export const Container = styled.div<ContainerProps>`
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: ${(props) => (props.hasDynamicHeight ? "auto" : "100%")};
padding-block-start: 2rem;
height: 100svh;
padding-block: 2rem;
overflow-y: ${(props) => (props.showScrollbar ? "auto" : "hidden")};;
pointer-events: ${(props) => (props.isHidden ? "none" : "visible")};
z-index: 2;

${(props) => props.hasDynamicHeight && containerDynamicHeightStyle};
background: ${(props) =>
props.isHidden ? "rgba(0, 0, 0, 0);" : "rgba(0, 0, 0, 0.5)"};
backdrop-filter: ${(props) => (props.isHidden ? "none" : "blur(25px)")};
z-index: 10;
transition: background ease-out 0.3s;
}
`;

Expand Down
105 changes: 56 additions & 49 deletions src/components/Overlay/Overlay.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import { FC, useContext, useEffect, useState } from "react";
import { FC, useContext, useEffect, useRef, useState } from "react";
import { createPortal } from "react-dom";
import { useTranslation } from "react-i18next";

import { AnimatePresence, useReducedMotion } from "framer-motion";
import { useWindowSize } from "usehooks-ts";

import { InterfaceContext } from "../../contexts/interface/Interface";
import useDebounce from "../../hooks/useDebounce";
import useElementSize from "../../hooks/useElementSize";
import useIsOverflowing from "../../hooks/useIsOverflowing";
import { useKeyPress } from "../../hooks/useKeyPress";
import CloseButton from "../../styled-components/CloseButton/CloseButton";
import {
Container,
StyledTitle,
Expand Down Expand Up @@ -44,27 +47,31 @@ export const overlayShowHideAnimationDuration = 0.3;
const Overlay: FC<OverlayProps> = ({
onClose,
title = "",
hasDynamicHeight = false,
isHidden = true,
subTitle = "",
shouldAnimate = true,
children,
className = "",
}) => {
const { t } = useTranslation();
const shouldReduceMotion = useReducedMotion();
const [initialized, setInitialized] = useState(false);
const animationIsDisabled = !shouldAnimate || (!isHidden && !initialized);
const ref = useRef<HTMLDivElement>(null);
const contentRef = useRef<HTMLDivElement>(null);

const { setShowOverlay } = useContext(InterfaceContext);
const { showOverlay, setShowOverlay } = useContext(InterfaceContext);
const [isAnimatedOut, setIsAnimatedOut] = useState(false);
const { height: containerHeight } = useWindowSize();
const { height: contentHeight } = useElementSize(contentRef);
const paddingBlock = 32;
const contentY = Math.max(
0,
(containerHeight - paddingBlock * 2 - contentHeight) / 2
);

useKeyPress(onClose, ["Escape"]);

useEffect(() => {
setInitialized(true);
}, []);
setIsAnimatedOut(false);

useEffect(() => {
if (isHidden) {
setShowOverlay(false);
}
Expand All @@ -74,55 +81,55 @@ const Overlay: FC<OverlayProps> = ({
() => {
// Make sure the animation ended before setting the showOverlay state
setShowOverlay(!isHidden);

if (isHidden) {
setIsAnimatedOut(true);
}
},
250,
[isHidden]
);

return (
return createPortal(
<Container
hasDynamicHeight={hasDynamicHeight}
ref={ref}
hasTitle={!!title}
hasOverflow={!contentY}
isHidden={isHidden}
showScrollbar={!!showOverlay && !isHidden}
style={{
visibility: isAnimatedOut ? "hidden" : "visible",
}}
className={className}
>
<AnimatePresence>
{!isHidden && (
<ContentContainer
key="content"
transition={{
ease: "easeOut",
duration:
shouldReduceMotion || animationIsDisabled
? 0
: overlayShowHideAnimationDuration,
}}
initial={{ y: "100vh" }}
animate={{ y: "0%" }}
exit={{ y: "100vh" }}
>
<TitleContainer>
<TitleSubContainer>
<StyledTitle type="h2" as="h1">
{title}
</StyledTitle>
{!!subTitle && (
<StyledInfoSubHeading>{subTitle}</StyledInfoSubHeading>
)}
</TitleSubContainer>
<StyledCloseButton
icon="exit-modal"
ariaLabel={t("common.back")}
iconSize={1}
tabIndex={isHidden ? -1 : 0}
onClick={onClose}
/>
</TitleContainer>
{children}
</ContentContainer>
)}
</AnimatePresence>
</Container>
<ContentContainer
isHidden={isHidden}
ref={contentRef}
style={{
marginTop: `${contentY}px`,
}}
>
<TitleContainer>
<TitleSubContainer>
<StyledTitle type="h2" as="h1">
{title}
</StyledTitle>
{!!subTitle && (
<StyledInfoSubHeading>{subTitle}</StyledInfoSubHeading>
)}
</TitleSubContainer>
<StyledCloseButton
icon="exit-modal"
ariaLabel={t("common.back")}
iconSize={1}
tabIndex={isHidden ? -1 : 0}
onClick={onClose}
/>
</TitleContainer>
{children}
</ContentContainer>
</Container>,
document.getElementById("root") as HTMLElement
);
};

Expand Down
15 changes: 9 additions & 6 deletions src/components/Page/Page.styles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export const InnerContainer = styled.div<{ $isScrollLocked?: boolean }>`
position: relative;
width: 100%;
height: 100%;
flex-grow: 1;

@media ${breakPoints.phoneOnly}, ${breakPoints.shallowScreenOnly} {
justify-content: flex-start;
Expand All @@ -24,25 +25,27 @@ export const InnerContainer = styled.div<{ $isScrollLocked?: boolean }>`
}
`;

export const StyledPage = styled.div`
export const StyledPage = styled.div<{ showOverlay?: boolean }>`
display: flex;
flex-direction: column;
position: relative;
min-width: 18rem;
height: 100vh;
min-height: 37.5rem;
min-height: 100vh;
min-height: 100svh;
max-height: ${(props) => (props.showOverlay ? "100vh" : "unset")};
overflow-x: hidden;
overflow-y: ${(props) => (props.showOverlay ? "hidden" : "unset")};

@media (min-height: 29rem) and (max-width: ${breakpointSizes.phone}) {
display: flex;
flex-direction: column;
justify-content: center;
height: 100vh;
padding-top: 0;
padding-bottom: 0;
}

@media ${breakPoints.phoneOnly} {
width: 100%;
height: 100vh;
min-height: ${sizes.widgetMobileSize};
padding: 0 ${sizes.pageMobilePadding};
}
`;
Expand Down
2 changes: 1 addition & 1 deletion src/components/Page/Page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ const Page: FC<PageProps> = ({ children, className }): ReactElement => {
}, []);

return (
<StyledPage style={{ height: `${pageHeight}px` }} className={className}>
<StyledPage showOverlay={showOverlay} className={className}>
<HelmetContainer title={t("app.title")} />
<InnerContainer>
<Toaster open={transactionsTabIsOpen} />
Expand Down
2 changes: 1 addition & 1 deletion src/components/TransactionsTab/TransactionsTab.styles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export const Container = styled(motion.div)`
display: flex;
flex-direction: column;
width: 100%;
max-width: ${sizes.widgetMobileSize};
max-width: ${sizes.widgetMobileWidth};
height: 100%;
padding: 1.5rem 1.5rem 0;
background-color: ${(props) => props.theme.colors.black};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export const StyledWalletProviderList = styled.div`
display: flex;
flex-direction: column;
margin-block-start: 3rem;
padding-block-end: 2rem;
padding-block-end: 3rem;
`;

export const TitleContainer = styled.div`
Expand Down
Loading
Loading