diff --git a/.storybook/preview.js b/.storybook/preview.js index 05a015bfe..cdfc52621 100644 --- a/.storybook/preview.js +++ b/.storybook/preview.js @@ -1,19 +1,18 @@ -import '../src/renderer/assets/sass/app.scss'; +import '../src/renderer/assets/reset.scss'; import '../src/renderer/Generics/redesign/globalStyle.css'; -import '../src/renderer/Generics/redesign/InterFont.css'; import '../src/renderer/i18n'; -import RedesignContainer from "../src/renderer/Generics/redesign/RedesignContainer" +import RedesignContainer from '../src/renderer/Generics/redesign/RedesignContainer'; export const parameters = { - actions: { argTypesRegex: "^on[A-Z].*" }, + actions: { argTypesRegex: '^on[A-Z].*' }, controls: { matchers: { color: /(background|color)$/i, date: /Date$/, }, }, -} +}; export const decorators = [ (Story) => ( diff --git a/assets/fonts/Inter.ttf b/assets/fonts/Inter.ttf deleted file mode 100644 index 969a990fb..000000000 Binary files a/assets/fonts/Inter.ttf and /dev/null differ diff --git a/src/renderer/App.tsx b/src/renderer/App.tsx index 360c84ee9..ee0a4a106 100644 --- a/src/renderer/App.tsx +++ b/src/renderer/App.tsx @@ -2,7 +2,6 @@ import { useEffect } from 'react'; import { MemoryRouter as Router, Routes, Route } from 'react-router-dom'; import * as Sentry from '@sentry/electron/renderer'; -import './Generics/redesign/InterFont.css'; import './Generics/redesign/globalStyle.css'; import './App.css'; import { useAppDispatch } from './state/hooks'; diff --git a/src/renderer/Generics/redesign/Banner/Banner.tsx b/src/renderer/Generics/redesign/Banner/Banner.tsx new file mode 100644 index 000000000..464171fcc --- /dev/null +++ b/src/renderer/Generics/redesign/Banner/Banner.tsx @@ -0,0 +1,17 @@ +import { Icon } from '../Icon/Icon'; +import { container, textContainer, offline, reconnect } from './banner.css'; + +/** + * Primary UI component for user interaction + */ +export const Banner = () => { + return ( +
+ +
+
Currently offline
+
Please reconnect to the internet
+
+
+ ); +}; diff --git a/src/renderer/Generics/redesign/Banner/banner.css.ts b/src/renderer/Generics/redesign/Banner/banner.css.ts new file mode 100644 index 000000000..28ff9e0a3 --- /dev/null +++ b/src/renderer/Generics/redesign/Banner/banner.css.ts @@ -0,0 +1,34 @@ +import { style } from '@vanilla-extract/css'; +import { vars } from '../theme.css'; + +export const container = style({ + display: 'flex', + flexDirection: 'row', + alignItems: 'flex-start', + gap: '12px', + width: '236px', + height: '56px', + boxSizing: 'border-box', + background: vars.components.bannerBackground, + boxShadow: vars.components.bannerBoxShadow, + borderRadius: '5px', + color: vars.color.font70, + padding: '12px', +}); + +export const textContainer = style({}); + +export const offline = style({ + fontStyle: 'normal', + fontWeight: '590', + fontSize: '13px', + lineHeight: '16px', + letterSpacing: '-0.12px', + marginBottom: '2px', +}); + +export const reconnect = style({ + fontWeight: '400', + fontSize: '11px', + lineHeight: '14px', +}); diff --git a/src/renderer/Generics/redesign/Bubble.tsx b/src/renderer/Generics/redesign/Bubble/Bubble.tsx similarity index 74% rename from src/renderer/Generics/redesign/Bubble.tsx rename to src/renderer/Generics/redesign/Bubble/Bubble.tsx index 89fe1d885..81f95bc7e 100644 --- a/src/renderer/Generics/redesign/Bubble.tsx +++ b/src/renderer/Generics/redesign/Bubble/Bubble.tsx @@ -1,3 +1,5 @@ +import { container } from './bubble.css'; + export interface BubbleProps { /** * What background color to use @@ -14,11 +16,7 @@ export interface BubbleProps { */ export const Bubble = ({ backgroundColor, count, ...props }: BubbleProps) => { return ( -
+
{count}
); diff --git a/src/renderer/Generics/redesign/Bubble/bubble.css.ts b/src/renderer/Generics/redesign/Bubble/bubble.css.ts new file mode 100644 index 000000000..18d05ee63 --- /dev/null +++ b/src/renderer/Generics/redesign/Bubble/bubble.css.ts @@ -0,0 +1,20 @@ +import { style } from '@vanilla-extract/css'; +import { common, vars } from '../theme.css'; + +export const container = style({ + flex: 'none', + display: 'flex', + flexDirection: 'row', + alignItems: 'flex-start', + padding: '2px 6px', + gap: '10px', + fontStyle: 'normal', + fontWeight: '590', + fontSize: '11px', + lineHeight: '14px', + textAlign: 'center', + color: common.color.white100, + maxWidth: 'fit-content', + background: common.color.red500, + borderRadius: '9px', +}); diff --git a/src/renderer/Generics/redesign/Button.tsx b/src/renderer/Generics/redesign/Button.tsx deleted file mode 100644 index ffb629cd4..000000000 --- a/src/renderer/Generics/redesign/Button.tsx +++ /dev/null @@ -1,83 +0,0 @@ -import { Icon } from './Icon'; - -export interface ButtonProps { - /** - * Is this the principal call to action on the page? - */ - primary?: boolean; - /** - * What state is the button in? - */ - disabled?: boolean; - /** - * Is this dark mode? - */ - darkMode?: boolean; - /** - * What background color to use - */ - backgroundColor?: string; - /** - * How large should the button be? - */ - size?: 'small' | 'medium' | 'large'; - /** - * Text only, with icon, or just icon? - */ - variant?: 'text' | 'icon-left' | 'icon-right' | 'icon'; - /** - * Which iconId? // TODO: Change this to drop down eventually - */ - iconId?: 'settings' | 'play'; - /** - * Button contents - */ - label: string; - /** - * Optional click handler - */ - onClick?: () => void; -} - -/** - * Primary UI component for user interaction - */ -export const Button = ({ - primary = false, - size = 'medium', - disabled = false, - darkMode = false, - variant = 'text', - iconId = 'settings', - backgroundColor, - label, - ...props -}: ButtonProps) => { - const mode = primary - ? 'storybook-button--primary' - : 'storybook-button--secondary'; - const darkStyle = darkMode ? 'darkMode' : ''; - return ( - - ); -}; diff --git a/src/renderer/Generics/redesign/Button/Button.tsx b/src/renderer/Generics/redesign/Button/Button.tsx index 38f4289ee..44c292abe 100644 --- a/src/renderer/Generics/redesign/Button/Button.tsx +++ b/src/renderer/Generics/redesign/Button/Button.tsx @@ -1,9 +1,13 @@ +import { IconId } from 'renderer/assets/images/icons'; +import { Icon } from '../Icon/Icon'; import { baseButton, primaryButton, secondaryButton, smallButton, + wideButton, iconLeft, + iconStyle, } from './button.css'; export interface ButtonProps { @@ -18,14 +22,18 @@ export interface ButtonProps { * Text only, with icon, or just icon? */ variant?: 'text' | 'icon-left' | 'icon-right' | 'icon'; + /** + * Is this button wide? + */ + wide?: boolean; /** * Optional icon */ - icon?: React.ReactNode; + iconId?: IconId; /** * Button text content */ - label: string; + label?: string; onClick?: () => void; } @@ -34,7 +42,8 @@ const Button = ({ size = 'medium', disabled = false, variant = 'text', - icon, + iconId = 'settings', + wide = false, backgroundColor, label, ...props @@ -44,6 +53,9 @@ const Button = ({ if (size === 'small') { classNames.push(smallButton); } + if (wide) { + classNames.push(wideButton); + } return ( ); }; diff --git a/src/renderer/Generics/redesign/Button/button.css.ts b/src/renderer/Generics/redesign/Button/button.css.ts index 7421a25f7..280cd2eb9 100644 --- a/src/renderer/Generics/redesign/Button/button.css.ts +++ b/src/renderer/Generics/redesign/Button/button.css.ts @@ -21,26 +21,32 @@ export const baseButton = style({ ':hover': { transform: 'none', }, - fontFamily: 'Inter', fontWeight: 500, fontSize: 13, lineHeight: '16px', + height: '32px', }); export const smallButton = style({ padding: '6px 10px', + height: '28px', + gap: '6px', +}); + +export const wideButton = style({ + width: '100%', }); export const primaryButton = style([ { - color: common.color.white, + color: common.color.white100, background: vars.color.primary, selectors: { '&:hover:enabled': { background: vars.color.primaryHover, }, '&:active:enabled': { - background: common.color.primary700, + background: vars.color.primaryActive, }, }, }, @@ -53,7 +59,7 @@ export const secondaryButton = style([ boxShadow: vars.components.buttonBoxShadow, selectors: { '&:hover:enabled': { - background: vars.color.background92, + background: vars.color.backgroundHoverGradient, }, '&:active:enabled': { background: vars.color.backgroundActiveGradient, @@ -65,3 +71,8 @@ export const secondaryButton = style([ export const iconLeft = style({ order: 1, }); + +export const iconStyle = style({ + width: 16, + height: 16, +}); diff --git a/src/renderer/Generics/redesign/Checklist/Checklist.tsx b/src/renderer/Generics/redesign/Checklist/Checklist.tsx index 6f05c5ffd..c9ea0c6ff 100644 --- a/src/renderer/Generics/redesign/Checklist/Checklist.tsx +++ b/src/renderer/Generics/redesign/Checklist/Checklist.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { container } from './checklist.css'; import ChecklistItem, { ChecklistItemProps } from './ChecklistItem'; -import HorizontalLine from '../HorizontalLine/HorizontalLine'; +import { HorizontalLine } from '../HorizontalLine/HorizontalLine'; export interface ChecklistProps { /** diff --git a/src/renderer/Generics/redesign/Checklist/ChecklistItem.tsx b/src/renderer/Generics/redesign/Checklist/ChecklistItem.tsx index 772f9faf6..6ddb69cf4 100644 --- a/src/renderer/Generics/redesign/Checklist/ChecklistItem.tsx +++ b/src/renderer/Generics/redesign/Checklist/ChecklistItem.tsx @@ -8,11 +8,9 @@ import { successIcon, warningIcon, errorIcon, + loadingIcon, } from './checklistItem.css'; -import { ReactComponent as InfoCircleFill } from '../../../assets/images/icons/Info-circle-filled.svg'; -import { ReactComponent as WarningCircleFill } from '../../../assets/images/icons/Warning-circle-filled.svg'; -import { ReactComponent as CheckCircleFillIcon } from '../../../assets/images/icons/Check-circle-filled.svg'; -import SpinnerIcon from '../Icons/SpinnerIcon'; +import { Icon } from '../Icon/Icon'; /** * checkTitle and status required @@ -55,31 +53,31 @@ const ChecklistItem = ({ if (status === 'complete') { statusIcon = ( - + ); } else if (status === 'information') { statusIcon = ( - + ); } else if (status === 'incomplete') { statusIcon = ( - + ); } else if (status === 'loading') { statusIcon = ( - - + + ); } else if (status === 'error') { statusIcon = ( - + ); } diff --git a/src/renderer/Generics/redesign/Checklist/checklistItem.css.ts b/src/renderer/Generics/redesign/Checklist/checklistItem.css.ts index 21c67c3b6..7b56811f9 100644 --- a/src/renderer/Generics/redesign/Checklist/checklistItem.css.ts +++ b/src/renderer/Generics/redesign/Checklist/checklistItem.css.ts @@ -1,5 +1,5 @@ -import { style } from '@vanilla-extract/css'; -import { vars } from '../theme.css'; +import { style, keyframes } from '@vanilla-extract/css'; +import { vars, common } from '../theme.css'; export const container = style({ // Auto layout @@ -51,13 +51,25 @@ export const captionTextClass = style({ }); export const successIcon = style({ - color: vars.color.green, + color: common.color.green, }); export const warningIcon = style({ - color: vars.color.yellow, + color: common.color.yellow, +}); + +const rotate = keyframes({ + '0%': { transform: 'rotate(0deg)' }, + '100%': { transform: 'rotate(360deg)' }, +}); + +export const loadingIcon = style({ + fill: vars.color.font, + animationName: rotate, + animationDuration: '3s', + animationIterationCount: 'infinite', }); export const errorIcon = style({ - color: vars.color.red, + color: common.color.red, }); diff --git a/src/renderer/Generics/redesign/ClientCard/ClientCard.tsx b/src/renderer/Generics/redesign/ClientCard/ClientCard.tsx new file mode 100644 index 000000000..6ad0085e9 --- /dev/null +++ b/src/renderer/Generics/redesign/ClientCard/ClientCard.tsx @@ -0,0 +1,133 @@ +import { NodeIconId } from '../../../assets/images/nodeIcons'; +import { + NodeBackgroundId, + NODE_BACKGROUNDS, +} from '../../../assets/images/nodeBackgrounds'; +import { + container, + cardTop, + cardContent, + clientDetails, + clientIcon, + clientTitle, + clientType, + clientLabels, + clientBackground, +} from './clientCard.css'; +import { NodeIcon } from '../NodeIcon/NodeIcon'; +import { Label } from '../Label/Label'; +import ProgressBar from '../ProgressBar/ProgressBar'; +import { ClientStatusProps } from '../consts'; + +const getLabelDetails = (label: string) => { + const labelDetails = { color: '', string: '' }; + switch (label) { + case 'synchronized': + labelDetails.color = 'green'; + labelDetails.string = 'Synchronized'; + break; + case 'lowPeerCount': + labelDetails.color = 'orange'; + labelDetails.string = 'Low peer count'; + break; + case 'updateAvailable': + labelDetails.color = 'purple'; + labelDetails.string = 'Update Available'; + break; + case 'stopped': + labelDetails.color = 'purple'; + labelDetails.string = 'Update'; + break; + default: + break; + } + return labelDetails; +}; + +export interface ClientCardProps { + /** + * Node client object + */ + client: { + name: NodeBackgroundId; + version: string; + nodeType: string; + status: ClientStatusProps; + stats: { + peers: number; + slot: string; + cpuLoad: number; + diskUsage: number; + }; + }; +} + +/** + * Primary UI component for user interaction + */ +export const ClientCard = ({ client }: ClientCardProps) => { + const { status, name, nodeType } = client; + const isNotSynchronizedAndStopped = !status.synchronized && !status.stopped; + const renderContents = () => { + if (isNotSynchronizedAndStopped) { + return ( + <> + {/* TODO: tie clients with progress bar colors */} + {/* TODO: modify height of the bar for card */} + + + ); + } + if (status.stopped) { + return