Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
79 commits
Select commit Hold shift + click to select a range
4795f1a
Implement Home page with balance visualisation and menu enhancements
joeljkrb Mar 10, 2025
1f5c21b
chore: tidy and fix
joeljkrb Mar 10, 2025
3554aeb
Updated the locale files for Spanish (ES) and Chinese (ZH) to include…
joeljkrb Mar 10, 2025
20d8c7b
chore: ES Lint fix
joeljkrb Mar 10, 2025
899f6a4
chore: Missing ES translations added
joeljkrb Mar 10, 2025
14582ac
chore: reorganise EN app
joeljkrb Mar 10, 2025
9da1fce
chore: add missing newlines
joeljkrb Mar 10, 2025
b807484
chore: EN Locales fix
joeljkrb Mar 10, 2025
f722f1b
chore: Fixed key ordering in all locale files
joeljkrb Mar 10, 2025
83b67e7
feat: Welcome Message on Home Page
joeljkrb Mar 13, 2025
32907c2
chore: improve welcome box appearance
joeljkrb Mar 13, 2025
8e0cd97
chore: improve Staking health information card
joeljkrb Mar 13, 2025
d2c932a
chore: Improve Home Page
joeljkrb Mar 13, 2025
3529ac0
Merge branch 'main' into feat/homeconcept
joeljkrb Apr 1, 2025
93c2aa6
fix: correct reward rate calculations in StakingHealth component
joeljkrb Apr 1, 2025
b9a3b9e
chore: fix ordering
joeljkrb Apr 1, 2025
f409152
Merge branch 'main' into feat/homeconcept
rossbulat Apr 7, 2025
4cfde0f
Merge branch 'main' into feat/homeconcept
rossbulat Apr 7, 2025
6fce5a0
merge fix
rossbulat Apr 7, 2025
fd07d00
Merge branch 'main' into feat/homeconcept
joeljkrb Apr 7, 2025
71b8ab4
refactor: normalise card styling for consistency
joeljkrb Apr 16, 2025
604d748
refactor: theme variables
joeljkrb Apr 16, 2025
f4b711f
chore: Add consistent section headers to Home page cards
joeljkrb Apr 16, 2025
cc1c3c1
chore - reshuffle order
joeljkrb Apr 16, 2025
7c7b5af
Merge branch 'main' into feat/homeconcept
rossbulat Apr 17, 2025
2c75933
merge main fixes
rossbulat Apr 17, 2025
eb14fc4
Merge branch 'main' into feat/homeconcept
rossbulat Apr 17, 2025
a3138d7
chore: remove redundant text
joeljkrb Apr 17, 2025
ad1e233
chore: pool staking info update
joeljkrb Apr 17, 2025
23d9f6a
feat: Add Price Widget
joeljkrb Apr 17, 2025
85e9803
feat(home): Redesign Home page layout - new content & better UX
joeljkrb Apr 17, 2025
124f987
chore: add missing keys
joeljkrb Apr 17, 2025
2963f65
feat: Enhance dashboard with Staking Progress and Quick Actions
joeljkrb Apr 21, 2025
55a3440
feat: Enhance StakingProgress component with improved guidance
joeljkrb Apr 21, 2025
acfd5e0
chore: Implement network-specific values and links
joeljkrb Apr 21, 2025
0526ea4
feat: Add dynamic support options to Request Help button
joeljkrb Apr 22, 2025
29b7cc3
feat(home): implement dynamic Claim Rewards button in Quick Actions
joeljkrb Apr 22, 2025
e595bb9
Merge branch 'main' into feat/homeconcept
rossbulat Apr 30, 2025
ecaecb4
fix merge main errors
rossbulat Apr 30, 2025
3e93f00
feat: add Easy/Advanced mode toggle button to top toolbar with networ…
joeljkrb May 8, 2025
d5e79d7
Merge branch 'main' into feat/easy-mode-switcher
joeljkrb May 8, 2025
cc5c0ff
Merge branch 'main' into feat/easy-mode-switcher
joeljkrb May 9, 2025
6b419bf
refactor: move Easy/Advanced toggle to side menu
joeljkrb May 9, 2025
71931a3
feat: Implement basic Advanced/Easy mode toggle logic
joeljkrb May 9, 2025
5646b00
feat: Add Advanced mode toggle to minimised sidebar
joeljkrb May 9, 2025
94a246d
chore: add rewards page to 'easy mode'
joeljkrb May 12, 2025
edc0851
chore: Disable Stake/Unstake/Rewards buttons when no tokens are staked
joeljkrb May 12, 2025
fc5695f
feat: add insufficient balance message to smart staking recommendation
joeljkrb May 12, 2025
a4a93ed
feat: enhance home page staking actions to use canvas modals
joeljkrb May 12, 2025
d7105a9
feat: Implement direct modal access for unstake actions on Home page
joeljkrb May 12, 2025
ae435b6
feat: Implement Send modal
joeljkrb May 12, 2025
402ac98
feat: Addition of compact staking card
joeljkrb May 12, 2025
27f8610
feat: Update pool staking card for improved UI consistency
joeljkrb May 14, 2025
3e484b5
feat: Update nominating staking card for improved UI consistency
joeljkrb May 14, 2025
fbc11b3
feat: Restructure home page layout
joeljkrb May 14, 2025
4edddd0
chore: restructure home page
joeljkrb May 14, 2025
1cecdc0
feat: add health status tiers & improve recommendation thresholds
joeljkrb May 15, 2025
8450cbe
fix: recommendation quick action for Pools
joeljkrb May 15, 2025
7a97120
fix: recommended quick action for nominators
joeljkrb May 15, 2025
2e4c3e4
chore: don't show send button if no balance
joeljkrb May 16, 2025
ba40830
feat: add rewards performance to welcome card
joeljkrb May 16, 2025
5289528
chore: dark mode & check list step improvements
joeljkrb May 16, 2025
09ffe43
chore: fix alignment within welcome card
joeljkrb May 16, 2025
a381c52
Merge branch 'main' into feat/homeconcept
rossbulat May 20, 2025
ecee024
position, icon
rossbulat May 20, 2025
28c1d1f
Merge branch 'main' into feat/homeconcept
rossbulat May 20, 2025
4ff815b
merge fixes
rossbulat May 20, 2025
df2c8dd
Merge branch 'main' into feat/homeconcept
joeljkrb May 27, 2025
1631346
chore: fix locales
joeljkrb May 27, 2025
146daaf
chore: update imports
joeljkrb May 27, 2025
2779d5e
feat: optimise home page performance and fix supply staked calculation
joeljkrb May 28, 2025
e9c5dd5
chore: help mode reminder
joeljkrb May 28, 2025
38f3d7f
chore: fix buttons availability for nominators
joeljkrb May 28, 2025
afce841
feat: Improve font consistency and styling across home page cards
joeljkrb May 28, 2025
0d858da
Merge branch 'main' into feat/homeconcept
joeljkrb Jun 9, 2025
683c28d
Merge branch 'main' into feat/homeconcept
joeljkrb Jun 10, 2025
aea7992
Merge branch 'main' into feat/homeconcept
joeljkrb Jun 16, 2025
542dd30
chore - fix errors in build
joeljkrb Jun 16, 2025
dd061e5
chore: update wallet balance logic for home
joeljkrb Jun 16, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 25 additions & 8 deletions packages/app/src/Router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,17 +85,34 @@ const RouterInner = () => {
<Headers />
<ErrorBoundary FallbackComponent={ErrorFallbackRoutes}>
<Routes>
{getPagesConfig(network, advancedMode).map((page, i) => (
<Route
key={`main_interface_page_${i}`}
path={page.hash}
element={<PageWithTitle page={page} />}
/>
))}
{getPagesConfig(network, advancedMode).map((page, i) => {
// Only allow home page and rewards page when in Easy mode (advancedMode is false)
// Allow all pages when in Advanced mode (advancedMode is true)
if (
!advancedMode &&
page.key !== 'home' &&
page.key !== 'rewards'
) {
return (
<Route
key={`main_interface_page_${i}`}
path={page.hash}
element={<Navigate to="/home" />}
/>
)
}
return (
<Route
key={`main_interface_page_${i}`}
path={page.hash}
element={<PageWithTitle page={page} />}
/>
)
})}
<Route
key="main_interface_navigate"
path="*"
element={<Navigate to="/overview" />}
element={<Navigate to="/home" />}
/>
</Routes>
</ErrorBoundary>
Expand Down
10 changes: 10 additions & 0 deletions packages/app/src/config/pages.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright 2025 @polkadot-cloud/polkadot-staking-dashboard authors & contributors
// SPDX-License-Identifier: GPL-3.0-only

import { Home } from 'pages/Home'
import { Nominate } from 'pages/Nominate'
import { Operators } from 'pages/Operators'
import { Overview } from 'pages/Overview'
Expand Down Expand Up @@ -28,6 +29,15 @@ export const PageCategories: PageCategoryItems = [
]

export const PagesConfig: PagesConfigItems = [
{
category: 1,
key: 'home',
uri: `${import.meta.env.BASE_URL}`,
hash: '/home',
Entry: Home,
lottie: 'home',
advanced: false,
},
{
category: 2,
key: 'overview',
Expand Down
96 changes: 96 additions & 0 deletions packages/app/src/library/Headers/ToggleMode.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// Copyright 2025 @polkadot-cloud/polkadot-staking-dashboard authors & contributors
// SPDX-License-Identifier: GPL-3.0-only

import { useState } from 'react'
import styled from 'styled-components'

const ToggleWrapper = styled.div`
position: relative;
display: flex;
align-items: stretch;
margin-left: 0.8rem;
background: var(--button-primary-background);
border-radius: 999px;
box-shadow: var(--card-shadow);
border: 1.5px solid var(--accent-color-primary);
height: 2.8rem;
min-width: 220px;
width: 220px;
padding: 0;
overflow: hidden;
`

const Slider = styled.div<{ mode: 'easy' | 'advanced' }>`
position: absolute;
top: 0;
left: ${({ mode }) => (mode === 'easy' ? '0' : '50%')};
width: 50%;
height: 100%;
background: var(--accent-color-primary);
border-radius: 999px;
transition: left 0.25s cubic-bezier(0.4, 0, 0.2, 1);
z-index: 1;
`

const ToggleButton = styled.button<{ $active: boolean }>`
position: relative;
z-index: 2;
flex: 1 1 50%;
border: none !important;
outline: none !important;
background: transparent;
font-family: InterSemiBold, sans-serif;
font-size: 1.1rem;
padding: 0 1.2rem;
margin: 0;
cursor: pointer;
border-radius: 0;
min-width: 0;
display: flex;
align-items: center;
justify-content: center;
color: ${({ $active }) =>
$active ? 'white' : 'var(--text-color-secondary)'};
transition: color 0.2s;
height: 100%;
box-shadow: none;

&:focus {
outline: none !important;
border: none !important;
box-shadow: none;
}
&:focus-visible {
outline: none !important;
border: none !important;
box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.08);
}
`

export const ToggleMode = () => {
const [mode, setMode] = useState<'easy' | 'advanced'>('easy')

return (
<ToggleWrapper aria-label="Display mode toggle" role="group" tabIndex={0}>
<Slider mode={mode} aria-hidden />
<ToggleButton
$active={mode === 'easy'}
aria-pressed={mode === 'easy'}
aria-label="Easy mode"
onClick={() => setMode('easy')}
type="button"
>
Easy
</ToggleButton>
<ToggleButton
$active={mode === 'advanced'}
aria-pressed={mode === 'advanced'}
aria-label="Advanced mode"
onClick={() => setMode('advanced')}
type="button"
>
Advanced
</ToggleButton>
</ToggleWrapper>
)
}
3 changes: 3 additions & 0 deletions packages/app/src/library/Help/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ export const Help = () => {

let definitions = meta?.definitions ?? []

// TODO: Integrate easy/advanced mode content from other PR
// When ready, use useUi() to get advancedMode and filter definitions accordingly

const activeDefinitions = definitions
.filter((d) => d !== definition)
.map((d) => {
Expand Down
144 changes: 144 additions & 0 deletions packages/app/src/library/SideMenu/AdvancedModeToggle.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
// Copyright 2025 @polkadot-cloud/polkadot-staking-dashboard authors & contributors
// SPDX-License-Identifier: GPL-3.0-only

import {
faChartLine,
faSlidersH,
faToggleOff,
faToggleOn,
} from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { useUi } from 'contexts/UI'
import type { UIContextInterface } from 'contexts/UI/types'
import { useTranslation } from 'react-i18next'
import styled from 'styled-components'

const ToggleContainer = styled.div`
position: relative;
margin-top: auto;
padding: 0;
width: 100%;
`

const MinimizedToggle = styled.div<{ $active: boolean }>`
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
user-select: none;
transition: all 0.15s;
padding: 0.75rem;
margin: 0.5rem 0;
width: 100%;
box-sizing: border-box;
border-radius: 0.75rem;
background: ${({ $active }) =>
$active ? 'var(--button-secondary-background)' : 'transparent'};

&:hover {
background: var(--button-secondary-background);
}

&:active {
transform: scale(0.98);
}
`

const ToggleWrapper = styled.div`
display: flex;
align-items: center;
justify-content: space-between;
cursor: pointer;
user-select: none;
transition: all 0.15s;
padding: 0.75rem 1rem;
margin: 0.5rem 0;
width: 100%;
box-sizing: border-box;
gap: 1.5rem;

&:active {
transform: scale(0.98);
}
`

const ToggleLabel = styled.div`
display: flex;
align-items: center;
font-family: InterSemiBold, sans-serif;
color: var(--text-color-secondary);
font-size: 1.1rem;

.icon {
width: 1.2rem;
height: 1.2rem;
display: flex;
align-items: center;
justify-content: center;
margin-right: 0.75rem;
min-width: 1.2rem;
flex-shrink: 0;
}
`

export const AdvancedModeToggle = ({ minimised }: { minimised: boolean }) => {
const { t } = useTranslation('app')
const { advancedMode, setAdvancedMode }: UIContextInterface = useUi()

const toggleAdvancedMode = () => {
setAdvancedMode(!advancedMode)
}

// If the sidebar is minimized, show a compact version
if (minimised) {
return (
<ToggleContainer>
<MinimizedToggle
onClick={toggleAdvancedMode}
role="switch"
aria-checked={advancedMode}
aria-label={t('advanced')}
$active={advancedMode}
>
<FontAwesomeIcon
icon={faChartLine}
color={
advancedMode
? 'var(--accent-color-primary)'
: 'var(--text-color-tertiary)'
}
transform="grow-2"
/>
</MinimizedToggle>
</ToggleContainer>
)
}

return (
<ToggleContainer>
<ToggleWrapper
onClick={toggleAdvancedMode}
role="switch"
aria-checked={advancedMode}
aria-label={t('advanced')}
>
<ToggleLabel>
<span className="icon" style={{ color: 'var(--text-color-primary)' }}>
<FontAwesomeIcon icon={faSlidersH} />
</span>
{t('advanced')}
</ToggleLabel>
<FontAwesomeIcon
icon={advancedMode ? faToggleOn : faToggleOff}
color={
advancedMode
? 'var(--accent-color-primary)'
: 'var(--text-color-tertiary)'
}
transform="grow-12"
style={{ marginTop: '1px' }}
/>
</ToggleWrapper>
</ToggleContainer>
)
}
64 changes: 41 additions & 23 deletions packages/app/src/library/SideMenu/Main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,29 +90,47 @@ export const Main = () => {
return (
<>
{pageConfig.categories.map(
({ id: categoryId, key: categoryKey }: PageCategory) => (
<div className="inner" key={`sidemenu_category_${categoryId}`}>
{categoryKey !== 'default' && (
<Heading title={t(categoryKey)} minimised={sideMenuMinimised} />
)}
{pagesToDisplay.map(
({ category, hash, key, lottie, bullet }: PageItem) => (
<Fragment key={`sidemenu_page_${categoryId}_${key}`}>
{category === categoryId && (
<Primary
name={t(key)}
to={hash}
active={hash === pathname}
lottie={lottie}
bullet={bullet}
minimised={sideMenuMinimised}
/>
)}
</Fragment>
)
)}
</div>
)
({ id: categoryId, key: categoryKey }: PageCategory) => {
// In Easy mode (advancedMode is false), show default category (Home) and stake category for Rewards
if (
!advancedMode &&
categoryKey !== 'default' &&
categoryKey !== 'stake'
) {
return null
}

return (
<div className="inner" key={`sidemenu_category_${categoryId}`}>
{categoryKey !== 'default' && advancedMode && (
<Heading title={t(categoryKey)} minimised={sideMenuMinimised} />
)}
{pagesToDisplay.map(
({ category, hash, key, lottie, bullet }: PageItem) => {
// In Easy mode, only show the Home page and Rewards page
if (!advancedMode && key !== 'home' && key !== 'rewards') {
return null
}

return (
<Fragment key={`sidemenu_page_${categoryId}_${key}`}>
{category === categoryId && (
<Primary
name={t(key)}
to={hash}
active={hash === pathname}
lottie={lottie}
bullet={bullet}
minimised={sideMenuMinimised}
/>
)}
</Fragment>
)
}
)}
</div>
)
}
)}
</>
)
Expand Down
Loading