Merge branch 'Create-Dashboard' of github.com:nimbus-gui/nimbus-gui into Create-Dashboard

This commit is contained in:
Ivana Andersson 2023-09-26 13:43:44 +03:00
commit fb9682755c
97 changed files with 1289 additions and 1035 deletions

View File

@ -55,6 +55,8 @@ jobs:
${{ runner.os }}-yarn-v3 ${{ runner.os }}-yarn-v3
- name: Build - name: Build
run: yarn build run: yarn build
- name: Check formatting
run: yarn format:check
- name: Pull Vercel configuration - name: Pull Vercel configuration
run: yarn vercel pull --yes --token ${{ secrets.vercel_token }} run: yarn vercel pull --yes --token ${{ secrets.vercel_token }}
- name: Build Vercel bundle - name: Build Vercel bundle

View File

@ -1,27 +1,36 @@
# nimbus-gui # nimbus-gui
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. A GUI for managing your [Nimbus](https://nimbus.team/) nodes.
Currently, two official plugins are available: ## Deployed pages showing the project
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh We have a Storybook up at https://nimbus-gui.github.io/nimbus-gui/ which shows
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh the components of the project. We also have a deployed version of the GUI up at
https://nimbus-gui.vercel.app/ which shows the GUI as it currently looks in the
`main` branch of the
[`nimbus-gui/nimbus-gui`](https://github.com/nimbus-gui/nimbus-gui) repository.
## Expanding the ESLint configuration ## Development and running the project yourself
If you are developing a production application, we recommend updating the configuration to enable type aware lint rules: ### Dependencies
- Configure the top-level `parserOptions` property like this: Run `yarn` in the root directory of the project in order to install dependencies.
```js ### Running a development server
parserOptions: {
ecmaVersion: 'latest', If you want to run a development server to see what the GUI looks like you can
sourceType: 'module', run the following command:
project: ['./tsconfig.json', './tsconfig.node.json'],
tsconfigRootDir: __dirname, ```bash
}, yarn dev
``` ```
- Replace `plugin:@typescript-eslint/recommended` to `plugin:@typescript-eslint/recommended-type-checked` or `plugin:@typescript-eslint/strict-type-checked` This will start the server on port 5173 and you can open https://localhost:5173
- Optionally add `plugin:@typescript-eslint/stylistic-type-checked` in order to see the page.
- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and add `plugin:react/recommended` & `plugin:react/jsx-runtime` to the `extends` list
### Running storybook locally
If you want to run the Storybook locally you can simply run `yarn storybook` in
the root of the project. This is useful if you want to contribute a component
and be sure that it renders as you expect it to, without testing it out on any
given page.

View File

@ -5,6 +5,20 @@
<link rel="icon" type="image/svg+xml" href="/vite.svg" /> <link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React + TS</title> <title>Vite + React + TS</title>
<link
rel="preload"
href="./Inter-font/Inter-Regular.ttf"
as="font"
type="font/ttf"
crossOrigin=""
/>
<link
rel="preload"
href="./Inter-font/Inter-Bold.ttf"
as="font"
type="font/ttf"
crossOrigin=""
/>
</head> </head>
<body> <body>
<script>window.global = window;</script> <script>window.global = window;</script>

View File

@ -10,7 +10,9 @@
"preview": "vite preview", "preview": "vite preview",
"storybook": "storybook dev -p 6006", "storybook": "storybook dev -p 6006",
"build-storybook": "storybook build", "build-storybook": "storybook build",
"test-storybook": "test-storybook" "test-storybook": "test-storybook",
"format:check": "yarn prettier --check src",
"format": "yarn prettier --write src"
}, },
"resolutions": { "resolutions": {
"@tamagui/web": "1.36.4", "@tamagui/web": "1.36.4",

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,5 +1,3 @@
<svg width="74" height="60" viewBox="0 0 74 60" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg xmlns="http://www.w3.org/2000/svg" width="74" height="60" viewBox="0 0 74 60" fill="none">
<g id="Frame 31443"> <path d="M59.1019 45.0375V59.0747C51.3854 59.0747 47.4072 58.373 42.7293 52.0562C38.0514 45.7393 35.0293 45.0373 31.0346 45.0373V59.0747H17.001V45.0373H31.0346V31C38.2347 31 42.7293 31.9358 47.4072 38.0187C52.0851 44.1016 54.5517 45.0375 59.1019 45.0375V31H73.1355V45.0375H59.1019Z" fill="#DCE0E5"/>
<path id="Vector" d="M59.1019 45.0375V59.0747C51.3854 59.0747 47.4072 58.373 42.7293 52.0562C38.0514 45.7393 35.0293 45.0373 31.0346 45.0373V59.0747H17.001V45.0373H31.0346V31C38.2347 31 42.7293 31.9358 47.4072 38.0187C52.0851 44.1016 54.5517 45.0375 59.1019 45.0375V31H73.1355V45.0375H59.1019Z" fill="#DCE0E5"/>
</g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 441 B

After

Width:  |  Height:  |  Size: 405 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 37 KiB

View File

@ -1,3 +1,3 @@
#root { #root {
width: 100%; width: 100%;
} }

View File

@ -1,6 +1,6 @@
import StandartLineChart from './StandardLineChart' import StandartLineChart from './StandardLineChart'
import IconText from '../General/IconText' import IconText from '../General/IconText'
import { Paragraph, Separator, XStack, YStack } from 'tamagui' import { Separator, XStack, YStack } from 'tamagui'
import { Shadow, Text } from '@status-im/components' import { Shadow, Text } from '@status-im/components'
import { CheckCircleIcon, IncorrectIcon } from '@status-im/icons' import { CheckCircleIcon, IncorrectIcon } from '@status-im/icons'
@ -38,8 +38,8 @@ const DeviceCPULoad: React.FC<DeviceCPULoadProps> = ({ load }) => {
<Shadow <Shadow
variant="$2" variant="$2"
style={{ style={{
width: '284px', width: '50%',
height: '136px', minHeight: '135px',
borderRadius: '16px', borderRadius: '16px',
border: message === 'Poor' ? '1px solid #D92344' : 'none', border: message === 'Poor' ? '1px solid #D92344' : 'none',
backgroundColor: message === 'Poor' ? '#fefafa' : '#fff', backgroundColor: message === 'Poor' ? '#fefafa' : '#fff',
@ -49,7 +49,7 @@ const DeviceCPULoad: React.FC<DeviceCPULoadProps> = ({ load }) => {
<XStack <XStack
justifyContent="space-between" justifyContent="space-between"
style={{ style={{
padding: '8px 16px', padding: '0.75rem 1rem',
position: 'relative', position: 'relative',
}} }}
> >
@ -57,16 +57,16 @@ const DeviceCPULoad: React.FC<DeviceCPULoadProps> = ({ load }) => {
<StandartLineChart data={chartData} /> <StandartLineChart data={chartData} />
</div> </div>
<YStack space={'$3'}> <YStack space={'$3'}>
<Paragraph color={'#09101C'} size={'$6'} fontWeight={'600'}> <Text size={15} weight={'semibold'}>
CPU CPU
</Paragraph> </Text>
<Paragraph color={'#09101C'} size={'$8'} fontWeight={'700'}> <Text size={27} weight={'semibold'}>
{currentLoad} GB {currentLoad} GB
</Paragraph> </Text>
</YStack> </YStack>
</XStack> </XStack>
<Separator borderColor={'#e3e3e3'} /> <Separator borderColor={'#e3e3e3'} />
<XStack space={'$4'} style={{ padding: '10px 16px 10px 16px' }}> <XStack space={'$4'} style={{ padding: '0.65rem 1rem' }}>
<IconText <IconText
icon={message === 'Good' ? <CheckCircleIcon size={16} /> : <IncorrectIcon size={16} />} icon={message === 'Good' ? <CheckCircleIcon size={16} /> : <IncorrectIcon size={16} />}
weight={'semibold'} weight={'semibold'}
@ -74,7 +74,7 @@ const DeviceCPULoad: React.FC<DeviceCPULoadProps> = ({ load }) => {
{message} {message}
</IconText> </IconText>
{message === 'Poor' && ( {message === 'Poor' && (
<Text size={13} color="#E95460"> <Text size={13} color={'#E95460'} weight={'semibold'}>
{((currentLoad / 80) * 100).toFixed(0)}% Utilization {((currentLoad / 80) * 100).toFixed(0)}% Utilization
</Text> </Text>
)} )}

View File

@ -1,7 +1,7 @@
import StandartLineChart from './StandardLineChart' import StandartLineChart from './StandardLineChart'
import IconText from '../General/IconText' import IconText from '../General/IconText'
import { Paragraph, Separator, XStack, YStack } from 'tamagui' import { Separator, XStack, YStack } from 'tamagui'
import { Shadow as ShadowBox, Text } from '@status-im/components' import { Shadow as ShadowBox, Text } from '@status-im/components'
import { CheckCircleIcon, IncorrectIcon } from '@status-im/icons' import { CheckCircleIcon, IncorrectIcon } from '@status-im/icons'
@ -42,8 +42,8 @@ const DeviceMemoryHealth = ({ currentMemory, maxMemory }: DeviceMemoryHealthProp
<ShadowBox <ShadowBox
variant="$2" variant="$2"
style={{ style={{
width: '284px', width: '50%',
height: '136px', minHeight: '135px',
borderRadius: '16px', borderRadius: '16px',
border: message === 'Poor' ? '1px solid #D92344' : 'none', border: message === 'Poor' ? '1px solid #D92344' : 'none',
backgroundColor: message === 'Poor' ? '#fefafa' : '#fff', backgroundColor: message === 'Poor' ? '#fefafa' : '#fff',
@ -53,7 +53,7 @@ const DeviceMemoryHealth = ({ currentMemory, maxMemory }: DeviceMemoryHealthProp
<XStack <XStack
justifyContent="space-between" justifyContent="space-between"
style={{ style={{
padding: '8px 16px', padding: '0.75rem 1rem',
position: 'relative', position: 'relative',
}} }}
> >
@ -61,23 +61,24 @@ const DeviceMemoryHealth = ({ currentMemory, maxMemory }: DeviceMemoryHealthProp
<StandartLineChart data={chartData} /> <StandartLineChart data={chartData} />
</div> </div>
<YStack space={'$3'}> <YStack space={'$3'}>
<Paragraph color={'#09101C'} size={'$6'} fontWeight={'600'}> <Text size={15} weight={'semibold'}>
Memory Memory
</Paragraph> </Text>
<Paragraph color={'#09101C'} size={'$8'} fontWeight={'700'}> <Text size={27} weight={'semibold'}>
{currentLoad} GB {currentLoad} GB
</Paragraph> </Text>
</YStack> </YStack>
</XStack> </XStack>
<Separator borderColor={'#e3e3e3'} /> <Separator borderColor={'#e3e3e3'} />
<XStack space={'$4'} style={{ padding: '10px 16px 10px 16px' }}> <XStack space={'$4'} style={{ padding: '0.65rem 1rem' }}>
<IconText <IconText
icon={message === 'Good' ? <CheckCircleIcon size={16} /> : <IncorrectIcon size={16} />} icon={message === 'Good' ? <CheckCircleIcon size={16} /> : <IncorrectIcon size={16} />}
weight={'semibold'}
> >
{message} {message}
</IconText> </IconText>
{message === 'Poor' && ( {message === 'Poor' && (
<Text size={13} color="#E95460"> <Text size={13} color={'#E95460'} weight={'semibold'}>
{((currentLoad / maxMemory || 0) * 100).toFixed(0)}% Utilization {((currentLoad / maxMemory || 0) * 100).toFixed(0)}% Utilization
</Text> </Text>
)} )}

View File

@ -1,6 +1,6 @@
import StandartLineChart from './StandardLineChart' import StandartLineChart from './StandardLineChart'
import IconText from '../General/IconText' import IconText from '../General/IconText'
import { Paragraph, Separator, XStack, YStack } from 'tamagui' import { Separator, XStack, YStack } from 'tamagui'
import { Shadow as ShadowBox, Text } from '@status-im/components' import { Shadow as ShadowBox, Text } from '@status-im/components'
import { CheckCircleIcon, IncorrectIcon } from '@status-im/icons' import { CheckCircleIcon, IncorrectIcon } from '@status-im/icons'
@ -47,8 +47,8 @@ const DeviceNetworkHealth = ({ uploadRate, downloadRate }: DeviceNetworkHealthPr
<ShadowBox <ShadowBox
variant="$2" variant="$2"
style={{ style={{
width: '284px', width: '50%',
height: '136px', minHeight: '135px',
borderRadius: '16px', borderRadius: '16px',
border: message === 'Poor' ? '1px solid #D92344' : 'none', border: message === 'Poor' ? '1px solid #D92344' : 'none',
backgroundColor: message === 'Poor' ? '#fefafa' : '#fff', backgroundColor: message === 'Poor' ? '#fefafa' : '#fff',
@ -58,7 +58,7 @@ const DeviceNetworkHealth = ({ uploadRate, downloadRate }: DeviceNetworkHealthPr
<XStack <XStack
justifyContent="space-between" justifyContent="space-between"
style={{ style={{
padding: '8px 16px', padding: '0.75rem 1rem',
position: 'relative', position: 'relative',
}} }}
> >
@ -66,23 +66,24 @@ const DeviceNetworkHealth = ({ uploadRate, downloadRate }: DeviceNetworkHealthPr
<StandartLineChart data={chartData} /> <StandartLineChart data={chartData} />
</div> </div>
<YStack space={'$3'}> <YStack space={'$3'}>
<Paragraph color={'#09101C'} size={'$6'} fontWeight={'600'}> <Text size={15} weight={'semibold'}>
Network Network
</Paragraph> </Text>
<Paragraph color={'#09101C'} size={'$8'} fontWeight={'700'}> <Text size={27} weight={'semibold'}>
{currentLoad} GB {currentLoad} GB
</Paragraph> </Text>
</YStack> </YStack>
</XStack> </XStack>
<Separator borderColor={'#e3e3e3'} /> <Separator borderColor={'#e3e3e3'} />
<XStack space={'$4'} style={{ padding: '10px 16px 10px 16px' }}> <XStack space={'$4'} style={{ padding: '0.65rem 1rem' }}>
<IconText <IconText
icon={message === 'Good' ? <CheckCircleIcon size={16} /> : <IncorrectIcon size={16} />} icon={message === 'Good' ? <CheckCircleIcon size={16} /> : <IncorrectIcon size={16} />}
weight={'semibold'}
> >
{message} {message}
</IconText> </IconText>
{message === 'Poor' && ( {message === 'Poor' && (
<Text size={13} color="#E95460"> <Text size={13} color={'#E95460'} weight={'semibold'}>
{((currentLoad / 60) * 100).toFixed(0)}% Utilization {((currentLoad / 60) * 100).toFixed(0)}% Utilization
</Text> </Text>
)} )}

View File

@ -1,5 +1,5 @@
import IconText from '../General/IconText' import IconText from '../General/IconText'
import { Paragraph, Separator, XStack, YStack } from 'tamagui' import { Separator, XStack, YStack } from 'tamagui'
import StandardGauge from './StandardGauge' import StandardGauge from './StandardGauge'
import { Shadow, Text } from '@status-im/components' import { Shadow, Text } from '@status-im/components'
import { CheckCircleIcon, IncorrectIcon } from '@status-im/icons' import { CheckCircleIcon, IncorrectIcon } from '@status-im/icons'
@ -33,8 +33,8 @@ const DeviceStorageHealth: React.FC<DeviceStorageHealthProps> = ({ storage, maxS
<Shadow <Shadow
variant="$2" variant="$2"
style={{ style={{
width: '284px', width: '50%',
height: '136px', minHeight: '135px',
borderRadius: '16px', borderRadius: '16px',
border: message === 'Poor' ? '1px solid #D92344' : 'none', border: message === 'Poor' ? '1px solid #D92344' : 'none',
backgroundColor: message === 'Poor' ? '#fefafa' : '#fff', backgroundColor: message === 'Poor' ? '#fefafa' : '#fff',
@ -44,31 +44,31 @@ const DeviceStorageHealth: React.FC<DeviceStorageHealthProps> = ({ storage, maxS
<XStack <XStack
justifyContent="space-between" justifyContent="space-between"
style={{ style={{
padding: '8px 16px', padding: '0.75rem 1rem',
position: 'relative', position: 'relative',
}} }}
> >
<div <div
style={{ style={{
position: 'absolute', position: 'absolute',
right: '44px', right: '33px',
width: '75px', width: '4.75rem',
height: '75px', height: '4.75rem',
}} }}
> >
<StandardGauge data={data(free)} /> <StandardGauge data={data(free)} />
</div> </div>
<YStack space={'$3'}> <YStack space={'$3'}>
<Paragraph color={'#09101C'} size={'$6'} fontWeight={'600'}> <Text size={15} weight={'semibold'}>
Storage Storage
</Paragraph> </Text>
<Paragraph color={'#09101C'} size={'$8'} fontWeight={'700'}> <Text size={27} weight={'semibold'}>
{storage} GB {storage} GB
</Paragraph> </Text>
</YStack> </YStack>
</XStack> </XStack>
<Separator borderColor={'#e3e3e3'} /> <Separator borderColor={'#e3e3e3'} />
<XStack space={'$4'} style={{ padding: '10px 16px 10px 16px' }}> <XStack space={'$4'} style={{ padding: '0.65rem 1rem' }}>
<IconText <IconText
icon={message === 'Good' ? <CheckCircleIcon size={16} /> : <IncorrectIcon size={16} />} icon={message === 'Good' ? <CheckCircleIcon size={16} /> : <IncorrectIcon size={16} />}
weight={'semibold'} weight={'semibold'}
@ -76,7 +76,7 @@ const DeviceStorageHealth: React.FC<DeviceStorageHealthProps> = ({ storage, maxS
{message} {message}
</IconText> </IconText>
{message === 'Poor' && ( {message === 'Poor' && (
<Text size={13} color="#E95460"> <Text size={13} color={'#E95460'} weight={'semibold'}>
{utilization.toFixed(0)}% Utilization {utilization.toFixed(0)}% Utilization
</Text> </Text>
)} )}

View File

@ -1,30 +1,30 @@
.breadcrumb-bar-nav { .breadcrumb-bar-nav {
width: 100%; width: 100%;
flex: 1 1 100%; flex: 1 1 100%;
padding: 1rem 2rem; padding: 1rem 2rem;
margin: 0.5rem; margin: 0.5rem;
} }
.breadcrumb-bar-ul { .breadcrumb-bar-ul {
display: flex; display: flex;
} }
.breadcrumb-bar-li { .breadcrumb-bar-li {
color: #647084; color: #647084;
font-weight: 500; font-weight: 500;
position: relative; position: relative;
} }
.breadcrumb-bar-li:last-child { .breadcrumb-bar-li:last-child {
color: #09101C; color: #09101c;
} }
.breadcrumb-bar-li::after { .breadcrumb-bar-li::after {
display: inline-block; display: inline-block;
content: url("./icons/chevron.svg"); content: url('./icons/chevron.svg');
color: #09101C; color: #09101c;
position: absolute; position: absolute;
top: 2px; top: 2px;
left: 100%; left: 100%;
transform: translateX(-50%); transform: translateX(-50%);
} }
.breadcrumb-bar-li:last-child::after { .breadcrumb-bar-li:last-child::after {
display: none; display: none;
} }

View File

@ -1,40 +1,40 @@
.color-picker-button { .color-picker-button {
width: 40px; width: 40px;
height: 40px; height: 40px;
border-radius: 50%; border-radius: 50%;
margin-bottom: 10px; margin-bottom: 10px;
margin-right: 10px; margin-right: 10px;
position: relative; position: relative;
outline: none; outline: none;
border: none; border: none;
} }
.color-picker-button::before , .color-picker-button::before,
.color-picker-button::after { .color-picker-button::after {
display: block; display: block;
content: ""; content: '';
position: absolute; position: absolute;
top: 50%; top: 50%;
left: 50%; left: 50%;
transform: translate(-50%,-50%); transform: translate(-50%, -50%);
transform-origin: center; transform-origin: center;
opacity: 0; opacity: 0;
transition: 120ms opacity ease-in-out; transition: 120ms opacity ease-in-out;
} }
.color-picker-button::before { .color-picker-button::before {
content: "\2713"; content: '\2713';
font-size: 25px; font-size: 25px;
color: white; color: white;
} }
.color-picker-button::after { .color-picker-button::after {
width: 40px; width: 40px;
height: 40px; height: 40px;
border-radius: 50%; border-radius: 50%;
border: 3px solid currentColor; border: 3px solid currentColor;
} }
.color-picker-button:focus::before, .color-picker-button:focus::before,
.color-picker-button:focus::after, .color-picker-button:focus::after,
.color-picker-button:hover::after { .color-picker-button:hover::after {
opacity: 1; opacity: 1;
} }

View File

@ -1,10 +1,10 @@
.device-avatar { .device-avatar {
width: 80px; width: 80px;
height: 80px; height: 80px;
border-radius: 50%; border-radius: 50%;
flex-grow: 1; flex-grow: 1;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
margin-right: -30px; margin-right: -30px;
} }

View File

@ -1,4 +1,4 @@
import { useState } from 'react' import { useEffect, useRef, useState } from 'react'
import { XStack, YStack } from 'tamagui' import { XStack, YStack } from 'tamagui'
import { Avatar, Text } from '@status-im/components' import { Avatar, Text } from '@status-im/components'
import { ReactionIcon } from '@status-im/icons' import { ReactionIcon } from '@status-im/icons'
@ -6,15 +6,30 @@ import './CreateAvatar.css'
import LabelInputField from '../LabelInputField' import LabelInputField from '../LabelInputField'
import ColorPicker from '../ColorPicker/ColorPicker' import ColorPicker from '../ColorPicker/ColorPicker'
import EmojiPickerDialog from '../EmojiPickerDialog' import EmojiPickerDialog from '../EmojiPickerDialog'
import { Emoji, EmojiClickData } from 'emoji-picker-react' import { Emoji, EmojiClickData, EmojiStyle } from 'emoji-picker-react'
const CreateAvatar = () => { const CreateAvatar = () => {
const [chosenColor, setChosenColor] = useState('#2A4AF5') const [chosenColor, setChosenColor] = useState('#2A4AF5')
const [isEmojiDialogOpen, setIsEmojiDialogOpen] = useState(false) const [isEmojiDialogOpen, setIsEmojiDialogOpen] = useState(false)
const [selectedEmoji, setSelectedEmoji] = useState<string>('1f600') const [selectedEmoji, setSelectedEmoji] = useState<string>('1f600')
const emojiRef = useRef<HTMLDivElement | null>(null)
function changeEmoji(emojiData: EmojiClickData) { function changeEmoji(emojiData: EmojiClickData) {
setSelectedEmoji(emojiData.unified) setSelectedEmoji(emojiData.unified)
} }
useEffect(() => {
function handleClickOutside(event: any) {
if (emojiRef.current && !emojiRef.current.contains(event.target)) {
setIsEmojiDialogOpen(false)
}
}
document.addEventListener('mousedown', handleClickOutside)
return () => {
document.removeEventListener('mousedown', handleClickOutside)
}
}, [emojiRef])
return ( return (
<YStack my={16}> <YStack my={16}>
<XStack space> <XStack space>
@ -27,7 +42,9 @@ const CreateAvatar = () => {
</Text> </Text>
<XStack my={10} alignItems={'end'}> <XStack my={10} alignItems={'end'}>
<div className="device-avatar" style={{ background: chosenColor }}> <div className="device-avatar" style={{ background: chosenColor }}>
{selectedEmoji ? <Emoji unified={selectedEmoji} size={30} /> : null} {selectedEmoji ? (
<Emoji unified={selectedEmoji} emojiStyle={EmojiStyle.TWITTER} size={30} />
) : null}
</div> </div>
<Avatar <Avatar
type="icon" type="icon"
@ -40,9 +57,11 @@ const CreateAvatar = () => {
/> />
} }
/> />
{isEmojiDialogOpen && ( <div ref={emojiRef}>
<EmojiPickerDialog changeEmoji={changeEmoji} emojiStyle="TWITTER" /> {isEmojiDialogOpen && (
)} <EmojiPickerDialog changeEmoji={changeEmoji} emojiStyle="TWITTER" />
)}
</div>
</XStack> </XStack>
</YStack> </YStack>
<YStack flexWrap="wrap" width="80%"> <YStack flexWrap="wrap" width="80%">

View File

@ -1,7 +1,6 @@
import type { Meta, StoryObj } from '@storybook/react' import type { Meta, StoryObj } from '@storybook/react'
import EmojiPickerDialog from './EmojiPickerDialog' import EmojiPickerDialog from './EmojiPickerDialog'
const meta = { const meta = {
title: 'General/EmojiPickerDialog', title: 'General/EmojiPickerDialog',
component: EmojiPickerDialog, component: EmojiPickerDialog,
@ -15,5 +14,5 @@ export default meta
type Story = StoryObj<typeof meta> type Story = StoryObj<typeof meta>
export const DefaultColors: Story = { export const DefaultColors: Story = {
args: {emojiStyle: 'TWITTER'}, args: { emojiStyle: 'TWITTER' },
} }

View File

@ -16,13 +16,13 @@ type EmojiPickerProps = {
function EmojiPickerDialog({ emojiStyle, changeEmoji }: EmojiPickerProps) { function EmojiPickerDialog({ emojiStyle, changeEmoji }: EmojiPickerProps) {
return ( return (
<Stack position="absolute" zIndex={1} left={100}> <Stack position="absolute" zIndex={1} left={100} top={-150}>
<EmojiPicker <EmojiPicker
onEmojiClick={changeEmoji} onEmojiClick={changeEmoji}
autoFocusSearch={false} autoFocusSearch={false}
theme={Theme.AUTO} theme={Theme.AUTO}
height={350} height={'50vh'}
width={350} width={'50vw'}
emojiVersion="1" emojiVersion="1"
lazyLoadEmojis={false} lazyLoadEmojis={false}
previewConfig={{ showPreview: false }} previewConfig={{ showPreview: false }}

View File

@ -8,7 +8,7 @@ type HeaderProps = {
const Header = ({ selectedTag }: HeaderProps) => { const Header = ({ selectedTag }: HeaderProps) => {
return ( return (
<XStack justifyContent="space-between" py={'25px'} mt={'70px'}> <XStack justifyContent="space-between" py={'25px'} mt={'4.4rem'}>
<NimbusLogo /> <NimbusLogo />
<TagContainer selectedTag={selectedTag} /> <TagContainer selectedTag={selectedTag} />
</XStack> </XStack>

View File

@ -17,7 +17,7 @@ const IconText = ({ icon, children, weight }: IconTextProps) => {
space={'$2'} space={'$2'}
> >
{icon} {icon}
<Text size={13} color={'#000000'} weight={weight}> <Text size={13} color={'#09101C'} weight={weight}>
{children} {children}
</Text> </Text>
</XStack> </XStack>

View File

@ -1,6 +1,6 @@
.input-container { .input-container {
background-color: #fff; background-color: #fff;
border-radius: 12px; border-radius: 12px;
margin-top: 8px; margin-top: 8px;
width: 100%; width: 100%;
} }

View File

@ -37,7 +37,15 @@ const LinkWithArrow = ({
onClick={navigateHandler} onClick={navigateHandler}
> >
{arrowLeft && <ArrowLeftIcon size={20} color="#2A4CF4" />} {arrowLeft && <ArrowLeftIcon size={20} color="#2A4CF4" />}
<Link style={{ color: textColor || '#2A4CF4', marginBottom: '2px' }} to={to}> <Link
style={{
color: textColor || '#2A4CF4',
marginBottom: '2px',
fontSize: 'inherit',
fontWeight: 'inherit',
}}
to={to}
>
{text} {text}
</Link> </Link>
{arrowRight && <ArrowRightIcon size={20} color="#2A4CF4" />} {arrowRight && <ArrowRightIcon size={20} color="#2A4CF4" />}

View File

@ -1,28 +1,28 @@
.quick-start-bar { .quick-start-bar {
border-radius: 18px; border-radius: 18px;
border: 1px solid rgba(0, 0, 0, 0.10); border: 1px solid rgba(0, 0, 0, 0.1);
opacity: 0.949999988079071; opacity: 0.949999988079071;
background: rgba(255, 255, 255, 0.70); background: rgba(255, 255, 255, 0.7);
backdrop-filter: blur(15px); backdrop-filter: blur(15px);
display: flex; display: flex;
align-items: center; align-items: center;
width: 66%; width: 66%;
margin: 0 auto; margin: 0 auto;
padding: 12px 1rem; padding: 12px 1rem;
position: relative; position: relative;
top: -18vh; top: -18vh;
} }
.quick-start-bar > div { .quick-start-bar > div {
width: 100%; width: 100%;
border-radius: 24px; border-radius: 24px;
background: rgba(100, 112, 132, 0.05); background: rgba(100, 112, 132, 0.05);
margin-left: 1rem; margin-left: 1rem;
padding: 1rem 0.5rem; padding: 1rem 0.5rem;
} }
.quick-start-bar ul { .quick-start-bar ul {
display: flex; display: flex;
} }
.quick-start-bar ul li { .quick-start-bar ul li {
color: #0D1625; color: #0d1625;
font-size: 13px; font-size: 13px;
} }

View File

@ -1,3 +1,3 @@
/* .tag-container div:nth-child(1) { /* .tag-container div:nth-child(1) {
background:transparent; background:transparent;
} */ } */

View File

@ -1,10 +1,9 @@
.nimbus-logomark {
.nimbus-logomark{ display: flex;
display: flex; justify-content: center;
justify-content: center; align-items: center;
align-items: center;
} }
.nimbus-logomark svg { .nimbus-logomark svg {
width: auto; width: auto;
height: 24px; height: 24px;
} }

View File

@ -8,6 +8,7 @@ type PageWrapperShadowProps = {
rightImageSrc?: string rightImageSrc?: string
rightImageLogo?: boolean rightImageLogo?: boolean
children: ReactNode children: ReactNode
imgHeight?: string
} }
const PageWrapperShadow = ({ const PageWrapperShadow = ({
@ -15,6 +16,7 @@ const PageWrapperShadow = ({
rightImageSrc, rightImageSrc,
rightImageLogo, rightImageLogo,
children, children,
imgHeight,
}: PageWrapperShadowProps) => { }: PageWrapperShadowProps) => {
const theme = useTheme() const theme = useTheme()
@ -26,10 +28,15 @@ const PageWrapperShadow = ({
<div className="container-inner">{children}</div> <div className="container-inner">{children}</div>
</div> </div>
</section> </section>
<section className="layout-right"> <section className="layout-right">
<div className="image-container"> <div className="image-container">
<img src={rightImageSrc} alt="background" className="background-img" /> <img
src={rightImageSrc}
alt="background"
className="background-img"
style={{ height: imgHeight }}
/>
{rightImageLogo ? <NimbusLogoMark /> : null} {rightImageLogo ? <NimbusLogoMark /> : null}
</div> </div>
</section> </section>

View File

@ -1,85 +1,85 @@
.layout{ .layout {
background-color: #FFF; background-color: #fff;
height: 100%; height: 100%;
position: relative; position: relative;
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
overflow: hidden; overflow: hidden;
} }
.layout::after { .layout::after {
display: block; display: block;
content: ""; content: '';
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
width: 100%; width: 100%;
height: 100%; height: 100%;
background: linear-gradient(to bottom, rgba(113, 64, 253, 0.075) 15%, rgba(255,255,255,0) 50%); background: linear-gradient(to bottom, rgba(113, 64, 253, 0.075) 15%, rgba(255, 255, 255, 0) 50%);
} }
.layout-left { .layout-left {
flex: 0 0 55%; flex: 0 0 55%;
max-width: 55%; max-width: 55%;
z-index: 2; z-index: 2;
} }
.container { .container {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
justify-content: end; justify-content: end;
height: 100%; height: 100%;
/* padding: 70px 0 0; */ /* padding: 70px 0 0; */
} }
.container-inner { .container-inner {
max-width: 70%; max-width: 70%;
flex: 1 0 70%; flex: 1 0 70%;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
} }
.content { .content {
flex-grow: 1; flex-grow: 1;
} }
/* LAYOUT RIGHT ELEMENT WITH IMAGE TAKING UP THE WHOLE HIGHT OF THE VIEWPORT */ /* LAYOUT RIGHT ELEMENT WITH IMAGE TAKING UP THE WHOLE HIGHT OF THE VIEWPORT */
.layout-right { .layout-right {
flex: 0 0 45%; flex: 0 0 45%;
max-width: 45%; max-width: 45%;
z-index: 0; z-index: 0;
} }
.image-container { .image-container {
height: 100%; height: 100%;
position: relative; position: relative;
overflow: hidden; overflow: hidden;
color: #FFF; color: #fff;
} }
.image-container::before { .image-container::before {
display: block; display: block;
content: ""; content: '';
padding-bottom: 100%; padding-bottom: 100%;
} }
.image-container::after { .image-container::after {
display: block; display: block;
content: ""; content: '';
position: absolute; position: absolute;
top: 0; top: 0;
left: -1%; left: -1%;
width: 50%; width: 50%;
height: 100%; height: 100%;
background: linear-gradient(to right, rgba(255, 255, 255, 1) 20%, rgba(255, 255, 255, 0.0)); background: linear-gradient(to right, rgba(255, 255, 255, 1) 20%, rgba(255, 255, 255, 0));
} }
.image-container .background-img { .image-container .background-img {
position: absolute; position: absolute;
top: 50%; top: 50%;
left: 50%; left: 50%;
transform: translate(-50%, -50%); transform: translate(-50%, -50%);
height: 140%; height: 140%;
width: auto; width: auto;
} }
.image-container .nimbus-logomark { .image-container .nimbus-logomark {
position: absolute; position: absolute;
top: 50%; top: 50%;
left: 50%; left: 50%;
transform: translate(-50%, -50%); transform: translate(-50%, -50%);
} }
.image-container .nimbus-logomark svg { .image-container .nimbus-logomark svg {
height: 73px; height: 73px;
} }

View File

@ -1,12 +1,55 @@
@font-face {
font-family: 'Inter';
src: url('./Inter-font/Inter-Light.ttf') format('truetype');
font-weight: 300;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Inter';
src: url('./Inter-font/Inter-Regular.ttf') format('truetype');
font-weight: 400;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Inter';
src: url('./Inter-font/Inter-Medium.ttf') format('truetype');
font-weight: 600;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Inter';
src: url('./Inter-font/Inter-SemiBold.ttf') format('truetype');
font-weight: 700;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Inter';
src: url('./Inter-font/Inter-Bold.ttf') format('truetype');
font-weight: 800;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Inter';
src: url('./Inter-font/Inter-Black.ttf') format('truetype');
font-weight: 900;
font-style: normal;
font-display: swap;
}
:root { :root {
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
line-height: 1.5; line-height: 1.5;
font-weight: 400; font-weight: 400;
color-scheme: light dark; color-scheme: light dark;
color: rgba(0, 0, 0, 0.87); color: rgba(0, 0, 0, 0.87);
background-color: #242424; background-color: #242424;
font-synthesis: none; font-synthesis: none;
text-rendering: optimizeLegibility; text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
@ -22,7 +65,12 @@ body {
min-width: 320px; min-width: 320px;
min-height: 100vh; min-height: 100vh;
} }
h1, h2, h3, h4, h5, h6 { h1,
h2,
h3,
h4,
h5,
h6 {
line-height: 1.2; line-height: 1.2;
font-weight: 700; font-weight: 700;
} }
@ -44,7 +92,7 @@ button:focus,
button:focus-visible { button:focus-visible {
outline: 4px auto -webkit-focus-ring-color; outline: 4px auto -webkit-focus-ring-color;
} }
ul{ ul {
list-style-type: none; list-style-type: none;
padding: 0; padding: 0;
margin: 0; margin: 0;
@ -55,7 +103,7 @@ ul li {
} }
@media (prefers-color-scheme: light) { @media (prefers-color-scheme: light) {
:root { :root {
color: #09101C; color: #09101c;
background-color: #ffffff; background-color: #ffffff;
} }
a:hover { a:hover {

View File

@ -38,7 +38,6 @@ const BalanceChartCard = () => {
return ( return (
<DashboardCardWrapper> <DashboardCardWrapper>
<YStack space={'$4'} style={{ width: '536px' }}> <YStack space={'$4'} style={{ width: '536px' }}>
<XStack justifyContent={'space-between'}> <XStack justifyContent={'space-between'}>
<YStack> <YStack>
@ -90,11 +89,10 @@ const BalanceChartCard = () => {
onSelect={handleRangeSelect} onSelect={handleRangeSelect}
/> />
)} )}
<Stack > <Stack>
<LineChart years={filteredYears} userGains={filteredUserGains} /> <LineChart years={filteredYears} userGains={filteredUserGains} />
</Stack> </Stack>
</YStack> </YStack>
</DashboardCardWrapper> </DashboardCardWrapper>
) )
} }

View File

@ -31,9 +31,7 @@ const LineChart = ({ years, userGains }: LineChartProps) => {
], ],
options: { options: {
responsive: true, responsive: true,
}, },
} }
return <Line options={data.options} data={data} /> return <Line options={data.options} data={data} />

View File

@ -1,354 +1,354 @@
.rdp { .rdp {
--rdp-cell-size: 32px; --rdp-cell-size: 32px;
--rdp-caption-font-size: 15px; --rdp-caption-font-size: 15px;
--rdp-accent-color: #2a4af5; --rdp-accent-color: #2a4af5;
--rdp-background-color: #e7edff; --rdp-background-color: #e7edff;
--rdp-background-color-selected-secondary: #f5f6f8; --rdp-background-color-selected-secondary: #f5f6f8;
--rdp-hover-color: #f5f6f8; --rdp-hover-color: #f5f6f8;
--rdp-hover-color-darker: #f0f2f5; --rdp-hover-color-darker: #f0f2f5;
--rdp-accent-color-dark: #223bc4; --rdp-accent-color-dark: #223bc4;
--rdp-outline: 2px solid var(--rdp-accent-color); /* Outline border for focused elements */ --rdp-outline: 2px solid var(--rdp-accent-color); /* Outline border for focused elements */
--rdp-outline-selected: 3px solid var(--rdp-accent-color); /* Outline border for focused _and_ selected elements */ --rdp-outline-selected: 3px solid var(--rdp-accent-color); /* Outline border for focused _and_ selected elements */
--rdp-text-color: #09101c; --rdp-text-color: #09101c;
color: var(--rdp-text-color); color: var(--rdp-text-color);
font-family: Inter, sans-serif; font-family: Inter, sans-serif;
font-weight: 500; font-weight: 500;
user-select: none; user-select: none;
} }
/* Hide elements for devices that are not screen readers */ /* Hide elements for devices that are not screen readers */
.rdp-vhidden { .rdp-vhidden {
box-sizing: border-box; box-sizing: border-box;
padding: 0; padding: 0;
margin: 0; margin: 0;
background: transparent; background: transparent;
border: 0; border: 0;
-moz-appearance: none; -moz-appearance: none;
-webkit-appearance: none; -webkit-appearance: none;
appearance: none; appearance: none;
position: absolute !important; position: absolute !important;
top: 0; top: 0;
width: 1px !important; width: 1px !important;
height: 1px !important; height: 1px !important;
padding: 0 !important; padding: 0 !important;
overflow: hidden !important; overflow: hidden !important;
clip: rect(1px, 1px, 1px, 1px) !important; clip: rect(1px, 1px, 1px, 1px) !important;
border: 0 !important; border: 0 !important;
} }
/* Buttons */ /* Buttons */
.rdp-button_reset { .rdp-button_reset {
appearance: none; appearance: none;
position: relative; position: relative;
margin: 0; margin: 0;
padding: 0; padding: 0;
cursor: default; cursor: default;
color: inherit; color: inherit;
background: none; background: none;
font: inherit; font: inherit;
-moz-appearance: none; -moz-appearance: none;
-webkit-appearance: none; -webkit-appearance: none;
} }
.rdp-button_reset:focus-visible { .rdp-button_reset:focus-visible {
/* Make sure to reset outline only when :focus-visible is supported */ /* Make sure to reset outline only when :focus-visible is supported */
outline: none; outline: none;
} }
.rdp-button { .rdp-button {
border: 2px solid transparent; border: 2px solid transparent;
font-size: 0.8125rem; font-size: 0.8125rem;
} }
.rdp-button[disabled]:not(.rdp-day_selected) { .rdp-button[disabled]:not(.rdp-day_selected) {
opacity: 0.25; opacity: 0.25;
} }
.rdp-button:not([disabled]) { .rdp-button:not([disabled]) {
cursor: pointer; cursor: pointer;
} }
.rdp-button:focus-visible:not([disabled]) { .rdp-button:focus-visible:not([disabled]) {
color: inherit; color: inherit;
background-color: var(--rdp-background-color); background-color: var(--rdp-background-color);
border: var(--rdp-outline); border: var(--rdp-outline);
} }
.rdp-button:hover:not([disabled]):not(.rdp-day_selected) { .rdp-button:hover:not([disabled]):not(.rdp-day_selected) {
background-color: var(--rdp-hover-color); background-color: var(--rdp-hover-color);
} }
.rdp-months { .rdp-months {
display: flex; display: flex;
} }
.rdp-month { .rdp-month {
margin: 0 1em; margin: 0 1em;
} }
.rdp-month:first-child { .rdp-month:first-child {
margin-left: 0; margin-left: 0;
} }
.rdp-month:last-child { .rdp-month:last-child {
margin-right: 0; margin-right: 0;
} }
.rdp-table { .rdp-table {
margin: 0; margin: 0;
max-width: calc(var(--rdp-cell-size) * 7); max-width: calc(var(--rdp-cell-size) * 7);
border-collapse: separate; border-collapse: separate;
border-spacing: 0 2px; border-spacing: 0 2px;
padding: 0 0.75rem 0.625rem 0.75rem; padding: 0 0.75rem 0.625rem 0.75rem;
} }
.rdp-with_weeknumber .rdp-table { .rdp-with_weeknumber .rdp-table {
max-width: calc(var(--rdp-cell-size) * 8); max-width: calc(var(--rdp-cell-size) * 8);
border-collapse: collapse; border-collapse: collapse;
} }
.rdp-caption { .rdp-caption {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
padding: 0; padding: 0;
text-align: left; text-align: left;
} }
.rdp-multiple_months .rdp-caption { .rdp-multiple_months .rdp-caption {
position: relative; position: relative;
display: block; display: block;
text-align: center; text-align: center;
} }
.rdp-caption_dropdowns { .rdp-caption_dropdowns {
position: relative; position: relative;
display: inline-flex; display: inline-flex;
} }
.rdp-caption_label { .rdp-caption_label {
position: relative; position: relative;
z-index: 1; z-index: 1;
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
margin: 0; margin: 0;
white-space: nowrap; white-space: nowrap;
color: currentColor; color: currentColor;
font-family: inherit; font-family: inherit;
font-size: var(--rdp-caption-font-size); font-size: var(--rdp-caption-font-size);
font-weight: bold; font-weight: bold;
} }
.rdp-nav { .rdp-nav {
white-space: nowrap; white-space: nowrap;
padding: 0.375rem 0.375rem 0 0.75rem; padding: 0.375rem 0.375rem 0 0.75rem;
} }
.rdp-multiple_months .rdp-caption_start .rdp-nav { .rdp-multiple_months .rdp-caption_start .rdp-nav {
position: absolute; position: absolute;
top: 50%; top: 50%;
left: 0; left: 0;
transform: translateY(-50%); transform: translateY(-50%);
} }
.rdp-multiple_months .rdp-caption_end .rdp-nav { .rdp-multiple_months .rdp-caption_end .rdp-nav {
position: absolute; position: absolute;
top: 50%; top: 50%;
right: 0; right: 0;
transform: translateY(-50%); transform: translateY(-50%);
} }
.rdp-nav_button { .rdp-nav_button {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
width: 20px; width: 20px;
height: 20px; height: 20px;
padding: 0.25em; padding: 0.25em;
border-radius: 10px; border-radius: 10px;
} }
/* ---------- */ /* ---------- */
/* Dropdowns */ /* Dropdowns */
/* ---------- */ /* ---------- */
.rdp-dropdown_year, .rdp-dropdown_year,
.rdp-dropdown_month { .rdp-dropdown_month {
position: relative; position: relative;
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
} }
.rdp-dropdown { .rdp-dropdown {
appearance: none; appearance: none;
position: absolute; position: absolute;
z-index: 2; z-index: 2;
top: 0; top: 0;
bottom: 0; bottom: 0;
left: 0; left: 0;
width: 100%; width: 100%;
margin: 0; margin: 0;
padding: 0; padding: 0;
cursor: inherit; cursor: inherit;
opacity: 0; opacity: 0;
border: none; border: none;
background-color: transparent; background-color: transparent;
font-family: inherit; font-family: inherit;
font-size: inherit; font-size: inherit;
line-height: inherit; line-height: inherit;
} }
.rdp-dropdown[disabled] { .rdp-dropdown[disabled] {
opacity: unset; opacity: unset;
color: unset; color: unset;
} }
.rdp-dropdown:focus-visible:not([disabled]) + .rdp-caption_label { .rdp-dropdown:focus-visible:not([disabled]) + .rdp-caption_label {
background-color: var(--rdp-background-color); background-color: var(--rdp-background-color);
border: var(--rdp-outline); border: var(--rdp-outline);
border-radius: 6px; border-radius: 6px;
} }
.rdp-dropdown_icon { .rdp-dropdown_icon {
margin: 0 0 0 5px; margin: 0 0 0 5px;
} }
.rdp-head { .rdp-head {
border: 0; border: 0;
} }
.rdp-head_row, .rdp-head_row,
.rdp-row { .rdp-row {
height: 100%; height: 100%;
padding-bottom: 2px; padding-bottom: 2px;
} }
.rdp-head_cell { .rdp-head_cell {
vertical-align: middle; vertical-align: middle;
font-size: 0.8125em; font-size: 0.8125em;
font-weight: 500; font-weight: 500;
text-align: center; text-align: center;
height: var(--rdp-cell-size); height: var(--rdp-cell-size);
padding: 0; padding: 0;
line-height: 140%; line-height: 140%;
color: #647084; color: #647084;
letter-spacing: -0.003em; letter-spacing: -0.003em;
} }
.rdp-tbody { .rdp-tbody {
border: 0; border: 0;
} }
.rdp-tfoot { .rdp-tfoot {
margin: 0.5em; margin: 0.5em;
} }
.rdp-cell { .rdp-cell {
width: var(--rdp-cell-size); width: var(--rdp-cell-size);
height: var(--rdp-cell-size); height: var(--rdp-cell-size);
text-align: center; text-align: center;
padding: 0; padding: 0;
} }
.rdp-cell_selected_start { .rdp-cell_selected_start {
border-top-left-radius: 10px; border-top-left-radius: 10px;
border-bottom-left-radius: 10px; border-bottom-left-radius: 10px;
background-color: var(--rdp-background-color-selected-secondary); background-color: var(--rdp-background-color-selected-secondary);
} }
.rdp-cell_selected_end { .rdp-cell_selected_end {
border-top-right-radius: 10px; border-top-right-radius: 10px;
border-bottom-right-radius: 10px; border-bottom-right-radius: 10px;
background-color: var(--rdp-background-color-selected-secondary); background-color: var(--rdp-background-color-selected-secondary);
} }
.rdp-cell_selected_range { .rdp-cell_selected_range {
background-color: var(--rdp-background-color-selected-secondary); background-color: var(--rdp-background-color-selected-secondary);
} }
.rdp-weeknumber { .rdp-weeknumber {
font-size: 0.75em; font-size: 0.75em;
} }
.rdp-weeknumber, .rdp-weeknumber,
.rdp-day { .rdp-day {
display: flex; display: flex;
overflow: hidden; overflow: hidden;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
box-sizing: border-box; box-sizing: border-box;
width: var(--rdp-cell-size); width: var(--rdp-cell-size);
max-width: var(--rdp-cell-size); max-width: var(--rdp-cell-size);
height: var(--rdp-cell-size); height: var(--rdp-cell-size);
margin: 0; margin: 0;
border: 2px solid transparent; border: 2px solid transparent;
border-radius: 10px; border-radius: 10px;
} }
.rdp-day_today:not(.rdp-day_outside) { .rdp-day_today:not(.rdp-day_outside) {
position: relative; position: relative;
} }
.rdp-day_today:not(.rdp-day_outside)::after { .rdp-day_today:not(.rdp-day_outside)::after {
content: ''; content: '';
position: absolute; position: absolute;
bottom: 3px; bottom: 3px;
left: 50%; left: 50%;
width: 4px; width: 4px;
height: 2px; height: 2px;
transform: translateX(-50%); transform: translateX(-50%);
border-radius: 10px; border-radius: 10px;
background-color: var(--rdp-accent-color); background-color: var(--rdp-accent-color);
} }
.rdp-day_selected { .rdp-day_selected {
opacity: 1; opacity: 1;
background-color: var(--rdp-accent-color); background-color: var(--rdp-accent-color);
color: var(--rdp-background-color); color: var(--rdp-background-color);
transition: all 150ms ease-in-out; transition: all 150ms ease-in-out;
} }
.rdp-day_selected:focus-visible, .rdp-day_selected:focus-visible,
.rdp-day_selected:hover { .rdp-day_selected:hover {
opacity: 1; opacity: 1;
background-color: var(--rdp-accent-color-dark); background-color: var(--rdp-accent-color-dark);
border-radius: 10px; border-radius: 10px;
} }
.rdp-day_outside { .rdp-day_outside {
opacity: 0.3; opacity: 0.3;
} }
.rdp-day_selected:focus-visible { .rdp-day_selected:focus-visible {
/* Since the background is the same use again the outline */ /* Since the background is the same use again the outline */
outline: var(--rdp-outline); outline: var(--rdp-outline);
outline-offset: 2px; outline-offset: 2px;
z-index: 1; z-index: 1;
} }
.rdp[dir='rtl'] .rdp-day_range_start:not(.rdp-day_range_end) { .rdp[dir='rtl'] .rdp-day_range_start:not(.rdp-day_range_end) {
border-top-left-radius: 0; border-top-left-radius: 0;
border-bottom-left-radius: 0; border-bottom-left-radius: 0;
} }
.rdp[dir='rtl'] .rdp-day_range_end:not(.rdp-day_range_start) { .rdp[dir='rtl'] .rdp-day_range_end:not(.rdp-day_range_start) {
border-top-right-radius: 0; border-top-right-radius: 0;
border-bottom-right-radius: 0; border-bottom-right-radius: 0;
} }
.rdp-day_range_end.rdp-day_range_start { .rdp-day_range_end.rdp-day_range_start {
border-radius: 10px; border-radius: 10px;
} }
.rdp-day_range_middle { .rdp-day_range_middle {
color: var(--rdp-text-color); color: var(--rdp-text-color);
background-color: var(--rdp-background-color-selected-secondary); background-color: var(--rdp-background-color-selected-secondary);
} }
.rdp-day_range_middle:hover { .rdp-day_range_middle:hover {
color: var(--rdp-text-color); color: var(--rdp-text-color);
background-color: var(--rdp-hover-color-darker); background-color: var(--rdp-hover-color-darker);
} }

View File

@ -18,5 +18,5 @@ export const Default: Story = {
args: { load: [32, 12, 45, 10] }, args: { load: [32, 12, 45, 10] },
} }
export const BadStats: Story = { export const BadStats: Story = {
args:{load:[12,32,14,35,65,90]} args: { load: [12, 32, 14, 35, 65, 90] },
} }

View File

@ -39,15 +39,16 @@ const CPUCard = ({ load }: CPUCardProps) => {
const message = currentLoad < 80 ? 'Good' : 'Poor' const message = currentLoad < 80 ? 'Good' : 'Poor'
return ( return (
<DashboardCardWrapper padding='0'> <DashboardCardWrapper padding="0">
<YStack style={{ <YStack
width: '284px', style={{
height: '136px', width: '284px',
borderRadius: '16px', height: '136px',
border: message === 'Poor' ? '1px solid #D92344' : 'none', borderRadius: '16px',
backgroundColor: message === 'Poor' ? '#fefafa' : '#fff', border: message === 'Poor' ? '1px solid #D92344' : 'none',
backgroundColor: message === 'Poor' ? '#fefafa' : '#fff',
}}> }}
>
<XStack <XStack
justifyContent="space-between" justifyContent="space-between"
style={{ style={{

View File

@ -3,17 +3,17 @@ import type { Meta, StoryObj } from '@storybook/react'
import DeviceUptime from './DeviceUptime' import DeviceUptime from './DeviceUptime'
const meta = { const meta = {
title: 'Dashboard/DeviceUptime', title: 'Dashboard/DeviceUptime',
component: DeviceUptime, component: DeviceUptime,
parameters: { parameters: {
layout: 'centered', layout: 'centered',
}, },
tags: ['autodocs'], tags: ['autodocs'],
} satisfies Meta<typeof DeviceUptime> } satisfies Meta<typeof DeviceUptime>
export default meta export default meta
type Story = StoryObj<typeof meta> type Story = StoryObj<typeof meta>
export const Default: Story = { export const Default: Story = {
args: {}, args: {},
} }

View File

@ -0,0 +1,40 @@
import { IconButton } from '@status-im/components'
import { Stack } from 'tamagui'
type IconButtonWithDotProps = {
iconEl: any
variant: 'ghost' | 'outline'
isDotOn: boolean
selected?: boolean
disabled?: boolean
}
const IconButtonWithDot = ({
iconEl,
variant,
isDotOn,
selected,
disabled,
}: IconButtonWithDotProps) => {
return (
<Stack style={{ position: 'relative', display: 'inline-block' }}>
<IconButton icon={iconEl} variant={variant} selected={selected} disabled={disabled} />
{isDotOn && (
<Stack
style={{
position: 'absolute',
right: 7,
top: 5,
width: '9px',
height: '9px',
borderRadius: '50%',
backgroundColor: '#1992D7',
border: '1.5px solid #fff',
}}
/>
)}
</Stack>
)
}
export default IconButtonWithDot

View File

@ -0,0 +1,19 @@
import type { Meta, StoryObj } from '@storybook/react'
import LeftSidebar from './LeftSidebar'
const meta = {
title: 'Dashboard/LeftSidebar',
component: LeftSidebar,
parameters: {
layout: 'centered',
},
tags: ['autodocs'],
} satisfies Meta<typeof LeftSidebar>
export default meta
type Story = StoryObj<typeof meta>
export const Default: Story = {
args: {},
}

View File

@ -1,4 +1,3 @@
import { IconButton } from '@status-im/components'
import { import {
DashboardIcon, DashboardIcon,
SpeedIcon, SpeedIcon,
@ -10,8 +9,12 @@ import {
SettingsIcon, SettingsIcon,
} from '@status-im/icons' } from '@status-im/icons'
import { YStack } from 'tamagui' import { YStack } from 'tamagui'
import IconButtonWithDot from './IconButtonWithDot'
import { useDispatch, useSelector } from 'react-redux'
const LeftSidebar = () => { const LeftSidebar = () => {
const buttons = useSelector((state: any) => state.leftSidebar.buttons)
console.log(buttons)
return ( return (
<YStack <YStack
space={'$4'} space={'$4'}
@ -24,14 +27,24 @@ const LeftSidebar = () => {
border: '1px solid #F0F2F5', border: '1px solid #F0F2F5',
}} }}
> >
<IconButton icon={<DashboardIcon size={20} />} variant="ghost" selected /> <IconButtonWithDot
<IconButton icon={<SpeedIcon size={20} />} variant="ghost" /> iconEl={<DashboardIcon size={20} />}
<IconButton icon={<ChartIcon size={20} />} variant="outline" disabled /> variant="ghost"
<IconButton icon={<HeartIcon size={20} />} variant="ghost" /> isDotOn={false}
<IconButton icon={<CodeBlockIcon size={20} />} variant="ghost" /> selected={true}
<IconButton icon={<CommunitiesIcon size={20} />} variant="ghost" /> />
<IconButton icon={<ActivityCenterIcon size={20} />} variant="ghost" /> <IconButtonWithDot iconEl={<SpeedIcon size={20} />} variant="ghost" isDotOn={false} />
<IconButton icon={<SettingsIcon size={20} />} variant="ghost" /> <IconButtonWithDot
iconEl={<ChartIcon size={20} />}
variant="outline"
isDotOn={false}
disabled={true}
/>
<IconButtonWithDot iconEl={<HeartIcon size={20} />} variant="ghost" isDotOn={false} />
<IconButtonWithDot iconEl={<CodeBlockIcon size={20} />} variant="ghost" isDotOn={false} />
<IconButtonWithDot iconEl={<CommunitiesIcon size={20} />} variant="ghost" isDotOn={false} />
<IconButtonWithDot iconEl={<ActivityCenterIcon size={20} />} variant="ghost" isDotOn={true} />
<IconButtonWithDot iconEl={<SettingsIcon size={20} />} variant="ghost" isDotOn={false} />
</YStack> </YStack>
) )
} }

View File

@ -3,20 +3,20 @@ import type { Meta, StoryObj } from '@storybook/react'
import MemoryCard from './MemoryCard' import MemoryCard from './MemoryCard'
const meta = { const meta = {
title: 'Dashboard/MemoryCard', title: 'Dashboard/MemoryCard',
component: MemoryCard, component: MemoryCard,
parameters: { parameters: {
layout: 'centered', layout: 'centered',
}, },
tags: ['autodocs'], tags: ['autodocs'],
} satisfies Meta<typeof MemoryCard> } satisfies Meta<typeof MemoryCard>
export default meta export default meta
type Story = StoryObj<typeof meta> type Story = StoryObj<typeof meta>
export const Default: Story = { export const Default: Story = {
args: { currentMemory: [12, 24, 12, 4, 30, 50], maxMemory: 100 }, args: { currentMemory: [12, 24, 12, 4, 30, 50], maxMemory: 100 },
} }
export const BadStats: Story = { export const BadStats: Story = {
args: { maxMemory: 60, currentMemory: [2, 5, 7, 32, 23, 12, 89] } args: { maxMemory: 60, currentMemory: [2, 5, 7, 32, 23, 12, 89] },
} }

View File

@ -1,5 +1,5 @@
import { Paragraph, Separator, Stack, XStack, YStack } from 'tamagui' import { Paragraph, Separator, Stack, XStack, YStack } from 'tamagui'
import { Text } from '@status-im/components' import { Text } from '@status-im/components'
import { CheckCircleIcon, IncorrectIcon } from '@status-im/icons' import { CheckCircleIcon, IncorrectIcon } from '@status-im/icons'
import StandartLineChart from '../../../components/Charts/StandardLineChart' import StandartLineChart from '../../../components/Charts/StandardLineChart'
@ -24,7 +24,6 @@ type MemoryCardProps = {
} }
const MemoryCard = ({ currentMemory, maxMemory }: MemoryCardProps) => { const MemoryCard = ({ currentMemory, maxMemory }: MemoryCardProps) => {
const chartData: ChartData[] = [ const chartData: ChartData[] = [
{ {
id: 'cpu', id: 'cpu',
@ -42,14 +41,16 @@ const MemoryCard = ({ currentMemory, maxMemory }: MemoryCardProps) => {
const message = currentLoad < maxMemory ? 'Good' : 'Poor' const message = currentLoad < maxMemory ? 'Good' : 'Poor'
return ( return (
<DashboardCardWrapper padding='0'> <DashboardCardWrapper padding="0">
<YStack style={{ <YStack
width: '284px', style={{
height: '136px', width: '284px',
borderRadius: '16px', height: '136px',
border: message === 'Poor' ? '1px solid #D92344' : 'none', borderRadius: '16px',
backgroundColor: message === 'Poor' ? '#fefafa' : '#fff', border: message === 'Poor' ? '1px solid #D92344' : 'none',
}}> backgroundColor: message === 'Poor' ? '#fefafa' : '#fff',
}}
>
<XStack <XStack
justifyContent="space-between" justifyContent="space-between"
style={{ style={{
@ -71,7 +72,7 @@ const MemoryCard = ({ currentMemory, maxMemory }: MemoryCardProps) => {
</XStack> </XStack>
<Separator borderColor={'#e3e3e3'} /> <Separator borderColor={'#e3e3e3'} />
<XStack space={'$4'} style={{ padding: '10px 16px 10px 16px' }}> <XStack space={'$4'} style={{ padding: '10px 16px 10px 16px' }}>
<IconText <IconText
icon={message === 'Good' ? <CheckCircleIcon size={16} /> : <IncorrectIcon size={16} />} icon={message === 'Good' ? <CheckCircleIcon size={16} /> : <IncorrectIcon size={16} />}
@ -85,7 +86,7 @@ const MemoryCard = ({ currentMemory, maxMemory }: MemoryCardProps) => {
)} )}
</XStack> </XStack>
</YStack> </YStack>
</DashboardCardWrapper > </DashboardCardWrapper>
) )
} }

View File

@ -3,20 +3,20 @@ import type { Meta, StoryObj } from '@storybook/react'
import NetworkCard from './NetworkCard' import NetworkCard from './NetworkCard'
const meta = { const meta = {
title: 'Dashboard/NetworkCard', title: 'Dashboard/NetworkCard',
component: NetworkCard, component: NetworkCard,
parameters: { parameters: {
layout: 'centered', layout: 'centered',
}, },
tags: ['autodocs'], tags: ['autodocs'],
} satisfies Meta<typeof NetworkCard> } satisfies Meta<typeof NetworkCard>
export default meta export default meta
type Story = StoryObj<typeof meta> type Story = StoryObj<typeof meta>
export const Default: Story = { export const Default: Story = {
args: {downloadRate:[12,24,12,4,30,50], uploadRate:[2,5,7,32,23,82] }, args: { downloadRate: [12, 24, 12, 4, 30, 50], uploadRate: [2, 5, 7, 32, 23, 82] },
} }
export const BadStats: Story = { export const BadStats: Story = {
args: { downloadRate:[12,24,12,4,30, 1], uploadRate:[2,5,7,32,23,12] } args: { downloadRate: [12, 24, 12, 4, 30, 1], uploadRate: [2, 5, 7, 32, 23, 12] },
} }

View File

@ -1,5 +1,5 @@
import { Paragraph, Separator, Stack, XStack, YStack } from 'tamagui' import { Paragraph, Separator, Stack, XStack, YStack } from 'tamagui'
import { Text } from '@status-im/components' import { Text } from '@status-im/components'
import { CheckCircleIcon, IncorrectIcon } from '@status-im/icons' import { CheckCircleIcon, IncorrectIcon } from '@status-im/icons'
import StandartLineChart from '../../../components/Charts/StandardLineChart' import StandartLineChart from '../../../components/Charts/StandardLineChart'
@ -23,7 +23,6 @@ type NetworkCardProps = {
} }
const NetworkCard = ({ uploadRate, downloadRate }: NetworkCardProps) => { const NetworkCard = ({ uploadRate, downloadRate }: NetworkCardProps) => {
const chartData: ChartData[] = [ const chartData: ChartData[] = [
{ {
id: 'uploadRate', id: 'uploadRate',
@ -49,16 +48,16 @@ const NetworkCard = ({ uploadRate, downloadRate }: NetworkCardProps) => {
const message = currentLoad > 60 ? 'Good' : 'Poor' const message = currentLoad > 60 ? 'Good' : 'Poor'
return ( return (
<DashboardCardWrapper padding='0'> <DashboardCardWrapper padding="0">
<YStack
style={{
<YStack style={{ width: '284px',
width: '284px', height: '136px',
height: '136px', borderRadius: '16px',
borderRadius: '16px', border: message === 'Poor' ? '1px solid #D92344' : 'none',
border: message === 'Poor' ? '1px solid #D92344' : 'none', backgroundColor: message === 'Poor' ? '#fefafa' : '#fff',
backgroundColor: message === 'Poor' ? '#fefafa' : '#fff', }}
}}> >
<XStack <XStack
justifyContent="space-between" justifyContent="space-between"
style={{ style={{

View File

@ -0,0 +1,19 @@
import type { Meta, StoryObj } from '@storybook/react'
import RightSidebar from './RightSidebar'
const meta = {
title: 'Dashboard/RightSidebar',
component: RightSidebar,
parameters: {
layout: 'centered',
},
tags: ['autodocs'],
} satisfies Meta<typeof RightSidebar>
export default meta
type Story = StoryObj<typeof meta>
export const Default: Story = {
args: {},
}

View File

@ -3,20 +3,20 @@ import type { Meta, StoryObj } from '@storybook/react'
import StorageCard from './StorageCard' import StorageCard from './StorageCard'
const meta = { const meta = {
title: 'Dashboard/StorageCard', title: 'Dashboard/StorageCard',
component: StorageCard, component: StorageCard,
parameters: { parameters: {
layout: 'centered', layout: 'centered',
}, },
tags: ['autodocs'], tags: ['autodocs'],
} satisfies Meta<typeof StorageCard> } satisfies Meta<typeof StorageCard>
export default meta export default meta
type Story = StoryObj<typeof meta> type Story = StoryObj<typeof meta>
export const Default: Story = { export const Default: Story = {
args: { storage: 45, maxStorage: 100 }, args: { storage: 45, maxStorage: 100 },
} }
export const BadStats: Story = { export const BadStats: Story = {
args: { storage: 110, maxStorage: 100 } args: { storage: 110, maxStorage: 100 },
} }

View File

@ -35,14 +35,16 @@ const StorageCard = ({ storage, maxStorage }: StorageCardProps) => {
} }
return ( return (
<DashboardCardWrapper padding="0" > <DashboardCardWrapper padding="0">
<YStack style={{ <YStack
width: '284px', style={{
height: '136px', width: '284px',
borderRadius: '16px', height: '136px',
border: message === 'Poor' ? '1px solid #D92344' : 'none', borderRadius: '16px',
backgroundColor: message === 'Poor' ? '#fefafa' : '#fff', border: message === 'Poor' ? '1px solid #D92344' : 'none',
}}> backgroundColor: message === 'Poor' ? '#fefafa' : '#fff',
}}
>
<XStack <XStack
justifyContent="space-between" justifyContent="space-between"
style={{ style={{

View File

@ -3,18 +3,17 @@ import type { Meta, StoryObj } from '@storybook/react'
import ConsensusClientCard from './ConsensusClientCard' import ConsensusClientCard from './ConsensusClientCard'
const meta = { const meta = {
title: 'Dashboard/ConsensusClientCard', title: 'Dashboard/ConsensusClientCard',
component: ConsensusClientCard, component: ConsensusClientCard,
parameters: { parameters: {
layout: 'centered', layout: 'centered',
}, },
tags: ['autodocs'], tags: ['autodocs'],
} satisfies Meta<typeof ConsensusClientCard> } satisfies Meta<typeof ConsensusClientCard>
export default meta export default meta
type Story = StoryObj<typeof meta> type Story = StoryObj<typeof meta>
export const Default: Story = { export const Default: Story = {
args: { value: 200000, total: 123562 }, args: { value: 200000, total: 123562 },
} }

View File

@ -9,58 +9,56 @@ import Icon from '../../../components/General/Icon'
import StandardGauge from '../../../components/Charts/StandardGauge' import StandardGauge from '../../../components/Charts/StandardGauge'
type ConsensusCardProps = { type ConsensusCardProps = {
value: number value: number
total: number total: number
} }
const ConsensusCard = ({ value, total }: ConsensusCardProps) => { const ConsensusCard = ({ value, total }: ConsensusCardProps) => {
const style: CSSProperties = {} const style: CSSProperties = {}
const data = [ const data = [
{ {
id: 'storage', id: 'storage',
label: 'Used', label: 'Used',
value: value, value: value,
color: '#ff6161', color: '#ff6161',
}, },
{ {
id: 'storage', id: 'storage',
label: 'Free', label: 'Free',
value: total, value: total,
color: '#E7EAEE', color: '#E7EAEE',
}, },
] ]
return (
return ( <Shadow variant="$1" style={style}>
<Shadow variant="$1" style={style}> <YStack>
<YStack> <Stack style={{ minHeight: '90px', padding: '12px 16px' }}>
<Stack style={{ minHeight: '90px', padding: '12px 16px' }}> <Text size={15} weight={'semibold'} color="#647084">
<Text size={15} weight={'semibold'} color="#647084"> Consensus Client
Consensus Client </Text>
</Text> <XStack style={{ justifyContent: 'space-between', alignItems: 'center' }}>
<XStack style={{ justifyContent: 'space-between', alignItems: 'center' }}> <Icon src="./icons/vector.svg" height={30} width={60} />
<Icon src="./icons/vector.svg" height={30} width={60} /> <Stack
<Stack style={{
style={{ height: '56px',
height: '56px', width: '56px',
width: '56px', }}
}} >
> <StandardGauge data={data} />
<StandardGauge data={data} /> </Stack>
</Stack> </XStack>
</XStack> </Stack>
</Stack> <Separator borderColor={'#e3e3e3'} />
<Separator borderColor={'#e3e3e3'} /> <XStack space={'$3'} style={{ padding: '12px 16px' }}>
<XStack space={'$3'} style={{ padding: '12px 16px' }}> <IconText icon={<SwapIcon size={16} />}>Syncing</IconText>
<IconText icon={<SwapIcon size={16} />}>Syncing</IconText> <Text size={13} weight={'semibold'}>
<Text size={13} weight={'semibold'}> {formatNumbersWithComa(value)} / {formatNumbersWithComa(total)}
{formatNumbersWithComa(value)} / {formatNumbersWithComa(total)} </Text>
</Text> </XStack>
</XStack> </YStack>
</YStack> </Shadow>
</Shadow> )
)
} }
export default ConsensusCard export default ConsensusCard

View File

@ -3,18 +3,17 @@ import type { Meta, StoryObj } from '@storybook/react'
import ExecutionClientCard from './ExecutionClientCard' import ExecutionClientCard from './ExecutionClientCard'
const meta = { const meta = {
title: 'Dashboard/ExecutionClientCard', title: 'Dashboard/ExecutionClientCard',
component: ExecutionClientCard, component: ExecutionClientCard,
parameters: { parameters: {
layout: 'centered', layout: 'centered',
}, },
tags: ['autodocs'], tags: ['autodocs'],
} satisfies Meta<typeof ExecutionClientCard> } satisfies Meta<typeof ExecutionClientCard>
export default meta export default meta
type Story = StoryObj<typeof meta> type Story = StoryObj<typeof meta>
export const Default: Story = { export const Default: Story = {
args: { value: 200000, total: 123562 }, args: { value: 200000, total: 123562 },
} }

View File

@ -11,7 +11,6 @@ import StandardGauge from '../../../components/Charts/StandardGauge'
type ExecutionClientCardProps = { type ExecutionClientCardProps = {
value: number value: number
total: number total: number
} }
const ExecutionClientCard = ({ value, total }: ExecutionClientCardProps) => { const ExecutionClientCard = ({ value, total }: ExecutionClientCardProps) => {
@ -31,8 +30,6 @@ const ExecutionClientCard = ({ value, total }: ExecutionClientCardProps) => {
] ]
const style: CSSProperties = {} const style: CSSProperties = {}
return ( return (
<Shadow variant="$1" style={style}> <Shadow variant="$1" style={style}>
<YStack> <YStack>
@ -41,7 +38,9 @@ const ExecutionClientCard = ({ value, total }: ExecutionClientCardProps) => {
Execution Client Execution Client
</Text> </Text>
<XStack style={{ justifyContent: 'space-between', alignItems: 'center' }}> <XStack style={{ justifyContent: 'space-between', alignItems: 'center' }}>
<Text size={19} weight={'semibold'}>Geth</Text> <Text size={19} weight={'semibold'}>
Geth
</Text>
<Stack <Stack
style={{ style={{
height: '56px', height: '56px',

View File

@ -3,17 +3,17 @@ import type { Meta, StoryObj } from '@storybook/react'
import SyncStatusCards from './SyncStatusCards' import SyncStatusCards from './SyncStatusCards'
const meta = { const meta = {
title: 'Dashboard/SyncStatusCards', title: 'Dashboard/SyncStatusCards',
component: SyncStatusCards, component: SyncStatusCards,
parameters: { parameters: {
layout: 'centered', layout: 'centered',
}, },
tags: ['autodocs'], tags: ['autodocs'],
} satisfies Meta<typeof SyncStatusCards> } satisfies Meta<typeof SyncStatusCards>
export default meta export default meta
type Story = StoryObj<typeof meta> type Story = StoryObj<typeof meta>
export const Default: Story = { export const Default: Story = {
args: {}, args: {},
} }

View File

@ -3,123 +3,122 @@ import type { Meta, StoryObj } from '@storybook/react'
import UptimeChart from './UptimeChart' import UptimeChart from './UptimeChart'
const meta = { const meta = {
title: 'Dashboard/UptimeChart', title: 'Dashboard/UptimeChart',
component: UptimeChart, component: UptimeChart,
parameters: { parameters: {
layout: 'centered', layout: 'centered',
}, },
decorators: [ decorators: [
Story => ( Story => (
<div style={{ height: '20vh', width: '50vh' }}> <div style={{ height: '20vh', width: '50vh' }}>
<Story /> <Story />
</div> </div>
), ),
], ],
tags: ['autodocs'], tags: ['autodocs'],
} satisfies Meta<typeof UptimeChart> } satisfies Meta<typeof UptimeChart>
export default meta export default meta
type Story = StoryObj<typeof meta> type Story = StoryObj<typeof meta>
export const WithoutLabels: Story = { export const WithoutLabels: Story = {
args: { args: {
data: [ data: [
{ {
pv: 1, pv: 1,
pa: 1, pa: 1,
}, },
{ {
pv: 0, pv: 0,
pa: 0, pa: 0,
}, },
{ {
pv: 0, pv: 0,
pa: 0, pa: 0,
}, },
{ {
pv: 0, pv: 0,
pa: 1, pa: 1,
}, },
{ {
pv: 0, pv: 0,
pa: 0, pa: 0,
}, },
{ {
pv: 1, pv: 1,
pa: 0, pa: 0,
}, },
{ {
pv: 0, pv: 0,
pa: 1, pa: 1,
}, },
] ],
},
},
} }
export const WithMonths: Story = { export const WithMonths: Story = {
args: { args: {
data: [ data: [
{ {
name: 'Jan', name: 'Jan',
pv: 0, pv: 0,
pa: 0, pa: 0,
}, },
{ {
name: 'Feb', name: 'Feb',
pv: 0, pv: 0,
pa: 0, pa: 0,
}, },
{ {
name: 'Mar', name: 'Mar',
pv: 0, pv: 0,
pa: 0, pa: 0,
}, },
{ {
name: 'Apr', name: 'Apr',
pv: 0, pv: 0,
pa: 0, pa: 0,
}, },
{ {
name: 'May', name: 'May',
pv: 0, pv: 0,
pa: 0, pa: 0,
}, },
{ {
name: 'Aug', name: 'Aug',
pv: 0, pv: 0,
pa: 0, pa: 0,
}, },
{ {
name: 'Jun', name: 'Jun',
pv: 0, pv: 0,
pa: 0, pa: 0,
}, },
{ {
name: 'Jul', name: 'Jul',
pv: 1, pv: 1,
pa: 0, pa: 0,
}, },
{ {
name: 'Sep', name: 'Sep',
pv: 0, pv: 0,
pa: 0, pa: 0,
}, },
{ {
name: 'Oct', name: 'Oct',
pv: 0, pv: 0,
pa: 0, pa: 0,
}, },
{ {
name: 'Nov', name: 'Nov',
pv: 1, pv: 1,
pa: 1, pa: 1,
}, },
{ {
name: 'Dec', name: 'Dec',
pv: 1, pv: 1,
pa: 1, pa: 1,
}, },
] ],
} },
} }

View File

@ -1,4 +1,4 @@
import { BarChart, Bar, ResponsiveContainer, XAxis } from 'recharts'; import { BarChart, Bar, ResponsiveContainer, XAxis } from 'recharts'
type DataItem = { type DataItem = {
name?: string name?: string
@ -12,20 +12,15 @@ type UptimeChartProps = {
const UptimeChart = ({ data }: UptimeChartProps) => { const UptimeChart = ({ data }: UptimeChartProps) => {
return ( return (
<ResponsiveContainer > <ResponsiveContainer>
<BarChart <BarChart data={data} style={{ backgroundColor: '#F0F2F5' }}>
data={data}
style={{ backgroundColor: '#F0F2F5' }}
>
<Bar dataKey="pv" barSize={2} fill="#E95460" /> <Bar dataKey="pv" barSize={2} fill="#E95460" />
{/* @NOTE: We can add as many Bar items as we need and use them for each day of the month */} {/* @NOTE: We can add as many Bar items as we need and use them for each day of the month */}
<Bar dataKey="pa" barSize={2} fill="#E95460" /> <Bar dataKey="pa" barSize={2} fill="#E95460" />
{data[0].name && ( {data[0].name && <XAxis dataKey="name" fontSize={'10px'} tickMargin={10} />}
<XAxis dataKey="name" fontSize={'10px'} tickMargin={10} />
)}
</BarChart> </BarChart>
</ResponsiveContainer> </ResponsiveContainer>
); )
} }
export default UptimeChart export default UptimeChart

View File

@ -16,13 +16,14 @@ const DeviceHealthCheck = () => {
const deviceHealthState = useSelector((state: RootState) => state.deviceHealth) const deviceHealthState = useSelector((state: RootState) => state.deviceHealth)
return ( return (
<PageWrapperShadow rightImageSrc="./background-images/eye-background.png"> <PageWrapperShadow rightImageSrc="./background-images/eye-background.png" imgHeight="100%">
<YStack <YStack
space={'$4'} space={'$4'}
style={{ style={{
justifyContent: 'end', justifyContent: 'end',
alignItems: 'start', alignItems: 'start',
marginBottom: '2rem', marginBottom: '2rem',
marginTop: '4.4rem',
maxWidth: '100%', maxWidth: '100%',
}} }}
> >
@ -32,14 +33,14 @@ const DeviceHealthCheck = () => {
subtitle="Configure your device to start Staking on Nimbus" subtitle="Configure your device to start Staking on Nimbus"
isAdvancedSettings={true} isAdvancedSettings={true}
/> />
<XStack space={'$4'}> <XStack space={'$4'} width={'100%'}>
<DeviceStorageHealth <DeviceStorageHealth
storage={deviceHealthState.storage} storage={deviceHealthState.storage}
maxStorage={deviceHealthState.maxMemory} maxStorage={deviceHealthState.maxMemory}
/> />
<DeviceCPULoad load={deviceHealthState.cpuLoad} /> <DeviceCPULoad load={deviceHealthState.cpuLoad} />
</XStack> </XStack>
<XStack space={'$4'}> <XStack space={'$4'} width={'100%'}>
<DeviceMemory <DeviceMemory
currentMemory={deviceHealthState.memory} currentMemory={deviceHealthState.memory}
maxMemory={deviceHealthState.maxMemory} maxMemory={deviceHealthState.maxMemory}

View File

@ -1,5 +1,5 @@
import type { Meta, StoryObj } from '@storybook/react' import type { Meta, StoryObj } from '@storybook/react'
import DeviceSyncStatus from './DeviceSyncStatus' import DeviceSyncStatus from './DeviceSyncStatus'
const meta = { const meta = {

View File

@ -25,13 +25,17 @@ const DeviceSyncStatus = () => {
}, [dispatch]) }, [dispatch])
return ( return (
<PageWrapperShadow rightImageSrc="./background-images/sync-status-background.png"> <PageWrapperShadow
rightImageSrc="./background-images/sync-status-background.png"
imgHeight="120%"
>
<YStack <YStack
space={'$4'} space={'$4'}
style={{ style={{
justifyContent: 'end', justifyContent: 'end',
alignItems: 'start', alignItems: 'start',
maxWidth: '100%', maxWidth: '100%',
marginTop: '4.4rem',
}} }}
> >
<NimbusLogo /> <NimbusLogo />

View File

@ -46,7 +46,7 @@ const SyncStatusCardConsensus: React.FC<DeviceStorageHealthProps> = ({ synced, t
style={{ style={{
padding: '8px 16px', padding: '8px 16px',
position: 'relative', position: 'relative',
height: '160px', minHeight: '180px',
}} }}
> >
<YStack space={'$3'} style={{ width: '100%' }}> <YStack space={'$3'} style={{ width: '100%' }}>

View File

@ -45,7 +45,7 @@ const SyncStatusCardExecution: React.FC<DeviceStorageHealthProps> = ({ synced, t
style={{ style={{
padding: '8px 16px', padding: '8px 16px',
position: 'relative', position: 'relative',
height: '160px', minHeight: '180px',
}} }}
> >
<YStack space={'$3'} style={{ width: '100%' }}> <YStack space={'$3'} style={{ width: '100%' }}>

View File

@ -1,4 +1,3 @@
.landing-page {
.landing-page { height: 100%;
height: 100%;
} }

View File

@ -16,7 +16,7 @@ const LandingPage = () => {
return ( return (
<> <>
<PageWrapperShadow rightImageSrc="./background-images/landing-page-bg.png"> <PageWrapperShadow rightImageSrc="./background-images/landing-page-bg.png" imgHeight="150%">
<YStack className="landing-page"> <YStack className="landing-page">
<XStack pt={'70px'}> <XStack pt={'70px'}>
<NimbusLogo /> <NimbusLogo />

View File

@ -48,8 +48,8 @@ const SyncStatus = ({
const timer = convertSecondsToTimerFormat(elapsedTime) const timer = convertSecondsToTimerFormat(elapsedTime)
const connectViaIpHandler = () => { const connectViaIpHandler = () => {
navigate('/connect-device'); navigate('/connect-device')
}; }
return ( return (
<YStack space={'$2'}> <YStack space={'$2'}>
@ -91,7 +91,7 @@ const SyncStatus = ({
)} )}
{isAwaitingPairing && ( {isAwaitingPairing && (
<XStack> <XStack>
<Button icon={<Icon src={ConnectionIcon} />} size={40} onPress={connectViaIpHandler} > <Button icon={<Icon src={ConnectionIcon} />} size={40} onPress={connectViaIpHandler}>
Connect via IP Connect via IP
</Button> </Button>
</XStack> </XStack>

View File

@ -20,22 +20,21 @@ export const Default: Story = {
args: { args: {
validatorsValue: '4', validatorsValue: '4',
executionSyncStatus1: { executionSyncStatus1: {
text: "Execution Sync Status", text: 'Execution Sync Status',
isGaugeIncluded: true, isGaugeIncluded: true,
gaugeColor: "$blue", gaugeColor: '$blue',
gaugeSynced: 123.524, gaugeSynced: 123.524,
gaugeTotal: 172.503, gaugeTotal: 172.503,
}, },
executionSyncStatus2: { executionSyncStatus2: {
text: "Execution Sync Status", text: 'Execution Sync Status',
isGaugeIncluded: true, isGaugeIncluded: true,
gaugeColor: "$red", gaugeColor: '$red',
gaugeSynced: 123.524, gaugeSynced: 123.524,
gaugeTotal: 172.503, gaugeTotal: 172.503,
}, },
currentAPRValue: "4.40%", currentAPRValue: '4.40%',
estimatedActivationTimeValue: "32 Days", estimatedActivationTimeValue: '32 Days',
validatorQueueValue: "92603", validatorQueueValue: '92603',
}, },
} }

View File

@ -48,20 +48,20 @@ const Activation = ({
}, []) }, [])
return ( return (
<Stack style={styles.confettiContainer} width={'100%'}> <Stack style={styles.confettiContainer} width={'100%'} minHeight={'65vh'}>
{showConfetti && <Confetti style={styles.confettiCanvas} />} {showConfetti && <Confetti style={styles.confettiCanvas} />}
<YStack style={{ padding: '16px 32px' }}> <YStack style={{ padding: '26px 32px' }}>
<YStack space={'$5'}> <YStack space={'$5'}>
<Text size={27} weight={'semibold'}> <Text size={27} weight={'semibold'}>
Activation Activation
</Text> </Text>
<Stack style={{ width: '66%' }}> <Stack style={{ width: '66%' }}>
<Text size={27}> <Text size={19}>
Congratulations! You have successfully setup your Nimbus Validators and are currently Congratulations! You have successfully setup your Nimbus Validators and are currently
syncing your nodes. syncing your nodes.
</Text> </Text>
</Stack> </Stack>
<YStack space={'$3'} marginTop={'10px'} width={'33%'}> <YStack space={'$3'} marginTop={'25px'} width={'33%'}>
<XStack space={'$3'} justifyContent={'space-between'}> <XStack space={'$3'} justifyContent={'space-between'}>
<ActivationCard text="Validators" value={validatorsValue} /> <ActivationCard text="Validators" value={validatorsValue} />
<ActivationCard {...executionSyncStatus1} /> <ActivationCard {...executionSyncStatus1} />
@ -81,7 +81,7 @@ const Activation = ({
text="Edit Validators" text="Edit Validators"
to="/" to="/"
arrowLeft={true} arrowLeft={true}
style={{ marginTop: '44px', marginBottom: '88px' }} style={{ marginTop: '44px', marginBottom: '88px', fontSize: '13px' }}
/> />
</YStack> </YStack>
</Stack> </Stack>

View File

@ -30,7 +30,7 @@ const ActivationCard = ({
}} }}
> >
{!isGaugeIncluded && ( {!isGaugeIncluded && (
<Stack> <Stack space={'$2'}>
<Text size={15} weight={'semibold'}> <Text size={15} weight={'semibold'}>
{text} {text}
</Text> </Text>
@ -40,7 +40,7 @@ const ActivationCard = ({
</Stack> </Stack>
)} )}
{isGaugeIncluded && ( {isGaugeIncluded && (
<Stack> <Stack space={'$2'}>
<Text size={15} weight={'semibold'}> <Text size={15} weight={'semibold'}>
{text} {text}
</Text> </Text>

View File

@ -15,8 +15,8 @@ const Advisories = () => {
return ( return (
<XStack <XStack
style={{ padding: '16px 32px', justifyContent: 'space-between' }} style={{ padding: '30px 33px', justifyContent: 'space-between' }}
height={'65vh'} minHeight={'65vh'}
width={'100%'} width={'100%'}
> >
<YStack space={'$2'}> <YStack space={'$2'}>
@ -33,7 +33,7 @@ const Advisories = () => {
space={'$2'} space={'$2'}
> >
<Text <Text
size={27} size={19}
weight={isSameTitle(title) && 'semibold'} weight={isSameTitle(title) && 'semibold'}
color={isSameTitle(title) ? 'blue' : ''} color={isSameTitle(title) ? 'blue' : ''}
> >

View File

@ -17,11 +17,11 @@ const AdvisoriesContent = ({ title, content }: AdvisoriesContentProps) => {
</Stack> </Stack>
<YStack space={'$4'}> <YStack space={'$4'}>
{content.map(row => ( {content.map(row => (
<Text key={row} size={19}> <Text key={row} size={15}>
{row} {row}
</Text> </Text>
))} ))}
<Text size={19}> <Text size={15}>
<Link <Link
to={'https://github.com/ethereum/consensus-specs'} to={'https://github.com/ethereum/consensus-specs'}
style={{ textDecorationLine: 'underline', color: '#484848' }} style={{ textDecorationLine: 'underline', color: '#484848' }}
@ -29,7 +29,7 @@ const AdvisoriesContent = ({ title, content }: AdvisoriesContentProps) => {
The Ethereum consensus layer specification The Ethereum consensus layer specification
</Link> </Link>
</Text> </Text>
<Text size={19} weight={'semibold'}> <Text size={15} weight={'semibold'}>
<Link <Link
to={'https://github.com/ethereum/consensus-specs'} to={'https://github.com/ethereum/consensus-specs'}
style={{ textDecorationLine: 'underline', color: '#2A4CF4', fontWeight: 'bold' }} style={{ textDecorationLine: 'underline', color: '#2A4CF4', fontWeight: 'bold' }}

View File

@ -6,7 +6,7 @@ import LinkWithArrow from '../../../components/General/LinkWithArrow'
const ClientSetup = () => { const ClientSetup = () => {
return ( return (
<YStack padding={'26px'} width={'100%'} space={'$5'}> <YStack space={'$8'} padding={'26px'} width={'100%'} minHeight={'65vh'}>
<SetupRow title={'Setup up Validators'} /> <SetupRow title={'Setup up Validators'} />
<Separator borderColor={'#F0F2F5'} /> <Separator borderColor={'#F0F2F5'} />
<WithdrawalAddress title={'Withdrawal address'} /> <WithdrawalAddress title={'Withdrawal address'} />
@ -14,7 +14,7 @@ const ClientSetup = () => {
text="Advanced Recovery Method" text="Advanced Recovery Method"
to={'/'} to={'/'}
arrowRight={true} arrowRight={true}
style={{ marginBottom: '50px' }} style={{ marginBottom: '50px', fontWeight: 'bold', fontSize: '15px' }}
/> />
</YStack> </YStack>
) )

View File

@ -22,7 +22,7 @@ const SetupRow = ({ title }: SetupRowProps) => {
return ( return (
<YStack space={'$4'}> <YStack space={'$4'}>
<Text size={27} weight={'semibold'}> <Text size={19} weight={'semibold'}>
{title} {title}
</Text> </Text>
<XStack justifyContent={'space-between'} width={'80%'}> <XStack justifyContent={'space-between'} width={'80%'}>
@ -38,7 +38,7 @@ const SetupRow = ({ title }: SetupRowProps) => {
/> />
</Stack> </Stack>
<YStack space={'$2'}> <YStack space={'$2'}>
<Text size={19} weight={'semibold'} color="#09101C"> <Text size={15} weight={'semibold'} color="#09101C">
ETH ETH
</Text> </Text>
<Text size={27} weight={'semibold'} color="#09101C"> <Text size={27} weight={'semibold'} color="#09101C">
@ -47,7 +47,7 @@ const SetupRow = ({ title }: SetupRowProps) => {
</YStack> </YStack>
<YStack space={'$2'}> <YStack space={'$2'}>
<XStack style={{ justifyContent: 'space-between' }}> <XStack style={{ justifyContent: 'space-between' }}>
<Text size={19} weight={'semibold'} color="#09101C"> <Text size={15} weight={'semibold'} color="#09101C">
USD USD
</Text> </Text>
<ChevronDownIcon size={16} color={'#919191'} /> <ChevronDownIcon size={16} color={'#919191'} />

View File

@ -20,7 +20,7 @@ const WithdrawalAddress = ({ title }: WithdrawalAddressProps) => {
return ( return (
<YStack space={'$4'}> <YStack space={'$4'}>
<Text size={27} weight={'semibold'}> <Text size={19} weight={'semibold'}>
{title} {title}
</Text> </Text>
<YStack space={'$3'}> <YStack space={'$3'}>

View File

@ -1,4 +1,4 @@
import { Stack, XStack } from 'tamagui' import { Stack, YStack } from 'tamagui'
import { Button, InformationBox } from '@status-im/components' import { Button, InformationBox } from '@status-im/components'
import { CloseCircleIcon } from '@status-im/icons' import { CloseCircleIcon } from '@status-im/icons'
import { useDispatch, useSelector } from 'react-redux' import { useDispatch, useSelector } from 'react-redux'
@ -43,7 +43,7 @@ const ContinueButton = ({
const isActivationValScreen = activeStep === 3 && subStepValidatorSetup === 3 const isActivationValScreen = activeStep === 3 && subStepValidatorSetup === 3
return ( return (
<XStack style={{ width: '100%', alignItems: 'center', zIndex: 999, marginTop: '40px' }}> <YStack style={{ width: '100%', alignItems: 'center', zIndex: 999, marginTop: '30px' }}>
<Stack style={{ width: '100%' }}> <Stack style={{ width: '100%' }}>
{isCopyPastedPhrase && ( {isCopyPastedPhrase && (
<InformationBox <InformationBox
@ -66,14 +66,13 @@ const ContinueButton = ({
width: '100%', width: '100%',
zIndex: 999, zIndex: 999,
alignItems: 'end', alignItems: 'end',
position: 'absolute',
}} }}
> >
<Button onPress={continueHandler} size={40} disabled={isDisabled()}> <Button onPress={continueHandler} size={40} disabled={isDisabled()}>
{activeStep < 5 ? 'Continue' : 'Continue to Dashboard'} {activeStep < 5 ? 'Continue' : 'Continue to Dashboard'}
</Button> </Button>
</Stack> </Stack>
</XStack> </YStack>
) )
} }

View File

@ -1,7 +1,23 @@
.custom-step { .custom-step {
background-color: #ffffff; background-color: #ffffff;
} }
div[class*='StepMain-'] {
align-items: start;
}
div[class*='LabelContainer-'] span[class*='Label-'] {
text-align: initial;
text-transform: uppercase;
font-family: 'Inter', sans-serif;
}
div[class*='ConnectorContainer-'] {
right: unset;
left: calc(-100% + 28px);
width: 100%;
}
span[class*='Connector-'] {
position: relative;
z-index: -1;
}
.custom-step.StepMain--active, .custom-step.StepMain--active,
.custom-step.StepMain--completed { .custom-step.StepMain--completed {
background-color: #2a4cf4; background-color: #2a4cf4;
@ -37,32 +53,9 @@
content: attr(data-subtitle); content: attr(data-subtitle);
position: absolute; position: absolute;
top: calc(100% + 4px); top: calc(100% + 4px);
left: 8px;
font-size: 12px; font-size: 12px;
color: #A2A9B0; font-family: 'Inter', sans-serif;
background: transparent; color: #a2a9b0;
border: none; width: max-content;
} }
[data-step="Overview"]::after {
left: 35%;
}
[data-step="Advisories"]::after {
left: 30%;
}
[data-step="Client Setup"]::after {
left: 32%;
}
[data-step="Validator Setup"]::after {
left: 25%;
}
[data-step="Key Generation"]::after {
left: 24.5%;
}
[data-step="Activation"]::after {
left: 33%;
}

View File

@ -22,7 +22,14 @@ const FormStepper = ({ activeStep, changeActiveStep }: FormStepperProps) => {
nonLinear={true} nonLinear={true}
styleConfig={stepStyle} styleConfig={stepStyle}
connectorStyleConfig={customConnectorStyle} connectorStyleConfig={customConnectorStyle}
style={{ fontSize: '14px', zIndex: 999, width: '100%', padding: 0, marginBottom: '2rem' }} style={{
fontSize: '14px',
zIndex: 999,
width: '100%',
padding: 0,
marginBottom: '3rem',
fontFamily: 'Inter',
}}
> >
{steps.map((step, index) => ( {steps.map((step, index) => (
<Step <Step

View File

@ -30,6 +30,8 @@
background-color: #f7f8f9; background-color: #f7f8f9;
width: 100%; width: 100%;
font-size: 16px; font-size: 16px;
color: rgb(13, 22, 37);
font-family: 'Inter', sans-serif;
} }
.input-wrapper { .input-wrapper {
@ -40,9 +42,9 @@
position: absolute; position: absolute;
left: 15px; left: 15px;
transform: translateY(-50%); transform: translateY(-50%);
pointer-events: none; pointer-events: none;
z-index: 2; z-index: 2;
color: #0D162566; color: #0d162566;
top: 48%; top: 48%;
} }
@ -76,4 +78,4 @@
.suggestion-list::-webkit-scrollbar-thumb:hover { .suggestion-list::-webkit-scrollbar-thumb:hover {
background-color: transparent; background-color: transparent;
} }

View File

@ -12,7 +12,7 @@ const ConfirmRecoveryPhrase = () => {
return ( return (
<YStack space={'$3'} style={{ width: '100%', marginTop: '20px' }}> <YStack space={'$3'} style={{ width: '100%', marginTop: '20px' }}>
<KeyGenerationTitle /> <KeyGenerationTitle />
<Text size={27}>Confirm Recovery Phrase</Text> <Text size={19}>Confirm Recovery Phrase</Text>
<Stack <Stack
style={{ style={{
display: 'grid', display: 'grid',

View File

@ -1,4 +1,4 @@
import { Text as TextTam, XStack, YStack } from 'tamagui' import { XStack, YStack } from 'tamagui'
import { Text } from '@status-im/components' import { Text } from '@status-im/components'
import OverviewCard from './OverviewCard' import OverviewCard from './OverviewCard'
@ -7,29 +7,37 @@ import LinkWithArrow from '../../../components/General/LinkWithArrow'
const Overview = () => { const Overview = () => {
return ( return (
<> <>
<YStack className="layout-left" space={'$5'} style={{ padding: '16px 32px' }}> <YStack
<TextTam fontSize={27} fontWeight={'600'}> className="layout-left"
Overview space={'$5'}
</TextTam> style={{ padding: '26px 0 32px 32px' }}
<Text size={27}> minHeight={'65vh'}
Becoming a validator is a big responsibility with important preparation steps. Only start justifyContent={'space-between'}
the deposit process when youre ready. >
</Text> <YStack space={'$5'}>
<Text size={15} color="#939BA1"> <Text size={27} weight={'semibold'}>
By running a validator, you'll be responsible for securing the network and receive Overview
continuous payouts for actions that help the network reach consensus. </Text>
</Text> <Text size={19}>
<Text size={15} color="#939BA1"> Becoming a validator is a big responsibility with important preparation steps. Only
Since the successful transition to proof-of-stake via The Merge, Ethereum is fully secured start the deposit process when you're ready.
by proof-of-stake validators. By running a validator, you'll be helping to secure the </Text>
Ethereum network. <Text size={15} color="#939BA1">
</Text> By running a validator, you'll be responsible for securing the network and receive
<LinkWithArrow continuous payouts for actions that help the network reach consensus.
text="Learn more" </Text>
to={'/'} <Text size={15} color="#939BA1">
arrowRight={true} Since the successful transition to proof-of-stake via The Merge, Ethereum is fully
style={{ marginBottom: '1%' }} secured by proof-of-stake validators. By running a validator, you'll be helping to
/> secure the Ethereum network.
</Text>
<LinkWithArrow
text="Learn More"
to={'/'}
arrowRight={true}
style={{ marginBottom: '1%', fontSize: '13px' }}
/>
</YStack>
<XStack space={'$3'}> <XStack space={'$3'}>
<OverviewCard text={'Current APR'} value={'4.40%'} /> <OverviewCard text={'Current APR'} value={'4.40%'} />
<OverviewCard text={'Total ETH Staked'} value={'9,451,123'} /> <OverviewCard text={'Total ETH Staked'} value={'9,451,123'} />

View File

@ -12,12 +12,12 @@ const OverviewCard = ({ text, value }: OverviewCardProps) => {
style={{ style={{
borderRadius: '16px', borderRadius: '16px',
border: '1px solid rgba(0, 0, 0, 0.15)', border: '1px solid rgba(0, 0, 0, 0.15)',
width: '46%', width: '44%',
padding: '12px 16px', padding: '12px 16px',
backgroundColor: '#FFF', backgroundColor: '#FFF',
}} }}
> >
<Text size={19} weight={'semibold'}> <Text size={15} weight={'semibold'}>
{text} {text}
</Text> </Text>
<Text size={27} color="blue" weight={'semibold'}> <Text size={27} color="blue" weight={'semibold'}>

View File

@ -82,8 +82,8 @@ const ValidatorOnboarding = () => {
<YStack <YStack
style={{ style={{
width: '100%', width: '100%',
margin: '0 auto', maxWidth: '1100px',
padding: '2% 10% 2%', margin: '4rem auto 2rem',
justifyContent: 'start', justifyContent: 'start',
alignItems: 'start', alignItems: 'start',
}} }}

View File

@ -18,10 +18,10 @@ const ConsensusClientCard = ({ name, icon }: ConsensusClientCardProps) => {
padding: '12px 16px', padding: '12px 16px',
width: '29%', width: '29%',
}} }}
space={'$10'} space={'$8'}
> >
<Stack> <Stack>
<Text size={27} weight={'semibold'}> <Text size={15} weight={'semibold'}>
{name} {name}
</Text> </Text>
</Stack> </Stack>

View File

@ -18,6 +18,9 @@ type Story = StoryObj<typeof meta>
export const Default: Story = { export const Default: Story = {
args: { args: {
color: 'orange', synced: 140000, total: 200000, title: 'Synced Files' color: 'orange',
synced: 140000,
total: 200000,
title: 'Synced Files',
}, },
} }

View File

@ -32,29 +32,29 @@ const ConsensusSelection = () => {
] ]
return ( return (
<YStack style={{ width: '100%', padding: '32px' }}> <YStack style={{ width: '100%', padding: '32px' }} minHeight={'65vh'}>
<XStack justifyContent={'space-between'}> <XStack justifyContent={'space-between'} alignItems={'center'} mb={'30px'}>
<Text size={27} weight={'semibold'}> <Text size={27} weight={'semibold'}>
Validator Setup Validator Setup
</Text> </Text>
<XStack space={'$2'}> <XStack space={'$2'}>
<PairedDeviceCard isVisibleState={true} />
<ConsensusGaugeCard <ConsensusGaugeCard
color="blue" color="blue"
synced={134879} synced={134879}
title="Execution Sync Status" title="Execution Sync Status"
total={150000} total={150000}
/> />
<PairedDeviceCard isVisibleState={true} />
</XStack> </XStack>
</XStack> </XStack>
<YStack> <YStack mb={'50px'}>
<Stack style={{ marginBottom: '4px' }}> <Stack style={{ marginBottom: '4px' }}>
<Text size={13} color="#647084"> <Text size={13} color="#647084">
Consensus Client Detection Consensus Client Detection
</Text> </Text>
</Stack> </Stack>
<Text size={15} weight={'regular'}> <Text size={15}>
No existing execution client installations have been detected on paired device. No existing execution client installations have been detected on paired device.
</Text> </Text>
<Text size={13} color="#828282"> <Text size={13} color="#828282">
@ -63,14 +63,14 @@ const ConsensusSelection = () => {
</Text> </Text>
</YStack> </YStack>
<TextTam fontSize={27} style={{ margin: '5px', marginLeft: 0, marginTop: '50px' }}> <TextTam fontSize={19} style={{ marginLeft: 0, marginTop: '50px', marginBottom: '25px' }}>
Install Consensus client Install Consensus client
</TextTam> </TextTam>
<XStack space={'$8'}> <XStack space={'$8'}>
<ConsensusClientCard name={clients[0].name} icon={clients[0].icon} /> <ConsensusClientCard name={clients[0].name} icon={clients[0].icon} />
<YStack width={'67%'} space={'$4'}> <YStack width={'67%'} space={'$4'}>
<Text size={27}>The resource efficient Ethereum Clients.</Text> <Text size={19}>The resource efficient Ethereum Clients.</Text>
<Text size={15}> <Text size={15}>
{selectedClient} is a client implementation for both execution and consensus layers that {selectedClient} is a client implementation for both execution and consensus layers that
strives to be as lightweight as possible in terms of resources used. This allows it to strives to be as lightweight as possible in terms of resources used. This allows it to
@ -81,6 +81,7 @@ const ConsensusSelection = () => {
<LinkWithArrow <LinkWithArrow
textColor="black" textColor="black"
text="Nimbus Documentation" text="Nimbus Documentation"
style={{ fontSize: '15px' }}
arrowRight={true} arrowRight={true}
to="https://www.youtube.com/watch?v=dQw4w9WgXcQ" to="https://www.youtube.com/watch?v=dQw4w9WgXcQ"
/> />

View File

@ -20,9 +20,9 @@ const PairedDeviceCard = ({ isVisibleState }: PairedDeviceCardProps) => {
<XStack <XStack
space={'$7'} space={'$7'}
style={{ style={{
padding: '2px 6px', padding: '6px 12px',
border: '1px solid #DCE0E5', border: '1px solid #DCE0E5',
borderRadius: '15px', borderRadius: '10px',
}} }}
alignItems={'center'} alignItems={'center'}
> >

View File

@ -4,16 +4,16 @@ import ActivationValidatorSetup from './ActivationValidatorSetup'
import { withRouter } from 'storybook-addon-react-router-v6' import { withRouter } from 'storybook-addon-react-router-v6'
const meta = { const meta = {
title: 'ValidatorOnboarding/ActivationValidatorSetup', title: 'ValidatorOnboarding/ActivationValidatorSetup',
component: ActivationValidatorSetup, component: ActivationValidatorSetup,
tags: ['autodocs'], tags: ['autodocs'],
decorators: [withRouter()], decorators: [withRouter()],
} satisfies Meta<typeof ActivationValidatorSetup> } satisfies Meta<typeof ActivationValidatorSetup>
export default meta export default meta
type Story = StoryObj<typeof meta> type Story = StoryObj<typeof meta>
export const Default: Story = { export const Default: Story = {
args: { }, args: {},
} }

View File

@ -19,21 +19,21 @@ const ActivationValidatorSetup = () => {
}, []) }, [])
return ( return (
<Stack style={styles.confettiContainer} width={'100%'}> <Stack style={styles.confettiContainer} width={'100%'} minHeight={'65vh'}>
{showConfetti && <Confetti style={styles.confettiCanvas} />} {showConfetti && <Confetti style={styles.confettiCanvas} />}
<YStack style={{ padding: '16px 32px' }}> <YStack style={{ padding: '26px 32px' }}>
<YStack space={'$3'}> <YStack space={'$5'}>
<Text size={27} weight={'semibold'}> <Text size={27} weight={'semibold'}>
Activation Activation
</Text> </Text>
<Stack> <Stack>
<Text size={27}> <Text size={19}>
Congratulations! You have successfully setup your Execution and Consensus clients and Congratulations! You have successfully setup your Execution and Consensus clients and
are currently syncing your nodes. You need to be sufficiently synced prior to setting are currently syncing your nodes. You need to be sufficiently synced prior to setting
up your validators and making a deposit. up your validators and making a deposit.
</Text> </Text>
</Stack> </Stack>
<YStack space={'$3'} marginTop={'10px'} width={'33%'}> <YStack space={'$3'} marginTop={'25px'} width={'33%'}>
<XStack width={'151%'} space={'$3'}> <XStack width={'151%'} space={'$3'}>
<ActivationCard <ActivationCard
text="Execution Sync Status" text="Execution Sync Status"

View File

@ -18,13 +18,13 @@ const OsCard = ({ name, icon, onClick, isSelected }: OsCardProps) => {
border: isSelected ? '1px solid #2A4AF566' : '1px solid rgba(0, 0, 0, 0.15);', border: isSelected ? '1px solid #2A4AF566' : '1px solid rgba(0, 0, 0, 0.15);',
borderRadius: '16px', borderRadius: '16px',
padding: '12px 16px', padding: '12px 16px',
width: '33%', width: '32%',
}} }}
space={'$12'} space={'$8'}
onPress={onClick} onPress={onClick}
> >
<Stack> <Stack>
<Text size={27} weight={'semibold'}> <Text size={19} weight={'semibold'}>
{name} {name}
</Text> </Text>
</Stack> </Stack>

View File

@ -13,7 +13,7 @@ const ValidatorSetupInstall = () => {
const selectedClient = useSelector((state: RootState) => state.execClient.selectedClient) const selectedClient = useSelector((state: RootState) => state.execClient.selectedClient)
return ( return (
<YStack style={{ width: '100%', padding: '16px 32px' }}> <YStack style={{ width: '100%', padding: '26px 32px' }}>
<XStack justifyContent={'space-between'} style={{ marginBottom: '10px' }}> <XStack justifyContent={'space-between'} style={{ marginBottom: '10px' }}>
<Text size={27} weight={'semibold'}> <Text size={27} weight={'semibold'}>
Validator Setup Validator Setup
@ -23,7 +23,7 @@ const ValidatorSetupInstall = () => {
<YStack> <YStack>
<Stack style={{ marginBottom: '4px' }}> <Stack style={{ marginBottom: '4px' }}>
<YStack space={'$3'}> <YStack space={'$3'}>
<Text size={19} weight={'semibold'}> <Text size={15} weight={'semibold'}>
{selectedClient} {selectedClient}
</Text> </Text>
@ -41,12 +41,12 @@ const ValidatorSetupInstall = () => {
style={{ style={{
border: '1px solid #00000026', border: '1px solid #00000026',
borderRadius: '16px', borderRadius: '16px',
padding: '6px 12px', padding: '19px 16px',
}} }}
space={'$3'} space={'$3'}
> >
<Text size={27}> Installing {selectedClient}</Text> <Text size={19}> Installing {selectedClient}</Text>
<Text size={19} color="#647084" weight={'regular'}> <Text size={15} color="#647084" weight={'regular'}>
There are several ways to install Geth, including via a package manager, downloading There are several ways to install Geth, including via a package manager, downloading
a pre-built bundle, running as a docker container or building from downloaded source a pre-built bundle, running as a docker container or building from downloaded source
code. On this page the various installation options are explained for several major code. On this page the various installation options are explained for several major
@ -59,10 +59,10 @@ const ValidatorSetupInstall = () => {
are also provided in each section. are also provided in each section.
</Text> </Text>
<XStack justifyContent={'space-between'} space={'$2'} margin={'50px 0px'}> <XStack justifyContent={'space-between'} my={'15px'}>
<OsCard <OsCard
icon="/icons/MAC.png" icon="/icons/MAC.png"
name="Mac" name="MacOS"
isSelected={selectedOs === 'Mac'} isSelected={selectedOs === 'Mac'}
onClick={() => setSelectedOs('Mac')} onClick={() => setSelectedOs('Mac')}
/> />
@ -80,17 +80,17 @@ const ValidatorSetupInstall = () => {
/> />
</XStack> </XStack>
<YStack space={'$2'}> <YStack space={'$2'}>
<Text size={27}> Package Managers</Text> <Text size={19}> Package Managers</Text>
<Text size={15} weight={'semibold'}> <Text size={15} weight={'semibold'}>
MacOS via Homebrew MacOS via Homebrew
</Text> </Text>
<Text size={19} color="#647084" weight={'regular'}> <Text size={15} color="#647084">
The easiest way to install go-ethereum is to use the Geth Homebrew tap. The first The easiest way to install go-ethereum is to use the Geth Homebrew tap. The first
step is to check that Homebrew is installed. The following command should return a step is to check that Homebrew is installed. The following command should return a
version number. version number.
</Text> </Text>
<SyntaxHighlighterBox rows={['brew -v']} /> <SyntaxHighlighterBox rows={['brew -v']} />
<Text size={19} color="#647084" weight={'regular'}> <Text size={15} color="#647084">
If a version number is returned, then Homebrew is installed. If not, Homebrew can If a version number is returned, then Homebrew is installed. If not, Homebrew can
be installed by following the instructions here. With Homebrew installed, the be installed by following the instructions here. With Homebrew installed, the
following commands add the Geth tap and install Geth: following commands add the Geth tap and install Geth:

View File

@ -24,19 +24,19 @@ const ExecClientCard = ({ name, icon, isComingSoon }: ExecClientCardProps) => {
border: isComingSoon border: isComingSoon
? '1px solid #F5F6F8' ? '1px solid #F5F6F8'
: isSelected : isSelected
? '1px solid #2A4AF5' ? '1px solid #2A4AF5'
: '1px solid #DCE0E5', : '1px solid #DCE0E5',
borderRadius: '16px', borderRadius: '16px',
padding: '12px 16px', padding: '12px 16px',
width: '19%', width: '19%',
}} }}
space={'$12'} space={'$8'}
onClick={() => { onClick={() => {
dispatch(selectClient(name)) dispatch(selectClient(name))
}} }}
> >
<Stack> <Stack>
<Text size={27} weight={'semibold'} color={isComingSoon ? '#DCE0E5' : ''}> <Text size={19} weight={'semibold'} color={isComingSoon ? '#DCE0E5' : ''}>
{name} {name}
</Text> </Text>
{isComingSoon && ( {isComingSoon && (
@ -46,9 +46,9 @@ const ExecClientCard = ({ name, icon, isComingSoon }: ExecClientCardProps) => {
display: 'flex', display: 'flex',
justifyContent: 'center', justifyContent: 'center',
alignItems: 'center', alignItems: 'center',
padding: '3px', padding: '3px 6px',
borderRadius: '67px', borderRadius: '67px',
width: '50%', width: 'fit-content',
}} }}
> >
<Text size={11} color="#fff"> <Text size={11} color="#fff">

View File

@ -7,8 +7,12 @@ import LinkWithArrow from '../../../../components/General/LinkWithArrow'
const ValidatorSetup = () => { const ValidatorSetup = () => {
return ( return (
<YStack style={{ width: '100%', padding: '16px 32px' }}> <YStack
<XStack justifyContent={'space-between'}> style={{ width: '100%', padding: '26px 32px' }}
minHeight={'65vh'}
justifyContent={'space-between'}
>
<XStack justifyContent={'space-between'} alignItems={'center'}>
<Text size={27} weight={'semibold'}> <Text size={27} weight={'semibold'}>
Validator Setup Validator Setup
</Text> </Text>
@ -21,7 +25,7 @@ const ValidatorSetup = () => {
Execution Client Detection Execution Client Detection
</Text> </Text>
</Stack> </Stack>
<Text size={15} weight={'regular'}> <Text size={15}>
No existing execution client installations have been detected on paired device. No existing execution client installations have been detected on paired device.
</Text> </Text>
<Text size={13} color="#828282"> <Text size={13} color="#828282">
@ -30,7 +34,7 @@ const ValidatorSetup = () => {
</Text> </Text>
</YStack> </YStack>
<TextTam fontSize={27} style={{ margin: '5px', marginLeft: 0 }}> <TextTam fontSize={27} style={{ marginTop: '15px', marginLeft: 0, marginBottom: '15px' }}>
Select Execution client Select Execution client
</TextTam> </TextTam>
<XStack justifyContent={'space-between'}> <XStack justifyContent={'space-between'}>
@ -43,7 +47,7 @@ const ValidatorSetup = () => {
<LinkWithArrow <LinkWithArrow
to="/" to="/"
text="View Execution client comparison chart" text="View Execution client comparison chart"
style={{ marginTop: '3%' }} style={{ marginTop: '6%', fontWeight: 'bold' }}
/> />
</YStack> </YStack>
) )

View File

@ -8,11 +8,11 @@
.gradient-wrapper:after { .gradient-wrapper:after {
display: block; display: block;
content: ""; content: '';
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
width: 100%; width: 100%;
height: 100%; height: 100%;
background: linear-gradient(to bottom, rgba(113, 64, 253, 0.075) 15%, rgba(255,255,255,0) 50%); background: linear-gradient(to bottom, rgba(113, 64, 253, 0.075) 15%, rgba(255, 255, 255, 0) 50%);
} }

View File

@ -0,0 +1,46 @@
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
interface SidebarButton {
id: string
isDotOn: boolean
isSelected: boolean
isDisabled?: boolean
}
interface LeftSidebarState {
buttons: SidebarButton[]
}
const initialState: LeftSidebarState = {
buttons: [
{ id: 'dashboard', isDotOn: false, isSelected: true },
{ id: 'speed', isDotOn: false, isSelected: false },
{ id: 'chart', isDotOn: false, isSelected: false, isDisabled: true },
{ id: 'heart', isDotOn: false, isSelected: false },
{ id: 'codeBlock', isDotOn: false, isSelected: false },
{ id: 'communities', isDotOn: false, isSelected: false },
{ id: 'activityCenter', isDotOn: true, isSelected: false },
{ id: 'settings', isDotOn: false, isSelected: false },
],
}
const leftSidebarSlice = createSlice({
name: 'leftSidebar',
initialState,
reducers: {
toggleButtonSelection: (state, action: PayloadAction<string>) => {
state.buttons.forEach(button => {
button.isSelected = button.id === action.payload
})
},
toggleDot: (state, action: PayloadAction<string>) => {
const button = state.buttons.find(button => button.id === action.payload)
if (button) button.isDotOn = !button.isDotOn
},
},
})
export const { toggleButtonSelection, toggleDot } = leftSidebarSlice.actions
export default leftSidebarSlice.reducer

View File

@ -4,6 +4,7 @@ import pinnedMessageReducer from './PinnedMessage/slice'
import execClientReducer from './ValidatorOnboarding/ValidatorSetup/slice' import execClientReducer from './ValidatorOnboarding/ValidatorSetup/slice'
import themeReducer from './theme/slice' import themeReducer from './theme/slice'
import keyGenerationReducer from './ValidatorOnboarding/KeyGeneration/slice' import keyGenerationReducer from './ValidatorOnboarding/KeyGeneration/slice'
import leftSidebarReducer from './Sidebars/slice'
const store = configureStore({ const store = configureStore({
reducer: { reducer: {
@ -12,6 +13,7 @@ const store = configureStore({
execClient: execClientReducer, execClient: execClientReducer,
theme: themeReducer, theme: themeReducer,
keyGeneration: keyGenerationReducer, keyGeneration: keyGenerationReducer,
leftSidebar: leftSidebarReducer,
}, },
}) })

View File

@ -26,13 +26,13 @@ export const convertSecondsToTimerFormat = (seconds: number) => {
} }
export const formatNumbersWithComa = (n: number): string => { export const formatNumbersWithComa = (n: number): string => {
const parts = n.toString().split('.'); const parts = n.toString().split('.')
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ','); parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',')
return parts.join('.'); return parts.join('.')
}; }
export const getMonthIndicesFromRange = (range: DateRange) => { export const getMonthIndicesFromRange = (range: DateRange) => {
if (!range.from || !range.to) return [0, 11] if (!range.from || !range.to) return [0, 11]
return [range.from.getMonth(), range.to.getMonth()] return [range.from.getMonth(), range.to.getMonth()]
} }