Compare commits
10
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
87731097b8 | ||
|
|
1e9209028e | ||
|
|
2861286bdb | ||
|
|
e93850484b | ||
|
|
521b6d6135 | ||
|
|
94772bf4dc | ||
|
|
149f21e7e0 | ||
|
|
0a3ef3a7ab | ||
|
|
fef9935883 | ||
|
|
c7a5b706e1 |
+18
-9
@@ -5,29 +5,35 @@ import styled from 'styled-components';
|
|||||||
|
|
||||||
import { store } from '@/state/_store';
|
import { store } from '@/state/_store';
|
||||||
|
|
||||||
|
import { GlobalStyle } from '@/styles/globalStyle';
|
||||||
|
|
||||||
import { SelectMenu, SelectItem } from '@/components/SelectMenu';
|
import { SelectMenu, SelectItem } from '@/components/SelectMenu';
|
||||||
|
|
||||||
|
import { AppThemeProvider } from '@/hooks/useAppTheme';
|
||||||
|
|
||||||
|
import { AppTheme, setAppTheme } from '@/state/configs';
|
||||||
import { setLocaleLoaded } from '@/state/localization';
|
import { setLocaleLoaded } from '@/state/localization';
|
||||||
|
|
||||||
import '@/index.css';
|
import '@/index.css';
|
||||||
import './ladle.css';
|
import './ladle.css';
|
||||||
|
|
||||||
export const StoryWrapper: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
export const StoryWrapper: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
||||||
const [theme, setTheme] = useState('Default theme');
|
const [theme, setTheme] = useState(AppTheme.Classic);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
store.dispatch(setAppTheme(theme));
|
||||||
switch (theme) {
|
switch (theme) {
|
||||||
case 'Dark theme': {
|
case AppTheme.Dark: {
|
||||||
document?.documentElement?.classList.remove('theme-light');
|
document?.documentElement?.classList.remove('theme-light');
|
||||||
document?.documentElement?.classList.add('theme-dark');
|
document?.documentElement?.classList.add('theme-dark');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'Light theme': {
|
case AppTheme.Light: {
|
||||||
document?.documentElement?.classList.remove('theme-dark');
|
document?.documentElement?.classList.remove('theme-dark');
|
||||||
document?.documentElement?.classList.add('theme-light');
|
document?.documentElement?.classList.add('theme-light');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
case AppTheme.Classic: {
|
||||||
document?.documentElement?.classList.remove('theme-dark', 'theme-light');
|
document?.documentElement?.classList.remove('theme-dark', 'theme-light');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -48,15 +54,15 @@ export const StoryWrapper: React.FC<{ children: React.ReactNode }> = ({ children
|
|||||||
>
|
>
|
||||||
{[
|
{[
|
||||||
{
|
{
|
||||||
value: 'Default theme',
|
value: AppTheme.Classic,
|
||||||
label: 'Default theme',
|
label: 'Default theme',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: 'Dark theme',
|
value: AppTheme.Dark,
|
||||||
label: 'Dark theme',
|
label: 'Dark theme',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: 'Light theme',
|
value: AppTheme.Light,
|
||||||
label: 'Light theme',
|
label: 'Light theme',
|
||||||
},
|
},
|
||||||
].map(({ value, label }) => (
|
].map(({ value, label }) => (
|
||||||
@@ -69,8 +75,11 @@ export const StoryWrapper: React.FC<{ children: React.ReactNode }> = ({ children
|
|||||||
</SelectMenu>
|
</SelectMenu>
|
||||||
</StoryHeader>
|
</StoryHeader>
|
||||||
<hr />
|
<hr />
|
||||||
<StoryContent>{children}</StoryContent>
|
<AppThemeProvider>
|
||||||
</Provider>
|
<GlobalStyle />
|
||||||
|
<StoryContent>{children}</StoryContent>
|
||||||
|
</AppThemeProvider>
|
||||||
|
</Provider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -39,7 +39,7 @@
|
|||||||
"@cosmjs/proto-signing": "^0.31.0",
|
"@cosmjs/proto-signing": "^0.31.0",
|
||||||
"@cosmjs/stargate": "^0.31.0",
|
"@cosmjs/stargate": "^0.31.0",
|
||||||
"@cosmjs/tendermint-rpc": "^0.31.0",
|
"@cosmjs/tendermint-rpc": "^0.31.0",
|
||||||
"@dydxprotocol/v4-abacus": "^1.2.3",
|
"@dydxprotocol/v4-abacus": "^1.2.5",
|
||||||
"@dydxprotocol/v4-client-js": "^1.0.11",
|
"@dydxprotocol/v4-client-js": "^1.0.11",
|
||||||
"@dydxprotocol/v4-localization": "^1.1.11",
|
"@dydxprotocol/v4-localization": "^1.1.11",
|
||||||
"@ethersproject/providers": "^5.7.2",
|
"@ethersproject/providers": "^5.7.2",
|
||||||
|
|||||||
Generated
+8
-8
@@ -1,9 +1,5 @@
|
|||||||
lockfileVersion: '6.0'
|
lockfileVersion: '6.0'
|
||||||
|
|
||||||
settings:
|
|
||||||
autoInstallPeers: true
|
|
||||||
excludeLinksFromLockfile: false
|
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
'@0xsquid/sdk':
|
'@0xsquid/sdk':
|
||||||
specifier: ^1.10.0
|
specifier: ^1.10.0
|
||||||
@@ -27,8 +23,8 @@ dependencies:
|
|||||||
specifier: ^0.31.0
|
specifier: ^0.31.0
|
||||||
version: 0.31.0
|
version: 0.31.0
|
||||||
'@dydxprotocol/v4-abacus':
|
'@dydxprotocol/v4-abacus':
|
||||||
specifier: ^1.2.3
|
specifier: ^1.2.5
|
||||||
version: 1.2.3
|
version: 1.2.5
|
||||||
'@dydxprotocol/v4-client-js':
|
'@dydxprotocol/v4-client-js':
|
||||||
specifier: ^1.0.11
|
specifier: ^1.0.11
|
||||||
version: 1.0.11
|
version: 1.0.11
|
||||||
@@ -991,8 +987,8 @@ packages:
|
|||||||
resolution: {integrity: sha512-RpfLEtTlyIxeNPGKcokS+p3BZII/Q3bYxryFRglh5H3A3T8q9fsLYm72VYAMEOOIBLEa8o93kFLiBDUWKrwXZA==}
|
resolution: {integrity: sha512-RpfLEtTlyIxeNPGKcokS+p3BZII/Q3bYxryFRglh5H3A3T8q9fsLYm72VYAMEOOIBLEa8o93kFLiBDUWKrwXZA==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@dydxprotocol/v4-abacus@1.2.3:
|
/@dydxprotocol/v4-abacus@1.2.5:
|
||||||
resolution: {integrity: sha512-OHGhN4uQo/ikRjeGzf+wGblFvb0uRA916QvQXG4LixsJy7H7HAt7AeZr9LqTM/GqYJicMmZCUS3WIMqgZ20hKA==}
|
resolution: {integrity: sha512-pB3Fv1bzJRUDp29kAN61daZ34gTSGrSTNh+/AP3TUB63/Q/gaXQVBf91xVcso4Hw23xM3FwIcrRK0cvOSWgXKg==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@dydxprotocol/v4-client-js@1.0.11:
|
/@dydxprotocol/v4-client-js@1.0.11:
|
||||||
@@ -14813,3 +14809,7 @@ packages:
|
|||||||
/zwitch@2.0.4:
|
/zwitch@2.0.4:
|
||||||
resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
|
resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
settings:
|
||||||
|
autoInstallPeers: true
|
||||||
|
excludeLinksFromLockfile: false
|
||||||
|
|||||||
@@ -0,0 +1,230 @@
|
|||||||
|
<svg width="254" height="77" viewBox="0 0 254 77" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g id="Group 1258">
|
||||||
|
<g id="Ellipse 9" opacity="0.4" filter="url(#filter0_f_20300_14972)">
|
||||||
|
<ellipse cx="86.5425" cy="-3.91219" rx="116.542" ry="20.0878" fill="#7774FF"/>
|
||||||
|
</g>
|
||||||
|
<g id="Ellipse 10" opacity="0.3" filter="url(#filter1_f_20300_14972)">
|
||||||
|
<circle cx="74.5734" cy="4.63007" r="1.00507" fill="#9A9AFF"/>
|
||||||
|
</g>
|
||||||
|
<g id="Ellipse 12" opacity="0.3" filter="url(#filter2_f_20300_14972)">
|
||||||
|
<circle cx="82.1105" cy="7.64179" r="1.00507" fill="#9A9AFF"/>
|
||||||
|
</g>
|
||||||
|
<g id="Ellipse 22" opacity="0.3" filter="url(#filter3_f_20300_14972)">
|
||||||
|
<circle cx="116.785" cy="4.63007" r="1.00507" fill="#9A9AFF"/>
|
||||||
|
</g>
|
||||||
|
<g id="Ellipse 11" opacity="0.3" filter="url(#filter4_f_20300_14972)">
|
||||||
|
<circle cx="64.774" cy="8.90488" r="0.502536" fill="#9A9AFF"/>
|
||||||
|
</g>
|
||||||
|
<g id="Ellipse 18" opacity="0.3" filter="url(#filter5_f_20300_14972)">
|
||||||
|
<circle cx="96.4322" cy="3.87363" r="0.502536" fill="#9A9AFF"/>
|
||||||
|
</g>
|
||||||
|
<g id="Ellipse 20" opacity="0.3" filter="url(#filter6_f_20300_14972)">
|
||||||
|
<circle cx="76.0807" cy="14.9361" r="0.502536" fill="#9A9AFF"/>
|
||||||
|
</g>
|
||||||
|
<g id="Ellipse 21" opacity="0.3" filter="url(#filter7_f_20300_14972)">
|
||||||
|
<circle cx="104.725" cy="4.87754" r="0.502536" fill="#9A9AFF"/>
|
||||||
|
</g>
|
||||||
|
<g id="Ellipse 23" opacity="0.3" filter="url(#filter8_f_20300_14972)">
|
||||||
|
<circle cx="114.021" cy="7.13925" r="0.502536" fill="#9A9AFF"/>
|
||||||
|
</g>
|
||||||
|
<g id="Ellipse 24" opacity="0.3" filter="url(#filter9_f_20300_14972)">
|
||||||
|
<circle cx="109.75" cy="15.4361" r="0.502536" fill="#9A9AFF"/>
|
||||||
|
</g>
|
||||||
|
<g id="Ellipse 25" opacity="0.3" filter="url(#filter10_f_20300_14972)">
|
||||||
|
<circle cx="119.801" cy="12.6705" r="0.502536" fill="#9A9AFF"/>
|
||||||
|
</g>
|
||||||
|
<g id="Ellipse 27" opacity="0.3" filter="url(#filter11_f_20300_14972)">
|
||||||
|
<circle cx="94.0885" cy="11.0182" r="0.502536" fill="#9A9AFF"/>
|
||||||
|
</g>
|
||||||
|
<g id="Ellipse 30" opacity="0.3" filter="url(#filter12_f_20300_14972)">
|
||||||
|
<circle cx="154.475" cy="11.6666" r="0.502536" fill="#9A9AFF"/>
|
||||||
|
</g>
|
||||||
|
<g id="Ellipse 29" opacity="0.3" filter="url(#filter13_f_20300_14972)">
|
||||||
|
<circle cx="146.435" cy="8.90488" r="0.502536" fill="#9A9AFF"/>
|
||||||
|
</g>
|
||||||
|
<g id="Ellipse 15" opacity="0.3" filter="url(#filter14_f_20300_14972)">
|
||||||
|
<circle cx="24.0103" cy="4.44785" r="0.502536" fill="#9A9AFF"/>
|
||||||
|
</g>
|
||||||
|
<g id="Ellipse 33" opacity="0.3" filter="url(#filter15_f_20300_14972)">
|
||||||
|
<circle cx="-1.05899" cy="13.6783" r="0.502536" fill="#9A9AFF"/>
|
||||||
|
</g>
|
||||||
|
<g id="Ellipse 16" opacity="0.3" filter="url(#filter16_f_20300_14972)">
|
||||||
|
<circle cx="17.441" cy="16.4908" r="0.502536" fill="#9A9AFF"/>
|
||||||
|
</g>
|
||||||
|
<g id="Ellipse 35" opacity="0.3" filter="url(#filter17_f_20300_14972)">
|
||||||
|
<circle cx="36.0553" cy="6.63535" r="0.502536" fill="#9A9AFF"/>
|
||||||
|
</g>
|
||||||
|
<g id="Ellipse 32" opacity="0.3" filter="url(#filter18_f_20300_14972)">
|
||||||
|
<circle cx="10.8707" cy="14.2994" r="0.502536" fill="#9A9AFF"/>
|
||||||
|
</g>
|
||||||
|
<g id="Ellipse 13" opacity="0.3" filter="url(#filter19_f_20300_14972)">
|
||||||
|
<circle cx="55.7274" cy="9.65615" r="0.753803" fill="#9A9AFF"/>
|
||||||
|
</g>
|
||||||
|
<g id="Ellipse 19" opacity="0.3" filter="url(#filter20_f_20300_14972)">
|
||||||
|
<circle cx="87.3886" cy="20.7108" r="0.753803" fill="#9A9AFF"/>
|
||||||
|
</g>
|
||||||
|
<g id="Ellipse 26" opacity="0.3" filter="url(#filter21_f_20300_14972)">
|
||||||
|
<circle cx="123.82" cy="15.1874" r="0.753803" fill="#9A9AFF"/>
|
||||||
|
</g>
|
||||||
|
<g id="Ellipse 36" opacity="0.3" filter="url(#filter22_f_20300_14972)">
|
||||||
|
<circle cx="134.876" cy="14.4335" r="0.753803" fill="#9A9AFF"/>
|
||||||
|
</g>
|
||||||
|
<g id="Ellipse 28" opacity="0.3" filter="url(#filter23_f_20300_14972)">
|
||||||
|
<circle cx="129.6" cy="6.38662" r="0.753803" fill="#9A9AFF"/>
|
||||||
|
</g>
|
||||||
|
<g id="Ellipse 14" opacity="0.3" filter="url(#filter24_f_20300_14972)">
|
||||||
|
<circle cx="41.6571" cy="14.9335" r="0.753803" fill="#9A9AFF"/>
|
||||||
|
</g>
|
||||||
|
<g id="Ellipse 31" opacity="0.3" filter="url(#filter25_f_20300_14972)">
|
||||||
|
<circle cx="4.21767" cy="17.9491" r="0.753803" fill="#9A9AFF"/>
|
||||||
|
</g>
|
||||||
|
<g id="Ellipse 34" opacity="0.3" filter="url(#filter26_f_20300_14972)">
|
||||||
|
<circle cx="12.2177" cy="6.88662" r="0.753803" fill="#9A9AFF"/>
|
||||||
|
</g>
|
||||||
|
<g id="Ellipse 17" opacity="0.3" filter="url(#filter27_f_20300_14972)">
|
||||||
|
<circle cx="50.2001" cy="3.6249" r="0.753803" fill="#9A9AFF"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<filter id="filter0_f_20300_14972" x="-94" y="-88" width="361.085" height="168.176" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="32" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter1_f_20300_14972" x="72.5633" y="2.61993" width="4.01991" height="4.02186" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter2_f_20300_14972" x="80.6029" y="6.13418" width="3.01484" height="3.01679" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.251268" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter3_f_20300_14972" x="115.278" y="3.12246" width="3.01484" height="3.01679" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.251268" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter4_f_20300_14972" x="63.2664" y="7.39727" width="3.01502" height="3.01405" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter5_f_20300_14972" x="94.9246" y="2.36602" width="3.01502" height="3.01405" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter6_f_20300_14972" x="74.5731" y="13.4285" width="3.01502" height="3.01405" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter7_f_20300_14972" x="103.218" y="3.36993" width="3.01502" height="3.01405" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter8_f_20300_14972" x="112.513" y="5.63165" width="3.01502" height="3.01405" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter9_f_20300_14972" x="108.242" y="13.9285" width="3.01502" height="3.01405" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter10_f_20300_14972" x="118.294" y="11.1629" width="3.01502" height="3.01405" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter11_f_20300_14972" x="92.5809" y="9.51055" width="3.01502" height="3.01405" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter12_f_20300_14972" x="153.47" y="10.6615" width="2.00995" height="2.00898" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.251268" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter13_f_20300_14972" x="144.928" y="7.39727" width="3.01502" height="3.01405" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter14_f_20300_14972" x="22.5027" y="2.94024" width="3.01502" height="3.01405" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter15_f_20300_14972" x="-2.56659" y="12.1707" width="3.01502" height="3.01405" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter16_f_20300_14972" x="15.9334" y="14.9832" width="3.01502" height="3.01405" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter17_f_20300_14972" x="35.0502" y="5.63028" width="2.00995" height="2.00898" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.251268" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter18_f_20300_14972" x="9.86563" y="13.2943" width="2.00995" height="2.00898" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.251268" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter19_f_20300_14972" x="53.9686" y="7.89727" width="3.51795" height="3.51795" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter20_f_20300_14972" x="85.6297" y="18.952" width="3.51795" height="3.51795" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter21_f_20300_14972" x="122.061" y="13.4285" width="3.51795" height="3.51795" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter22_f_20300_14972" x="133.117" y="12.6746" width="3.51795" height="3.51795" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter23_f_20300_14972" x="127.842" y="4.62774" width="3.51795" height="3.51795" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter24_f_20300_14972" x="39.8982" y="13.1746" width="3.51795" height="3.51795" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter25_f_20300_14972" x="2.4588" y="16.1902" width="3.51795" height="3.51795" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter26_f_20300_14972" x="10.4588" y="5.12774" width="3.51795" height="3.51795" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter27_f_20300_14972" x="48.4412" y="1.86602" width="3.51795" height="3.51795" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 15 KiB |
+40
-34
@@ -16,6 +16,7 @@ import {
|
|||||||
} from '@/hooks';
|
} from '@/hooks';
|
||||||
import { DydxProvider } from '@/hooks/useDydxClient';
|
import { DydxProvider } from '@/hooks/useDydxClient';
|
||||||
import { AccountsProvider } from '@/hooks/useAccounts';
|
import { AccountsProvider } from '@/hooks/useAccounts';
|
||||||
|
import { AppThemeProvider } from '@/hooks/useAppTheme';
|
||||||
import { DialogAreaProvider, useDialogArea } from '@/hooks/useDialogArea';
|
import { DialogAreaProvider, useDialogArea } from '@/hooks/useDialogArea';
|
||||||
import { LocaleProvider } from '@/hooks/useLocaleSeparators';
|
import { LocaleProvider } from '@/hooks/useLocaleSeparators';
|
||||||
import { NotificationsProvider } from '@/hooks/useNotifications';
|
import { NotificationsProvider } from '@/hooks/useNotifications';
|
||||||
@@ -35,6 +36,7 @@ import { GlobalCommandDialog } from '@/views/dialogs/GlobalCommandDialog';
|
|||||||
import { config } from '@/lib/wagmi';
|
import { config } from '@/lib/wagmi';
|
||||||
|
|
||||||
import { breakpoints } from '@/styles';
|
import { breakpoints } from '@/styles';
|
||||||
|
import { GlobalStyle } from '@/styles/globalStyle';
|
||||||
import { layoutMixins } from '@/styles/layoutMixins';
|
import { layoutMixins } from '@/styles/layoutMixins';
|
||||||
import { LoadingSpace } from './components/Loading/LoadingSpinner';
|
import { LoadingSpace } from './components/Loading/LoadingSpinner';
|
||||||
|
|
||||||
@@ -66,49 +68,52 @@ const Content = () => {
|
|||||||
const { chainTokenLabel } = useTokenConfigs();
|
const { chainTokenLabel } = useTokenConfigs();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Styled.Content isShowingHeader={isShowingHeader} isShowingFooter={isShowingFooter}>
|
<>
|
||||||
{isNotTablet && <HeaderDesktop />}
|
<GlobalStyle />
|
||||||
|
<Styled.Content isShowingHeader={isShowingHeader} isShowingFooter={isShowingFooter}>
|
||||||
|
{isNotTablet && <HeaderDesktop />}
|
||||||
|
|
||||||
<Styled.Main>
|
<Styled.Main>
|
||||||
<Suspense fallback={<LoadingSpace id="main" />}>
|
<Suspense fallback={<LoadingSpace id="main" />}>
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path={AppRoute.Trade}>
|
<Route path={AppRoute.Trade}>
|
||||||
<Route path=":market" element={<TradePage />} />
|
<Route path=":market" element={<TradePage />} />
|
||||||
<Route path={AppRoute.Trade} element={<TradePage />} />
|
<Route path={AppRoute.Trade} element={<TradePage />} />
|
||||||
</Route>
|
</Route>
|
||||||
|
|
||||||
<Route path={AppRoute.Markets} element={<MarketsPage />} />
|
<Route path={AppRoute.Markets} element={<MarketsPage />} />
|
||||||
<Route path={`/${chainTokenLabel}`} element={<RewardsPage />} />
|
<Route path={`/${chainTokenLabel}`} element={<RewardsPage />} />
|
||||||
{isTablet && (
|
{isTablet && (
|
||||||
<>
|
<>
|
||||||
<Route path={AppRoute.Alerts} element={<AlertsPage />} />
|
<Route path={AppRoute.Alerts} element={<AlertsPage />} />
|
||||||
<Route path={AppRoute.Profile} element={<ProfilePage />} />
|
<Route path={AppRoute.Profile} element={<ProfilePage />} />
|
||||||
<Route path={`${AppRoute.Settings}/*`} element={<SettingsPage />} />
|
<Route path={`${AppRoute.Settings}/*`} element={<SettingsPage />} />
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Route element={<GuardedMobileRoute />}>
|
<Route element={<GuardedMobileRoute />}>
|
||||||
<Route path={`${AppRoute.Portfolio}/*`} element={<PortfolioPage />} />
|
<Route path={`${AppRoute.Portfolio}/*`} element={<PortfolioPage />} />
|
||||||
</Route>
|
</Route>
|
||||||
|
|
||||||
<Route path={AppRoute.Terms} element={<TermsOfUsePage />} />
|
<Route path={AppRoute.Terms} element={<TermsOfUsePage />} />
|
||||||
<Route path={AppRoute.Privacy} element={<PrivacyPolicyPage />} />
|
<Route path={AppRoute.Privacy} element={<PrivacyPolicyPage />} />
|
||||||
|
|
||||||
<Route path="*" element={<Navigate to={DEFAULT_TRADE_ROUTE} replace />} />
|
<Route path="*" element={<Navigate to={DEFAULT_TRADE_ROUTE} replace />} />
|
||||||
</Routes>
|
</Routes>
|
||||||
</Suspense>
|
</Suspense>
|
||||||
</Styled.Main>
|
</Styled.Main>
|
||||||
|
|
||||||
{isTablet ? <FooterMobile /> : <FooterDesktop />}
|
{isTablet ? <FooterMobile /> : <FooterDesktop />}
|
||||||
|
|
||||||
<Styled.NotificationsToastArea />
|
<Styled.NotificationsToastArea />
|
||||||
|
|
||||||
<Styled.DialogArea ref={setDialogArea}>
|
<Styled.DialogArea ref={setDialogArea}>
|
||||||
<DialogManager />
|
<DialogManager />
|
||||||
</Styled.DialogArea>
|
</Styled.DialogArea>
|
||||||
|
|
||||||
<GlobalCommandDialog />
|
<GlobalCommandDialog />
|
||||||
</Styled.Content>
|
</Styled.Content>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -131,6 +136,7 @@ const providers = [
|
|||||||
wrapProvider(LocalNotificationsProvider),
|
wrapProvider(LocalNotificationsProvider),
|
||||||
wrapProvider(NotificationsProvider),
|
wrapProvider(NotificationsProvider),
|
||||||
wrapProvider(DialogAreaProvider),
|
wrapProvider(DialogAreaProvider),
|
||||||
|
wrapProvider(AppThemeProvider),
|
||||||
];
|
];
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ import {
|
|||||||
PriceChartIcon,
|
PriceChartIcon,
|
||||||
PrivacyIcon,
|
PrivacyIcon,
|
||||||
QrIcon,
|
QrIcon,
|
||||||
|
RewardStarIcon,
|
||||||
SearchIcon,
|
SearchIcon,
|
||||||
SendIcon,
|
SendIcon,
|
||||||
ShareIcon,
|
ShareIcon,
|
||||||
@@ -134,6 +135,7 @@ export enum IconName {
|
|||||||
PriceChart = 'PriceChart',
|
PriceChart = 'PriceChart',
|
||||||
Privacy = 'Privacy',
|
Privacy = 'Privacy',
|
||||||
Qr = 'Qr',
|
Qr = 'Qr',
|
||||||
|
RewardStar = 'RewardStar',
|
||||||
Search = 'Search',
|
Search = 'Search',
|
||||||
Send = 'Send',
|
Send = 'Send',
|
||||||
Share = 'Share',
|
Share = 'Share',
|
||||||
@@ -208,6 +210,7 @@ const icons = {
|
|||||||
[IconName.PriceChart]: PriceChartIcon,
|
[IconName.PriceChart]: PriceChartIcon,
|
||||||
[IconName.Privacy]: PrivacyIcon,
|
[IconName.Privacy]: PrivacyIcon,
|
||||||
[IconName.Qr]: QrIcon,
|
[IconName.Qr]: QrIcon,
|
||||||
|
[IconName.RewardStar]: RewardStarIcon,
|
||||||
[IconName.Search]: SearchIcon,
|
[IconName.Search]: SearchIcon,
|
||||||
[IconName.Send]: SendIcon,
|
[IconName.Send]: SendIcon,
|
||||||
[IconName.Share]: ShareIcon,
|
[IconName.Share]: ShareIcon,
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import styled, { type AnyStyledComponent } from 'styled-components';
|
import styled, { type AnyStyledComponent } from 'styled-components';
|
||||||
|
|
||||||
import { RiskLevels } from '@/constants/abacus';
|
import { RiskLevels } from '@/constants/abacus';
|
||||||
import { UsageColorFromRiskLevel } from '@/styles/colors';
|
|
||||||
|
|
||||||
import { Ring } from '@/components/Ring';
|
import { Ring } from '@/components/Ring';
|
||||||
|
|
||||||
import { abacusHelper } from '@/lib/abacus';
|
import { abacusHelper } from '@/lib/abacus';
|
||||||
|
import { UsageColorFromRiskLevel } from '@/lib/styles';
|
||||||
|
|
||||||
type ElementProps = {
|
type ElementProps = {
|
||||||
value: number;
|
value: number;
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ Styled.Root = styled(Root)`
|
|||||||
--switch-thumb-backgroundColor: var(--color-layer-6);
|
--switch-thumb-backgroundColor: var(--color-layer-6);
|
||||||
|
|
||||||
--switch-active-backgroundColor: var(--color-accent);
|
--switch-active-backgroundColor: var(--color-accent);
|
||||||
--switch-active-thumb-backgroundColor: var(--color-white);
|
--switch-active-thumb-backgroundColor: ${({ theme }) => theme.switchThumbActiveBackground};
|
||||||
|
|
||||||
position: relative;
|
position: relative;
|
||||||
width: var(--switch-width);
|
width: var(--switch-width);
|
||||||
|
|||||||
@@ -27,9 +27,8 @@ export const ToastArea = ({ swipeDirection, children, className }: ToastAreaProp
|
|||||||
const $ToastArea = styled.aside`
|
const $ToastArea = styled.aside`
|
||||||
// Params
|
// Params
|
||||||
--toasts-gap: 0.5rem;
|
--toasts-gap: 0.5rem;
|
||||||
|
|
||||||
// Rules
|
// Rules
|
||||||
${layoutMixins.scrollArea}
|
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ import styled, { type AnyStyledComponent } from 'styled-components';
|
|||||||
|
|
||||||
import { type RiskLevels } from '@/constants/abacus';
|
import { type RiskLevels } from '@/constants/abacus';
|
||||||
|
|
||||||
import { UsageColorFromRiskLevel } from '@/styles/colors';
|
|
||||||
|
|
||||||
import { abacusHelper } from '@/lib/abacus';
|
import { abacusHelper } from '@/lib/abacus';
|
||||||
|
import { UsageColorFromRiskLevel } from '@/lib/styles';
|
||||||
|
|
||||||
type ElementProps = {
|
type ElementProps = {
|
||||||
value: number;
|
value: number;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -110,12 +110,7 @@ Styled.Abbr = styled.abbr`
|
|||||||
|
|
||||||
Styled.Content = styled(Content)`
|
Styled.Content = styled(Content)`
|
||||||
--tooltip-backgroundColor: var(--color-layer-4);
|
--tooltip-backgroundColor: var(--color-layer-4);
|
||||||
--tooltip-backgroundColor: hsl(
|
--tooltip-backgroundColor: ${({ theme }) => theme.tooltipBackground};
|
||||||
var(--layer-base-hue),
|
|
||||||
var(--layer-base-saturation),
|
|
||||||
calc(var(--layer-base-lightness) + 4%),
|
|
||||||
0.66
|
|
||||||
);
|
|
||||||
|
|
||||||
${popoverMixins.popover}
|
${popoverMixins.popover}
|
||||||
--popover-backgroundColor: var(--tooltip-backgroundColor);
|
--popover-backgroundColor: var(--tooltip-backgroundColor);
|
||||||
|
|||||||
@@ -27,12 +27,7 @@ Styled.TooltipContent = styled.aside<{ accentColor?: string }>`
|
|||||||
|
|
||||||
${popoverMixins.popover}
|
${popoverMixins.popover}
|
||||||
--popover-radius: 0.5rem;
|
--popover-radius: 0.5rem;
|
||||||
--popover-background-color: hsl(
|
--popover-background-color: ${({ theme }) => theme.popoverBackground};
|
||||||
var(--layer-base-hue),
|
|
||||||
var(--layer-base-saturation),
|
|
||||||
calc(var(--layer-base-lightness)),
|
|
||||||
0.9
|
|
||||||
);
|
|
||||||
--popover-backdrop-filter: saturate(120%) blur(12px);
|
--popover-backdrop-filter: saturate(120%) blur(12px);
|
||||||
|
|
||||||
display: grid;
|
display: grid;
|
||||||
|
|||||||
@@ -96,6 +96,7 @@ export type AnalyticsEventData<T extends AnalyticsEvent> =
|
|||||||
elapsedTime?: number;
|
elapsedTime?: number;
|
||||||
blockHeight?: number;
|
blockHeight?: number;
|
||||||
indexerBlockHeight?: number;
|
indexerBlockHeight?: number;
|
||||||
|
trailingBlocks?: number;
|
||||||
}
|
}
|
||||||
: // Navigation
|
: // Navigation
|
||||||
T extends AnalyticsEvent.NavigatePage
|
T extends AnalyticsEvent.NavigatePage
|
||||||
|
|||||||
@@ -87,6 +87,8 @@ export type NotificationDisplayData = {
|
|||||||
slotTitleLeft?: React.ReactNode;
|
slotTitleLeft?: React.ReactNode;
|
||||||
slotTitleRight?: React.ReactNode;
|
slotTitleRight?: React.ReactNode;
|
||||||
|
|
||||||
|
groupKey: string; // Grouping key toast notification stacking
|
||||||
|
|
||||||
// Overrides title/body for Notification in NotificationMenu
|
// Overrides title/body for Notification in NotificationMenu
|
||||||
renderCustomBody?: ({
|
renderCustomBody?: ({
|
||||||
isToast,
|
isToast,
|
||||||
|
|||||||
@@ -0,0 +1,70 @@
|
|||||||
|
export enum ColorToken {
|
||||||
|
Black = '#000000',
|
||||||
|
White = '#FFFFFF',
|
||||||
|
|
||||||
|
LightGray0 = '#FAFAFA',
|
||||||
|
LightGray1 = '#F7F8FA',
|
||||||
|
LightGray2 = '#FAFAFD',
|
||||||
|
LightGray3 = '#F5F5F5',
|
||||||
|
LightGray4 = '#EDF0F2',
|
||||||
|
LightGray5 = '#EDEDED',
|
||||||
|
LightGray6 = '#E9ECEE',
|
||||||
|
LightGray7 = '#E6E6E6',
|
||||||
|
LightGray8 = '#DBDBDB',
|
||||||
|
LightGray9 = '#D5DADF',
|
||||||
|
LightGray10 = '#D1D9E0',
|
||||||
|
|
||||||
|
MediumGray0 = '#CACACE',
|
||||||
|
MediumGray1 = '#C2CBD3',
|
||||||
|
|
||||||
|
DarkGray0 = '#888891',
|
||||||
|
DarkGray1 = '#737373',
|
||||||
|
DarkGray2 = '#56565C',
|
||||||
|
DarkGray3 = '#4B4B4B',
|
||||||
|
DarkGray4 = '#494950',
|
||||||
|
DarkGray5 = '#3B3B3F',
|
||||||
|
DarkGray6 = '#303033',
|
||||||
|
DarkGray7 = '#313135',
|
||||||
|
DarkGray8 = '#292929',
|
||||||
|
DarkGray9 = '#23232F',
|
||||||
|
DarkGray10 = '#212124',
|
||||||
|
DarkGray11 = '#18181B',
|
||||||
|
DarkGray12 = '#181818',
|
||||||
|
DarkGray13 = '#0C0C0D',
|
||||||
|
|
||||||
|
GrayBlue0 = '#464659',
|
||||||
|
GrayBlue1 = '#38384D',
|
||||||
|
GrayBlue2 = '#303045',
|
||||||
|
GrayBlue3 = '#29293D',
|
||||||
|
GrayBlue4 = '#212131',
|
||||||
|
GrayBlue5 = '#181825',
|
||||||
|
GrayBlue6 = '#101018',
|
||||||
|
GrayBlue7 = '#08080C',
|
||||||
|
|
||||||
|
GrayPurple0 = '#DFDADF',
|
||||||
|
GrayPurple1 = '#C8C7D8',
|
||||||
|
GrayPurple2 = '#807E98',
|
||||||
|
|
||||||
|
Purple0 = '#7774FF',
|
||||||
|
Purple1 = '#6966FF',
|
||||||
|
|
||||||
|
Green0 = '#1AFFB9',
|
||||||
|
Green1 = '#3ED9A4',
|
||||||
|
Green2 = '#2CCC98',
|
||||||
|
Green3 = '#3EB68A',
|
||||||
|
|
||||||
|
Yellow0 = '#FFCC48',
|
||||||
|
Yellow1 = '#FFB647',
|
||||||
|
|
||||||
|
Red0 = '#FF5C5C',
|
||||||
|
Red1 = '#E76565',
|
||||||
|
Red2 = '#E45555',
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Maps opacity to corresponding hex value */
|
||||||
|
export enum OpacityToken {
|
||||||
|
Opacity16 = '29',
|
||||||
|
Opacity20 = '33',
|
||||||
|
Opacity66 = 'A8',
|
||||||
|
Opacity90 = 'E6',
|
||||||
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
export type ThemeColors = LayerColors &
|
||||||
|
BorderColors &
|
||||||
|
TextColors &
|
||||||
|
GradientColors &
|
||||||
|
AccentColors &
|
||||||
|
StatusColors &
|
||||||
|
DirectionalColors &
|
||||||
|
RiskColors &
|
||||||
|
IconColors &
|
||||||
|
ComponentColors;
|
||||||
|
|
||||||
|
type LayerColors = {
|
||||||
|
layer0: string;
|
||||||
|
layer1: string;
|
||||||
|
layer2: string;
|
||||||
|
layer3: string;
|
||||||
|
layer4: string;
|
||||||
|
layer5: string;
|
||||||
|
layer6: string;
|
||||||
|
layer7: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type BorderColors = {
|
||||||
|
borderDefault: string;
|
||||||
|
borderDestructive: string;
|
||||||
|
borderButton: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type TextColors = {
|
||||||
|
textPrimary: string;
|
||||||
|
textSecondary: string;
|
||||||
|
textTertiary: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type GradientColors = {
|
||||||
|
gradientBase0: string;
|
||||||
|
gradientBase1: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type AccentColors = {
|
||||||
|
accent: string;
|
||||||
|
accentFaded: string;
|
||||||
|
favorite: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type StatusColors = {
|
||||||
|
success: string;
|
||||||
|
warning: string;
|
||||||
|
error: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type DirectionalColors = {
|
||||||
|
positive: string;
|
||||||
|
negative: string;
|
||||||
|
positiveFaded: string;
|
||||||
|
negativeFaded: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type RiskColors = {
|
||||||
|
riskLow: string;
|
||||||
|
riskMedium: string;
|
||||||
|
riskHigh: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type IconColors = {
|
||||||
|
logoFill: string;
|
||||||
|
profileYellow: string;
|
||||||
|
profileRed: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type ComponentColors = {
|
||||||
|
inputBackground: string;
|
||||||
|
popoverBackground: string;
|
||||||
|
switchThumbActiveBackground: string;
|
||||||
|
toggleBackground: string;
|
||||||
|
tooltipBackground: string;
|
||||||
|
};
|
||||||
@@ -4,7 +4,6 @@ import { useSelector } from 'react-redux';
|
|||||||
import type { IChartingLibraryWidget, ThemeName } from 'public/tradingview/charting_library';
|
import type { IChartingLibraryWidget, ThemeName } from 'public/tradingview/charting_library';
|
||||||
|
|
||||||
import { AppTheme } from '@/state/configs';
|
import { AppTheme } from '@/state/configs';
|
||||||
|
|
||||||
import { getAppTheme } from '@/state/configsSelectors';
|
import { getAppTheme } from '@/state/configsSelectors';
|
||||||
|
|
||||||
import { getWidgetOverrides } from '@/lib/tradingView/utils';
|
import { getWidgetOverrides } from '@/lib/tradingView/utils';
|
||||||
@@ -29,7 +28,7 @@ export const useTradingViewTheme = ({
|
|||||||
tvWidget: (IChartingLibraryWidget & { _id?: string; _ready?: boolean }) | null;
|
tvWidget: (IChartingLibraryWidget & { _id?: string; _ready?: boolean }) | null;
|
||||||
isWidgetReady?: boolean;
|
isWidgetReady?: boolean;
|
||||||
}) => {
|
}) => {
|
||||||
const appTheme = useSelector(getAppTheme);
|
const appTheme: AppTheme = useSelector(getAppTheme);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (tvWidget && isWidgetReady) {
|
if (tvWidget && isWidgetReady) {
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ export const useAnalytics = () => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// AnalyticsEvent.NetworkStatus
|
// AnalyticsEvent.NetworkStatus
|
||||||
const { height, indexerHeight, status } = useApiState();
|
const { height, indexerHeight, status, trailingBlocks} = useApiState();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (status) {
|
if (status) {
|
||||||
@@ -114,6 +114,7 @@ export const useAnalytics = () => {
|
|||||||
elapsedTime: lastSuccessfulIndexerRpcQuery && Date.now() - lastSuccessfulIndexerRpcQuery,
|
elapsedTime: lastSuccessfulIndexerRpcQuery && Date.now() - lastSuccessfulIndexerRpcQuery,
|
||||||
blockHeight: height ?? undefined,
|
blockHeight: height ?? undefined,
|
||||||
indexerBlockHeight: indexerHeight ?? undefined,
|
indexerBlockHeight: indexerHeight ?? undefined,
|
||||||
|
trailingBlocks: trailingBlocks ?? undefined
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, [status]);
|
}, [status]);
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ export const getIndexerHeight = (apiState: Nullable<AbacusApiState>) => {
|
|||||||
export const useApiState = () => {
|
export const useApiState = () => {
|
||||||
const stringGetter = useStringGetter();
|
const stringGetter = useStringGetter();
|
||||||
const apiState = useSelector(getApiState, shallowEqual);
|
const apiState = useSelector(getApiState, shallowEqual);
|
||||||
const { haltedBlock, height, status, trailingBlocks } = apiState ?? {};
|
const { haltedBlock, height, status, trailingBlocks} = apiState ?? {};
|
||||||
const statusErrorMessage = getStatusErrorMessage({ apiState, stringGetter });
|
const statusErrorMessage = getStatusErrorMessage({ apiState, stringGetter });
|
||||||
const indexerHeight = getIndexerHeight(apiState);
|
const indexerHeight = getIndexerHeight(apiState);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import { useSelector } from 'react-redux';
|
||||||
|
import { ThemeProvider } from 'styled-components';
|
||||||
|
|
||||||
|
import { AppTheme } from '@/state/configs';
|
||||||
|
import { getAppTheme } from '@/state/configsSelectors';
|
||||||
|
|
||||||
|
import { Themes } from '@/styles/themes';
|
||||||
|
|
||||||
|
export const AppThemeProvider = ({ ...props }) => {
|
||||||
|
return <ThemeProvider theme={useAppThemeContext()} {...props} />
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useAppThemeContext = () => {
|
||||||
|
const theme: AppTheme = useSelector(getAppTheme);
|
||||||
|
return Themes[theme];
|
||||||
|
}
|
||||||
@@ -28,6 +28,7 @@ import { useLocalNotifications } from '@/hooks/useLocalNotifications';
|
|||||||
|
|
||||||
import { AssetIcon } from '@/components/AssetIcon';
|
import { AssetIcon } from '@/components/AssetIcon';
|
||||||
import { Icon, IconName } from '@/components/Icon';
|
import { Icon, IconName } from '@/components/Icon';
|
||||||
|
import { BlockRewardNotification } from '@/views/notifications/BlockRewardNotification';
|
||||||
import { TradeNotification } from '@/views/notifications/TradeNotification';
|
import { TradeNotification } from '@/views/notifications/TradeNotification';
|
||||||
import { TransferStatusNotification } from '@/views/notifications/TransferStatusNotification';
|
import { TransferStatusNotification } from '@/views/notifications/TransferStatusNotification';
|
||||||
|
|
||||||
@@ -80,6 +81,7 @@ export const notificationTypes: NotificationTypeConfig[] = [
|
|||||||
body: abacusNotif.text ? stringGetter({ key: abacusNotif.text, params }) : '',
|
body: abacusNotif.text ? stringGetter({ key: abacusNotif.text, params }) : '',
|
||||||
toastDuration: DEFAULT_TOAST_AUTO_CLOSE_MS,
|
toastDuration: DEFAULT_TOAST_AUTO_CLOSE_MS,
|
||||||
toastSensitivity: 'foreground',
|
toastSensitivity: 'foreground',
|
||||||
|
groupKey: abacusNotificationType,
|
||||||
renderCustomBody: ({ isToast, notification }) => (
|
renderCustomBody: ({ isToast, notification }) => (
|
||||||
<TradeNotification
|
<TradeNotification
|
||||||
isToast={isToast}
|
isToast={isToast}
|
||||||
@@ -93,6 +95,29 @@ export const notificationTypes: NotificationTypeConfig[] = [
|
|||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'blockReward': {
|
||||||
|
trigger(
|
||||||
|
abacusNotif.id,
|
||||||
|
{
|
||||||
|
icon: abacusNotif.image && <$Icon src={abacusNotif.image} alt="" />,
|
||||||
|
title: stringGetter({ key: abacusNotif.title }),
|
||||||
|
body: abacusNotif.text ? stringGetter({ key: abacusNotif.text, params }) : '',
|
||||||
|
toastDuration: DEFAULT_TOAST_AUTO_CLOSE_MS,
|
||||||
|
toastSensitivity: 'foreground',
|
||||||
|
groupKey: abacusNotificationType,
|
||||||
|
renderCustomBody: ({ isToast, notification }) => (
|
||||||
|
<BlockRewardNotification
|
||||||
|
isToast={isToast}
|
||||||
|
data={parsedData}
|
||||||
|
notification={notification}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
[abacusNotif.updateTimeInMilliseconds, abacusNotif.data],
|
||||||
|
true
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
trigger(
|
trigger(
|
||||||
abacusNotif.id,
|
abacusNotif.id,
|
||||||
@@ -102,6 +127,7 @@ export const notificationTypes: NotificationTypeConfig[] = [
|
|||||||
body: abacusNotif.text ? stringGetter({ key: abacusNotif.text, params }) : '',
|
body: abacusNotif.text ? stringGetter({ key: abacusNotif.text, params }) : '',
|
||||||
toastDuration: DEFAULT_TOAST_AUTO_CLOSE_MS,
|
toastDuration: DEFAULT_TOAST_AUTO_CLOSE_MS,
|
||||||
toastSensitivity: 'foreground',
|
toastSensitivity: 'foreground',
|
||||||
|
groupKey: abacusNotificationType,
|
||||||
},
|
},
|
||||||
[abacusNotif.updateTimeInMilliseconds, abacusNotif.data]
|
[abacusNotif.updateTimeInMilliseconds, abacusNotif.data]
|
||||||
);
|
);
|
||||||
@@ -197,6 +223,7 @@ export const notificationTypes: NotificationTypeConfig[] = [
|
|||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
toastSensitivity: 'foreground',
|
toastSensitivity: 'foreground',
|
||||||
|
groupKey: NotificationType.SquidTransfer,
|
||||||
},
|
},
|
||||||
[isFinished]
|
[isFinished]
|
||||||
);
|
);
|
||||||
@@ -242,6 +269,7 @@ export const notificationTypes: NotificationTypeConfig[] = [
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
toastSensitivity: 'foreground',
|
toastSensitivity: 'foreground',
|
||||||
|
groupKey: NotificationType.ReleaseUpdates,
|
||||||
},
|
},
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ export { default as PriceChartIcon } from './price-chart.svg';
|
|||||||
export { default as PrivacyIcon } from './privacy.svg';
|
export { default as PrivacyIcon } from './privacy.svg';
|
||||||
export { default as ProfileIcon } from './profile.svg';
|
export { default as ProfileIcon } from './profile.svg';
|
||||||
export { default as QrIcon } from './qr.svg';
|
export { default as QrIcon } from './qr.svg';
|
||||||
|
export { default as RewardStarIcon } from './reward-star.svg';
|
||||||
export { default as SearchIcon } from './search.svg';
|
export { default as SearchIcon } from './search.svg';
|
||||||
export { default as SendIcon } from './send.svg';
|
export { default as SendIcon } from './send.svg';
|
||||||
export { default as ShareIcon } from './share.svg';
|
export { default as ShareIcon } from './share.svg';
|
||||||
|
|||||||
+50
-43
@@ -1,45 +1,52 @@
|
|||||||
const LogoShortIcon: React.FC<{ id?: string }> = ({ id }: { id?: string }) => (
|
import { useAppThemeContext } from '@/hooks/useAppTheme';
|
||||||
<svg
|
|
||||||
width="135"
|
const LogoShortIcon: React.FC<{ id?: string }> = ({ id }: { id?: string }) => {
|
||||||
height="145"
|
const theme = useAppThemeContext();
|
||||||
viewBox="0 0 135 145"
|
const fill = theme.logoFill;
|
||||||
fill="none"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
return (
|
||||||
>
|
<svg
|
||||||
<path d="M100.986 0L0 144.988H31.0048L132.514 0H100.986Z" fill="white" />
|
width="135"
|
||||||
<path
|
height="145"
|
||||||
d="M34.2346 0L63.9475 42.7232L48.4451 66.0268L2.58386 0H34.2346Z"
|
viewBox="0 0 135 145"
|
||||||
fill={`url(#${id ? `${id}_logo_gradient_0` : 'paint0_linear'})`}
|
fill="none"
|
||||||
/>
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
<path
|
>
|
||||||
d="M103.995 145L71.0526 97.7455L86.555 75.0893L135 145H103.995Z"
|
<path d="M100.986 0L0 144.988H31.0048L132.514 0H100.986Z" fill={fill} />
|
||||||
fill={`url(#${id ? `${id}_logo_gradient_1` : 'paint1_linear'})`}
|
<path
|
||||||
/>
|
d="M34.2346 0L63.9475 42.7232L48.4451 66.0268L2.58386 0H34.2346Z"
|
||||||
<defs>
|
fill={`url(#${id ? `${id}_logo_gradient_0` : 'paint0_linear'})`}
|
||||||
<linearGradient
|
/>
|
||||||
id={id ? `${id}_logo_gradient_0` : 'paint0_linear'}
|
<path
|
||||||
x1="27.1293"
|
d="M103.995 145L71.0526 97.7455L86.555 75.0893L135 145H103.995Z"
|
||||||
y1="9.0625"
|
fill={`url(#${id ? `${id}_logo_gradient_1` : 'paint1_linear'})`}
|
||||||
x2="69.773"
|
/>
|
||||||
y2="60.4324"
|
<defs>
|
||||||
gradientUnits="userSpaceOnUse"
|
<linearGradient
|
||||||
>
|
id={id ? `${id}_logo_gradient_0` : 'paint0_linear'}
|
||||||
<stop stopColor="white" />
|
x1="27.1293"
|
||||||
<stop offset="1" stopColor="white" stopOpacity="0.55" />
|
y1="9.0625"
|
||||||
</linearGradient>
|
x2="69.773"
|
||||||
<linearGradient
|
y2="60.4324"
|
||||||
id={id ? `${id}_logo_gradient_1` : 'paint1_linear'}
|
gradientUnits="userSpaceOnUse"
|
||||||
x1="111.1"
|
>
|
||||||
y1="133.996"
|
<stop stopColor={fill} />
|
||||||
x2="58.6959"
|
<stop offset="1" stopColor={fill} stopOpacity="0.55" />
|
||||||
y2="63.4999"
|
</linearGradient>
|
||||||
gradientUnits="userSpaceOnUse"
|
<linearGradient
|
||||||
>
|
id={id ? `${id}_logo_gradient_1` : 'paint1_linear'}
|
||||||
<stop stopColor="#6966FF" />
|
x1="111.1"
|
||||||
<stop offset="1" stopColor="#6966FF" stopOpacity="0.36" />
|
y1="133.996"
|
||||||
</linearGradient>
|
x2="58.6959"
|
||||||
</defs>
|
y2="63.4999"
|
||||||
</svg>
|
gradientUnits="userSpaceOnUse"
|
||||||
);
|
>
|
||||||
|
<stop stopColor="#6966FF" />
|
||||||
|
<stop offset="1" stopColor="#6966FF" stopOpacity="0.36" />
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export default LogoShortIcon;
|
export default LogoShortIcon;
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 481 KiB |
@@ -1,6 +1,5 @@
|
|||||||
@import 'styles/fonts.css';
|
@import 'styles/fonts.css';
|
||||||
@import 'styles/text.css';
|
@import 'styles/text.css';
|
||||||
@import 'styles/colors.css';
|
|
||||||
@import 'styles/animations.css';
|
@import 'styles/animations.css';
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
|
|||||||
+34
-59
@@ -1,7 +1,11 @@
|
|||||||
import { useMemo, useState } from 'react';
|
import { useState } from 'react';
|
||||||
import styled, { css } from 'styled-components';
|
import styled, { css } from 'styled-components';
|
||||||
|
|
||||||
import { NotificationStatus } from '@/constants/notifications';
|
import {
|
||||||
|
type Notification,
|
||||||
|
type NotificationDisplayData,
|
||||||
|
NotificationStatus,
|
||||||
|
} from '@/constants/notifications';
|
||||||
import { ButtonShape, ButtonSize } from '@/constants/buttons';
|
import { ButtonShape, ButtonSize } from '@/constants/buttons';
|
||||||
import { useNotifications } from '@/hooks/useNotifications';
|
import { useNotifications } from '@/hooks/useNotifications';
|
||||||
import { useBreakpoints } from '@/hooks/useBreakpoints';
|
import { useBreakpoints } from '@/hooks/useBreakpoints';
|
||||||
@@ -13,54 +17,31 @@ import { Toast } from '@/components/Toast';
|
|||||||
import { ToastArea } from '@/components/ToastArea';
|
import { ToastArea } from '@/components/ToastArea';
|
||||||
import { ToggleButton } from '@/components/ToggleButton';
|
import { ToggleButton } from '@/components/ToggleButton';
|
||||||
|
|
||||||
|
type ElementProps = {
|
||||||
|
notifications: {
|
||||||
|
notification: Notification<any, any>;
|
||||||
|
key: string;
|
||||||
|
displayData: NotificationDisplayData;
|
||||||
|
}[];
|
||||||
|
};
|
||||||
|
|
||||||
type StyleProps = {
|
type StyleProps = {
|
||||||
className?: string;
|
className?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const MAX_TOASTS = 10;
|
export const NotificationStack = ({ notifications, className }: ElementProps & StyleProps) => {
|
||||||
|
|
||||||
export const NotificationsToastArea = ({ className }: StyleProps) => {
|
|
||||||
const [shouldStackNotifications, setshouldStackNotifications] = useState(true);
|
const [shouldStackNotifications, setshouldStackNotifications] = useState(true);
|
||||||
|
|
||||||
const {
|
const { markUnseen, markSeen, onNotificationAction } = useNotifications();
|
||||||
notifications,
|
|
||||||
getKey,
|
|
||||||
getDisplayData,
|
|
||||||
markUnseen,
|
|
||||||
markSeen,
|
|
||||||
isMenuOpen,
|
|
||||||
onNotificationAction,
|
|
||||||
} = useNotifications();
|
|
||||||
|
|
||||||
const { isMobile } = useBreakpoints();
|
const { isMobile } = useBreakpoints();
|
||||||
const notificationMap = useMemo(() => {
|
const hasMultipleToasts = notifications.length > 1;
|
||||||
return (
|
|
||||||
Object.values(notifications)
|
|
||||||
// Sort by time of first trigger
|
|
||||||
.sort(
|
|
||||||
(n1, n2) =>
|
|
||||||
n1.timestamps[NotificationStatus.Triggered]! -
|
|
||||||
n2.timestamps[NotificationStatus.Triggered]!
|
|
||||||
)
|
|
||||||
.map((notification) => ({
|
|
||||||
notification,
|
|
||||||
key: getKey(notification),
|
|
||||||
displayData: getDisplayData(notification),
|
|
||||||
}))
|
|
||||||
.filter(
|
|
||||||
({ displayData, notification }) =>
|
|
||||||
displayData && notification.status < NotificationStatus.Unseen
|
|
||||||
)
|
|
||||||
.slice(-MAX_TOASTS)
|
|
||||||
);
|
|
||||||
}, [notifications, getKey, getDisplayData]);
|
|
||||||
|
|
||||||
if (isMenuOpen) return null;
|
|
||||||
|
|
||||||
const hasMultipleToasts = notificationMap.length > 1;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledToastArea swipeDirection={isMobile ? 'up' : 'right'} className={className}>
|
<StyledToastArea
|
||||||
|
swipeDirection={isMobile ? 'up' : 'right'}
|
||||||
|
className={className}
|
||||||
|
size={notifications.length}
|
||||||
|
>
|
||||||
{hasMultipleToasts && (
|
{hasMultipleToasts && (
|
||||||
<StyledToggleButton
|
<StyledToggleButton
|
||||||
shape={ButtonShape.Pill}
|
shape={ButtonShape.Pill}
|
||||||
@@ -72,12 +53,12 @@ export const NotificationsToastArea = ({ className }: StyleProps) => {
|
|||||||
</StyledToggleButton>
|
</StyledToggleButton>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{notificationMap.map(({ notification, key, displayData }, idx) => (
|
{notifications.map(({ notification, key, displayData }, idx) => (
|
||||||
<StyledToast
|
<StyledToast
|
||||||
key={key}
|
key={key}
|
||||||
isStacked={shouldStackNotifications}
|
isStacked={idx > 0 && shouldStackNotifications}
|
||||||
isOpen={notification.status < NotificationStatus.Unseen}
|
isOpen={notification.status < NotificationStatus.Unseen}
|
||||||
layer={notificationMap.length - 1 - idx}
|
layer={idx}
|
||||||
notification={notification}
|
notification={notification}
|
||||||
slotIcon={displayData.icon}
|
slotIcon={displayData.icon}
|
||||||
slotTitle={displayData.title}
|
slotTitle={displayData.title}
|
||||||
@@ -110,19 +91,13 @@ export const NotificationsToastArea = ({ className }: StyleProps) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const StyledToastArea = styled(ToastArea)`
|
const StyledToastArea = styled(ToastArea)<{ size: number }>`
|
||||||
position: absolute;
|
position: relative;
|
||||||
width: min(17.5rem, 100%);
|
${({ size }) =>
|
||||||
inset: 0 0 0 auto;
|
size &&
|
||||||
|
css`
|
||||||
padding: 0.75rem 0.75rem 0.75rem 0;
|
padding-bottom: calc(${size - 1} * 2px);
|
||||||
|
`}
|
||||||
mask-image: linear-gradient(to left, transparent, white 0.5rem);
|
|
||||||
|
|
||||||
@media ${breakpoints.mobile} {
|
|
||||||
width: 100%;
|
|
||||||
position: fixed;
|
|
||||||
}
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const StyledToast = styled(Toast)<{ isStacked?: boolean; layer: number }>`
|
const StyledToast = styled(Toast)<{ isStacked?: boolean; layer: number }>`
|
||||||
@@ -133,7 +108,7 @@ const StyledToast = styled(Toast)<{ isStacked?: boolean; layer: number }>`
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0;
|
left: 0;
|
||||||
top: calc(${layer} * 2px);
|
top: calc(${layer} * 2px);
|
||||||
right: calc(${layer} * -2px);
|
right: 0;
|
||||||
`
|
`
|
||||||
: css`
|
: css`
|
||||||
margin-bottom: 0.75rem;
|
margin-bottom: 0.75rem;
|
||||||
@@ -145,7 +120,7 @@ const StyledToggleButton = styled(ToggleButton)<{ isPressed: boolean }>`
|
|||||||
pointer-events: auto;
|
pointer-events: auto;
|
||||||
display: none;
|
display: none;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 4px;
|
top: -0.5rem;
|
||||||
left: calc(50% - 0.75rem);
|
left: calc(50% - 0.75rem);
|
||||||
--button-width: 2rem;
|
--button-width: 2rem;
|
||||||
--button-height: 1rem;
|
--button-height: 1rem;
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
import { useMemo } from 'react';
|
||||||
|
import { groupBy } from 'lodash';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
|
||||||
|
import { breakpoints } from '@/styles';
|
||||||
|
import { layoutMixins } from '@/styles/layoutMixins';
|
||||||
|
|
||||||
|
import { NotificationStatus } from '@/constants/notifications';
|
||||||
|
import { useNotifications } from '@/hooks/useNotifications';
|
||||||
|
|
||||||
|
import { NotificationStack } from './NotifcationStack';
|
||||||
|
|
||||||
|
type StyleProps = {
|
||||||
|
className?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const MAX_TOASTS = 10;
|
||||||
|
|
||||||
|
export const NotificationsToastArea = ({ className }: StyleProps) => {
|
||||||
|
const { notifications, getKey, getDisplayData, isMenuOpen } = useNotifications();
|
||||||
|
|
||||||
|
const notificationMapByType = useMemo(() => {
|
||||||
|
const notificationMap = Object.values(notifications)
|
||||||
|
// Sort by time of first trigger
|
||||||
|
.sort(
|
||||||
|
(n1, n2) =>
|
||||||
|
n1.timestamps[NotificationStatus.Triggered]! -
|
||||||
|
n2.timestamps[NotificationStatus.Triggered]!
|
||||||
|
)
|
||||||
|
.map((notification) => ({
|
||||||
|
notification,
|
||||||
|
key: getKey(notification),
|
||||||
|
displayData: getDisplayData(notification),
|
||||||
|
}))
|
||||||
|
.filter(
|
||||||
|
({ displayData, notification }) =>
|
||||||
|
displayData && notification.status < NotificationStatus.Unseen
|
||||||
|
)
|
||||||
|
.slice(-MAX_TOASTS);
|
||||||
|
return groupBy(notificationMap, (notification) => notification.displayData?.groupKey);
|
||||||
|
}, [notifications, getKey, getDisplayData]);
|
||||||
|
|
||||||
|
if (isMenuOpen) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<StyledToastArea className={className}>
|
||||||
|
{Object.keys(notificationMapByType).map((groupKey) => (
|
||||||
|
<NotificationStack notifications={notificationMapByType[groupKey]} key={groupKey} />
|
||||||
|
))}
|
||||||
|
</StyledToastArea>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const StyledToastArea = styled.div`
|
||||||
|
${layoutMixins.scrollArea}
|
||||||
|
|
||||||
|
position: absolute;
|
||||||
|
width: min(17.5rem, 100%);
|
||||||
|
inset: 0 0 0 auto;
|
||||||
|
|
||||||
|
padding: 0.75rem 0.75rem 0.75rem 0;
|
||||||
|
|
||||||
|
mask-image: linear-gradient(to left, transparent, white 0.5rem);
|
||||||
|
|
||||||
|
pointer-events: none;
|
||||||
|
|
||||||
|
@media ${breakpoints.mobile} {
|
||||||
|
width: 100%;
|
||||||
|
position: fixed;
|
||||||
|
}
|
||||||
|
`;
|
||||||
@@ -56,6 +56,10 @@ class DydxChainTransactions implements AbacusDYDXChainTransactionsProtocol {
|
|||||||
this.store = undefined;
|
this.store = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get isNobleClientConnected(): boolean {
|
||||||
|
return this.nobleClient?.isConnected ?? false;
|
||||||
|
}
|
||||||
|
|
||||||
setStore(store: RootStore): void {
|
setStore(store: RootStore): void {
|
||||||
this.store = store;
|
this.store = store;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import { css } from 'styled-components';
|
||||||
|
|
||||||
|
import { type RiskLevels } from '@/constants/abacus';
|
||||||
|
|
||||||
|
export const UsageColorFromRiskLevel = (riskLevel: RiskLevels) =>
|
||||||
|
({
|
||||||
|
low: css`
|
||||||
|
color: var(--color-risk-low);
|
||||||
|
`,
|
||||||
|
medium: css`
|
||||||
|
color: var(--color-risk-medium);
|
||||||
|
`,
|
||||||
|
high: css`
|
||||||
|
color: var(--color-risk-high);
|
||||||
|
`,
|
||||||
|
}[riskLevel.name]);
|
||||||
|
|
||||||
|
export const generateFadedColorVariant = (colorHex: string, opacityHex: string) => {
|
||||||
|
return `${colorHex}${opacityHex}`;
|
||||||
|
};
|
||||||
@@ -11,16 +11,16 @@ class TestFlags {
|
|||||||
const params = new URLSearchParams(queryParamsString);
|
const params = new URLSearchParams(queryParamsString);
|
||||||
|
|
||||||
for (const [key, value] of params) {
|
for (const [key, value] of params) {
|
||||||
this.queryParams[key] = value;
|
this.queryParams[key.toLowerCase()] = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get displayInitializingMarkets() {
|
get displayInitializingMarkets() {
|
||||||
return !!this.queryParams.displayInitializingMarkets;
|
return !!this.queryParams.displayinitializingmarkets;
|
||||||
}
|
}
|
||||||
|
|
||||||
get withCCTP() {
|
get showMobileSignInOption() {
|
||||||
return !!this.queryParams.withCCTP;
|
return !!this.queryParams.mobilesignin;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
import Color from 'color';
|
|
||||||
import isEmpty from 'lodash/isEmpty';
|
|
||||||
|
|
||||||
import { Candle, TradingViewBar, TradingViewSymbol } from '@/constants/candles';
|
import { Candle, TradingViewBar, TradingViewSymbol } from '@/constants/candles';
|
||||||
import { Colors } from '@/styles/colors';
|
|
||||||
|
|
||||||
import { AppTheme } from '@/state/configs';
|
import { AppTheme } from '@/state/configs';
|
||||||
|
|
||||||
|
import { Themes } from '@/styles/themes';
|
||||||
|
|
||||||
export const mapCandle = ({
|
export const mapCandle = ({
|
||||||
startedAt,
|
startedAt,
|
||||||
open,
|
open,
|
||||||
@@ -49,42 +47,42 @@ export const getHistorySlice = ({
|
|||||||
return bars.filter(({ time }) => time >= fromMs);
|
return bars.filter(({ time }) => time >= fromMs);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getWidgetOverrides = (theme: AppTheme) => {
|
export const getWidgetOverrides = (appTheme: AppTheme) => {
|
||||||
const colors = Colors[theme];
|
const theme = Themes[appTheme];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
overrides: {
|
overrides: {
|
||||||
'paneProperties.background': Color(colors.layer2).hex(),
|
'paneProperties.background': theme.layer2,
|
||||||
'paneProperties.horzGridProperties.color': Color(colors.layer3).hex(),
|
'paneProperties.horzGridProperties.color': theme.layer3,
|
||||||
'paneProperties.vertGridProperties.color': Color(colors.layer3).hex(),
|
'paneProperties.vertGridProperties.color': theme.layer3,
|
||||||
'paneProperties.crossHairProperties.style': 1,
|
'paneProperties.crossHairProperties.style': 1,
|
||||||
'paneProperties.legendProperties.showBarChange': false,
|
'paneProperties.legendProperties.showBarChange': false,
|
||||||
'paneProperties.backgroundType': 'solid',
|
'paneProperties.backgroundType': 'solid',
|
||||||
|
|
||||||
'mainSeriesProperties.style': 1,
|
'mainSeriesProperties.style': 1,
|
||||||
'mainSeriesProperties.candleStyle.upColor': Color(colors.positive).hex(),
|
'mainSeriesProperties.candleStyle.upColor': theme.positive,
|
||||||
'mainSeriesProperties.candleStyle.borderUpColor': Color(colors.positive).hex(),
|
'mainSeriesProperties.candleStyle.borderUpColor': theme.positive,
|
||||||
'mainSeriesProperties.candleStyle.wickUpColor': Color(colors.positive).hex(),
|
'mainSeriesProperties.candleStyle.wickUpColor': theme.positive,
|
||||||
'mainSeriesProperties.candleStyle.downColor': Color(colors.negative).hex(),
|
'mainSeriesProperties.candleStyle.downColor': theme.negative,
|
||||||
'mainSeriesProperties.candleStyle.borderDownColor': Color(colors.negative).hex(),
|
'mainSeriesProperties.candleStyle.borderDownColor': theme.negative,
|
||||||
'mainSeriesProperties.candleStyle.wickDownColor': Color(colors.negative).hex(),
|
'mainSeriesProperties.candleStyle.wickDownColor': theme.negative,
|
||||||
'mainSeriesProperties.statusViewStyle.symbolTextSource': 'ticker',
|
'mainSeriesProperties.statusViewStyle.symbolTextSource': 'ticker',
|
||||||
|
|
||||||
'scalesProperties.textColor': Color(colors.text1).hex(),
|
'scalesProperties.textColor': theme.textPrimary,
|
||||||
'scalesProperties.backgroundColor': Color(colors.layer2).hex(),
|
'scalesProperties.backgroundColor': theme.layer2,
|
||||||
'scalesProperties.lineColor': Color(colors.layer3).hex(),
|
'scalesProperties.lineColor': theme.layer3,
|
||||||
},
|
},
|
||||||
studies_overrides: {
|
studies_overrides: {
|
||||||
'volume.volume.color.0': Color(colors.negative).hex(),
|
'volume.volume.color.0': theme.negative,
|
||||||
'volume.volume.color.1': Color(colors.positive).hex(),
|
'volume.volume.color.1': theme.positive,
|
||||||
'volume.volume ma.visible': false,
|
'volume.volume ma.visible': false,
|
||||||
'relative strength index.plot.color': Color(colors.accent).hex(),
|
'relative strength index.plot.color': theme.accent,
|
||||||
'relative strength index.plot.linewidth': 1.5,
|
'relative strength index.plot.linewidth': 1.5,
|
||||||
'relative strength index.hlines background.color': '#134A9F',
|
'relative strength index.hlines background.color': '#134A9F',
|
||||||
},
|
},
|
||||||
loading_screen: {
|
loading_screen: {
|
||||||
backgroundColor: Color(colors.layer2).hex(),
|
backgroundColor: theme.layer2,
|
||||||
foregroundColor: Color(colors.layer2).hex(),
|
foregroundColor: theme.layer2,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -259,8 +259,8 @@ Styled.ProfileIcon = styled.div`
|
|||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
background: linear-gradient(
|
background: linear-gradient(
|
||||||
135deg,
|
135deg,
|
||||||
var(--theme-classic-color-yellow) 0%,
|
${({ theme }) => theme.profileYellow} 0%,
|
||||||
var(--theme-classic-color-red) 100%
|
${({ theme }) => theme.profileRed} 100%
|
||||||
);
|
);
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|||||||
@@ -1,180 +0,0 @@
|
|||||||
:root {
|
|
||||||
/* Parameters */
|
|
||||||
|
|
||||||
/*
|
|
||||||
--layer-base-hue
|
|
||||||
--layer-base-saturation
|
|
||||||
--layer-base-lightness
|
|
||||||
|
|
||||||
--color-text-0
|
|
||||||
--color-text-1
|
|
||||||
--color-text-2
|
|
||||||
|
|
||||||
--color-accent
|
|
||||||
--color-positive
|
|
||||||
--color-negative
|
|
||||||
--color-success
|
|
||||||
--color-warning
|
|
||||||
--color-error
|
|
||||||
--color-favorite
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Computed: Layers */
|
|
||||||
|
|
||||||
--color-layer-0: hsl(
|
|
||||||
var(--layer-base-hue),
|
|
||||||
var(--layer-base-saturation),
|
|
||||||
calc(var(--layer-base-lightness) - 12%)
|
|
||||||
);
|
|
||||||
|
|
||||||
--color-layer-1: hsl(
|
|
||||||
var(--layer-base-hue),
|
|
||||||
var(--layer-base-saturation),
|
|
||||||
calc(var(--layer-base-lightness) - 8%)
|
|
||||||
);
|
|
||||||
|
|
||||||
--color-layer-2: hsl(
|
|
||||||
var(--layer-base-hue),
|
|
||||||
var(--layer-base-saturation),
|
|
||||||
calc(var(--layer-base-lightness) - 4%)
|
|
||||||
);
|
|
||||||
|
|
||||||
--color-layer-3: hsl(
|
|
||||||
var(--layer-base-hue),
|
|
||||||
var(--layer-base-saturation),
|
|
||||||
var(--layer-base-lightness)
|
|
||||||
);
|
|
||||||
|
|
||||||
--color-layer-4: hsl(
|
|
||||||
var(--layer-base-hue),
|
|
||||||
var(--layer-base-saturation),
|
|
||||||
calc(var(--layer-base-lightness) + 4%)
|
|
||||||
);
|
|
||||||
|
|
||||||
--color-layer-5: hsl(
|
|
||||||
var(--layer-base-hue),
|
|
||||||
calc(var(--layer-base-saturation) - 2%),
|
|
||||||
calc(var(--layer-base-lightness) + 7%)
|
|
||||||
);
|
|
||||||
|
|
||||||
--color-layer-6: hsl(
|
|
||||||
var(--layer-base-hue),
|
|
||||||
calc(var(--layer-base-saturation) - 4%),
|
|
||||||
calc(var(--layer-base-lightness) + 10%)
|
|
||||||
);
|
|
||||||
|
|
||||||
--color-layer-7: hsla(var(--layer-base-hue), 0%, 100%, 0.07);
|
|
||||||
|
|
||||||
--color-gradient-base-0: hsl(
|
|
||||||
var(--layer-base-hue),
|
|
||||||
calc(var(--layer-base-saturation) - 5%),
|
|
||||||
var(--layer-base-lightness)
|
|
||||||
);
|
|
||||||
|
|
||||||
--color-gradient-base-1: hsl(
|
|
||||||
var(--layer-base-hue),
|
|
||||||
calc(var(--layer-base-saturation) - 1%),
|
|
||||||
calc(var(--layer-base-lightness) + 7%)
|
|
||||||
);
|
|
||||||
|
|
||||||
/* Computed: Borders */
|
|
||||||
|
|
||||||
--color-border: var(--color-layer-5);
|
|
||||||
--color-border-white: hsla(0, 0%, 100%, 0.2);
|
|
||||||
--color-border-red: hsla(360, 73%, 61%, 0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Theme: Classic (default) */
|
|
||||||
:root {
|
|
||||||
/* Constants */
|
|
||||||
|
|
||||||
--theme-classic-hue-purple: 240;
|
|
||||||
--theme-classic-color-green: hsl(159, 67%, 39%);
|
|
||||||
--theme-classic-color-yellow: hsl(36, 100%, 64%);
|
|
||||||
--theme-classic-color-red: hsl(360, 73%, 61%);
|
|
||||||
|
|
||||||
/* Parameters */
|
|
||||||
|
|
||||||
--layer-base-hue: var(--theme-classic-hue-purple);
|
|
||||||
--layer-base-saturation: 20%;
|
|
||||||
--layer-base-lightness: 16%;
|
|
||||||
|
|
||||||
--color-text-0: hsl(245, 11%, 55%);
|
|
||||||
--color-text-1: hsl(244, 18%, 81%);
|
|
||||||
--color-text-2: hsl(240, 43%, 99%);
|
|
||||||
|
|
||||||
--color-accent: hsl(var(--theme-classic-hue-purple), 100%, 70%);
|
|
||||||
--color-positive: var(--theme-classic-color-green);
|
|
||||||
--color-negative: var(--theme-classic-color-red);
|
|
||||||
--color-success: var(--theme-classic-color-green);
|
|
||||||
--color-warning: var(--theme-classic-color-yellow);
|
|
||||||
--color-error: var(--theme-classic-color-red);
|
|
||||||
--color-favorite: var(--theme-classic-color-yellow);
|
|
||||||
|
|
||||||
--color-white: #fff;
|
|
||||||
--color-black: #000;
|
|
||||||
|
|
||||||
--color-gradient-positive: hsla(158, 49%, 48%, 0.16);
|
|
||||||
--color-gradient-negative: hsla(0, 100%, 66%, 0.16);
|
|
||||||
--color-accent-faded: hsla(var(--theme-classic-hue-purple), 100%, 70%, 0.16);
|
|
||||||
|
|
||||||
--color-risk-low: var(--theme-classic-color-green);
|
|
||||||
--color-risk-medium: var(--theme-classic-color-yellow);
|
|
||||||
--color-risk-high: var(--theme-classic-color-red);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Theme: Light */
|
|
||||||
:root.theme-light {
|
|
||||||
/* Constants */
|
|
||||||
|
|
||||||
--theme-light-hue-purple: 234;
|
|
||||||
--theme-light-color-green: hsl(159, 67%, 39%);
|
|
||||||
--theme-light-color-yellow: hsl(36, 100%, 64%);
|
|
||||||
--theme-light-color-red: hsl(360, 73%, 61%);
|
|
||||||
|
|
||||||
/* Parameters */
|
|
||||||
|
|
||||||
--layer-base-hue: var(--theme-light-hue-purple);
|
|
||||||
--layer-base-saturation: 0%;
|
|
||||||
--layer-base-lightness: 86%;
|
|
||||||
|
|
||||||
--color-text-0: hsl(0, 0%, 55%);
|
|
||||||
--color-text-1: hsl(0, 0%, 40%);
|
|
||||||
--color-text-2: hsl(0, 0%, 5%);
|
|
||||||
|
|
||||||
--color-accent: hsl(var(--theme-light-hue-purple), 100%, 70%);
|
|
||||||
--color-positive: var(--theme-light-color-green);
|
|
||||||
--color-negative: var(--theme-light-color-red);
|
|
||||||
--color-success: var(--theme-light-color-green);
|
|
||||||
--color-warning: var(--theme-light-color-yellow);
|
|
||||||
--color-error: var(--theme-light-color-red);
|
|
||||||
--color-favorite: var(--theme-light-color-yellow);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Theme: Dark */
|
|
||||||
:root.theme-dark {
|
|
||||||
/* Constants */
|
|
||||||
|
|
||||||
--theme-dark-hue-purple: 240;
|
|
||||||
--theme-dark-color-green: hsl(159, 67%, 39%);
|
|
||||||
--theme-dark-color-yellow: hsl(36, 100%, 64%);
|
|
||||||
--theme-dark-color-red: hsl(360, 73%, 61%);
|
|
||||||
|
|
||||||
/* Parameters */
|
|
||||||
|
|
||||||
--layer-base-hue: 0;
|
|
||||||
--layer-base-saturation: 0%;
|
|
||||||
--layer-base-lightness: 16%;
|
|
||||||
|
|
||||||
--color-text-0: hsl(0, 0%, 47%);
|
|
||||||
--color-text-1: hsl(0, 0%, 67%);
|
|
||||||
--color-text-2: hsl(0, 0%, 100%);
|
|
||||||
|
|
||||||
--color-accent: hsl(var(--theme-dark-hue-purple), 100%, 70%);
|
|
||||||
--color-positive: var(--theme-dark-color-green);
|
|
||||||
--color-negative: var(--theme-dark-color-red);
|
|
||||||
--color-success: var(--theme-dark-color-green);
|
|
||||||
--color-warning: var(--theme-dark-color-yellow);
|
|
||||||
--color-error: var(--theme-dark-color-red);
|
|
||||||
--color-favorite: var(--theme-dark-color-yellow);
|
|
||||||
}
|
|
||||||
@@ -1,125 +0,0 @@
|
|||||||
import { css } from 'styled-components';
|
|
||||||
|
|
||||||
import { type RiskLevels } from '@/constants/abacus';
|
|
||||||
|
|
||||||
import { AppTheme } from '@/state/configs';
|
|
||||||
|
|
||||||
const BaseElements = {
|
|
||||||
[AppTheme.Classic]: {
|
|
||||||
hue: 240,
|
|
||||||
saturation: 20,
|
|
||||||
lightness: 16,
|
|
||||||
},
|
|
||||||
[AppTheme.Dark]: {
|
|
||||||
hue: 0,
|
|
||||||
saturation: 0,
|
|
||||||
lightness: 16,
|
|
||||||
},
|
|
||||||
[AppTheme.Light]: {
|
|
||||||
hue: 234,
|
|
||||||
saturation: 0,
|
|
||||||
lightness: 86,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const LayerColors = ({ theme }: { theme: AppTheme }) => {
|
|
||||||
const { hue, saturation, lightness } = BaseElements[theme];
|
|
||||||
|
|
||||||
return {
|
|
||||||
layer0: `hsl(${hue}, ${saturation}%, ${lightness - 12}%)`,
|
|
||||||
layer1: `hsl(${hue}, ${saturation}%, ${lightness - 8}%)`,
|
|
||||||
layer2: `hsl(${hue}, ${saturation}%, ${lightness - 4}%)`,
|
|
||||||
layer3: `hsl(${hue}, ${saturation}%, ${lightness}%)`,
|
|
||||||
layer4: `hsl(${hue}, ${saturation}%, ${lightness + 4}%)`,
|
|
||||||
layer5: `hsl(${hue}, ${saturation - 2}%, ${lightness + 7}%)`,
|
|
||||||
layer6: `hsl(${hue}, ${saturation - 4}%, ${lightness + 10}%)`,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const AccentColor = ({ theme }: { theme: AppTheme }) => {
|
|
||||||
const purpleHue = {
|
|
||||||
Classic: 240,
|
|
||||||
Dark: 240,
|
|
||||||
Light: 234,
|
|
||||||
}[theme];
|
|
||||||
|
|
||||||
return {
|
|
||||||
accent: `hsl(${purpleHue}, 100%, 70%)`,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export const Colors = {
|
|
||||||
[AppTheme.Classic]: {
|
|
||||||
...LayerColors({ theme: AppTheme.Classic }),
|
|
||||||
text0: 'hsl(245, 11%, 55%)',
|
|
||||||
text1: 'hsl(244, 18%, 81%)',
|
|
||||||
text2: 'hsl(240, 43%, 99%)',
|
|
||||||
|
|
||||||
...AccentColor({ theme: AppTheme.Classic }),
|
|
||||||
green: 'hsl(159, 67%, 39%)',
|
|
||||||
yellow: 'hsl(36, 100%, 64%)',
|
|
||||||
red: 'hsl(360, 73%, 61%)',
|
|
||||||
|
|
||||||
positive: 'hsl(159, 67%, 39%)',
|
|
||||||
negative: 'hsl(360, 73%, 61%)',
|
|
||||||
|
|
||||||
success: 'hsl(159, 67%, 39%)',
|
|
||||||
warning: 'hsl(36, 100%, 64%)',
|
|
||||||
error: 'hsl(360, 73%, 61%)',
|
|
||||||
|
|
||||||
favorite: 'hsl(36, 100%, 64%)',
|
|
||||||
},
|
|
||||||
[AppTheme.Dark]: {
|
|
||||||
...LayerColors({ theme: AppTheme.Dark }),
|
|
||||||
text0: 'hsl(0, 0%, 47%)',
|
|
||||||
text1: 'hsl(0, 0%, 67%)',
|
|
||||||
text2: 'hsl(0, 0%, 100%)',
|
|
||||||
|
|
||||||
...AccentColor({ theme: AppTheme.Dark }),
|
|
||||||
green: 'hsl(159, 67%, 39%)',
|
|
||||||
yellow: 'hsl(36, 100%, 64%)',
|
|
||||||
red: 'hsl(360, 73%, 61%)',
|
|
||||||
|
|
||||||
positive: 'hsl(159, 67%, 39%)',
|
|
||||||
negative: 'hsl(360, 73%, 61%)',
|
|
||||||
|
|
||||||
success: 'hsl(159, 67%, 39%)',
|
|
||||||
warning: 'hsl(36, 100%, 64%)',
|
|
||||||
error: 'hsl(360, 73%, 61%)',
|
|
||||||
|
|
||||||
favorite: 'hsl(36, 100%, 64%)',
|
|
||||||
},
|
|
||||||
[AppTheme.Light]: {
|
|
||||||
...LayerColors({ theme: AppTheme.Light }),
|
|
||||||
text0: 'hsl(0, 0%, 55%)',
|
|
||||||
text1: 'hsl(0, 0%, 40%)',
|
|
||||||
text2: 'hsl(0, 0%, 5%)',
|
|
||||||
|
|
||||||
...AccentColor({ theme: AppTheme.Light }),
|
|
||||||
green: 'hsl(159, 67%, 39%)',
|
|
||||||
yellow: 'hsl(36, 100%, 64%)',
|
|
||||||
red: 'hsl(360, 73%, 61%)',
|
|
||||||
|
|
||||||
positive: 'hsl(159, 67%, 39%)',
|
|
||||||
negative: 'hsl(360, 73%, 61%)',
|
|
||||||
|
|
||||||
success: 'hsl(159, 67%, 39%)',
|
|
||||||
warning: 'hsl(36, 100%, 64%)',
|
|
||||||
error: 'hsl(360, 73%, 61%)',
|
|
||||||
|
|
||||||
favorite: 'hsl(36, 100%, 64%)',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export const UsageColorFromRiskLevel = (riskLevel: RiskLevels) =>
|
|
||||||
({
|
|
||||||
low: css`
|
|
||||||
color: var(--color-risk-low);
|
|
||||||
`,
|
|
||||||
medium: css`
|
|
||||||
color: var(--color-risk-medium);
|
|
||||||
`,
|
|
||||||
high: css`
|
|
||||||
color: var(--color-risk-high);
|
|
||||||
`,
|
|
||||||
}[riskLevel.name]);
|
|
||||||
@@ -21,7 +21,7 @@ export const formMixins: Record<
|
|||||||
--input-radius: 0.5em;
|
--input-radius: 0.5em;
|
||||||
--input-height: var(--form-input-height);
|
--input-height: var(--form-input-height);
|
||||||
--input-width: 100%;
|
--input-width: 100%;
|
||||||
--input-backgroundColor: var(--color-layer-4);
|
--input-backgroundColor: ${({ theme }) => theme.inputBackground};
|
||||||
--input-borderColor: var(--color-layer-6);
|
--input-borderColor: var(--color-layer-6);
|
||||||
|
|
||||||
${layoutMixins.row}
|
${layoutMixins.row}
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
import { createGlobalStyle } from 'styled-components';
|
||||||
|
|
||||||
|
export const GlobalStyle = createGlobalStyle`
|
||||||
|
:root {
|
||||||
|
--color-layer-0: ${({ theme }) => theme.layer0};
|
||||||
|
--color-layer-1: ${({ theme }) => theme.layer1};
|
||||||
|
--color-layer-2: ${({ theme }) => theme.layer2};
|
||||||
|
--color-layer-3: ${({ theme }) => theme.layer3};
|
||||||
|
--color-layer-4: ${({ theme }) => theme.layer4};
|
||||||
|
--color-layer-5: ${({ theme }) => theme.layer5};
|
||||||
|
--color-layer-6: ${({ theme }) => theme.layer6};
|
||||||
|
--color-layer-7: ${({ theme }) => theme.layer7};
|
||||||
|
|
||||||
|
--color-border: ${({ theme }) => theme.borderDefault};
|
||||||
|
--color-border-white: ${({ theme }) => theme.borderButton};
|
||||||
|
--color-border-red: ${({ theme }) => theme.borderDestructive};
|
||||||
|
|
||||||
|
--color-text-0: ${({ theme }) => theme.textTertiary};
|
||||||
|
--color-text-1: ${({ theme }) => theme.textSecondary};
|
||||||
|
--color-text-2: ${({ theme }) => theme.textPrimary};
|
||||||
|
|
||||||
|
--color-gradient-base-0: ${({ theme }) => theme.gradientBase0};
|
||||||
|
--color-gradient-base-1: ${({ theme }) => theme.gradientBase1};
|
||||||
|
|
||||||
|
--color-accent: ${({ theme }) => theme.accent};
|
||||||
|
--color-accent-faded: ${({ theme }) => theme.accentFaded};
|
||||||
|
--color-favorite: ${({ theme }) => theme.favorite};
|
||||||
|
|
||||||
|
--color-success: ${({ theme }) => theme.success};
|
||||||
|
--color-warning: ${({ theme }) => theme.warning};
|
||||||
|
--color-error: ${({ theme }) => theme.error};
|
||||||
|
|
||||||
|
--color-positive: ${({ theme }) => theme.positive};
|
||||||
|
--color-negative: ${({ theme }) => theme.negative};
|
||||||
|
--color-gradient-positive: ${({ theme }) => theme.positiveFaded};
|
||||||
|
--color-gradient-negative: ${({ theme }) => theme.negativeFaded};
|
||||||
|
|
||||||
|
--color-risk-low: ${({ theme }) => theme.riskLow};
|
||||||
|
--color-risk-medium: ${({ theme }) => theme.riskMedium};
|
||||||
|
--color-risk-high: ${({ theme }) => theme.riskHigh};
|
||||||
|
}
|
||||||
|
`;
|
||||||
@@ -0,0 +1,157 @@
|
|||||||
|
import { AppTheme } from '@/state/configs';
|
||||||
|
import { ThemeColors } from '@/constants/styles/colors';
|
||||||
|
import { ColorToken, OpacityToken } from '@/constants/styles/base';
|
||||||
|
import { generateFadedColorVariant } from '@/lib/styles';
|
||||||
|
|
||||||
|
const ClassicTheme: ThemeColors = {
|
||||||
|
layer0: ColorToken.GrayBlue7,
|
||||||
|
layer1: ColorToken.GrayBlue6,
|
||||||
|
layer2: ColorToken.GrayBlue5,
|
||||||
|
layer3: ColorToken.GrayBlue4,
|
||||||
|
layer4: ColorToken.GrayBlue3,
|
||||||
|
layer5: ColorToken.GrayBlue2,
|
||||||
|
layer6: ColorToken.GrayBlue1,
|
||||||
|
layer7: ColorToken.GrayBlue0,
|
||||||
|
|
||||||
|
borderDefault: ColorToken.GrayBlue2,
|
||||||
|
borderDestructive: generateFadedColorVariant(ColorToken.Red2, OpacityToken.Opacity20),
|
||||||
|
borderButton: generateFadedColorVariant(ColorToken.White, OpacityToken.Opacity20),
|
||||||
|
|
||||||
|
textPrimary: ColorToken.LightGray2,
|
||||||
|
textSecondary: ColorToken.GrayPurple1,
|
||||||
|
textTertiary: ColorToken.GrayPurple2,
|
||||||
|
|
||||||
|
gradientBase0: ColorToken.DarkGray9,
|
||||||
|
gradientBase1: ColorToken.GrayBlue2,
|
||||||
|
|
||||||
|
accent: ColorToken.Purple1,
|
||||||
|
accentFaded: generateFadedColorVariant(ColorToken.Purple1, OpacityToken.Opacity16),
|
||||||
|
favorite: ColorToken.Yellow0,
|
||||||
|
|
||||||
|
success: ColorToken.Green1,
|
||||||
|
warning: ColorToken.Yellow0,
|
||||||
|
error: ColorToken.Red2,
|
||||||
|
|
||||||
|
positive: ColorToken.Green1,
|
||||||
|
negative: ColorToken.Red2,
|
||||||
|
positiveFaded: generateFadedColorVariant(ColorToken.Green1, OpacityToken.Opacity16),
|
||||||
|
negativeFaded: generateFadedColorVariant(ColorToken.Red2, OpacityToken.Opacity16),
|
||||||
|
|
||||||
|
riskLow: ColorToken.Green1,
|
||||||
|
riskMedium: ColorToken.Yellow0,
|
||||||
|
riskHigh: ColorToken.Red2,
|
||||||
|
|
||||||
|
logoFill: ColorToken.White,
|
||||||
|
profileYellow: ColorToken.Yellow1,
|
||||||
|
profileRed: ColorToken.Red2,
|
||||||
|
|
||||||
|
inputBackground: ColorToken.GrayBlue3,
|
||||||
|
popoverBackground: generateFadedColorVariant(ColorToken.GrayBlue4, OpacityToken.Opacity90),
|
||||||
|
switchThumbActiveBackground: ColorToken.White,
|
||||||
|
toggleBackground: ColorToken.GrayBlue3,
|
||||||
|
tooltipBackground: generateFadedColorVariant(ColorToken.GrayBlue3, OpacityToken.Opacity66),
|
||||||
|
};
|
||||||
|
|
||||||
|
const DarkTheme: ThemeColors = {
|
||||||
|
layer0: ColorToken.Black,
|
||||||
|
layer1: ColorToken.DarkGray11,
|
||||||
|
layer2: ColorToken.DarkGray13,
|
||||||
|
layer3: ColorToken.DarkGray10,
|
||||||
|
layer4: ColorToken.DarkGray6,
|
||||||
|
layer5: ColorToken.DarkGray5,
|
||||||
|
layer6: ColorToken.DarkGray4,
|
||||||
|
layer7: ColorToken.DarkGray2,
|
||||||
|
|
||||||
|
borderDefault: ColorToken.DarkGray4,
|
||||||
|
borderDestructive: generateFadedColorVariant(ColorToken.Red0, OpacityToken.Opacity20),
|
||||||
|
borderButton: generateFadedColorVariant(ColorToken.White, OpacityToken.Opacity20),
|
||||||
|
|
||||||
|
textPrimary: ColorToken.LightGray0,
|
||||||
|
textSecondary: ColorToken.MediumGray0,
|
||||||
|
textTertiary: ColorToken.DarkGray0,
|
||||||
|
|
||||||
|
gradientBase0: ColorToken.DarkGray8,
|
||||||
|
gradientBase1: ColorToken.DarkGray5,
|
||||||
|
|
||||||
|
accent: ColorToken.Purple0,
|
||||||
|
accentFaded: generateFadedColorVariant(ColorToken.Purple0, OpacityToken.Opacity16),
|
||||||
|
favorite: ColorToken.Yellow0,
|
||||||
|
|
||||||
|
success: ColorToken.Green0,
|
||||||
|
warning: ColorToken.Yellow0,
|
||||||
|
error: ColorToken.Red0,
|
||||||
|
|
||||||
|
positive: ColorToken.Green0,
|
||||||
|
negative: ColorToken.Red0,
|
||||||
|
positiveFaded: generateFadedColorVariant(ColorToken.Green0, OpacityToken.Opacity16),
|
||||||
|
negativeFaded: generateFadedColorVariant(ColorToken.Red0, OpacityToken.Opacity16),
|
||||||
|
|
||||||
|
riskLow: ColorToken.Green0,
|
||||||
|
riskMedium: ColorToken.Yellow0,
|
||||||
|
riskHigh: ColorToken.Red0,
|
||||||
|
|
||||||
|
logoFill: ColorToken.White,
|
||||||
|
profileYellow: ColorToken.Yellow1,
|
||||||
|
profileRed: ColorToken.Red2,
|
||||||
|
|
||||||
|
inputBackground: ColorToken.DarkGray6,
|
||||||
|
popoverBackground: generateFadedColorVariant(ColorToken.DarkGray8, OpacityToken.Opacity90),
|
||||||
|
switchThumbActiveBackground: ColorToken.White,
|
||||||
|
toggleBackground: ColorToken.DarkGray6,
|
||||||
|
tooltipBackground: generateFadedColorVariant(ColorToken.DarkGray6, OpacityToken.Opacity66),
|
||||||
|
};
|
||||||
|
|
||||||
|
const LightTheme: ThemeColors = {
|
||||||
|
layer0: ColorToken.White,
|
||||||
|
layer1: ColorToken.LightGray6,
|
||||||
|
layer2: ColorToken.White,
|
||||||
|
layer3: ColorToken.LightGray1,
|
||||||
|
layer4: ColorToken.White,
|
||||||
|
layer5: ColorToken.LightGray4,
|
||||||
|
layer6: ColorToken.LightGray9,
|
||||||
|
layer7: ColorToken.MediumGray1,
|
||||||
|
|
||||||
|
borderDefault: ColorToken.LightGray10,
|
||||||
|
borderDestructive: generateFadedColorVariant(ColorToken.Red1, OpacityToken.Opacity20),
|
||||||
|
borderButton: generateFadedColorVariant(ColorToken.Black, OpacityToken.Opacity20),
|
||||||
|
|
||||||
|
textPrimary: ColorToken.DarkGray12,
|
||||||
|
textSecondary: ColorToken.DarkGray3,
|
||||||
|
textTertiary: ColorToken.DarkGray1,
|
||||||
|
|
||||||
|
gradientBase0: ColorToken.LightGray8,
|
||||||
|
gradientBase1: ColorToken.LightGray5,
|
||||||
|
|
||||||
|
accent: ColorToken.Purple0,
|
||||||
|
accentFaded: generateFadedColorVariant(ColorToken.Purple0, OpacityToken.Opacity16),
|
||||||
|
favorite: ColorToken.Yellow0,
|
||||||
|
|
||||||
|
success: ColorToken.Green2,
|
||||||
|
warning: ColorToken.Yellow0,
|
||||||
|
error: ColorToken.Red1,
|
||||||
|
|
||||||
|
positive: ColorToken.Green2,
|
||||||
|
negative: ColorToken.Red1,
|
||||||
|
positiveFaded: generateFadedColorVariant(ColorToken.Green2, OpacityToken.Opacity16),
|
||||||
|
negativeFaded: generateFadedColorVariant(ColorToken.Red1, OpacityToken.Opacity16),
|
||||||
|
|
||||||
|
riskLow: ColorToken.Green2,
|
||||||
|
riskMedium: ColorToken.Yellow0,
|
||||||
|
riskHigh: ColorToken.Red1,
|
||||||
|
|
||||||
|
logoFill: ColorToken.Black,
|
||||||
|
profileYellow: ColorToken.Yellow1,
|
||||||
|
profileRed: ColorToken.Red2,
|
||||||
|
|
||||||
|
inputBackground: ColorToken.White,
|
||||||
|
popoverBackground: generateFadedColorVariant(ColorToken.LightGray8, OpacityToken.Opacity90),
|
||||||
|
switchThumbActiveBackground: ColorToken.White,
|
||||||
|
toggleBackground: ColorToken.LightGray4,
|
||||||
|
tooltipBackground: generateFadedColorVariant(ColorToken.LightGray7, OpacityToken.Opacity66),
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Themes = {
|
||||||
|
[AppTheme.Classic]: ClassicTheme,
|
||||||
|
[AppTheme.Dark]: DarkTheme,
|
||||||
|
[AppTheme.Light]: LightTheme,
|
||||||
|
};
|
||||||
@@ -29,7 +29,6 @@ export const MarketDetails: React.FC = () => {
|
|||||||
if (!configs) return null;
|
if (!configs) return null;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
basePositionNotional,
|
|
||||||
tickSize,
|
tickSize,
|
||||||
stepSize,
|
stepSize,
|
||||||
initialMarginFraction,
|
initialMarginFraction,
|
||||||
|
|||||||
@@ -235,6 +235,10 @@ export const DepositForm = ({ onDeposit, onError }: DepositFormProps) => {
|
|||||||
throw new Error('Missing request payload');
|
throw new Error('Missing request payload');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isCctp && !abacusStateManager.chainTransactions.isNobleClientConnected) {
|
||||||
|
throw new Error('Noble RPC endpoint unaccessible');
|
||||||
|
}
|
||||||
|
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
|
|
||||||
await validateTokenApproval();
|
await validateTokenApproval();
|
||||||
|
|||||||
@@ -148,6 +148,10 @@ export const WithdrawForm = () => {
|
|||||||
throw new Error('Invalid request payload');
|
throw new Error('Invalid request payload');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isCctp && !abacusStateManager.chainTransactions.isNobleClientConnected) {
|
||||||
|
throw new Error('Noble RPC endpoint unaccessible');
|
||||||
|
}
|
||||||
|
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
setError(undefined);
|
setError(undefined);
|
||||||
|
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ export const WithdrawButtonAndReceipt = ({
|
|||||||
const stringGetter = useStringGetter();
|
const stringGetter = useStringGetter();
|
||||||
|
|
||||||
const { leverage } = useSelector(getSubaccount, shallowEqual) || {};
|
const { leverage } = useSelector(getSubaccount, shallowEqual) || {};
|
||||||
const { isCctp, summary, requestPayload } = useSelector(getTransferInputs, shallowEqual) || {};
|
const { summary, requestPayload } = useSelector(getTransferInputs, shallowEqual) || {};
|
||||||
const canAccountTrade = useSelector(calculateCanAccountTrade, shallowEqual);
|
const canAccountTrade = useSelector(calculateCanAccountTrade, shallowEqual);
|
||||||
const { usdcLabel } = useTokenConfigs();
|
const { usdcLabel } = useTokenConfigs();
|
||||||
|
|
||||||
@@ -85,26 +85,6 @@ export const WithdrawButtonAndReceipt = ({
|
|||||||
|
|
||||||
const totalFees = (summary?.bridgeFee || 0) + (summary?.gasFee || 0);
|
const totalFees = (summary?.bridgeFee || 0) + (summary?.gasFee || 0);
|
||||||
|
|
||||||
const { toAmount, toAmountMin } = useMemo(() => {
|
|
||||||
if (isCctp) {
|
|
||||||
return {
|
|
||||||
toAmount: summary?.toAmount,
|
|
||||||
toAmountMin: summary?.toAmountMin,
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
return {
|
|
||||||
toAmount:
|
|
||||||
summary?.toAmount &&
|
|
||||||
withdrawToken?.decimals &&
|
|
||||||
formatUnits(BigInt(summary.toAmount), withdrawToken.decimals),
|
|
||||||
toAmountMin:
|
|
||||||
summary?.toAmountMin &&
|
|
||||||
withdrawToken?.decimals &&
|
|
||||||
formatUnits(BigInt(summary.toAmountMin), withdrawToken.decimals),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}, [isCctp, summary, withdrawToken]);
|
|
||||||
|
|
||||||
const submitButtonReceipt = [
|
const submitButtonReceipt = [
|
||||||
{
|
{
|
||||||
key: 'total-fees',
|
key: 'total-fees',
|
||||||
@@ -153,7 +133,7 @@ export const WithdrawButtonAndReceipt = ({
|
|||||||
{withdrawToken && <Tag>{withdrawToken?.symbol}</Tag>}
|
{withdrawToken && <Tag>{withdrawToken?.symbol}</Tag>}
|
||||||
</span>
|
</span>
|
||||||
),
|
),
|
||||||
value: <Output type={OutputType.Asset} value={toAmount} fractionDigits={TOKEN_DECIMALS} />,
|
value: <Output type={OutputType.Asset} value={summary?.toAmount} fractionDigits={TOKEN_DECIMALS} />,
|
||||||
subitems: [
|
subitems: [
|
||||||
{
|
{
|
||||||
key: 'minimum-amount-received',
|
key: 'minimum-amount-received',
|
||||||
@@ -164,7 +144,7 @@ export const WithdrawButtonAndReceipt = ({
|
|||||||
</span>
|
</span>
|
||||||
),
|
),
|
||||||
value: (
|
value: (
|
||||||
<Output type={OutputType.Asset} value={toAmountMin} fractionDigits={TOKEN_DECIMALS} />
|
<Output type={OutputType.Asset} value={summary?.toAmountMin} fractionDigits={TOKEN_DECIMALS} />
|
||||||
),
|
),
|
||||||
tooltip: 'minimum-amount-received',
|
tooltip: 'minimum-amount-received',
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ export const TradeSideToggle = memo(() => {
|
|||||||
const ToggleContainer = styled(ToggleGroup)<{ value: OrderSide }>`
|
const ToggleContainer = styled(ToggleGroup)<{ value: OrderSide }>`
|
||||||
--toggle-radius: 0.5em;
|
--toggle-radius: 0.5em;
|
||||||
--toggle-color: var(--color-negative);
|
--toggle-color: var(--color-negative);
|
||||||
|
--toggle-background: ${({ theme }) => theme.toggleBackground};
|
||||||
|
|
||||||
${({ value }) =>
|
${({ value }) =>
|
||||||
value === OrderSide.BUY &&
|
value === OrderSide.BUY &&
|
||||||
@@ -52,7 +53,7 @@ const ToggleContainer = styled(ToggleGroup)<{ value: OrderSide }>`
|
|||||||
`}
|
`}
|
||||||
|
|
||||||
border-radius: var(--toggle-radius);
|
border-radius: var(--toggle-radius);
|
||||||
background-color: var(--color-layer-4);
|
background-color: var(--toggle-background);
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
> button {
|
> button {
|
||||||
|
|||||||
@@ -10,6 +10,9 @@ import { STRING_KEYS, StringGetterFunction, TOOLTIP_STRING_KEYS } from '@/consta
|
|||||||
import { isMainnet } from '@/constants/networks';
|
import { isMainnet } from '@/constants/networks';
|
||||||
import { DydxChainAsset, wallets } from '@/constants/wallets';
|
import { DydxChainAsset, wallets } from '@/constants/wallets';
|
||||||
|
|
||||||
|
import { layoutMixins } from '@/styles/layoutMixins';
|
||||||
|
import { headerMixins } from '@/styles/headerMixins';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
useAccounts,
|
useAccounts,
|
||||||
useBreakpoints,
|
useBreakpoints,
|
||||||
@@ -35,10 +38,8 @@ import { getOnboardingState, getSubaccount } from '@/state/accountSelectors';
|
|||||||
|
|
||||||
import { isTruthy } from '@/lib/isTruthy';
|
import { isTruthy } from '@/lib/isTruthy';
|
||||||
import { truncateAddress } from '@/lib/wallet';
|
import { truncateAddress } from '@/lib/wallet';
|
||||||
|
|
||||||
import { layoutMixins } from '@/styles/layoutMixins';
|
|
||||||
import { headerMixins } from '@/styles/headerMixins';
|
|
||||||
import { MustBigNumber } from '@/lib/numbers';
|
import { MustBigNumber } from '@/lib/numbers';
|
||||||
|
import { testFlags } from '@/lib/testFlags';
|
||||||
|
|
||||||
export const AccountMenu = () => {
|
export const AccountMenu = () => {
|
||||||
const stringGetter = useStringGetter();
|
const stringGetter = useStringGetter();
|
||||||
@@ -178,7 +179,7 @@ export const AccountMenu = () => {
|
|||||||
},
|
},
|
||||||
...(onboardingState === OnboardingState.AccountConnected && hdKey
|
...(onboardingState === OnboardingState.AccountConnected && hdKey
|
||||||
? [
|
? [
|
||||||
!isMainnet && {
|
(!isMainnet || testFlags.showMobileSignInOption) && {
|
||||||
value: 'MobileQrSignIn',
|
value: 'MobileQrSignIn',
|
||||||
icon: <Icon iconName={IconName.Qr} />,
|
icon: <Icon iconName={IconName.Qr} />,
|
||||||
label: stringGetter({ key: STRING_KEYS.TITLE_SIGN_INTO_MOBILE }),
|
label: stringGetter({ key: STRING_KEYS.TITLE_SIGN_INTO_MOBILE }),
|
||||||
|
|||||||
@@ -0,0 +1,78 @@
|
|||||||
|
import styled, { type AnyStyledComponent } from 'styled-components';
|
||||||
|
|
||||||
|
import { STRING_KEYS } from '@/constants/localization';
|
||||||
|
import { useStringGetter } from '@/hooks';
|
||||||
|
|
||||||
|
import { Details } from '@/components/Details';
|
||||||
|
import { Notification, NotificationProps } from '@/components/Notification';
|
||||||
|
import { Output, OutputType } from '@/components/Output';
|
||||||
|
import { Icon, IconName } from '@/components/Icon';
|
||||||
|
|
||||||
|
type ElementProps = {
|
||||||
|
data: {
|
||||||
|
BLOCK_REWARD_AMOUNT: string;
|
||||||
|
BLOCK_REWARD_HEIGHT: string;
|
||||||
|
BLOCK_REWARD_TIME_MILLISECONDS: string;
|
||||||
|
TOKEN_NAME: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export type BlockRewardNotificationProps = NotificationProps & ElementProps;
|
||||||
|
|
||||||
|
export const BlockRewardNotification = ({
|
||||||
|
isToast,
|
||||||
|
data,
|
||||||
|
notification,
|
||||||
|
}: BlockRewardNotificationProps) => {
|
||||||
|
const stringGetter = useStringGetter();
|
||||||
|
const { BLOCK_REWARD_AMOUNT, TOKEN_NAME } = data;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Styled.Notification
|
||||||
|
isToast={isToast}
|
||||||
|
notification={notification}
|
||||||
|
slotIcon={<Icon iconName={IconName.RewardStar} />}
|
||||||
|
slotTitle={stringGetter({ key: STRING_KEYS.TRADING_REWARD_RECEIVED })}
|
||||||
|
slotCustomContent={
|
||||||
|
<Styled.Details
|
||||||
|
items={[
|
||||||
|
{
|
||||||
|
key: 'block_reward',
|
||||||
|
label: stringGetter({ key: STRING_KEYS.BLOCK_REWARD }),
|
||||||
|
value: (
|
||||||
|
<Styled.Output
|
||||||
|
type={OutputType.Asset}
|
||||||
|
value={BLOCK_REWARD_AMOUNT}
|
||||||
|
tag={TOKEN_NAME}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const Styled: Record<string, AnyStyledComponent> = {};
|
||||||
|
|
||||||
|
Styled.Details = styled(Details)`
|
||||||
|
--details-item-height: 1.5rem;
|
||||||
|
|
||||||
|
dd {
|
||||||
|
color: var(--color-text-2);
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
Styled.Notification = styled(Notification)`
|
||||||
|
background-image: url('/dots-background-2.svg');
|
||||||
|
background-size: cover;
|
||||||
|
`;
|
||||||
|
|
||||||
|
Styled.Output = styled(Output)`
|
||||||
|
&:before {
|
||||||
|
content: '+';
|
||||||
|
color: var(--color-positive);
|
||||||
|
margin-right: 0.5ch;
|
||||||
|
}
|
||||||
|
`;
|
||||||
Reference in New Issue
Block a user