Files
dydx-v4-web/src/components/WithSidebar.tsx
T
Jared Vu 1a41ccaf2a Liquid Staking CTA (#281)
* 🚧 feat(token-page): Scaffold sidebar components for token page

* 🚧 feat(staking/governance): Scaffold adding Panels to Staking and Governance page

*  Update and add icons

* 🧱 Add strideZoneApp to shared config

* 🧱 Add dialogs, update ExternalLinkDialog

* 🚧 Add New Panels/Update paths

* Fix mobile Profile Panel

* 💄 fix desktop padding

*  Add New tag

* 💄 Highlight tag on StrideStakingPanel

* 💄 Single columns for panels on mobile breakpoint

* 💄 fix import nits and alignment nits on panels

* Add circular keplr icon
2024-02-07 11:17:54 -08:00

204 lines
5.2 KiB
TypeScript

import React from 'react';
import { useDispatch, useSelector } from 'react-redux';
import styled, { type AnyStyledComponent, keyframes } from 'styled-components';
import { ButtonShape, ButtonSize } from '@/constants/buttons';
import { STRING_KEYS } from '@/constants/localization';
import { useStringGetter } from '@/hooks';
import { breakpoints } from '@/styles';
import { layoutMixins } from '@/styles/layoutMixins';
import { ToggleButton } from '@/components/ToggleButton';
import { Icon, IconName } from '@/components/Icon';
import { setIsSidebarOpen } from '@/state/layout';
import { getIsSidebarOpen } from '@/state/layoutSelectors';
type ElementProps = {
children: React.ReactNode;
sidebar: React.ReactNode;
};
export type WithSidebarProps = ElementProps;
export const WithSidebar: React.FC<WithSidebarProps> = ({ children, sidebar }) => {
const dispatch = useDispatch();
const isSidebarOpen = useSelector(getIsSidebarOpen);
const stringGetter = useStringGetter();
return (
<Styled.Container data-state={!sidebar ? 'none' : isSidebarOpen ? 'open' : 'closed'}>
{sidebar && (
<Styled.Side>
<Styled.TriggerButton
shape={ButtonShape.Pill}
size={isSidebarOpen ? ButtonSize.XSmall : ButtonSize.Base}
isPressed={!isSidebarOpen}
onPressedChange={(isPressed: boolean) => dispatch(setIsSidebarOpen(!isPressed))}
>
{isSidebarOpen ? (
stringGetter({ key: STRING_KEYS.HIDE })
) : (
<Icon iconName={IconName.Menu} />
)}
</Styled.TriggerButton>
<Styled.Sidebar data-state={isSidebarOpen ? 'open' : 'closed'}>{sidebar}</Styled.Sidebar>
</Styled.Side>
)}
<Styled.Content>{children}</Styled.Content>
</Styled.Container>
);
};
const Styled: Record<string, AnyStyledComponent> = {};
Styled.Container = styled.div`
/* Params */
--withSidebar-containerWidth: 100vw;
--withSidebar-open-sidebarWidth: var(--sidebar-width);
--withSidebar-closed-sidebarWidth: var(--collapsed-sidebar-width);
--withSidebar-gap: var(--border-width);
/* Computed */
--withSidebar-current-sidebarWidth: 0px;
--withSidebar-current-contentAreaWidth: calc(
var(--withSidebar-containerWidth) - var(--withSidebar-gap) -
var(--withSidebar-current-sideAreaWidth)
);
&[data-state='none'] {
--withSidebar-open-sideAreaWidth: 0px;
--withSidebar-closed-sideAreaWidth: 0px;
}
&[data-state='open'] {
--withSidebar-current-sidebarWidth: var(--withSidebar-open-sidebarWidth);
}
&[data-state='closed'] {
--withSidebar-current-sidebarWidth: var(--withSidebar-closed-sidebarWidth);
}
@media ${breakpoints.notTablet} {
/* Dynamic sidebarArea, open sidebar shrinks contentArea */
--withSidebar-current-sideAreaWidth: var(--withSidebar-current-sidebarWidth);
/* prettier-ignore */
--withSidebar-gridTemplate:
'Side Content' 100%
/ auto 1fr;
}
@media ${breakpoints.tablet} {
/* No sidebar */
--withSidebar-current-sideAreaWidth: 0px;
/* prettier-ignore */
--withSidebar-gridTemplate:
'Content' 100%
/ 1fr;
}
/* Rules */
${layoutMixins.stickyArea1}
--stickyArea1-leftWidth: var(--withSidebar-current-sideAreaWidth);
--stickyArea1-leftGap: var(--border-width);
min-height: var(--stickyArea-height);
display: grid;
grid-template: var(--withSidebar-gridTemplate);
`;
Styled.Side = styled.aside`
grid-area: Side;
${layoutMixins.container}
${layoutMixins.sticky}
max-height: var(--stickyArea-height);
backdrop-filter: none;
background-color: var(--color-layer-2);
${layoutMixins.stack}
`;
Styled.Sidebar = styled.div`
--current-sidebar-width: var(--sidebar-width);
${layoutMixins.scrollArea}
width: min(var(--withSidebar-current-sidebarWidth), var(--withSidebar-containerWidth));
transition: var(--ease-out-expo) 0.3s;
transform: perspective(62.5em);
transform-origin: left top;
&[data-state='closed'] {
--current-sidebar-width: var(--collapsed-sidebar-width);
opacity: 0;
pointer-events: none;
transform: perspective(62.5em) translateZ(-12.5em);
}
${layoutMixins.sticky}
&:hover {
will-change: width;
}
`;
Styled.TriggerButton = styled(ToggleButton)`
--button-toggle-on-backgroundColor: transparent;
place-self: start end;
z-index: 2;
min-width: 0;
min-height: 0;
&[data-state='off'] {
margin: 0.75rem;
@media (prefers-reduced-motion: no-preference) {
animation: ${keyframes`
10%, 40% {
opacity: 0;
scale: 0;
}
`} 0.2s;
}
}
&[data-state='on'] {
--button-border: none;
--button-radius: 0;
min-width: 100%;
min-height: 100%;
outline-color: transparent;
@media (prefers-reduced-motion: no-preference) {
transition: var(--ease-out-expo) 0.25s;
animation: ${keyframes`
20% {
opacity: 0;
scale: 0;
}
`} 0.2s;
}
}
`;
Styled.Content = styled.article`
grid-area: Content;
${layoutMixins.contentContainerPage}
--content-container-width: var(--withSidebar-current-contentAreaWidth);
${layoutMixins.stickyArea2}
transition: var(--ease-out-expo) 0.25s;
`;