Skip to content

Commit 0ef16ab

Browse files
committed
feature: swap in real rnbw staking contract and token
1 parent c753916 commit 0ef16ab

File tree

10 files changed

+494
-24
lines changed

10 files changed

+494
-24
lines changed

src/components/text/GradientText.tsx

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,26 @@
1+
import { type TextProps } from '@/design-system/components/Text/Text';
12
import { useTextStyle } from '@/design-system/components/Text/useTextStyle';
23
import MaskedView from '@react-native-masked-view/masked-view';
34
import React, { memo, useMemo } from 'react';
5+
import { StyleSheet, type TextStyle, View } from 'react-native';
46
import { LinearGradient, type LinearGradientProps } from 'expo-linear-gradient';
57

8+
interface TextShadowConfig {
9+
textShadowColor: string;
10+
textShadowOffset?: TextStyle['textShadowOffset'];
11+
textShadowRadius?: number;
12+
}
13+
614
interface GradientTextProps extends LinearGradientProps {
715
bleed?: number;
8-
children: React.ReactElement<any>;
16+
children: React.ReactElement<TextProps>;
17+
shadow?: TextShadowConfig;
918
}
1019

1120
const GradientText = memo(function GradientText({
1221
children,
1322
bleed = 0,
23+
shadow,
1424
start = { x: 0, y: 0.5 },
1525
end = { x: 1, y: 0.5 },
1626
...linearGradientProps
@@ -24,6 +34,7 @@ const GradientText = memo(function GradientText({
2434
weight: children.props.weight,
2535
});
2636

37+
const { marginTop, marginBottom } = textStyle;
2738
textStyle = {
2839
...textStyle,
2940
marginTop: 0,
@@ -42,8 +53,16 @@ const GradientText = memo(function GradientText({
4253
});
4354
}, [children, textStyle]);
4455

45-
return (
46-
<MaskedView style={{ marginTop: textStyle.marginTop, marginBottom: textStyle.marginBottom }} maskElement={visibleChild}>
56+
const shadowChild = useMemo(() => {
57+
if (!shadow) return null;
58+
return React.cloneElement(children, {
59+
color: { custom: 'transparent' },
60+
style: [textStyle, children.props.style, shadow],
61+
});
62+
}, [children, shadow, textStyle]);
63+
64+
const maskedView = (
65+
<MaskedView style={shadow ? undefined : { marginTop, marginBottom }} maskElement={visibleChild}>
4766
<LinearGradient
4867
start={start}
4968
end={end}
@@ -56,6 +75,22 @@ const GradientText = memo(function GradientText({
5675
</LinearGradient>
5776
</MaskedView>
5877
);
78+
79+
if (!shadow) return maskedView;
80+
81+
return (
82+
<View style={{ marginTop, marginBottom }}>
83+
<View style={styles.shadow}>{shadowChild}</View>
84+
{maskedView}
85+
</View>
86+
);
87+
});
88+
89+
const styles = StyleSheet.create({
90+
shadow: {
91+
position: 'absolute',
92+
alignSelf: 'center',
93+
},
5994
});
6095

6196
export default GradientText;
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import { memo } from 'react';
2+
import { Text, useColorMode } from '@/design-system';
3+
import { TIER_VISUALS } from '@/features/rnbw-membership/constants';
4+
import { GradientBorderView } from '@/components/gradient-border/GradientBorderView';
5+
import { InnerShadow } from '@/features/polymarket/components/InnerShadow';
6+
import { LinearGradient } from 'expo-linear-gradient';
7+
import { opacity } from '@/framework/ui/utils/opacity';
8+
import { getValueForColorMode, globalColors } from '@/design-system/color/palettes';
9+
import { StyleSheet, View } from 'react-native';
10+
import type { Tier as TierType } from '@/features/rnbw-membership/types';
11+
import GradientText from '@/components/text/GradientText';
12+
13+
const BORDER_GRADIENT_START = { x: 0, y: 1 };
14+
const BORDER_GRADIENT_END = { x: 0, y: 0 };
15+
16+
export const TierBadge = memo(function TierBadge({ tier }: { tier: TierType }) {
17+
const { colorMode } = useColorMode();
18+
const { badgeGradient, badgeTextGradient, badgeTextShadow, badgeShadow, badgeBorderGradient } = TIER_VISUALS[tier.level];
19+
const {
20+
colors: badgeGradientColors,
21+
locations: badgeGradientLocations,
22+
start: badgeStart = { x: 0, y: 0 },
23+
end: badgeEnd = { x: 0, y: 1 },
24+
} = getValueForColorMode(badgeGradient, colorMode);
25+
const {
26+
colors: badgeTextGradientColors,
27+
locations: badgeTextGradientLocations,
28+
start: badgeTextStart = { x: 0, y: 0 },
29+
end: badgeTextEnd = { x: 0, y: 1 },
30+
} = getValueForColorMode(badgeTextGradient, colorMode);
31+
const {
32+
colors: borderGradientColors,
33+
locations: borderGradientLocations,
34+
start: borderStart = BORDER_GRADIENT_START,
35+
end: borderEnd = BORDER_GRADIENT_END,
36+
} = getValueForColorMode(badgeBorderGradient, colorMode);
37+
const shadowStyle = getValueForColorMode(badgeShadow, colorMode);
38+
const textShadowStyle = getValueForColorMode(badgeTextShadow, colorMode);
39+
40+
return (
41+
<View style={[styles.shadowWrapper, shadowStyle]}>
42+
<GradientBorderView
43+
borderGradientColors={borderGradientColors}
44+
locations={borderGradientLocations}
45+
start={borderStart}
46+
end={borderEnd}
47+
borderWidth={2}
48+
style={styles.tierBadge}
49+
>
50+
<InnerShadow color={opacity(globalColors.white100, 0.1)} blur={1} dx={0} dy={3} />
51+
<LinearGradient
52+
colors={badgeGradientColors}
53+
locations={badgeGradientLocations}
54+
start={badgeStart}
55+
end={badgeEnd}
56+
style={StyleSheet.absoluteFill}
57+
/>
58+
<GradientText
59+
colors={badgeTextGradientColors}
60+
locations={badgeTextGradientLocations}
61+
start={badgeTextStart}
62+
end={badgeTextEnd}
63+
shadow={textShadowStyle}
64+
>
65+
<Text size="22pt" weight="heavy" color="label">
66+
{tier.name.toLocaleUpperCase()}
67+
</Text>
68+
</GradientText>
69+
</GradientBorderView>
70+
</View>
71+
);
72+
});
73+
74+
const styles = StyleSheet.create({
75+
shadowWrapper: {
76+
alignSelf: 'center',
77+
borderRadius: 40,
78+
},
79+
tierBadge: {
80+
height: 42,
81+
paddingHorizontal: 16,
82+
justifyContent: 'center',
83+
alignItems: 'center',
84+
backgroundColor: globalColors.blue60,
85+
borderRadius: 40,
86+
overflow: 'hidden',
87+
},
88+
});
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import type { Tier } from '@/features/rnbw-membership/types';
2+
import { memo } from 'react';
3+
import { useColorMode, type TextProps } from '@/design-system';
4+
import { TIER_VISUALS } from '@/features/rnbw-membership/constants';
5+
import GradientText from '@/components/text/GradientText';
6+
import { getValueForColorMode } from '@/design-system/color/palettes';
7+
8+
const GRADIENT_START = { x: 0, y: 0 };
9+
const GRADIENT_END = { x: 0, y: 1 };
10+
11+
export const TierThemedLabel = memo(function TierThemedLabel({ tier, children }: { tier: Tier; children: React.ReactElement<TextProps> }) {
12+
const { colorMode, isDarkMode } = useColorMode();
13+
14+
if (isDarkMode) return children;
15+
16+
const { textGradient } = TIER_VISUALS[tier.level];
17+
const {
18+
colors: textGradientColors,
19+
locations: textGradientLocations,
20+
start: textGradientStart = GRADIENT_START,
21+
end: textGradientEnd = GRADIENT_END,
22+
} = getValueForColorMode(textGradient, colorMode);
23+
24+
return (
25+
<GradientText colors={textGradientColors} locations={textGradientLocations} start={textGradientStart} end={textGradientEnd}>
26+
{children}
27+
</GradientText>
28+
);
29+
});
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
import { globalColors } from '@/design-system/color/palettes';
2+
import type { Tier, TierId } from '@/features/rnbw-membership/types';
3+
import { opacity } from '@/framework/ui/utils/opacity';
4+
import type { LinearGradientProps } from 'expo-linear-gradient';
5+
6+
type Themed<T> = { light: T; dark: T };
7+
8+
type ShadowConfig = {
9+
shadowColor: string;
10+
shadowOffset: { width: number; height: number };
11+
shadowOpacity: number;
12+
shadowRadius: number;
13+
};
14+
15+
type GradientConfig = {
16+
colors: LinearGradientProps['colors'];
17+
locations?: LinearGradientProps['locations'];
18+
start?: { x: number; y: number };
19+
end?: { x: number; y: number };
20+
};
21+
22+
type TextShadowConfig = {
23+
textShadowColor: string;
24+
textShadowOffset: { width: number; height: number };
25+
textShadowRadius: number;
26+
};
27+
28+
type TierVisuals = {
29+
backgroundGradient: Themed<GradientConfig>;
30+
textGradient: Themed<GradientConfig>;
31+
badgeTextGradient: Themed<GradientConfig>;
32+
badgeGradient: Themed<GradientConfig>;
33+
badgeBorderGradient: Themed<GradientConfig>;
34+
badgeShadow: Themed<ShadowConfig>;
35+
badgeTextShadow: Themed<TextShadowConfig>;
36+
};
37+
38+
export const TIER_VISUALS: Record<TierId, TierVisuals> = {
39+
STAKING_TIER_LEVEL_BASIC: {
40+
backgroundGradient: {
41+
light: { colors: [opacity('#0086FF', 0.4), opacity('#0086FF', 0)] },
42+
dark: { colors: [opacity('#0086FF', 0.16), opacity('#0086FF', 0)] },
43+
},
44+
textGradient: { light: { colors: ['#000000', '#000000'] }, dark: { colors: ['#FFFFFF', '#FFFFFF'] } },
45+
badgeTextGradient: { light: { colors: ['#FFFFFF', '#FFFFFF'] }, dark: { colors: ['#FFFFFF', '#FFFFFF'] } },
46+
badgeGradient: { light: { colors: ['#2B80F4', '#1661C9'] }, dark: { colors: ['#2B80F4', '#1661C9'] } },
47+
badgeBorderGradient: {
48+
light: { colors: [opacity(globalColors.grey100, 0.02), opacity(globalColors.grey100, 0.05)] },
49+
dark: { colors: [opacity(globalColors.grey100, 0.02), opacity(globalColors.grey100, 0.05)] },
50+
},
51+
badgeShadow: {
52+
light: { shadowColor: '#000000', shadowOffset: { width: 0, height: 8 }, shadowOpacity: 0.1, shadowRadius: 9 },
53+
dark: { shadowColor: '#000000', shadowOffset: { width: 0, height: 8 }, shadowOpacity: 0.1, shadowRadius: 9 },
54+
},
55+
badgeTextShadow: {
56+
light: { textShadowColor: 'rgba(0, 0, 0, 0.14)', textShadowOffset: { width: 0, height: 1 }, textShadowRadius: 1 },
57+
dark: { textShadowColor: 'rgba(0, 0, 0, 0.14)', textShadowOffset: { width: 0, height: 1 }, textShadowRadius: 1 },
58+
},
59+
},
60+
STAKING_TIER_LEVEL_SILVER: {
61+
backgroundGradient: {
62+
light: { colors: [opacity('#E6E6E6', 0.4), opacity('#E6E6E6', 0)] },
63+
dark: { colors: [opacity('#CFCFCF', 0.16), opacity('#CFCFCF', 0)] },
64+
},
65+
textGradient: { light: { colors: ['#313131', '#888888'] }, dark: { colors: ['#313131', '#888888'] } },
66+
badgeTextGradient: { light: { colors: ['#313131', '#888888'] }, dark: { colors: ['#111111', '#585858'] } },
67+
badgeGradient: { light: { colors: ['#EFEFEF', '#CDCDCD'] }, dark: { colors: ['#D6D6D6', '#828282'] } },
68+
badgeBorderGradient: {
69+
light: { colors: [opacity(globalColors.grey100, 0.02), opacity(globalColors.grey100, 0.05)] },
70+
dark: { colors: [opacity(globalColors.grey100, 0.02), opacity(globalColors.grey100, 0.05)] },
71+
},
72+
badgeShadow: {
73+
light: { shadowColor: '#000000', shadowOffset: { width: 0, height: 4 }, shadowOpacity: 0.06, shadowRadius: 6 },
74+
dark: { shadowColor: '#B2B2B2', shadowOffset: { width: 0, height: 0 }, shadowOpacity: 0.3, shadowRadius: 15 },
75+
},
76+
badgeTextShadow: {
77+
light: { textShadowColor: 'rgba(255, 255, 255, 0.46)', textShadowOffset: { width: 1, height: 1 }, textShadowRadius: 0 },
78+
dark: { textShadowColor: 'rgba(255, 255, 255, 0.46)', textShadowOffset: { width: 1, height: 1 }, textShadowRadius: 0 },
79+
},
80+
},
81+
STAKING_TIER_LEVEL_GOLD: {
82+
backgroundGradient: {
83+
light: { colors: [opacity('#FADB71', 0.4), opacity('#FADB71', 0)] },
84+
dark: { colors: [opacity('#FADB71', 0.16), opacity('#FADB71', 0)] },
85+
},
86+
textGradient: { light: { colors: ['#4F3605', '#90630E'] }, dark: { colors: ['#4F3605', '#90630E'] } },
87+
badgeTextGradient: { light: { colors: ['#4F3605', '#90630E'] }, dark: { colors: ['#4F3605', '#90630E'] } },
88+
badgeGradient: { light: { colors: ['#FFE380', '#E3A700'] }, dark: { colors: ['#FFE380', '#E3A700'] } },
89+
badgeBorderGradient: {
90+
light: { colors: [opacity(globalColors.grey100, 0.02), opacity(globalColors.grey100, 0.05)] },
91+
dark: { colors: [opacity(globalColors.grey100, 0.02), opacity(globalColors.grey100, 0.05)] },
92+
},
93+
badgeShadow: {
94+
light: { shadowColor: '#000000', shadowOffset: { width: 0, height: 4 }, shadowOpacity: 0.06, shadowRadius: 6 },
95+
dark: { shadowColor: '#FFDD20', shadowOffset: { width: 0, height: 0 }, shadowOpacity: 0.3, shadowRadius: 15 },
96+
},
97+
badgeTextShadow: {
98+
light: { textShadowColor: 'rgba(255, 255, 255, 0.26)', textShadowOffset: { width: 1, height: 1 }, textShadowRadius: 0 },
99+
dark: { textShadowColor: 'rgba(255, 255, 255, 0.26)', textShadowOffset: { width: 1, height: 1 }, textShadowRadius: 0 },
100+
},
101+
},
102+
STAKING_TIER_LEVEL_DIAMOND: {
103+
backgroundGradient: {
104+
light: { colors: [opacity('#D1E9F0', 0.4), opacity('#D1E9F0', 0)] },
105+
dark: { colors: [opacity('#42D2EB', 0.16), opacity('#42D2EB', 0)] },
106+
},
107+
textGradient: { light: { colors: ['#424749', '#7CADB4'] }, dark: { colors: ['#424749', '#7CADB4'] } },
108+
badgeTextGradient: { light: { colors: ['#424749', '#7CADB4'] }, dark: { colors: ['#314145', '#1D5D67'] } },
109+
badgeGradient: { light: { colors: ['#ECF2F8', '#C8D1D7'] }, dark: { colors: ['#D5DCE3', '#9AA7B0'] } },
110+
badgeBorderGradient: {
111+
light: { colors: [opacity(globalColors.grey100, 0.02), opacity(globalColors.grey100, 0.05)] },
112+
dark: { colors: [opacity(globalColors.grey100, 0.02), opacity(globalColors.grey100, 0.05)] },
113+
},
114+
badgeShadow: {
115+
light: { shadowColor: '#000000', shadowOffset: { width: 0, height: 4 }, shadowOpacity: 0.06, shadowRadius: 6 },
116+
dark: { shadowColor: '#42D2EB', shadowOffset: { width: 0, height: 0 }, shadowOpacity: 0.3, shadowRadius: 15 },
117+
},
118+
badgeTextShadow: {
119+
light: { textShadowColor: opacity('#CBF6FF', 0.46), textShadowOffset: { width: 1, height: 1 }, textShadowRadius: 0 },
120+
dark: { textShadowColor: opacity('#CBF6FF', 0.46), textShadowOffset: { width: 1, height: 1 }, textShadowRadius: 0 },
121+
},
122+
},
123+
STAKING_TIER_LEVEL_BLACK: {
124+
backgroundGradient: {
125+
light: { colors: [opacity('#FFFFFF', 0), opacity('#FFFFFF', 0)] },
126+
dark: { colors: [opacity('#FFFFFF', 0), opacity('#FFFFFF', 0)] },
127+
},
128+
textGradient: { light: { colors: ['#000000', '#000000'] }, dark: { colors: ['#FFFFFF', '#FFFFFF'] } },
129+
badgeTextGradient: { light: { colors: ['#FFFFFF', '#FFFFFF'] }, dark: { colors: ['#FFFFFF', '#FFFFFF'] } },
130+
badgeGradient: {
131+
light: { colors: ['#444444', '#000000'] },
132+
dark: { colors: ['#444444', '#000000'] },
133+
},
134+
badgeBorderGradient: {
135+
light: { colors: [opacity(globalColors.grey100, 0.02), opacity(globalColors.grey100, 0.05)] },
136+
dark: { colors: [opacity(globalColors.grey100, 0.02), opacity(globalColors.grey100, 0.05)] },
137+
},
138+
badgeShadow: {
139+
light: { shadowColor: '#000000', shadowOffset: { width: 0, height: 4 }, shadowOpacity: 0.06, shadowRadius: 6 },
140+
dark: { shadowColor: '#1A1C22', shadowOffset: { width: 0, height: 4 }, shadowOpacity: 0.3, shadowRadius: 8 },
141+
},
142+
badgeTextShadow: {
143+
light: { textShadowColor: 'rgba(0, 0, 0, 0)', textShadowOffset: { width: 0, height: 0 }, textShadowRadius: 0 },
144+
dark: { textShadowColor: 'rgba(0, 0, 0, 0)', textShadowOffset: { width: 0, height: 0 }, textShadowRadius: 0 },
145+
},
146+
},
147+
};
148+
149+
export const FALLBACK_TIERS: Tier[] = [
150+
{
151+
level: 'STAKING_TIER_LEVEL_BASIC',
152+
name: 'Basic',
153+
minStakeAmount: '0',
154+
cashbackBps: 1000,
155+
},
156+
{
157+
level: 'STAKING_TIER_LEVEL_SILVER',
158+
name: 'Silver',
159+
minStakeAmount: '5000000000000000000000',
160+
cashbackBps: 2500,
161+
},
162+
{
163+
level: 'STAKING_TIER_LEVEL_GOLD',
164+
name: 'Gold',
165+
minStakeAmount: '10000000000000000000000',
166+
cashbackBps: 5000,
167+
},
168+
{
169+
level: 'STAKING_TIER_LEVEL_DIAMOND',
170+
name: 'Diamond',
171+
minStakeAmount: '15000000000000000000000',
172+
cashbackBps: 7500,
173+
},
174+
{
175+
level: 'STAKING_TIER_LEVEL_BLACK',
176+
name: 'Black',
177+
minStakeAmount: '20000000000000000000000',
178+
cashbackBps: 10000,
179+
},
180+
];

0 commit comments

Comments
 (0)