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

Banner + notification popup + other fixes #21

Merged
merged 1 commit into from
Dec 10, 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
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,10 @@ yarn-error.log*
# typescript
*.tsbuildinfo
next-env.d.ts

.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/sdks
!.yarn/versions
Binary file modified .yarn/install-state.gz
Binary file not shown.
15 changes: 11 additions & 4 deletions blocks/button/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ const StyledButton = styled.button<ButtonProps>`
font-family: var(--font-family);
justify-content: center;
white-space: nowrap;
flex-shrink: 0;
border: none;

/* Common icon css added through CSS class */
.icon {
Expand All @@ -48,15 +50,18 @@ const StyledButton = styled.button<ButtonProps>`
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%;'}
Expand Down Expand Up @@ -104,7 +109,9 @@ const Button = forwardRef<HTMLButtonElement, ButtonProps>(
{leadingIcon && <span className="icon icon-text">{leadingIcon}</span>}
{!iconOnly && children}
{trailingIcon && <span className="icon icon-text">{trailingIcon}</span>}
{iconOnly && !loading && !children && <span className="icon icon-only">{iconOnly}</span>}
{iconOnly && !loading && !children && (
<span className="icon icon-only">{iconOnly}</span>
)}
</StyledButton>
)
);
Expand Down
9 changes: 7 additions & 2 deletions blocks/button/Button.utils.ts
Original file line number Diff line number Diff line change
@@ -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);
${
Expand Down
31 changes: 31 additions & 0 deletions blocks/icons/components/Sale.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { FC } from 'react';
import { IconWrapper } from '../IconWrapper';
import { IconProps } from '../Icons.types';

const Sale: FC<IconProps> = (allProps) => {
const { svgProps: props, ...restProps } = allProps;
return (
<IconWrapper
componentName="Sale"
icon={
<svg
xmlns="http://www.w3.org/2000/svg"
width="inherit"
height="inherit"
viewBox="0 0 22 22"
fill="none"
{...props}
>
<path
d="M1.22222 10.7778C6.49717 10.7778 10.7778 6.49717 10.7778 1.22222C10.7778 1.09984 10.8776 1 11 1C11.1224 1 11.2222 1.09984 11.2222 1.22222C11.2222 6.49717 15.5028 10.7778 20.7778 10.7778C20.9002 10.7778 21 10.8776 21 11C21 11.1224 20.9002 11.2222 20.7778 11.2222C15.5028 11.2222 11.2222 15.5028 11.2222 20.7778C11.2222 20.9002 11.1224 21 11 21C10.8776 21 10.7778 20.9002 10.7778 20.7778C10.7778 15.5028 6.49717 11.2222 1.22222 11.2222C1.09984 11.2222 1 11.1224 1 11C1 10.8776 1.09984 10.7778 1.22222 10.7778Z"
stroke="currentColor"
stroke-width="2"
/>
</svg>
}
{...restProps}
/>
);
};

export default Sale;
2 changes: 2 additions & 0 deletions blocks/icons/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down
67 changes: 67 additions & 0 deletions common/components/ChainAlertBar.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<HeroButton
onClick={() => {
if (url) window.open(url, '_blank');
}}
>
<Sale size={16} color="icon-brand-subtle" />
<AlertText>
<AlertTextPrefix>{textPrefix}</AlertTextPrefix> {text}
</AlertText>
<Front size={16} color="icon-brand-subtle" />
</HeroButton>
);
};

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;
199 changes: 199 additions & 0 deletions common/components/DevnetVotingPopup.tsx
Original file line number Diff line number Diff line change
@@ -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(
() => (
<NotificationItem
firstTitle="Vote for"
secondTitle="Push Devnet"
description="Governance proposal is live! Vote today to make Push Chain a reality"
position="bottom-left"
onClose={() => {
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 <StyledToaster offset={13} visibleToasts={5} />;
};

// Notification Item Component
const NotificationItem: FC<NotificationProps> = ({
firstTitle,
secondTitle,
description,
onClick,
onClose,
}) => {
const handleNotificationClick = () => onClick?.();
const handleNotificationClose = () => {
onClose?.();
toast.dismiss();
};

return (
<NotificationContainer onClick={handleNotificationClick}>
<CloseButton
onClick={(e) => {
e.stopPropagation();
handleNotificationClose();
}}
>
<Cross size={24} color="icon-primary" />
</CloseButton>
<TextContainer>
<VideoCameraFilled size={72} color="icon-primary" />
<NotificationTitle>
{firstTitle}
<br />
{secondTitle}
</NotificationTitle>
<Button
onClick={() => {
localStorage.setItem('chainNotificationShown', 'true');
window.open('https://gov.push.org', '_blank');
toast.dismiss();
}}
>
Learn More
</Button>
<NotificationDescription>{description}</NotificationDescription>
</TextContainer>
</NotificationContainer>
);
};

// 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;
`;
4 changes: 3 additions & 1 deletion common/components/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
export * from './ContentLayout';
export * from './ContentLayout';
export * from './ChainAlertBar';
export * from './DevnetVotingPopup';
2 changes: 1 addition & 1 deletion components/Home/LiveBlocks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export default function LiveBlocks() {
{
title: 'VALIDATOR',
dataIndex: 'validator',
render: (text) => <Address address={centerMaskString(text)} />,
render: (text) => <Address address={text} />,
cellAlignment: 'flex-start',
headerAlignment: 'flex-start',
width: '135px',
Expand Down
Loading
Loading