Compare commits
11
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
87731097b8 | ||
|
|
1e9209028e | ||
|
|
2861286bdb | ||
|
|
e93850484b | ||
|
|
521b6d6135 | ||
|
|
94772bf4dc | ||
|
|
149f21e7e0 | ||
|
|
0a3ef3a7ab | ||
|
|
fef9935883 | ||
|
|
c7a5b706e1 | ||
|
|
f304bb069a |
+18
-9
@@ -5,29 +5,35 @@ import styled from 'styled-components';
|
||||
|
||||
import { store } from '@/state/_store';
|
||||
|
||||
import { GlobalStyle } from '@/styles/globalStyle';
|
||||
|
||||
import { SelectMenu, SelectItem } from '@/components/SelectMenu';
|
||||
|
||||
import { AppThemeProvider } from '@/hooks/useAppTheme';
|
||||
|
||||
import { AppTheme, setAppTheme } from '@/state/configs';
|
||||
import { setLocaleLoaded } from '@/state/localization';
|
||||
|
||||
import '@/index.css';
|
||||
import './ladle.css';
|
||||
|
||||
export const StoryWrapper: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
||||
const [theme, setTheme] = useState('Default theme');
|
||||
const [theme, setTheme] = useState(AppTheme.Classic);
|
||||
|
||||
useEffect(() => {
|
||||
store.dispatch(setAppTheme(theme));
|
||||
switch (theme) {
|
||||
case 'Dark theme': {
|
||||
case AppTheme.Dark: {
|
||||
document?.documentElement?.classList.remove('theme-light');
|
||||
document?.documentElement?.classList.add('theme-dark');
|
||||
break;
|
||||
}
|
||||
case 'Light theme': {
|
||||
case AppTheme.Light: {
|
||||
document?.documentElement?.classList.remove('theme-dark');
|
||||
document?.documentElement?.classList.add('theme-light');
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
case AppTheme.Classic: {
|
||||
document?.documentElement?.classList.remove('theme-dark', 'theme-light');
|
||||
break;
|
||||
}
|
||||
@@ -48,15 +54,15 @@ export const StoryWrapper: React.FC<{ children: React.ReactNode }> = ({ children
|
||||
>
|
||||
{[
|
||||
{
|
||||
value: 'Default theme',
|
||||
value: AppTheme.Classic,
|
||||
label: 'Default theme',
|
||||
},
|
||||
{
|
||||
value: 'Dark theme',
|
||||
value: AppTheme.Dark,
|
||||
label: 'Dark theme',
|
||||
},
|
||||
{
|
||||
value: 'Light theme',
|
||||
value: AppTheme.Light,
|
||||
label: 'Light theme',
|
||||
},
|
||||
].map(({ value, label }) => (
|
||||
@@ -69,8 +75,11 @@ export const StoryWrapper: React.FC<{ children: React.ReactNode }> = ({ children
|
||||
</SelectMenu>
|
||||
</StoryHeader>
|
||||
<hr />
|
||||
<StoryContent>{children}</StoryContent>
|
||||
</Provider>
|
||||
<AppThemeProvider>
|
||||
<GlobalStyle />
|
||||
<StoryContent>{children}</StoryContent>
|
||||
</AppThemeProvider>
|
||||
</Provider>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
+1
-1
@@ -39,7 +39,7 @@
|
||||
"@cosmjs/proto-signing": "^0.31.0",
|
||||
"@cosmjs/stargate": "^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-localization": "^1.1.11",
|
||||
"@ethersproject/providers": "^5.7.2",
|
||||
|
||||
Generated
+8
-8
@@ -1,9 +1,5 @@
|
||||
lockfileVersion: '6.0'
|
||||
|
||||
settings:
|
||||
autoInstallPeers: true
|
||||
excludeLinksFromLockfile: false
|
||||
|
||||
dependencies:
|
||||
'@0xsquid/sdk':
|
||||
specifier: ^1.10.0
|
||||
@@ -27,8 +23,8 @@ dependencies:
|
||||
specifier: ^0.31.0
|
||||
version: 0.31.0
|
||||
'@dydxprotocol/v4-abacus':
|
||||
specifier: ^1.2.3
|
||||
version: 1.2.3
|
||||
specifier: ^1.2.5
|
||||
version: 1.2.5
|
||||
'@dydxprotocol/v4-client-js':
|
||||
specifier: ^1.0.11
|
||||
version: 1.0.11
|
||||
@@ -991,8 +987,8 @@ packages:
|
||||
resolution: {integrity: sha512-RpfLEtTlyIxeNPGKcokS+p3BZII/Q3bYxryFRglh5H3A3T8q9fsLYm72VYAMEOOIBLEa8o93kFLiBDUWKrwXZA==}
|
||||
dev: true
|
||||
|
||||
/@dydxprotocol/v4-abacus@1.2.3:
|
||||
resolution: {integrity: sha512-OHGhN4uQo/ikRjeGzf+wGblFvb0uRA916QvQXG4LixsJy7H7HAt7AeZr9LqTM/GqYJicMmZCUS3WIMqgZ20hKA==}
|
||||
/@dydxprotocol/v4-abacus@1.2.5:
|
||||
resolution: {integrity: sha512-pB3Fv1bzJRUDp29kAN61daZ34gTSGrSTNh+/AP3TUB63/Q/gaXQVBf91xVcso4Hw23xM3FwIcrRK0cvOSWgXKg==}
|
||||
dev: false
|
||||
|
||||
/@dydxprotocol/v4-client-js@1.0.11:
|
||||
@@ -14813,3 +14809,7 @@ packages:
|
||||
/zwitch@2.0.4:
|
||||
resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
|
||||
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';
|
||||
import { DydxProvider } from '@/hooks/useDydxClient';
|
||||
import { AccountsProvider } from '@/hooks/useAccounts';
|
||||
import { AppThemeProvider } from '@/hooks/useAppTheme';
|
||||
import { DialogAreaProvider, useDialogArea } from '@/hooks/useDialogArea';
|
||||
import { LocaleProvider } from '@/hooks/useLocaleSeparators';
|
||||
import { NotificationsProvider } from '@/hooks/useNotifications';
|
||||
@@ -35,6 +36,7 @@ import { GlobalCommandDialog } from '@/views/dialogs/GlobalCommandDialog';
|
||||
import { config } from '@/lib/wagmi';
|
||||
|
||||
import { breakpoints } from '@/styles';
|
||||
import { GlobalStyle } from '@/styles/globalStyle';
|
||||
import { layoutMixins } from '@/styles/layoutMixins';
|
||||
import { LoadingSpace } from './components/Loading/LoadingSpinner';
|
||||
|
||||
@@ -66,49 +68,52 @@ const Content = () => {
|
||||
const { chainTokenLabel } = useTokenConfigs();
|
||||
|
||||
return (
|
||||
<Styled.Content isShowingHeader={isShowingHeader} isShowingFooter={isShowingFooter}>
|
||||
{isNotTablet && <HeaderDesktop />}
|
||||
<>
|
||||
<GlobalStyle />
|
||||
<Styled.Content isShowingHeader={isShowingHeader} isShowingFooter={isShowingFooter}>
|
||||
{isNotTablet && <HeaderDesktop />}
|
||||
|
||||
<Styled.Main>
|
||||
<Suspense fallback={<LoadingSpace id="main" />}>
|
||||
<Routes>
|
||||
<Route path={AppRoute.Trade}>
|
||||
<Route path=":market" element={<TradePage />} />
|
||||
<Route path={AppRoute.Trade} element={<TradePage />} />
|
||||
</Route>
|
||||
<Styled.Main>
|
||||
<Suspense fallback={<LoadingSpace id="main" />}>
|
||||
<Routes>
|
||||
<Route path={AppRoute.Trade}>
|
||||
<Route path=":market" element={<TradePage />} />
|
||||
<Route path={AppRoute.Trade} element={<TradePage />} />
|
||||
</Route>
|
||||
|
||||
<Route path={AppRoute.Markets} element={<MarketsPage />} />
|
||||
<Route path={`/${chainTokenLabel}`} element={<RewardsPage />} />
|
||||
{isTablet && (
|
||||
<>
|
||||
<Route path={AppRoute.Alerts} element={<AlertsPage />} />
|
||||
<Route path={AppRoute.Profile} element={<ProfilePage />} />
|
||||
<Route path={`${AppRoute.Settings}/*`} element={<SettingsPage />} />
|
||||
</>
|
||||
)}
|
||||
<Route path={AppRoute.Markets} element={<MarketsPage />} />
|
||||
<Route path={`/${chainTokenLabel}`} element={<RewardsPage />} />
|
||||
{isTablet && (
|
||||
<>
|
||||
<Route path={AppRoute.Alerts} element={<AlertsPage />} />
|
||||
<Route path={AppRoute.Profile} element={<ProfilePage />} />
|
||||
<Route path={`${AppRoute.Settings}/*`} element={<SettingsPage />} />
|
||||
</>
|
||||
)}
|
||||
|
||||
<Route element={<GuardedMobileRoute />}>
|
||||
<Route path={`${AppRoute.Portfolio}/*`} element={<PortfolioPage />} />
|
||||
</Route>
|
||||
<Route element={<GuardedMobileRoute />}>
|
||||
<Route path={`${AppRoute.Portfolio}/*`} element={<PortfolioPage />} />
|
||||
</Route>
|
||||
|
||||
<Route path={AppRoute.Terms} element={<TermsOfUsePage />} />
|
||||
<Route path={AppRoute.Privacy} element={<PrivacyPolicyPage />} />
|
||||
<Route path={AppRoute.Terms} element={<TermsOfUsePage />} />
|
||||
<Route path={AppRoute.Privacy} element={<PrivacyPolicyPage />} />
|
||||
|
||||
<Route path="*" element={<Navigate to={DEFAULT_TRADE_ROUTE} replace />} />
|
||||
</Routes>
|
||||
</Suspense>
|
||||
</Styled.Main>
|
||||
<Route path="*" element={<Navigate to={DEFAULT_TRADE_ROUTE} replace />} />
|
||||
</Routes>
|
||||
</Suspense>
|
||||
</Styled.Main>
|
||||
|
||||
{isTablet ? <FooterMobile /> : <FooterDesktop />}
|
||||
{isTablet ? <FooterMobile /> : <FooterDesktop />}
|
||||
|
||||
<Styled.NotificationsToastArea />
|
||||
<Styled.NotificationsToastArea />
|
||||
|
||||
<Styled.DialogArea ref={setDialogArea}>
|
||||
<DialogManager />
|
||||
</Styled.DialogArea>
|
||||
<Styled.DialogArea ref={setDialogArea}>
|
||||
<DialogManager />
|
||||
</Styled.DialogArea>
|
||||
|
||||
<GlobalCommandDialog />
|
||||
</Styled.Content>
|
||||
<GlobalCommandDialog />
|
||||
</Styled.Content>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -131,6 +136,7 @@ const providers = [
|
||||
wrapProvider(LocalNotificationsProvider),
|
||||
wrapProvider(NotificationsProvider),
|
||||
wrapProvider(DialogAreaProvider),
|
||||
wrapProvider(AppThemeProvider),
|
||||
];
|
||||
|
||||
const App = () => {
|
||||
|
||||
@@ -59,6 +59,7 @@ import {
|
||||
PriceChartIcon,
|
||||
PrivacyIcon,
|
||||
QrIcon,
|
||||
RewardStarIcon,
|
||||
SearchIcon,
|
||||
SendIcon,
|
||||
ShareIcon,
|
||||
@@ -134,6 +135,7 @@ export enum IconName {
|
||||
PriceChart = 'PriceChart',
|
||||
Privacy = 'Privacy',
|
||||
Qr = 'Qr',
|
||||
RewardStar = 'RewardStar',
|
||||
Search = 'Search',
|
||||
Send = 'Send',
|
||||
Share = 'Share',
|
||||
@@ -208,6 +210,7 @@ const icons = {
|
||||
[IconName.PriceChart]: PriceChartIcon,
|
||||
[IconName.Privacy]: PrivacyIcon,
|
||||
[IconName.Qr]: QrIcon,
|
||||
[IconName.RewardStar]: RewardStarIcon,
|
||||
[IconName.Search]: SearchIcon,
|
||||
[IconName.Send]: SendIcon,
|
||||
[IconName.Share]: ShareIcon,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import styled, { type AnyStyledComponent } from 'styled-components';
|
||||
|
||||
import { RiskLevels } from '@/constants/abacus';
|
||||
import { UsageColorFromRiskLevel } from '@/styles/colors';
|
||||
|
||||
import { Ring } from '@/components/Ring';
|
||||
|
||||
import { abacusHelper } from '@/lib/abacus';
|
||||
import { UsageColorFromRiskLevel } from '@/lib/styles';
|
||||
|
||||
type ElementProps = {
|
||||
value: number;
|
||||
|
||||
@@ -47,7 +47,7 @@ Styled.Root = styled(Root)`
|
||||
--switch-thumb-backgroundColor: var(--color-layer-6);
|
||||
|
||||
--switch-active-backgroundColor: var(--color-accent);
|
||||
--switch-active-thumb-backgroundColor: var(--color-white);
|
||||
--switch-active-thumb-backgroundColor: ${({ theme }) => theme.switchThumbActiveBackground};
|
||||
|
||||
position: relative;
|
||||
width: var(--switch-width);
|
||||
|
||||
@@ -27,9 +27,8 @@ export const ToastArea = ({ swipeDirection, children, className }: ToastAreaProp
|
||||
const $ToastArea = styled.aside`
|
||||
// Params
|
||||
--toasts-gap: 0.5rem;
|
||||
|
||||
|
||||
// Rules
|
||||
${layoutMixins.scrollArea}
|
||||
z-index: 1;
|
||||
|
||||
pointer-events: none;
|
||||
|
||||
@@ -2,9 +2,9 @@ import styled, { type AnyStyledComponent } from 'styled-components';
|
||||
|
||||
import { type RiskLevels } from '@/constants/abacus';
|
||||
|
||||
import { UsageColorFromRiskLevel } from '@/styles/colors';
|
||||
|
||||
import { abacusHelper } from '@/lib/abacus';
|
||||
import { UsageColorFromRiskLevel } from '@/lib/styles';
|
||||
|
||||
type ElementProps = {
|
||||
value: number;
|
||||
};
|
||||
|
||||
@@ -110,12 +110,7 @@ Styled.Abbr = styled.abbr`
|
||||
|
||||
Styled.Content = styled(Content)`
|
||||
--tooltip-backgroundColor: var(--color-layer-4);
|
||||
--tooltip-backgroundColor: hsl(
|
||||
var(--layer-base-hue),
|
||||
var(--layer-base-saturation),
|
||||
calc(var(--layer-base-lightness) + 4%),
|
||||
0.66
|
||||
);
|
||||
--tooltip-backgroundColor: ${({ theme }) => theme.tooltipBackground};
|
||||
|
||||
${popoverMixins.popover}
|
||||
--popover-backgroundColor: var(--tooltip-backgroundColor);
|
||||
|
||||
@@ -27,12 +27,7 @@ Styled.TooltipContent = styled.aside<{ accentColor?: string }>`
|
||||
|
||||
${popoverMixins.popover}
|
||||
--popover-radius: 0.5rem;
|
||||
--popover-background-color: hsl(
|
||||
var(--layer-base-hue),
|
||||
var(--layer-base-saturation),
|
||||
calc(var(--layer-base-lightness)),
|
||||
0.9
|
||||
);
|
||||
--popover-background-color: ${({ theme }) => theme.popoverBackground};
|
||||
--popover-backdrop-filter: saturate(120%) blur(12px);
|
||||
|
||||
display: grid;
|
||||
|
||||
@@ -87,6 +87,8 @@ export type NotificationDisplayData = {
|
||||
slotTitleLeft?: React.ReactNode;
|
||||
slotTitleRight?: React.ReactNode;
|
||||
|
||||
groupKey: string; // Grouping key toast notification stacking
|
||||
|
||||
// Overrides title/body for Notification in NotificationMenu
|
||||
renderCustomBody?: ({
|
||||
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 { AppTheme } from '@/state/configs';
|
||||
|
||||
import { getAppTheme } from '@/state/configsSelectors';
|
||||
|
||||
import { getWidgetOverrides } from '@/lib/tradingView/utils';
|
||||
@@ -29,7 +28,7 @@ export const useTradingViewTheme = ({
|
||||
tvWidget: (IChartingLibraryWidget & { _id?: string; _ready?: boolean }) | null;
|
||||
isWidgetReady?: boolean;
|
||||
}) => {
|
||||
const appTheme = useSelector(getAppTheme);
|
||||
const appTheme: AppTheme = useSelector(getAppTheme);
|
||||
|
||||
useEffect(() => {
|
||||
if (tvWidget && isWidgetReady) {
|
||||
|
||||
@@ -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 { Icon, IconName } from '@/components/Icon';
|
||||
import { BlockRewardNotification } from '@/views/notifications/BlockRewardNotification';
|
||||
import { TradeNotification } from '@/views/notifications/TradeNotification';
|
||||
import { TransferStatusNotification } from '@/views/notifications/TransferStatusNotification';
|
||||
|
||||
@@ -80,6 +81,7 @@ export const notificationTypes: NotificationTypeConfig[] = [
|
||||
body: abacusNotif.text ? stringGetter({ key: abacusNotif.text, params }) : '',
|
||||
toastDuration: DEFAULT_TOAST_AUTO_CLOSE_MS,
|
||||
toastSensitivity: 'foreground',
|
||||
groupKey: abacusNotificationType,
|
||||
renderCustomBody: ({ isToast, notification }) => (
|
||||
<TradeNotification
|
||||
isToast={isToast}
|
||||
@@ -93,6 +95,29 @@ export const notificationTypes: NotificationTypeConfig[] = [
|
||||
);
|
||||
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:
|
||||
trigger(
|
||||
abacusNotif.id,
|
||||
@@ -102,6 +127,7 @@ export const notificationTypes: NotificationTypeConfig[] = [
|
||||
body: abacusNotif.text ? stringGetter({ key: abacusNotif.text, params }) : '',
|
||||
toastDuration: DEFAULT_TOAST_AUTO_CLOSE_MS,
|
||||
toastSensitivity: 'foreground',
|
||||
groupKey: abacusNotificationType,
|
||||
},
|
||||
[abacusNotif.updateTimeInMilliseconds, abacusNotif.data]
|
||||
);
|
||||
@@ -197,6 +223,7 @@ export const notificationTypes: NotificationTypeConfig[] = [
|
||||
/>
|
||||
),
|
||||
toastSensitivity: 'foreground',
|
||||
groupKey: NotificationType.SquidTransfer,
|
||||
},
|
||||
[isFinished]
|
||||
);
|
||||
@@ -242,6 +269,7 @@ export const notificationTypes: NotificationTypeConfig[] = [
|
||||
},
|
||||
}),
|
||||
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 ProfileIcon } from './profile.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 SendIcon } from './send.svg';
|
||||
export { default as ShareIcon } from './share.svg';
|
||||
|
||||
+50
-43
@@ -1,45 +1,52 @@
|
||||
const LogoShortIcon: React.FC<{ id?: string }> = ({ id }: { id?: string }) => (
|
||||
<svg
|
||||
width="135"
|
||||
height="145"
|
||||
viewBox="0 0 135 145"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path d="M100.986 0L0 144.988H31.0048L132.514 0H100.986Z" fill="white" />
|
||||
<path
|
||||
d="M34.2346 0L63.9475 42.7232L48.4451 66.0268L2.58386 0H34.2346Z"
|
||||
fill={`url(#${id ? `${id}_logo_gradient_0` : 'paint0_linear'})`}
|
||||
/>
|
||||
<path
|
||||
d="M103.995 145L71.0526 97.7455L86.555 75.0893L135 145H103.995Z"
|
||||
fill={`url(#${id ? `${id}_logo_gradient_1` : 'paint1_linear'})`}
|
||||
/>
|
||||
<defs>
|
||||
<linearGradient
|
||||
id={id ? `${id}_logo_gradient_0` : 'paint0_linear'}
|
||||
x1="27.1293"
|
||||
y1="9.0625"
|
||||
x2="69.773"
|
||||
y2="60.4324"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
>
|
||||
<stop stopColor="white" />
|
||||
<stop offset="1" stopColor="white" stopOpacity="0.55" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id={id ? `${id}_logo_gradient_1` : 'paint1_linear'}
|
||||
x1="111.1"
|
||||
y1="133.996"
|
||||
x2="58.6959"
|
||||
y2="63.4999"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
>
|
||||
<stop stopColor="#6966FF" />
|
||||
<stop offset="1" stopColor="#6966FF" stopOpacity="0.36" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
);
|
||||
import { useAppThemeContext } from '@/hooks/useAppTheme';
|
||||
|
||||
const LogoShortIcon: React.FC<{ id?: string }> = ({ id }: { id?: string }) => {
|
||||
const theme = useAppThemeContext();
|
||||
const fill = theme.logoFill;
|
||||
|
||||
return (
|
||||
<svg
|
||||
width="135"
|
||||
height="145"
|
||||
viewBox="0 0 135 145"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path d="M100.986 0L0 144.988H31.0048L132.514 0H100.986Z" fill={fill} />
|
||||
<path
|
||||
d="M34.2346 0L63.9475 42.7232L48.4451 66.0268L2.58386 0H34.2346Z"
|
||||
fill={`url(#${id ? `${id}_logo_gradient_0` : 'paint0_linear'})`}
|
||||
/>
|
||||
<path
|
||||
d="M103.995 145L71.0526 97.7455L86.555 75.0893L135 145H103.995Z"
|
||||
fill={`url(#${id ? `${id}_logo_gradient_1` : 'paint1_linear'})`}
|
||||
/>
|
||||
<defs>
|
||||
<linearGradient
|
||||
id={id ? `${id}_logo_gradient_0` : 'paint0_linear'}
|
||||
x1="27.1293"
|
||||
y1="9.0625"
|
||||
x2="69.773"
|
||||
y2="60.4324"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
>
|
||||
<stop stopColor={fill} />
|
||||
<stop offset="1" stopColor={fill} stopOpacity="0.55" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id={id ? `${id}_logo_gradient_1` : 'paint1_linear'}
|
||||
x1="111.1"
|
||||
y1="133.996"
|
||||
x2="58.6959"
|
||||
y2="63.4999"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
>
|
||||
<stop stopColor="#6966FF" />
|
||||
<stop offset="1" stopColor="#6966FF" stopOpacity="0.36" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
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/text.css';
|
||||
@import 'styles/colors.css';
|
||||
@import 'styles/animations.css';
|
||||
|
||||
:root {
|
||||
|
||||
+34
-59
@@ -1,7 +1,11 @@
|
||||
import { useMemo, useState } from 'react';
|
||||
import { useState } from 'react';
|
||||
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 { useNotifications } from '@/hooks/useNotifications';
|
||||
import { useBreakpoints } from '@/hooks/useBreakpoints';
|
||||
@@ -13,54 +17,31 @@ import { Toast } from '@/components/Toast';
|
||||
import { ToastArea } from '@/components/ToastArea';
|
||||
import { ToggleButton } from '@/components/ToggleButton';
|
||||
|
||||
type ElementProps = {
|
||||
notifications: {
|
||||
notification: Notification<any, any>;
|
||||
key: string;
|
||||
displayData: NotificationDisplayData;
|
||||
}[];
|
||||
};
|
||||
|
||||
type StyleProps = {
|
||||
className?: string;
|
||||
};
|
||||
|
||||
const MAX_TOASTS = 10;
|
||||
|
||||
export const NotificationsToastArea = ({ className }: StyleProps) => {
|
||||
export const NotificationStack = ({ notifications, className }: ElementProps & StyleProps) => {
|
||||
const [shouldStackNotifications, setshouldStackNotifications] = useState(true);
|
||||
|
||||
const {
|
||||
notifications,
|
||||
getKey,
|
||||
getDisplayData,
|
||||
markUnseen,
|
||||
markSeen,
|
||||
isMenuOpen,
|
||||
onNotificationAction,
|
||||
} = useNotifications();
|
||||
|
||||
const { markUnseen, markSeen, onNotificationAction } = useNotifications();
|
||||
const { isMobile } = useBreakpoints();
|
||||
const notificationMap = useMemo(() => {
|
||||
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;
|
||||
const hasMultipleToasts = notifications.length > 1;
|
||||
|
||||
return (
|
||||
<StyledToastArea swipeDirection={isMobile ? 'up' : 'right'} className={className}>
|
||||
<StyledToastArea
|
||||
swipeDirection={isMobile ? 'up' : 'right'}
|
||||
className={className}
|
||||
size={notifications.length}
|
||||
>
|
||||
{hasMultipleToasts && (
|
||||
<StyledToggleButton
|
||||
shape={ButtonShape.Pill}
|
||||
@@ -72,12 +53,12 @@ export const NotificationsToastArea = ({ className }: StyleProps) => {
|
||||
</StyledToggleButton>
|
||||
)}
|
||||
|
||||
{notificationMap.map(({ notification, key, displayData }, idx) => (
|
||||
{notifications.map(({ notification, key, displayData }, idx) => (
|
||||
<StyledToast
|
||||
key={key}
|
||||
isStacked={shouldStackNotifications}
|
||||
isStacked={idx > 0 && shouldStackNotifications}
|
||||
isOpen={notification.status < NotificationStatus.Unseen}
|
||||
layer={notificationMap.length - 1 - idx}
|
||||
layer={idx}
|
||||
notification={notification}
|
||||
slotIcon={displayData.icon}
|
||||
slotTitle={displayData.title}
|
||||
@@ -110,19 +91,13 @@ export const NotificationsToastArea = ({ className }: StyleProps) => {
|
||||
);
|
||||
};
|
||||
|
||||
const StyledToastArea = styled(ToastArea)`
|
||||
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);
|
||||
|
||||
@media ${breakpoints.mobile} {
|
||||
width: 100%;
|
||||
position: fixed;
|
||||
}
|
||||
const StyledToastArea = styled(ToastArea)<{ size: number }>`
|
||||
position: relative;
|
||||
${({ size }) =>
|
||||
size &&
|
||||
css`
|
||||
padding-bottom: calc(${size - 1} * 2px);
|
||||
`}
|
||||
`;
|
||||
|
||||
const StyledToast = styled(Toast)<{ isStacked?: boolean; layer: number }>`
|
||||
@@ -133,7 +108,7 @@ const StyledToast = styled(Toast)<{ isStacked?: boolean; layer: number }>`
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: calc(${layer} * 2px);
|
||||
right: calc(${layer} * -2px);
|
||||
right: 0;
|
||||
`
|
||||
: css`
|
||||
margin-bottom: 0.75rem;
|
||||
@@ -145,7 +120,7 @@ const StyledToggleButton = styled(ToggleButton)<{ isPressed: boolean }>`
|
||||
pointer-events: auto;
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
top: -0.5rem;
|
||||
left: calc(50% - 0.75rem);
|
||||
--button-width: 2rem;
|
||||
--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;
|
||||
}
|
||||
|
||||
get isNobleClientConnected(): boolean {
|
||||
return this.nobleClient?.isConnected ?? false;
|
||||
}
|
||||
|
||||
setStore(store: RootStore): void {
|
||||
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);
|
||||
|
||||
for (const [key, value] of params) {
|
||||
this.queryParams[key] = value;
|
||||
this.queryParams[key.toLowerCase()] = value;
|
||||
}
|
||||
}
|
||||
|
||||
get displayInitializingMarkets() {
|
||||
return !!this.queryParams.displayInitializingMarkets;
|
||||
return !!this.queryParams.displayinitializingmarkets;
|
||||
}
|
||||
|
||||
get withCCTP() {
|
||||
return !!this.queryParams.withCCTP;
|
||||
get showMobileSignInOption() {
|
||||
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 { Colors } from '@/styles/colors';
|
||||
|
||||
import { AppTheme } from '@/state/configs';
|
||||
|
||||
import { Themes } from '@/styles/themes';
|
||||
|
||||
export const mapCandle = ({
|
||||
startedAt,
|
||||
open,
|
||||
@@ -49,42 +47,42 @@ export const getHistorySlice = ({
|
||||
return bars.filter(({ time }) => time >= fromMs);
|
||||
};
|
||||
|
||||
export const getWidgetOverrides = (theme: AppTheme) => {
|
||||
const colors = Colors[theme];
|
||||
export const getWidgetOverrides = (appTheme: AppTheme) => {
|
||||
const theme = Themes[appTheme];
|
||||
|
||||
return {
|
||||
overrides: {
|
||||
'paneProperties.background': Color(colors.layer2).hex(),
|
||||
'paneProperties.horzGridProperties.color': Color(colors.layer3).hex(),
|
||||
'paneProperties.vertGridProperties.color': Color(colors.layer3).hex(),
|
||||
'paneProperties.background': theme.layer2,
|
||||
'paneProperties.horzGridProperties.color': theme.layer3,
|
||||
'paneProperties.vertGridProperties.color': theme.layer3,
|
||||
'paneProperties.crossHairProperties.style': 1,
|
||||
'paneProperties.legendProperties.showBarChange': false,
|
||||
'paneProperties.backgroundType': 'solid',
|
||||
|
||||
'mainSeriesProperties.style': 1,
|
||||
'mainSeriesProperties.candleStyle.upColor': Color(colors.positive).hex(),
|
||||
'mainSeriesProperties.candleStyle.borderUpColor': Color(colors.positive).hex(),
|
||||
'mainSeriesProperties.candleStyle.wickUpColor': Color(colors.positive).hex(),
|
||||
'mainSeriesProperties.candleStyle.downColor': Color(colors.negative).hex(),
|
||||
'mainSeriesProperties.candleStyle.borderDownColor': Color(colors.negative).hex(),
|
||||
'mainSeriesProperties.candleStyle.wickDownColor': Color(colors.negative).hex(),
|
||||
'mainSeriesProperties.candleStyle.upColor': theme.positive,
|
||||
'mainSeriesProperties.candleStyle.borderUpColor': theme.positive,
|
||||
'mainSeriesProperties.candleStyle.wickUpColor': theme.positive,
|
||||
'mainSeriesProperties.candleStyle.downColor': theme.negative,
|
||||
'mainSeriesProperties.candleStyle.borderDownColor': theme.negative,
|
||||
'mainSeriesProperties.candleStyle.wickDownColor': theme.negative,
|
||||
'mainSeriesProperties.statusViewStyle.symbolTextSource': 'ticker',
|
||||
|
||||
'scalesProperties.textColor': Color(colors.text1).hex(),
|
||||
'scalesProperties.backgroundColor': Color(colors.layer2).hex(),
|
||||
'scalesProperties.lineColor': Color(colors.layer3).hex(),
|
||||
'scalesProperties.textColor': theme.textPrimary,
|
||||
'scalesProperties.backgroundColor': theme.layer2,
|
||||
'scalesProperties.lineColor': theme.layer3,
|
||||
},
|
||||
studies_overrides: {
|
||||
'volume.volume.color.0': Color(colors.negative).hex(),
|
||||
'volume.volume.color.1': Color(colors.positive).hex(),
|
||||
'volume.volume.color.0': theme.negative,
|
||||
'volume.volume.color.1': theme.positive,
|
||||
'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.hlines background.color': '#134A9F',
|
||||
},
|
||||
loading_screen: {
|
||||
backgroundColor: Color(colors.layer2).hex(),
|
||||
foregroundColor: Color(colors.layer2).hex(),
|
||||
backgroundColor: theme.layer2,
|
||||
foregroundColor: theme.layer2,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
@@ -259,8 +259,8 @@ Styled.ProfileIcon = styled.div`
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(
|
||||
135deg,
|
||||
var(--theme-classic-color-yellow) 0%,
|
||||
var(--theme-classic-color-red) 100%
|
||||
${({ theme }) => theme.profileYellow} 0%,
|
||||
${({ theme }) => theme.profileRed} 100%
|
||||
);
|
||||
`;
|
||||
|
||||
|
||||
@@ -17,11 +17,14 @@ import { TransferHistoryTable } from '@/views/tables/TransferHistoryTable';
|
||||
import { Button } from '@/components/Button';
|
||||
import { Icon, IconName } from '@/components/Icon';
|
||||
import { NavigationMenu } from '@/components/NavigationMenu';
|
||||
import { Tag, TagType } from '@/components/Tag';
|
||||
import { WithSidebar } from '@/components/WithSidebar';
|
||||
|
||||
import { getOnboardingState, getSubaccount } from '@/state/accountSelectors';
|
||||
import { getOnboardingState, getSubaccount, getTradeInfoNumbers } from '@/state/accountSelectors';
|
||||
import { openDialog } from '@/state/dialogs';
|
||||
|
||||
import { shortenNumberForDisplay } from '@/lib/numbers';
|
||||
|
||||
import { PortfolioNavMobile } from './PortfolioNavMobile';
|
||||
import { LoadingSpace } from '@/components/Loading/LoadingSpinner';
|
||||
|
||||
@@ -42,6 +45,10 @@ export default () => {
|
||||
const { freeCollateral } = useSelector(getSubaccount, shallowEqual) || {};
|
||||
const { nativeTokenBalance } = useAccountBalance();
|
||||
|
||||
const { numTotalPositions, numTotalOpenOrders } = useSelector(getTradeInfoNumbers, shallowEqual) || {};
|
||||
const numPositions = shortenNumberForDisplay(numTotalPositions);
|
||||
const numOrders = shortenNumberForDisplay(numTotalOpenOrders);
|
||||
|
||||
const usdcBalance = freeCollateral?.current || 0;
|
||||
|
||||
useDocumentTitle(stringGetter({ key: STRING_KEYS.PORTFOLIO }));
|
||||
@@ -119,13 +126,27 @@ export default () => {
|
||||
{
|
||||
value: PortfolioRoute.Positions,
|
||||
slotBefore: <Styled.Icon iconName={IconName.Positions} />,
|
||||
label: stringGetter({ key: STRING_KEYS.POSITIONS }),
|
||||
label: (
|
||||
<>
|
||||
{stringGetter({ key: STRING_KEYS.POSITIONS })}
|
||||
{numPositions > 0 && (
|
||||
<Tag type={TagType.Number}> {numPositions} </Tag>
|
||||
)}
|
||||
</>
|
||||
),
|
||||
href: PortfolioRoute.Positions,
|
||||
},
|
||||
{
|
||||
value: PortfolioRoute.Orders,
|
||||
slotBefore: <Styled.Icon iconName={IconName.OrderPending} />,
|
||||
label: stringGetter({ key: STRING_KEYS.ORDERS }),
|
||||
label: (
|
||||
<>
|
||||
{stringGetter({ key: STRING_KEYS.ORDERS })}
|
||||
{numOrders > 0 && (
|
||||
<Tag type={TagType.Number}> {numOrders} </Tag>
|
||||
)}
|
||||
</>
|
||||
),
|
||||
href: PortfolioRoute.Orders,
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import { createSelector } from 'reselect';
|
||||
|
||||
import { SubaccountPosition } from '@/constants/abacus';
|
||||
import { OnboardingState, OnboardingSteps } from '@/constants/account';
|
||||
|
||||
import {
|
||||
getExistingOpenPositions,
|
||||
getOnboardingGuards,
|
||||
getOnboardingState,
|
||||
getSubaccountId,
|
||||
@@ -60,13 +58,8 @@ export const calculateIsAccountViewOnly = createSelector(
|
||||
);
|
||||
|
||||
/**
|
||||
* @description calculate whether the subaccount has open positions
|
||||
* @description calculate whether the subaccount has uncommitted positions
|
||||
*/
|
||||
export const calculateHasOpenPositions = createSelector(
|
||||
[getExistingOpenPositions],
|
||||
(openPositions?: SubaccountPosition[]) => (openPositions?.length || 0) > 0
|
||||
);
|
||||
|
||||
export const calculateHasUncommittedOrders = createSelector(
|
||||
[getUncommittedOrderClientIds],
|
||||
(uncommittedOrderClientIds: number[]) => uncommittedOrderClientIds.length > 0
|
||||
|
||||
@@ -2,6 +2,7 @@ import { OrderSide } from '@dydxprotocol/v4-client-js';
|
||||
import { createSelector } from 'reselect';
|
||||
|
||||
import {
|
||||
type AbacusOrderStatuses,
|
||||
type SubaccountOrder,
|
||||
type SubaccountFill,
|
||||
type SubaccountFundingPayment,
|
||||
@@ -43,7 +44,6 @@ export const getSubaccountBuyingPower = (state: RootState) => state.account.suba
|
||||
export const getSubaccountEquity = (state: RootState) => state.account.subaccount?.equity;
|
||||
|
||||
export const getSubaccountHistoricalPnl = (state: RootState) => state.account?.historicalPnl;
|
||||
|
||||
/**
|
||||
* @param state
|
||||
* @returns list of a subaccount's open positions. Each item in the list is an open position in a different market.
|
||||
@@ -258,6 +258,14 @@ export const getCurrentMarketFundingPayments = createSelector(
|
||||
!currentMarketId ? [] : marketFundingPayments[currentMarketId]
|
||||
);
|
||||
|
||||
/**
|
||||
* @param state
|
||||
* @returns boolean on whether an order status is considered open
|
||||
*/
|
||||
const isOpenOrderStatus = (status: AbacusOrderStatuses) => {
|
||||
return status !== AbacusOrderStatus.filled && status !== AbacusOrderStatus.cancelled;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param state
|
||||
* @returns Total numbers of the subaccount's open positions, open orders and fills
|
||||
@@ -266,8 +274,7 @@ export const getTradeInfoNumbers = createSelector(
|
||||
[getExistingOpenPositions, getSubaccountOrders, getSubaccountFills, getSubaccountFundingPayments],
|
||||
(positions, orders, fills, fundingPayments) => ({
|
||||
numTotalPositions: positions?.length,
|
||||
numTotalOpenOrders: orders?.filter((order) => order.status !== AbacusOrderStatus.cancelled)
|
||||
.length,
|
||||
numTotalOpenOrders: orders?.filter((order) => isOpenOrderStatus(order.status)).length,
|
||||
numTotalFills: fills?.length,
|
||||
numTotalFundingPayments: fundingPayments?.length,
|
||||
})
|
||||
@@ -281,8 +288,7 @@ export const getCurrentMarketTradeInfoNumbers = createSelector(
|
||||
[getCurrentMarketOrders, getCurrentMarketFills, getCurrentMarketFundingPayments],
|
||||
(marketOrders, marketFills, marketFundingPayments) => {
|
||||
return {
|
||||
numOpenOrders: marketOrders?.filter((order) => order.status !== AbacusOrderStatus.cancelled)
|
||||
.length,
|
||||
numOpenOrders: marketOrders?.filter((order) => isOpenOrderStatus(order.status)).length,
|
||||
numFills: marketFills?.length,
|
||||
numFundingPayments: marketFundingPayments?.length,
|
||||
};
|
||||
|
||||
@@ -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-height: var(--form-input-height);
|
||||
--input-width: 100%;
|
||||
--input-backgroundColor: var(--color-layer-4);
|
||||
--input-backgroundColor: ${({ theme }) => theme.inputBackground};
|
||||
--input-borderColor: var(--color-layer-6);
|
||||
|
||||
${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;
|
||||
|
||||
const {
|
||||
basePositionNotional,
|
||||
tickSize,
|
||||
stepSize,
|
||||
initialMarginFraction,
|
||||
|
||||
@@ -235,6 +235,10 @@ export const DepositForm = ({ onDeposit, onError }: DepositFormProps) => {
|
||||
throw new Error('Missing request payload');
|
||||
}
|
||||
|
||||
if (isCctp && !abacusStateManager.chainTransactions.isNobleClientConnected) {
|
||||
throw new Error('Noble RPC endpoint unaccessible');
|
||||
}
|
||||
|
||||
setIsLoading(true);
|
||||
|
||||
await validateTokenApproval();
|
||||
|
||||
@@ -148,6 +148,10 @@ export const WithdrawForm = () => {
|
||||
throw new Error('Invalid request payload');
|
||||
}
|
||||
|
||||
if (isCctp && !abacusStateManager.chainTransactions.isNobleClientConnected) {
|
||||
throw new Error('Noble RPC endpoint unaccessible');
|
||||
}
|
||||
|
||||
setIsLoading(true);
|
||||
setError(undefined);
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ export const WithdrawButtonAndReceipt = ({
|
||||
const stringGetter = useStringGetter();
|
||||
|
||||
const { leverage } = useSelector(getSubaccount, shallowEqual) || {};
|
||||
const { isCctp, summary, requestPayload } = useSelector(getTransferInputs, shallowEqual) || {};
|
||||
const { summary, requestPayload } = useSelector(getTransferInputs, shallowEqual) || {};
|
||||
const canAccountTrade = useSelector(calculateCanAccountTrade, shallowEqual);
|
||||
const { usdcLabel } = useTokenConfigs();
|
||||
|
||||
@@ -85,26 +85,6 @@ export const WithdrawButtonAndReceipt = ({
|
||||
|
||||
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 = [
|
||||
{
|
||||
key: 'total-fees',
|
||||
@@ -153,7 +133,7 @@ export const WithdrawButtonAndReceipt = ({
|
||||
{withdrawToken && <Tag>{withdrawToken?.symbol}</Tag>}
|
||||
</span>
|
||||
),
|
||||
value: <Output type={OutputType.Asset} value={toAmount} fractionDigits={TOKEN_DECIMALS} />,
|
||||
value: <Output type={OutputType.Asset} value={summary?.toAmount} fractionDigits={TOKEN_DECIMALS} />,
|
||||
subitems: [
|
||||
{
|
||||
key: 'minimum-amount-received',
|
||||
@@ -164,7 +144,7 @@ export const WithdrawButtonAndReceipt = ({
|
||||
</span>
|
||||
),
|
||||
value: (
|
||||
<Output type={OutputType.Asset} value={toAmountMin} fractionDigits={TOKEN_DECIMALS} />
|
||||
<Output type={OutputType.Asset} value={summary?.toAmountMin} fractionDigits={TOKEN_DECIMALS} />
|
||||
),
|
||||
tooltip: 'minimum-amount-received',
|
||||
},
|
||||
|
||||
@@ -44,6 +44,7 @@ export const TradeSideToggle = memo(() => {
|
||||
const ToggleContainer = styled(ToggleGroup)<{ value: OrderSide }>`
|
||||
--toggle-radius: 0.5em;
|
||||
--toggle-color: var(--color-negative);
|
||||
--toggle-background: ${({ theme }) => theme.toggleBackground};
|
||||
|
||||
${({ value }) =>
|
||||
value === OrderSide.BUY &&
|
||||
@@ -52,7 +53,7 @@ const ToggleContainer = styled(ToggleGroup)<{ value: OrderSide }>`
|
||||
`}
|
||||
|
||||
border-radius: var(--toggle-radius);
|
||||
background-color: var(--color-layer-4);
|
||||
background-color: var(--toggle-background);
|
||||
position: relative;
|
||||
|
||||
> button {
|
||||
|
||||
@@ -10,6 +10,9 @@ import { STRING_KEYS, StringGetterFunction, TOOLTIP_STRING_KEYS } from '@/consta
|
||||
import { isMainnet } from '@/constants/networks';
|
||||
import { DydxChainAsset, wallets } from '@/constants/wallets';
|
||||
|
||||
import { layoutMixins } from '@/styles/layoutMixins';
|
||||
import { headerMixins } from '@/styles/headerMixins';
|
||||
|
||||
import {
|
||||
useAccounts,
|
||||
useBreakpoints,
|
||||
@@ -35,10 +38,8 @@ import { getOnboardingState, getSubaccount } from '@/state/accountSelectors';
|
||||
|
||||
import { isTruthy } from '@/lib/isTruthy';
|
||||
import { truncateAddress } from '@/lib/wallet';
|
||||
|
||||
import { layoutMixins } from '@/styles/layoutMixins';
|
||||
import { headerMixins } from '@/styles/headerMixins';
|
||||
import { MustBigNumber } from '@/lib/numbers';
|
||||
import { testFlags } from '@/lib/testFlags';
|
||||
|
||||
export const AccountMenu = () => {
|
||||
const stringGetter = useStringGetter();
|
||||
@@ -178,7 +179,7 @@ export const AccountMenu = () => {
|
||||
},
|
||||
...(onboardingState === OnboardingState.AccountConnected && hdKey
|
||||
? [
|
||||
!isMainnet && {
|
||||
(!isMainnet || testFlags.showMobileSignInOption) && {
|
||||
value: 'MobileQrSignIn',
|
||||
icon: <Icon iconName={IconName.Qr} />,
|
||||
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