diff --git a/.changelog/580.trivial.md b/.changelog/580.trivial.md new file mode 100644 index 000000000..f5221243f --- /dev/null +++ b/.changelog/580.trivial.md @@ -0,0 +1 @@ +Update ParaTime picker based on internal feedback diff --git a/src/app/components/LayerStatus/index.tsx b/src/app/components/LayerStatus/index.tsx index cd6480b0e..dcd7bbb5a 100644 --- a/src/app/components/LayerStatus/index.tsx +++ b/src/app/components/LayerStatus/index.tsx @@ -2,6 +2,7 @@ import { FC } from 'react' import { useTranslation } from 'react-i18next' import CheckCircleIcon from '@mui/icons-material/CheckCircle' import ErrorIcon from '@mui/icons-material/Error' +import Tooltip from '@mui/material/Tooltip' import Typography from '@mui/material/Typography' import { COLORS } from '../../../styles/theme/colors' @@ -10,6 +11,17 @@ type LayerStatusProps = { withLabel?: boolean } +type OutOfDateLayerStatusIconProps = { + tooltip?: boolean +} + +const OutOfDateLayerStatusIcon: FC = ({ tooltip }) => { + const { t } = useTranslation() + const errorIcon = + + return tooltip ? {errorIcon} : errorIcon +} + export const LayerStatus: FC = ({ isOutOfDate, withLabel = false }) => { const { t } = useTranslation() @@ -25,7 +37,7 @@ export const LayerStatus: FC = ({ isOutOfDate, withLabel = fal )} {isOutOfDate ? ( - + ) : ( )} diff --git a/src/app/components/PageLayout/Header.tsx b/src/app/components/PageLayout/Header.tsx index 714044c07..4a5ecb2e9 100644 --- a/src/app/components/PageLayout/Header.tsx +++ b/src/app/components/PageLayout/Header.tsx @@ -1,4 +1,4 @@ -import { FC, useEffect, useRef } from 'react' +import { FC } from 'react' import AppBar from '@mui/material/AppBar' import Grid from '@mui/material/Unstable_Grid2' import useScrollTrigger from '@mui/material/useScrollTrigger' @@ -8,35 +8,18 @@ import { NetworkSelector } from './NetworkSelector' import Box from '@mui/material/Box' import { useScopeParam } from '../../hooks/useScopeParam' import { useScreenSize } from '../../hooks/useScreensize' -import useResizeObserver from 'use-resize-observer' export const Header: FC = () => { const theme = useTheme() - const { isMobile, isTablet } = useScreenSize() + const { isMobile } = useScreenSize() const scope = useScopeParam() const scrollTrigger = useScrollTrigger({ disableHysteresis: true, threshold: 0, }) - const headerRef = useRef(null) - - const { height: headerHeight } = useResizeObserver({ - ref: headerRef, - }) - - useEffect(() => { - if (!isTablet) { - return - } - - if (headerRef.current !== null) { - document.body.style.setProperty('--app-header-height', `${headerHeight?.toFixed(2) || 0}px`) - } - }, [isTablet, headerHeight]) return ( ({ transitionProperty: 'background-color, color', transitionDuration: `${theme.transitions.duration.standard}ms`, transitionTimingFunction: theme.transitions.easing.easeInOut, - height: '47px', - display: 'flex', - alignItems: 'center', padding: `0 ${theme.spacing(4)}`, - borderTopLeftRadius: '12px', - borderBottomLeftRadius: '12px', - borderRightWidth: theme.spacing(1), - borderRightStyle: 'solid', - borderRightColor: theme.palette.layout.secondary, - backgroundColor: COLORS.white, + margin: 0, }, [`& .${buttonClasses.endIcon}`]: { + transitionProperty: 'background-color, color', + transitionDuration: `${theme.transitions.duration.standard}ms`, + transitionTimingFunction: theme.transitions.easing.easeInOut, + height: '47px', + display: 'flex', + alignItems: 'center', padding: `0 ${theme.spacing(4)}`, + borderTopRightRadius: '12px', + borderBottomRightRadius: '12px', + borderLeftWidth: theme.spacing(1), + borderLeftStyle: 'solid', + borderLeftColor: theme.palette.layout.secondary, + backgroundColor: COLORS.white, }, '&:hover, &:focus-visible': { @@ -50,7 +54,7 @@ export const StyledNetworkButton = styled(Button)(({ theme }) => ({ color: COLORS.white, borderColor: theme.palette.layout.hoverBorder, - [`& .${buttonClasses.startIcon}`]: { + [`& .${buttonClasses.endIcon}`]: { color: COLORS.brandDark, backgroundColor: theme.palette.layout.secondaryBackground, borderColor: theme.palette.layout.hoverBorder, @@ -63,7 +67,6 @@ export const StyledBox = styled(Box)(({ theme }) => ({ display: 'flex', alignItems: 'center', gap: theme.spacing(3), - paddingLeft: theme.spacing(3), })) type NetworkButtonProps = { diff --git a/src/app/components/PageLayout/index.tsx b/src/app/components/PageLayout/index.tsx index 38587daf9..3253e6d05 100644 --- a/src/app/components/PageLayout/index.tsx +++ b/src/app/components/PageLayout/index.tsx @@ -1,4 +1,4 @@ -import { FC, PropsWithChildren, ReactNode, useEffect, useRef } from 'react' +import { FC, PropsWithChildren, ReactNode } from 'react' import { Header } from './Header' import { Footer } from './Footer' import Box from '@mui/material/Box' @@ -10,7 +10,6 @@ import { NetworkOfflineBanner, RuntimeOfflineBanner } from '../OfflineBanner' import { Search } from '../Search' import { useIsApiReachable } from '../OfflineBanner/hook' import { Network } from '../../../types/network' -import useResizeObserver from 'use-resize-observer' interface PageLayoutProps { mobileFooterAction?: ReactNode @@ -25,29 +24,12 @@ export const PageLayout: FC> = ({ children, m const { isMobile, isTablet } = useScreenSize() const scope = useScopeParam() const isApiReachable = useIsApiReachable(scope?.network || Network.mainnet).reachable - const bannersRef = useRef(null) - - const { height: bannersHeight } = useResizeObserver({ - ref: bannersRef, - }) - - useEffect(() => { - if (!isTablet) { - return - } - - if (bannersRef.current !== null) { - document.body.style.setProperty('--app-banners-height', `${bannersHeight?.toFixed(2) || 0}px`) - } - }, [isTablet, bannersHeight]) return ( <> - - - - {scope?.valid && } - + + + {scope?.valid && } ({ }, }) +export const StyledButton = styled(Button)(({ theme }) => ({ + height: 30, + paddingLeft: 0, + marginRight: theme.spacing(3), + fontSize: 24, + color: COLORS.brandDark, + fontWeight: 700, + '&&:hover, &&:active': { + color: COLORS.brandDark, + textDecoration: 'none', + }, +})) + type LayerDetailsProps = { - activeLayer: Layer + handleConfirm: () => void network: Network selectedLayer: Layer } @@ -78,10 +93,10 @@ type LayerDetailsProps = { // Prevent modal height from changing height when switching between layers const contentMinHeight = '270px' -export const LayerDetails: FC = ({ network, selectedLayer }) => { +export const LayerDetails: FC = ({ handleConfirm, network, selectedLayer }) => { const { t } = useTranslation() const theme = useTheme() - const { isTablet } = useScreenSize() + const { isMobile, isTablet } = useScreenSize() const labels = getNetworkNames(t) const layerLabels = getLayerLabels(t) const icons = getNetworkIcons() @@ -113,15 +128,15 @@ export const LayerDetails: FC = ({ network, selectedLayer }) sx={{ display: 'flex', alignItems: 'center', - pb: 2, + pb: 3, }} > - + {getNameForScope(t, { network, layer })} - - + + - + {details.description} @@ -161,7 +176,7 @@ export const LayerDetails: FC = ({ network, selectedLayer }) display: 'flex', alignItems: 'center', gap: 2, - fontSize: '12px', + fontSize: '14px', fontWeight: 400, }} > diff --git a/src/app/components/ParaTimePicker/LayerMenu.tsx b/src/app/components/ParaTimePicker/LayerMenu.tsx index e14cbf26b..889fd73ec 100644 --- a/src/app/components/ParaTimePicker/LayerMenu.tsx +++ b/src/app/components/ParaTimePicker/LayerMenu.tsx @@ -116,7 +116,7 @@ export const LayerMenu: FC = ({ .sort(orderByLayer) return ( - + {options.map((option, index) => { if (!option.enabled) { return ( diff --git a/src/app/components/ParaTimePicker/NetworkMenu.tsx b/src/app/components/ParaTimePicker/NetworkMenu.tsx index 29505531d..8d609ec84 100644 --- a/src/app/components/ParaTimePicker/NetworkMenu.tsx +++ b/src/app/components/ParaTimePicker/NetworkMenu.tsx @@ -85,7 +85,7 @@ export const NetworkMenu: FC = ({ activeNetwork, selectedNetwo return ( <> - + {stableOptions.map((network, index) => ( = ({ network }) => { - const icons = getNetworkIcons() - - return ( - - - {icons[network]} - - - ) -} diff --git a/src/app/components/ParaTimePicker/index.tsx b/src/app/components/ParaTimePicker/index.tsx index 44e7da6b4..c9e893a80 100644 --- a/src/app/components/ParaTimePicker/index.tsx +++ b/src/app/components/ParaTimePicker/index.tsx @@ -2,18 +2,14 @@ import { FC, useState } from 'react' import { useTranslation } from 'react-i18next' import Box from '@mui/material/Box' import Button from '@mui/material/Button' -import Drawer, { drawerClasses } from '@mui/material/Drawer' -import KeyboardDoubleArrowRightIcon from '@mui/icons-material/KeyboardDoubleArrowRight' -import KeyboardDoubleArrowLeftIcon from '@mui/icons-material/KeyboardDoubleArrowLeft' +import Drawer from '@mui/material/Drawer' import Divider from '@mui/material/Divider' -import IconButton from '@mui/material/IconButton' import Grid from '@mui/material/Unstable_Grid2' import { Logotype } from '../PageLayout/Logotype' import { COLORS } from '../../../styles/theme/colors' import { Network } from '../../../types/network' import { Layer } from '../../../oasis-indexer/api' import { useRequiredScopeParam } from '../../hooks/useScopeParam' -import { NetworkMenuIcon } from './NetworkMenuIcon' import { NetworkMenu } from './NetworkMenu' import { LayerMenu } from './LayerMenu' import { LayerDetails } from './LayerDetails' @@ -21,6 +17,8 @@ import { RouteUtils } from '../../utils/route-utils' import { styled } from '@mui/material/styles' import KeyboardArrowLeft from '@mui/icons-material/KeyboardArrowLeft' import { useScreenSize } from '../../hooks/useScreensize' +import { MobileNetworkButton } from '../PageLayout/NetworkButton' +import { useRuntimeFreshness } from '../OfflineBanner/hook' type ParaTimePickerProps = { onClose: () => void @@ -28,16 +26,10 @@ type ParaTimePickerProps = { open: boolean } -const ParaTimePickerDrawer = styled(Drawer)(() => ({ - [`.${drawerClasses.root}`]: { - height: '100vh', - }, -})) - export const ParaTimePicker: FC = ({ onClose, onConfirm, open }) => ( - + - + ) const StyledParaTimePickerContent = styled(Box)(({ theme }) => ({ @@ -65,8 +57,12 @@ const TabletBackButton = styled(Button)({ textDecoration: 'none', }) -const TabletActionBar = styled(Box)(() => ({ - minHeight: '50px', +const TabletActionBar = styled(Box)(({ theme }) => ({ + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', + minHeight: '55px', + paddingBottom: theme.spacing(3), })) const ActionBar = styled(Box)(({ theme }) => ({ @@ -87,10 +83,9 @@ enum ParaTimePickerTabletStep { } const ParaTimePickerContent: FC = ({ onClose, onConfirm }) => { - const { isTablet } = useScreenSize() + const { isMobile, isTablet } = useScreenSize() const { t } = useTranslation() const { network, layer } = useRequiredScopeParam() - const [showNetworkMenu, setShowNetworkMenu] = useState(isTablet || network !== Network.mainnet) const [selectedLayer, setSelectedLayer] = useState(layer) const [selectedNetwork, setSelectedNetwork] = useState(network) const [tabletStep, setTabletStep] = useState( @@ -100,29 +95,17 @@ const ParaTimePickerContent: FC = ({ onClose, onConf setSelectedNetwork(newNetwork) setSelectedLayer(RouteUtils.getEnabledLayersForNetwork(newNetwork)[0]) } + const handleConfirm = () => onConfirm(selectedNetwork, selectedLayer) + const { outOfDate } = useRuntimeFreshness({ network, layer }) return ( - {!isTablet && ( - <> - - - - setShowNetworkMenu(!showNetworkMenu)} - sx={{ - color: COLORS.brandDark, - ml: 3, - }} - > - {showNetworkMenu ? : } - - - )} + + + {isTablet && ( - <> - + +
{tabletStep === ParaTimePickerTabletStep.ParaTime && ( = ({ onClose, onConf {t('paraTimePicker.viewParaTimes')} )} - - +
+ +
)} - {!showNetworkMenu && !isTablet && ( - - - - )} - {((!isTablet && showNetworkMenu) || - (isTablet && tabletStep === ParaTimePickerTabletStep.Network)) && ( + {(!isTablet || (isTablet && tabletStep === ParaTimePickerTabletStep.Network)) && ( = ({ onClose, onConf )} {(!isTablet || (isTablet && tabletStep === ParaTimePickerTabletStep.ParaTimeDetails)) && ( - - + + )} @@ -201,14 +188,10 @@ const ParaTimePickerContent: FC = ({ onClose, onConf {t('common.cancel')} - diff --git a/src/app/components/TextList/index.tsx b/src/app/components/TextList/index.tsx index bb721cd32..999427b1f 100644 --- a/src/app/components/TextList/index.tsx +++ b/src/app/components/TextList/index.tsx @@ -8,13 +8,15 @@ type TextListProps = { children: ReactNode } -const StyledList = styled(List)(() => ({ +const StyledList = styled(List)(({ theme }) => ({ listStyleType: 'disc', - listStylePosition: 'inside', + listStylePosition: 'outside', color: COLORS.brandExtraDark, - fontSize: '12px', + fontSize: '14px', + paddingLeft: theme.spacing(4), '& ul': { paddingTop: 0, + paddingBottom: 0, }, })) @@ -22,7 +24,7 @@ export const TextList: FC = ({ children }) => {childr const StyledListItem = styled(ListItem)(({ theme }) => ({ display: 'list-item', - paddingTop: 0, + padding: 0, paddingBottom: theme.spacing(1), })) diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index ed4c48e7f..5ba1a01cb 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -256,14 +256,14 @@ "chainId": "Chain ID:", "decimal": "Decimal: {{ id }}", "comingSoon": "(coming soon)", + "goToDashboard": "Go to dashboard", "hex": "Hex: {{ id }}", "less": "Show Less", "more": "Show More", "readMore": "Read more about {{ layer }} on {{ network }} in Oasis Docs", "rpcHttp": "RPC HTTP endpoint: {{ endpoint }}", "rpcWebSockets": "RPC WebSockets endpoint: {{ endpoint }}", - "selected": "(currently active)", - "toggleNetworkMenu": "Toggle networks menu", + "selected": "(active)", "viewNetworks": "View Networks", "viewParaTimes": "View ParaTimes", "mainnet": { diff --git a/src/styles/index.css b/src/styles/index.css index 1b4753f03..ea67cc3b1 100644 --- a/src/styles/index.css +++ b/src/styles/index.css @@ -1,11 +1,6 @@ @import '../../node_modules/@fontsource-variable/figtree/index.css'; @import '../../node_modules/@fontsource-variable/roboto-mono/index.css'; -:root { - --app-header-height: 0px; - --app-banners-height: 0px; -} - html { scroll-behavior: smooth; } @@ -16,7 +11,8 @@ html { font-style: normal; font-display: swap; font-weight: 100 700; - src: url('../../node_modules/@fontsource-variable/figtree/files/figtree-latin-wght-normal.woff2') format('woff2'); + src: url('../../node_modules/@fontsource-variable/figtree/files/figtree-latin-wght-normal.woff2') + format('woff2'); unicode-range: U+2026; } diff --git a/src/styles/theme/defaultTheme.ts b/src/styles/theme/defaultTheme.ts index 18381fb39..547b8b3af 100644 --- a/src/styles/theme/defaultTheme.ts +++ b/src/styles/theme/defaultTheme.ts @@ -6,7 +6,6 @@ import { inputBaseClasses } from '@mui/material/InputBase' import { inputAdornmentClasses } from '@mui/material/InputAdornment' import { tabClasses } from '@mui/material/Tab' import { menuItemClasses } from '@mui/material/MenuItem' -import { modalClasses } from '@mui/material/Modal' declare module '@mui/material/styles' { interface Palette { @@ -504,17 +503,9 @@ export const defaultTheme = createTheme({ borderRadius: '0 0 12px 12px', padding: `${theme.spacing(4)} 5%`, }), - modal: ({ theme }) => ({ - [theme.breakpoints.down('md')]: { - [`& .${modalClasses.backdrop}`]: { - background: 'transparent', - }, - }, - }), paper: ({ theme }) => ({ [theme.breakpoints.down('md')]: { - height: `calc(100vh - var(--app-header-height) - var(--app-banners-height))`, - top: `calc(var(--app-header-height) + var(--app-banners-height))`, + height: '100vh', }, }), }, @@ -847,6 +838,13 @@ export const defaultTheme = createTheme({ }, }, }, + MuiList: { + styleOverrides: { + padding: { + paddingTop: 0, + }, + }, + }, MuiListItemIcon: { styleOverrides: { root: {