From 7b0e16f0aee714f374f8f0cf0d4d7a2c6a19fa77 Mon Sep 17 00:00:00 2001
From: lubej <9722540+lubej@users.noreply.github.com>
Date: Wed, 5 Jul 2023 14:34:28 +0200
Subject: [PATCH] Replace network select
---
src/app/components/Select/index.tsx | 85 +++++++--
.../HomePage/Graph/NetworkSelector/index.tsx | 177 +++++++++++-------
.../HomePage/Graph/ParaTimeSelector/index.tsx | 2 +-
src/stories/ButtonsShowroom.stories.tsx | 8 -
4 files changed, 172 insertions(+), 100 deletions(-)
diff --git a/src/app/components/Select/index.tsx b/src/app/components/Select/index.tsx
index 083baf43f4..e292f0c5ad 100644
--- a/src/app/components/Select/index.tsx
+++ b/src/app/components/Select/index.tsx
@@ -1,6 +1,6 @@
import SelectUnstyled, { SelectProps, selectClasses, SelectRootSlotProps } from '@mui/base/Select'
import Option, { optionClasses } from '@mui/base/Option'
-import Popper from '@mui/base/Popper'
+import Popper, { PopperPlacementType } from '@mui/base/Popper'
import { styled } from '@mui/material/styles'
import Box from '@mui/material/Box'
import {
@@ -21,8 +21,11 @@ import ExpandLessIcon from '@mui/icons-material/ExpandLess'
import ExpandMoreIcon from '@mui/icons-material/ExpandMore'
import { COLORS } from '../../../styles/theme/colors'
import { useTranslation } from 'react-i18next'
+import { WithOptionalOwnerState } from '@mui/base/utils'
+import { SelectPopperSlotProps, SelectSlots } from '@mui/base/Select/Select.types'
+import * as React from 'react'
-const StyledButton = styled(Button)(({ theme }) => ({
+export const StyledSelectButton = styled(Button)(({ theme }) => ({
height: '36px',
minWidth: '135px',
padding: `0 ${theme.spacing(4)}`,
@@ -35,7 +38,7 @@ const StyledButton = styled(Button)(({ theme }) => ({
},
}))
-const StyledListbox = styled('ul')(({ theme }) => ({
+export const StyledSelectListbox = styled('ul')(({ theme }) => ({
boxSizing: 'border-box',
padding: theme.spacing(0),
margin: `${theme.spacing(3)} ${theme.spacing(0)}`,
@@ -47,7 +50,7 @@ const StyledListbox = styled('ul')(({ theme }) => ({
filter: 'drop-shadow(0px 4px 4px rgba(0, 0, 0, 0.25))',
}))
-const StyledOption = styled(Option)(({ theme }) => ({
+export const StyledSelectOption = styled(Option)(({ theme }) => ({
display: 'flex',
alignItems: 'center',
boxSizing: 'border-box',
@@ -85,28 +88,48 @@ const TertiaryButton = forwardRef(
const { t } = useTranslation()
return (
-
+
{children ? children : t('select.placeholder')}
{ownerState.open ? : }
-
+
)
},
)
const CustomSelect = forwardRef(function CustomSelect(
- props: SelectProps,
+ {
+ root,
+ listbox,
+ popper,
+ placement,
+ ...restProps
+ }: SelectProps & SelectSlots & Partial>,
ref: ForwardedRef,
) {
const slots: SelectProps['slots'] = {
- root: TertiaryButton,
- listbox: StyledListbox,
- popper: StyledPopper,
- ...props.slots,
+ root,
+ listbox,
+ popper,
+ ...restProps.slots,
}
- return
+ return (
+
+ )
}) as (
- props: SelectProps & RefAttributes,
+ props: SelectProps &
+ SelectSlots &
+ Partial> &
+ RefAttributes,
) => JSX.Element
export interface SelectOptionBase {
@@ -114,11 +137,23 @@ export interface SelectOptionBase {
value: string | number
}
+const SelectOption = ({ value, label }: T): ReactElement => (
+
+ {label}
+
+)
+
interface SelectCmpProps {
label?: string
options: T[]
defaultValue?: T['value']
handleChange?: (selectedOption: T['value'] | null) => void
+ placement?: PopperPlacementType
+ className?: string
+ root?: React.ElementType
+ Option?: typeof SelectOption | undefined
+ listbox?: React.ElementType
+ popper?: React.ComponentType>>
}
const SelectCmp = ({
@@ -126,6 +161,12 @@ const SelectCmp = ({
options,
defaultValue,
handleChange,
+ placement = 'bottom-start',
+ className,
+ root = TertiaryButton,
+ listbox = StyledSelectListbox,
+ popper = StyledPopper,
+ Option = SelectOption,
}: SelectCmpProps): ReactElement => {
const selectId = useId()
@@ -137,17 +178,23 @@ const SelectCmp = ({
)
return (
-
+
{label && (
)}
- id={selectId} defaultValue={defaultValue} onChange={onChange}>
- {options.map(({ label, value }) => (
-
- {label}
-
+
+ id={selectId}
+ defaultValue={defaultValue}
+ onChange={onChange}
+ root={root}
+ listbox={listbox}
+ popper={popper}
+ placement={placement}
+ >
+ {options.map((props: T) => (
+
))}
diff --git a/src/app/pages/HomePage/Graph/NetworkSelector/index.tsx b/src/app/pages/HomePage/Graph/NetworkSelector/index.tsx
index 48b0b3a130..dbf5e23be3 100644
--- a/src/app/pages/HomePage/Graph/NetworkSelector/index.tsx
+++ b/src/app/pages/HomePage/Graph/NetworkSelector/index.tsx
@@ -1,100 +1,133 @@
-import { FC, useState } from 'react'
+import { FC, ForwardedRef, forwardRef, ReactElement } from 'react'
import { useTranslation } from 'react-i18next'
-import { useTheme } from '@mui/material/styles'
-import { useScreenSize } from '../../../../hooks/useScreensize'
-import AddIcon from '@mui/icons-material/Add'
import Box from '@mui/material/Box'
-import Button from '@mui/material/Button'
-import IconButton from '@mui/material/IconButton'
-import RemoveIcon from '@mui/icons-material/Remove'
import Typography from '@mui/material/Typography'
import { styled } from '@mui/material/styles'
import { COLORS } from '../../../../../styles/theme/colors'
import { getNetworkNames, Network } from '../../../../../types/network'
-import Collapse from '@mui/material/Collapse'
import { RouteUtils } from '../../../../utils/route-utils'
+import {
+ Select,
+ SelectOptionBase,
+ StyledSelectButton,
+ StyledSelectListbox,
+ StyledSelectOption,
+} from '../../../../components/Select'
+import { SelectRootSlotProps } from '@mui/base/Select'
+import ExpandLessIcon from '@mui/icons-material/ExpandLess'
+import ExpandMoreIcon from '@mui/icons-material/ExpandMore'
+import { getNetworkIcons } from '../../../../utils/content'
+import { optionClasses } from '@mui/base/Option'
-const StyledNetworkSelector = styled(Box)(() => ({
+interface NetworkOption extends SelectOptionBase {
+ label: Network
+ value: Network
+}
+
+const StyledNetworkSelector = styled(Select)(({ theme }) => ({
position: 'absolute',
- bottom: 0,
+ bottom: theme.spacing(5),
display: 'flex',
width: '100%',
justifyContent: 'center',
}))
-const StyledBox = styled(Box)(({ theme }) => ({
+const StyledButton = styled(StyledSelectButton)(({ theme }) => ({
+ height: '44px',
+ minWidth: '200px',
backgroundColor: theme.palette.layout.primaryBackground,
- border: `solid 3px ${theme.palette.layout.lightBorder}`,
- borderRadius: '45px',
- padding: `${theme.spacing(3)} ${theme.spacing(4)}`,
- display: 'inline-flex',
- alignItems: 'center',
+ border: `2px solid ${theme.palette.layout.lightBorder}`,
+ color: theme.palette.layout.main,
+ '&:hover': {
+ backgroundColor: theme.palette.layout.primaryBackground,
+ },
}))
-export const SelectNetworkButton = styled(Button, {
- shouldForwardProp: prop => prop !== 'isSelectedNetwork',
-})<{ isSelectedNetwork: boolean }>(({ isSelectedNetwork, theme }) => ({
- height: '30px',
- padding: `${theme.spacing(2)} ${theme.spacing(3)}`,
- textTransform: 'capitalize',
- fontSize: '16px',
- borderRadius: '9px',
- backgroundColor: isSelectedNetwork
- ? theme.palette.layout.primaryBackground
- : theme.palette.layout.secondary,
- borderColor: isSelectedNetwork ? theme.palette.layout.hoverBorder : theme.palette.layout.secondary,
- borderWidth: theme.spacing(1),
- color: theme.palette.layout.main,
- '&:hover, &:focus-visible': {
- backgroundColor: theme.palette.layout.secondary,
- borderWidth: theme.spacing(1),
- borderColor: COLORS.white,
+const StyledListbox = styled(StyledSelectListbox)(() => ({
+ minWidth: '200px',
+ background: COLORS.white,
+ color: COLORS.grayDark,
+}))
+
+const StyledOption = styled(StyledSelectOption)(() => ({
+ height: '44px',
+ color: COLORS.grayDark,
+ svg: {
+ color: COLORS.grayExtraDark,
+ },
+ [`&:hover:not(.${optionClasses.disabled}),
+ &.${optionClasses.highlighted}`]: {
+ backgroundColor: 'transparent',
},
}))
-SelectNetworkButton.defaultProps = {
- size: 'small',
- variant: 'outlined',
- sx: { ml: 4 },
+
+const SelectOption = ({ value }: NetworkOption): ReactElement => {
+ const { t } = useTranslation()
+
+ const labels = getNetworkNames(t)
+ const icons = getNetworkIcons()
+
+ return (
+
+ ({ display: 'flex', gap: theme.spacing(3), pl: theme.spacing(3), alignItems: 'center' })}
+ >
+ {icons[value]}
+ {labels[value]}
+
+
+ )
}
-type NetworkSelectorProps = {
+const NetworkSelectorButton = forwardRef(
+ (props: SelectRootSlotProps, ref: ForwardedRef) => {
+ const { ownerState, ...restProps } = props
+ const { open, value } = ownerState
+ // Expecting value as Network
+ const networkValue = value as Network
+ const { t } = useTranslation()
+ const label = getNetworkNames(t)
+ const icons = getNetworkIcons()
+
+ return (
+
+ ({
+ display: 'flex',
+ gap: theme.spacing(3),
+ pl: theme.spacing(3),
+ alignItems: 'center',
+ })}
+ >
+ {icons[networkValue]}
+ {label[networkValue]}
+
+ {open ? : }
+
+ )
+ },
+)
+
+interface NetworkSelectProps {
network: Network
- setNetwork: (network: Network) => void
+ setNetwork: (network: Network | null) => void
}
-export const NetworkSelector: FC = ({ network, setNetwork }) => {
- const { t } = useTranslation()
- const theme = useTheme()
- const { isMobile } = useScreenSize()
- const [open, setOpen] = useState(false)
- const options: Network[] = RouteUtils.getEnabledNetworks()
- const labels = getNetworkNames(t)
+export const NetworkSelector: FC = ({ network, setNetwork }) => {
+ const options = RouteUtils.getEnabledNetworks().map(network => ({
+ label: network,
+ value: network,
+ }))
return (
-
-
- {!isMobile && (
-
- {t('home.selectNetwork')}
-
- )}
-
- {options.map(option => (
-
- setNetwork(option)} isSelectedNetwork={option === network}>
- {labels[option]}
-
-
- ))}
-
- setOpen(!open)}>
- {open ? (
-
- ) : (
-
- )}
-
-
-
+
)
}
diff --git a/src/app/pages/HomePage/Graph/ParaTimeSelector/index.tsx b/src/app/pages/HomePage/Graph/ParaTimeSelector/index.tsx
index bc4768922f..29db46d6f4 100644
--- a/src/app/pages/HomePage/Graph/ParaTimeSelector/index.tsx
+++ b/src/app/pages/HomePage/Graph/ParaTimeSelector/index.tsx
@@ -260,7 +260,7 @@ const ParaTimeSelectorCmp: FC = ({
)}
{step === ParaTimeSelectorStep.Explore && (
-
+ setNetwork(network ?? Network.mainnet)} />
)}
{activeMobileGraphTooltip.current && (
diff --git a/src/stories/ButtonsShowroom.stories.tsx b/src/stories/ButtonsShowroom.stories.tsx
index 2beb629e1b..72e86cad86 100644
--- a/src/stories/ButtonsShowroom.stories.tsx
+++ b/src/stories/ButtonsShowroom.stories.tsx
@@ -7,8 +7,6 @@ import { GetStartedBtn } from '../app/pages/HomePage/Graph/HelpScreen'
import { ViewResultButton } from '../app/pages/SearchResultsPage/ResultsGroupByType'
import { LoadMoreButton } from '../app/components/LoadMoreButton'
import { withRouter } from 'storybook-addon-react-router-v6'
-import { SelectNetworkButton } from '../app/pages/HomePage/Graph/NetworkSelector'
-import { NetworkButton } from '../app/components/PageLayout/NetworkButton'
import WidgetsIcon from '@mui/icons-material/Widgets'
export default {
@@ -37,12 +35,6 @@ const Template: StoryFn = () => {
- SelectNetworkButton
- {}} />
-
-
-
-
'', selectedPage: 1 }} />
)