diff --git a/.gitignore b/.gitignore index 86cfe68..67fa450 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,10 @@ yarn-error.log* # typescript *.tsbuildinfo next-env.d.ts + +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/sdks +!.yarn/versions \ No newline at end of file diff --git a/.yarn/install-state.gz b/.yarn/install-state.gz index 3e197eb..b7c902d 100644 Binary files a/.yarn/install-state.gz and b/.yarn/install-state.gz differ diff --git a/blocks/button/Button.tsx b/blocks/button/Button.tsx index ceef6f8..f24e076 100644 --- a/blocks/button/Button.tsx +++ b/blocks/button/Button.tsx @@ -40,6 +40,8 @@ const StyledButton = styled.button` font-family: var(--font-family); justify-content: center; white-space: nowrap; + flex-shrink: 0; + border: none; /* Common icon css added through CSS class */ .icon { @@ -48,15 +50,18 @@ const StyledButton = styled.button` justify-content: center; } /* Button variant CSS styles */ - ${({ variant, loading }) => getButtonVariantStyles(variant || 'primary', loading!)} + ${({ variant, loading }) => + getButtonVariantStyles(variant || 'primary', loading!)} ${({ loading }) => loading && 'opacity: var(--opacity-80);'} /* Button and font size CSS styles */ - ${({ iconOnly, size }) => getButtonSizeStyles({ iconOnly: !!iconOnly, size: size || 'medium' })} + ${({ iconOnly, size }) => + getButtonSizeStyles({ iconOnly: !!iconOnly, size: size || 'medium' })} /* Circular CSS for rounded icon only buttons */ - ${({ circular, iconOnly }) => circular && iconOnly && `border-radius: var(--r10)`} + ${({ circular, iconOnly }) => + circular && iconOnly && `border-radius: var(--r10);`} /* Prop specific CSS */ ${({ block }) => block && 'width: 100%;'} @@ -104,7 +109,9 @@ const Button = forwardRef( {leadingIcon && {leadingIcon}} {!iconOnly && children} {trailingIcon && {trailingIcon}} - {iconOnly && !loading && !children && {iconOnly}} + {iconOnly && !loading && !children && ( + {iconOnly} + )} ) ); diff --git a/blocks/button/Button.utils.ts b/blocks/button/Button.utils.ts index 8dd243f..a313f9f 100644 --- a/blocks/button/Button.utils.ts +++ b/blocks/button/Button.utils.ts @@ -1,12 +1,17 @@ import { FlattenSimpleInterpolation, css } from 'styled-components'; import { ButtonSize, ButtonVariant } from './Button.types'; -export const getButtonVariantStyles = (variant: ButtonVariant, loading: boolean) => { +export const getButtonVariantStyles = ( + variant: ButtonVariant, + loading: boolean +) => { switch (variant) { case 'primary': { return ` background-color: var(--${ - loading ? 'components-button-primary-background-loading' : 'components-button-primary-background-default' + loading + ? 'components-button-primary-background-loading' + : 'components-button-primary-background-default' }); color: var(--components-button-primary-text-default); ${ diff --git a/blocks/icons/components/Sale.tsx b/blocks/icons/components/Sale.tsx new file mode 100644 index 0000000..5b6d4b4 --- /dev/null +++ b/blocks/icons/components/Sale.tsx @@ -0,0 +1,31 @@ +import { FC } from 'react'; +import { IconWrapper } from '../IconWrapper'; +import { IconProps } from '../Icons.types'; + +const Sale: FC = (allProps) => { + const { svgProps: props, ...restProps } = allProps; + return ( + + + + } + {...restProps} + /> + ); +}; + +export default Sale; diff --git a/blocks/icons/index.ts b/blocks/icons/index.ts index 8eef860..3470266 100644 --- a/blocks/icons/index.ts +++ b/blocks/icons/index.ts @@ -162,6 +162,8 @@ export { default as Settings } from './components/Settings'; export { default as Swap } from './components/Swap'; +export { default as Sale } from './components/Sale'; + export { default as Tick } from './components/Tick'; export { default as TickCircleFilled } from './components/TickCircleFilled'; export { default as TickDecoratedCircleFilled } from './components/TickDecoratedCircleFilled'; diff --git a/common/components/ChainAlertBar.tsx b/common/components/ChainAlertBar.tsx new file mode 100644 index 0000000..2ba7045 --- /dev/null +++ b/common/components/ChainAlertBar.tsx @@ -0,0 +1,67 @@ +import React from 'react'; +import styled from 'styled-components'; +import { Front, Sale } from '../../blocks'; + +type AlertBarProps = { + text: string; + url?: string; + textPrefix?: string; +}; + +const ChainAlertBar = ({ text, url, textPrefix }: AlertBarProps) => { + return ( + { + if (url) window.open(url, '_blank'); + }} + > + + + {textPrefix} {text} + + + + ); +}; + +const HeroButton = styled.div` + font-family: 'FK Grotesk Neue', sans-serif; + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + padding: 12px 16px; + gap: 8px; + margin: 0 auto; + width: -webkit-fill-available; + + border-radius: 16px; + border: 1px solid var(--stroke-secondary, #313338); + background: var(--surface-primary, #202124); + cursor: pointer; + + @media (max-width: 768px) { + gap: 6px; + } + + @media (max-width: 480px) { + gap: 6px; + padding: 12px 10px; + box-sizing: border-box; + } +`; + +const AlertText = styled.span` + font-family: var(--font-family); + color: var(--text-primary, #f5f6f8); + font-size: 14px; + font-style: normal; + font-weight: 400; + line-height: 20px; +`; + +const AlertTextPrefix = styled(AlertText)` + color: var(--text-brand-medium, #cf59e2); +`; + +export default ChainAlertBar; diff --git a/common/components/DevnetVotingPopup.tsx b/common/components/DevnetVotingPopup.tsx new file mode 100644 index 0000000..ec86cdd --- /dev/null +++ b/common/components/DevnetVotingPopup.tsx @@ -0,0 +1,199 @@ +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-nocheck +import React, { useEffect, useState, FC, ReactNode } from 'react'; +import styled from 'styled-components'; +import { toast, Toaster } from 'sonner'; +import { Button, Cross, VideoCameraFilled } from '../../blocks'; + +type NotificationProps = { + image?: ReactNode; + /* Title of the notification */ + firstTitle?: string; + /* Title of the notification */ + secondTitle?: string; + /* Description of the notification */ + description?: string; + /* Optional onClose action for the notification */ + onClose?: () => void; + /* Custom React component to be passed as the image. */ + overlay?: ReactNode; + /* Optional onClick event for the notification */ + onClick?: () => void; + /* Position of the notification */ + position?: 'bottom-right' | 'bottom-left' | 'top-center' | 'bottom-center'; + /* Optional duration of the notification component */ + duration?: number; +}; + +// Custom Hook +export const useChainNotification = () => { + const [hasMounted, setHasMounted] = useState(false); + + const showNotification = () => { + const toastId = toast.custom( + () => ( + { + localStorage.setItem('chainNotificationShown', 'true'); + toast.dismiss(toastId); + }} + /> + ), + { + duration: Infinity, + position: 'bottom-left', + } + ); + }; + + useEffect(() => { + if (typeof window !== 'undefined') { + const notificationAlreadyShown = + localStorage.getItem('chainNotificationShown') === 'true'; + + if (!notificationAlreadyShown && !hasMounted) { + showNotification(); + setHasMounted(true); + } else { + toast.dismiss(); + setHasMounted(false); + } + } + }, []); +}; + +export const Notification = () => { + return ; +}; + +// Notification Item Component +const NotificationItem: FC = ({ + firstTitle, + secondTitle, + description, + onClick, + onClose, +}) => { + const handleNotificationClick = () => onClick?.(); + const handleNotificationClose = () => { + onClose?.(); + toast.dismiss(); + }; + + return ( + + { + e.stopPropagation(); + handleNotificationClose(); + }} + > + + + + + + {firstTitle} +
+ {secondTitle} +
+ + {description} +
+
+ ); +}; + +// Notification Container +const NotificationContainer = styled.div` + position: relative; + border-radius: var(--radius-md, 24px); + border: 1px solid var(--stroke-secondary, #313338); + background: var(--surface-primary, #202124); + display: flex; + flex-direction: column; + align-items: stretch; + height: 368px; + width: 320px; + cursor: pointer; + box-sizing: border-box; + font-family: var(--font-family); + overflow: hidden; + + @media (max-width: 425px) { + width: 100%; + } + + img { + width: 72px; + height: auto; + margin: 0 auto; + } +`; + +const StyledToaster = styled(Toaster)` + width: 397px; + + @media (max-width: 425px) { + width: 100%; + } +`; + +const TextContainer = styled.div` + display: flex; + flex-direction: column; + align-items: flex-start; + justify-content: flex-start; + padding: 24px; + flex: 1; + box-sizing: border-box; + gap: 16px; + align-items: center; +`; + +const NotificationTitle = styled.span` + font-family: 'FK Grotesk Neue', sans-serif; + color: var(--text-primary); + text-align: center; + font-family: var(--font-family); + font-size: 26px; + font-style: normal; + font-weight: 500; + line-height: 36px; /* 138.462% */ +`; + +const NotificationDescription = styled.span` + font-family: 'FK Grotesk Neue', sans-serif; + color: var(--text-primary); + text-align: center; + font-family: var(--font-family); + font-size: 16px; + font-style: normal; + font-weight: 400; + line-height: 140%; + letter-spacing: -0.32px; + overflow: hidden; +`; + +const CloseButton = styled.button` + background-color: transparent; + cursor: pointer; + color: #fff; + padding: 0px; + position: absolute; + right: 8px; + top: 8px; + border: none; +`; diff --git a/common/components/index.ts b/common/components/index.ts index 18f74fc..c87f2f3 100644 --- a/common/components/index.ts +++ b/common/components/index.ts @@ -1 +1,3 @@ -export * from './ContentLayout'; \ No newline at end of file +export * from './ContentLayout'; +export * from './ChainAlertBar'; +export * from './DevnetVotingPopup'; diff --git a/components/Home/LiveBlocks.tsx b/components/Home/LiveBlocks.tsx index 5f7a5a1..655f6d3 100644 --- a/components/Home/LiveBlocks.tsx +++ b/components/Home/LiveBlocks.tsx @@ -36,7 +36,7 @@ export default function LiveBlocks() { { title: 'VALIDATOR', dataIndex: 'validator', - render: (text) =>
, + render: (text) =>
, cellAlignment: 'flex-start', headerAlignment: 'flex-start', width: '135px', diff --git a/components/Home/LiveTransactions.tsx b/components/Home/LiveTransactions.tsx index 66a0942..3fc1a64 100644 --- a/components/Home/LiveTransactions.tsx +++ b/components/Home/LiveTransactions.tsx @@ -125,7 +125,7 @@ export default function LiveTransactions() { Live Transactions - + router.push('/home')} > - - - PushScan - + + + + PushScan + + {asPath !== '/dashboard' && ( - + - Analytics + App Ecosystem )} diff --git a/pages/_app.tsx b/pages/_app.tsx index a37f9ed..5b730d7 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -1,5 +1,5 @@ // React, NextJS imports -import React, { useEffect } from 'react'; +import React from 'react'; // import localFont from '@next/font/local'; import type { AppProps } from 'next/app'; @@ -14,15 +14,18 @@ import { ThemeProvider as GlobalThemeProvider } from '../contexts/ThemeContext'; import { DataProvider } from '../contexts/DataContext'; import { QueryClient, QueryClientProvider } from 'react-query'; +import { Notification, useChainNotification } from '../common'; const queryClient = new QueryClient(); export default function App({ Component, pageProps }: AppProps) { + useChainNotification(); return ( + diff --git a/sections/Home/index.tsx b/sections/Home/index.tsx index 2ec65dc..d5a1f85 100644 --- a/sections/Home/index.tsx +++ b/sections/Home/index.tsx @@ -7,6 +7,7 @@ import SearchBar from '../../components/Home/SearchBar'; import OverView from '../../components/Home/OverView'; import LiveBlocks from '../../components/Home/LiveBlocks'; import LiveTransactions from '../../components/Home/LiveTransactions'; +import ChainAlertBar from '../../common/components/ChainAlertBar'; const Home = () => { return ( @@ -14,37 +15,49 @@ const Home = () => { width="-webkit-fill-available" display="flex" flexDirection="column" - gap="spacing-xxxl" + gap="spacing-lg" > + - - Push Blockchain Explorer - - - - - - - + + + Push Blockchain Explorer + + + - - - + + + + + + + + ); diff --git a/yarn.lock b/yarn.lock index a040541..b3f882f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5148,12 +5148,12 @@ __metadata: linkType: hard "sonner@npm:^1.5.0": - version: 1.7.0 - resolution: "sonner@npm:1.7.0" + version: 1.7.1 + resolution: "sonner@npm:1.7.1" peerDependencies: react: ^18.0.0 || ^19.0.0 || ^19.0.0-rc react-dom: ^18.0.0 || ^19.0.0 || ^19.0.0-rc - checksum: 10c0/02b16249b0c6e3a62c50dbcb643bb089aecd82c4f0ae988d00903e427d5485933d6cb59047fe5da338b548b6a3311643e511f63ed60a938458295015f7a3fdfd + checksum: 10c0/f934fc30305a1b9ae562cd1b7980127bca65a41dce34b3b8aa8ceed8e1ca04b37daf2a0c0bb5e2b3ef9769b2438aa6799eff1880653d75e709538afe7fe70e05 languageName: node linkType: hard