diff --git a/packages/core-mobile/AppSwitcher.tsx b/packages/core-mobile/AppSwitcher.tsx
index 9d507a8e16..80efff3861 100644
--- a/packages/core-mobile/AppSwitcher.tsx
+++ b/packages/core-mobile/AppSwitcher.tsx
@@ -12,6 +12,8 @@ const isInternalBuild =
bundleId === 'org.avalabs.avaxwallet.internal' ||
bundleId === 'com.avaxwallet.internal'
+const APP_SWITCH_NUMBER_OF_TOUCHES = 2
+
export const AppSwitcher = (): React.JSX.Element => {
const [isNewApp, setIsNewApp] = useState(
commonStorage.getBoolean(StorageKey.K2_ALPINE)
@@ -27,7 +29,14 @@ export const AppSwitcher = (): React.JSX.Element => {
() =>
PanResponder.create({
onStartShouldSetPanResponder: (evt, gestureState) => {
- if (gestureState.numberActiveTouches === 2) {
+ return (
+ gestureState.numberActiveTouches === APP_SWITCH_NUMBER_OF_TOUCHES
+ )
+ },
+ onPanResponderGrant: (evt, gestureState) => {
+ if (
+ gestureState.numberActiveTouches === APP_SWITCH_NUMBER_OF_TOUCHES
+ ) {
Alert.alert('Switch App Experience?', '', [
{
text: 'Cancel',
@@ -44,7 +53,7 @@ export const AppSwitcher = (): React.JSX.Element => {
)
// only allow switching to new app on internal builds
- if (!isInternalBuild) return
+ if (!isInternalBuild && !__DEV__) return
return (
diff --git a/packages/core-mobile/app/new/components/BlurBackgroundView.tsx b/packages/core-mobile/app/new/components/BlurBackgroundView.tsx
deleted file mode 100644
index 673d028a6d..0000000000
--- a/packages/core-mobile/app/new/components/BlurBackgroundView.tsx
+++ /dev/null
@@ -1,19 +0,0 @@
-import { BlurView } from '@react-native-community/blur'
-import React from 'react'
-import { View, Sx } from '@avalabs/k2-alpine'
-import { useColorScheme } from 'react-native'
-
-const BlurBackgroundView = ({ sx }: { sx: Sx }): JSX.Element => {
- const colorScheme = useColorScheme()
-
- return (
-
-
-
- )
-}
-
-export default BlurBackgroundView
diff --git a/packages/core-mobile/app/new/components/navigation/BackBarButton.tsx b/packages/core-mobile/app/new/components/navigation/BackBarButton.tsx
index d6b2695ecd..fdf61c6337 100644
--- a/packages/core-mobile/app/new/components/navigation/BackBarButton.tsx
+++ b/packages/core-mobile/app/new/components/navigation/BackBarButton.tsx
@@ -1,11 +1,15 @@
import React from 'react'
-import { View, Text } from '@avalabs/k2-alpine'
+import { Icons, View, useTheme } from '@avalabs/k2-alpine'
const BackBarButton = (): JSX.Element => {
+ const { theme } = useTheme()
+
return (
- // todo: use k2-alpine icon
-
- {'<<'}
+
+ {/* todo: please remove the ts-expect-error comments after we address this issue
+ https://ava-labs.atlassian.net/browse/CP-9297
+ @ts-expect-error */}
+
)
}
diff --git a/packages/core-mobile/app/new/components/navigation/BlurredBackgroundView.tsx b/packages/core-mobile/app/new/components/navigation/BlurredBackgroundView.tsx
new file mode 100644
index 0000000000..81c171faa0
--- /dev/null
+++ b/packages/core-mobile/app/new/components/navigation/BlurredBackgroundView.tsx
@@ -0,0 +1,16 @@
+import React from 'react'
+import { useColorScheme } from 'react-native'
+import { GlassView } from '@avalabs/k2-alpine'
+
+const BlurredBackgroundView = (): JSX.Element => {
+ const colorScheme = useColorScheme()
+
+ return (
+
+ )
+}
+
+export default BlurredBackgroundView
diff --git a/packages/core-mobile/app/new/components/navigation/HeaderBackground.tsx b/packages/core-mobile/app/new/components/navigation/HeaderBackground.tsx
deleted file mode 100644
index 2080ef92ef..0000000000
--- a/packages/core-mobile/app/new/components/navigation/HeaderBackground.tsx
+++ /dev/null
@@ -1,20 +0,0 @@
-import React from 'react'
-import { useSafeAreaInsets } from 'react-native-safe-area-context'
-import { Platform } from 'react-native'
-import BlurBackgroundView from '../BlurBackgroundView'
-
-const HeaderBackground = (): JSX.Element => {
- const { top } = useSafeAreaInsets()
-
- return (
-
- )
-}
-
-const HEADER_HEIGHT = Platform.OS === 'ios' ? 44 : 56
-
-export default HeaderBackground
diff --git a/packages/core-mobile/app/new/components/navigation/TabBarBackground.tsx b/packages/core-mobile/app/new/components/navigation/TabBarBackground.tsx
deleted file mode 100644
index cdff01f23a..0000000000
--- a/packages/core-mobile/app/new/components/navigation/TabBarBackground.tsx
+++ /dev/null
@@ -1,20 +0,0 @@
-import React from 'react'
-import { useSafeAreaInsets } from 'react-native-safe-area-context'
-import { Platform } from 'react-native'
-import BlurBackgroundView from '../BlurBackgroundView'
-
-const TabBarBackground = (): JSX.Element => {
- const { bottom } = useSafeAreaInsets()
-
- return (
-
- )
-}
-
-const BOTTOM_TAB_BAR_HEIGHT = Platform.OS === 'ios' ? 45 : 50
-
-export default TabBarBackground
diff --git a/packages/core-mobile/app/new/routes/(signedIn)/(modals)/settings/account.tsx b/packages/core-mobile/app/new/routes/(signedIn)/(modals)/settings/account.tsx
index 4374b63b3a..48f4bab4a7 100644
--- a/packages/core-mobile/app/new/routes/(signedIn)/(modals)/settings/account.tsx
+++ b/packages/core-mobile/app/new/routes/(signedIn)/(modals)/settings/account.tsx
@@ -1,14 +1,16 @@
import { Link } from 'expo-router'
import React from 'react'
-import { View, Text } from '@avalabs/k2-alpine'
+import { View, Text, Button } from '@avalabs/k2-alpine'
const AccountScreen = (): JSX.Element => {
return (
Account Settings
-
- Delete Wallet
+
+
)
diff --git a/packages/core-mobile/app/new/routes/(signedIn)/(modals)/settings/index.tsx b/packages/core-mobile/app/new/routes/(signedIn)/(modals)/settings/index.tsx
index 712fe45bc6..5eb91244ba 100644
--- a/packages/core-mobile/app/new/routes/(signedIn)/(modals)/settings/index.tsx
+++ b/packages/core-mobile/app/new/routes/(signedIn)/(modals)/settings/index.tsx
@@ -1,5 +1,5 @@
import React from 'react'
-import { Text, View } from '@avalabs/k2-alpine'
+import { Button, Text, View } from '@avalabs/k2-alpine'
import { Link } from 'expo-router'
const SettingsScreen = (): JSX.Element => {
@@ -12,8 +12,10 @@ const SettingsScreen = (): JSX.Element => {
gap: 16
}}>
Settings
-
- Go to Account Setting
+
+
)
diff --git a/packages/core-mobile/app/new/routes/(signedIn)/(tabs)/_layout.tsx b/packages/core-mobile/app/new/routes/(signedIn)/(tabs)/_layout.tsx
index e3e1f5cd70..c48e169759 100644
--- a/packages/core-mobile/app/new/routes/(signedIn)/(tabs)/_layout.tsx
+++ b/packages/core-mobile/app/new/routes/(signedIn)/(tabs)/_layout.tsx
@@ -1,9 +1,9 @@
-import TabBarBackground from 'new/components/navigation/TabBarBackground'
import { Tabs } from 'expo-router'
import React, { useCallback } from 'react'
+import BlurredBackgroundView from 'new/components/navigation/BlurredBackgroundView'
export default function TabLayout(): JSX.Element {
- const tabBarBackground = useCallback(() => , [])
+ const tabBarBackground = useCallback(() => , [])
return (
{
paddingTop: 16,
paddingBottom: 16,
alignItems: 'center',
+ paddingHorizontal: 16,
gap: 16
}}>
Portfolio
-
- Go to Portfolio Assets
+
+
-
+
diff --git a/packages/core-mobile/app/new/routes/index.tsx b/packages/core-mobile/app/new/routes/index.tsx
index 312695bfc8..d60c84e459 100644
--- a/packages/core-mobile/app/new/routes/index.tsx
+++ b/packages/core-mobile/app/new/routes/index.tsx
@@ -1,5 +1,5 @@
import { Link } from 'expo-router'
-import { View, Text } from '@avalabs/k2-alpine'
+import { View, Button } from '@avalabs/k2-alpine'
import React from 'react'
export default function Index(): JSX.Element {
@@ -11,11 +11,15 @@ export default function Index(): JSX.Element {
justifyContent: 'center',
gap: 16
}}>
-
- Sign in
+
+
-
- Sign up
+
+
)
diff --git a/packages/core-mobile/app/new/routes/signup/index.tsx b/packages/core-mobile/app/new/routes/signup/index.tsx
index f429fbc486..8b6bc424e5 100644
--- a/packages/core-mobile/app/new/routes/signup/index.tsx
+++ b/packages/core-mobile/app/new/routes/signup/index.tsx
@@ -1,11 +1,16 @@
import { Link } from 'expo-router'
import { View } from 'react-native'
import React from 'react'
+import { Button } from '@avalabs/k2-alpine'
const SignUpScreen = (): JSX.Element => {
return (
- Sign up
+
+
+
)
}
diff --git a/packages/core-mobile/app/new/utils/navigation/screenOptions.tsx b/packages/core-mobile/app/new/utils/navigation/screenOptions.tsx
index 0c4dadd4c8..89c05dea8e 100644
--- a/packages/core-mobile/app/new/utils/navigation/screenOptions.tsx
+++ b/packages/core-mobile/app/new/utils/navigation/screenOptions.tsx
@@ -8,7 +8,7 @@ import {
import { Animated } from 'react-native'
import Grabber from 'new/components/navigation/Grabber'
import BackBarButton from 'new/components/navigation/BackBarButton'
-import HeaderBackground from 'new/components/navigation/HeaderBackground'
+import BlurredBackgroundView from 'new/components/navigation/BlurredBackgroundView'
import { Text, View } from '@avalabs/k2-alpine'
import { Link } from 'expo-router'
@@ -24,7 +24,7 @@ const commonNavigatorScreenOptions: StackNavigationOptions = {
export const stackNavigatorScreenOptions: StackNavigationOptions = {
...commonNavigatorScreenOptions,
headerTransparent: true,
- headerBackground: () =>
+ headerBackground: () =>
}
export const modalStackNavigatorScreenOptions: StackNavigationOptions = {
diff --git a/packages/core-mobile/ios/Podfile.lock b/packages/core-mobile/ios/Podfile.lock
index c8c8414dbc..7829490f52 100644
--- a/packages/core-mobile/ios/Podfile.lock
+++ b/packages/core-mobile/ios/Podfile.lock
@@ -45,6 +45,8 @@ PODS:
- ExpoModulesCore
- GoogleSignIn (~> 7.1)
- React-Core
+ - ExpoBlur (12.9.2):
+ - ExpoModulesCore
- ExpoFileSystem (16.0.9):
- ExpoModulesCore
- ExpoHead (3.4.10):
@@ -1352,6 +1354,7 @@ DEPENDENCIES:
- EXFont (from `../node_modules/expo-font/ios`)
- Expo (from `../node_modules/expo`)
- "ExpoAdapterGoogleSignIn (from `../node_modules/@react-native-google-signin/google-signin/expo/ios`)"
+ - ExpoBlur (from `../node_modules/expo-blur/ios`)
- ExpoFileSystem (from `../node_modules/expo-file-system/ios`)
- ExpoHead (from `../node_modules/expo-router/ios`)
- ExpoKeepAwake (from `../node_modules/expo-keep-awake/ios`)
@@ -1511,6 +1514,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/expo"
ExpoAdapterGoogleSignIn:
:path: "../node_modules/@react-native-google-signin/google-signin/expo/ios"
+ ExpoBlur:
+ :path: "../node_modules/expo-blur/ios"
ExpoFileSystem:
:path: "../node_modules/expo-file-system/ios"
ExpoHead:
@@ -1730,6 +1735,7 @@ SPEC CHECKSUMS:
EXFont: f20669cb266ef48b004f1eb1f2b20db96cd1df9f
Expo: 7b9976a9b2be116a701b233d6655b229a3c9316e
ExpoAdapterGoogleSignIn: da10ae7e7c1d73a10c2facebcdfe5ebea8e073ce
+ ExpoBlur: e832d874bd94afc0645daddbd3162ec1ce172080
ExpoFileSystem: 74cc0fae916f9f044248433971dcfc8c3befd057
ExpoHead: 89ffd324e60520751c2c285233fe45e875c91874
ExpoKeepAwake: 0f5cad99603a3268e50af9a6eb8b76d0d9ac956c
diff --git a/packages/core-mobile/package.json b/packages/core-mobile/package.json
index 99b493741c..b3d2fafe51 100644
--- a/packages/core-mobile/package.json
+++ b/packages/core-mobile/package.json
@@ -104,6 +104,7 @@
"ethers": "6.8.1",
"events": "3.3.0",
"expo": "50.0.21",
+ "expo-blur": "12.9.2",
"expo-constants": "15.4.6",
"expo-linking": "6.2.2",
"expo-router": "3.4.10",
diff --git a/packages/k2-alpine/declarations.d.ts b/packages/k2-alpine/declarations.d.ts
new file mode 100644
index 0000000000..d2ecf6ad63
--- /dev/null
+++ b/packages/k2-alpine/declarations.d.ts
@@ -0,0 +1,6 @@
+declare module '*.svg' {
+ import React from 'react'
+ import { SvgProps } from 'react-native-svg'
+ const content: React.FC
+ export default content
+}
diff --git a/packages/k2-alpine/metro.config.js b/packages/k2-alpine/metro.config.js
new file mode 100644
index 0000000000..33e369e7b9
--- /dev/null
+++ b/packages/k2-alpine/metro.config.js
@@ -0,0 +1,15 @@
+const { getDefaultConfig } = require('expo/metro-config')
+
+module.exports = (() => {
+ const config = getDefaultConfig(__dirname)
+
+ config.transformer.babelTransformerPath = require.resolve(
+ 'react-native-svg-transformer'
+ )
+ config.resolver.assetExts = config.resolver.assetExts.filter(
+ ext => ext !== 'svg'
+ )
+ config.resolver.sourceExts = [...config.resolver.sourceExts, 'svg']
+
+ return config
+})()
diff --git a/packages/k2-alpine/package.json b/packages/k2-alpine/package.json
index 95128e48e5..a27fef987d 100644
--- a/packages/k2-alpine/package.json
+++ b/packages/k2-alpine/package.json
@@ -19,12 +19,15 @@
"dependencies": {
"dripsy": "4.3.7",
"expo": "50.0.21",
+ "expo-blur": "12.9.2",
"expo-font": "11.10.3",
+ "expo-linear-gradient": "12.7.2",
"expo-splash-screen": "0.27.6",
"expo-status-bar": "1.12.1",
"react": "18.3.1",
"react-native": "0.73.7",
- "react-native-reanimated": "3.8.0"
+ "react-native-reanimated": "3.8.0",
+ "react-native-svg": "15.7.1"
},
"peerDependencies": {
"react": "18.3.1",
@@ -52,6 +55,7 @@
"patch-package": "8.0.0",
"react-dom": "18.3.1",
"react-native-safe-area-context": "4.11.0",
+ "react-native-svg-transformer": "1.5.0",
"tinycolor2": "1.6.0",
"typescript": "5.6.3"
},
diff --git a/packages/k2-alpine/src/assets/icons/back_arrow_custom.svg b/packages/k2-alpine/src/assets/icons/back_arrow_custom.svg
new file mode 100644
index 0000000000..e5fe9c2601
--- /dev/null
+++ b/packages/k2-alpine/src/assets/icons/back_arrow_custom.svg
@@ -0,0 +1,11 @@
+
diff --git a/packages/k2-alpine/src/assets/icons/check.svg b/packages/k2-alpine/src/assets/icons/check.svg
new file mode 100644
index 0000000000..91782936d7
--- /dev/null
+++ b/packages/k2-alpine/src/assets/icons/check.svg
@@ -0,0 +1,3 @@
+
diff --git a/packages/k2-alpine/src/assets/icons/expand_more.svg b/packages/k2-alpine/src/assets/icons/expand_more.svg
new file mode 100644
index 0000000000..7892f4ebab
--- /dev/null
+++ b/packages/k2-alpine/src/assets/icons/expand_more.svg
@@ -0,0 +1,3 @@
+
diff --git a/packages/k2-alpine/src/components/Button/Button.stories.tsx b/packages/k2-alpine/src/components/Button/Button.stories.tsx
new file mode 100644
index 0000000000..19bc34a00c
--- /dev/null
+++ b/packages/k2-alpine/src/components/Button/Button.stories.tsx
@@ -0,0 +1,138 @@
+import React, { FC, PropsWithChildren, useState } from 'react'
+import { StyleSheet, Switch } from 'react-native'
+import { LinearGradient } from 'expo-linear-gradient'
+import { ScrollView, Text, View } from '../Primitives'
+import Link from '../../utils/Link'
+import { useTheme } from '../..'
+import { Button, ButtonSize, ButtonType } from './Button'
+
+export default {
+ title: 'Button'
+}
+
+export const All = (): JSX.Element => {
+ const types: ButtonType[] = ['primary', 'secondary', 'tertiary']
+ const sizes: ButtonSize[] = ['large', 'medium', 'small']
+ const [isBlurTesting, setIsBlurTesting] = useState(false)
+ const { theme } = useTheme()
+
+ const renderRow = (type: ButtonType, disabled?: boolean): JSX.Element => {
+ return (
+
+ {sizes.map((size, index) => (
+
+ ))}
+
+ )
+ }
+
+ const BackgroundComponent = isBlurTesting ? BackgroundForBlur : View
+
+ return (
+
+
+
+
+
+ Blur Test
+
+
+
+ {types.map((type, index) => (
+
+ {renderRow(type)}
+
+ ))}
+ {renderRow('primary', true)}
+
+ {types.map((type, index) => (
+
+ ))}
+
+
+
+
+ )
+}
+
+const BackgroundForBlur: FC = ({ children }) => (
+
+ {children}
+
+)
+
+const styles = StyleSheet.create({
+ row: {
+ alignItems: 'flex-start',
+ flexDirection: 'row'
+ }
+})
+
+const FIGMA_LINK =
+ 'https://www.figma.com/design/opZ4C1UGzcoGRjxE4ZIE3J/K2-Alpine?node-id=7-1465&m=dev'
diff --git a/packages/k2-alpine/src/components/Button/Button.tsx b/packages/k2-alpine/src/components/Button/Button.tsx
new file mode 100644
index 0000000000..24f0a82e0f
--- /dev/null
+++ b/packages/k2-alpine/src/components/Button/Button.tsx
@@ -0,0 +1,237 @@
+import React, { forwardRef, PropsWithChildren, useMemo } from 'react'
+import {
+ Platform,
+ StyleProp,
+ StyleSheet,
+ TouchableOpacity,
+ ViewStyle
+} from 'react-native'
+import { useDripsyTheme as useTheme } from 'dripsy'
+import { Text, View } from '../Primitives'
+import { Icons } from '../../theme/tokens/Icons'
+import { darkModeColors, lightModeColors } from '../../theme/tokens/colors'
+import { TextVariant } from '../../theme/tokens/text'
+import { GlassView } from '../../components/GlassView/GlassView'
+import { alpha, overlayColor } from '../../utils/colors'
+import { K2AlpineTheme } from '../../theme/theme'
+
+export type ButtonType = 'primary' | 'secondary' | 'tertiary'
+export type ButtonSize = 'small' | 'medium' | 'large'
+
+type ButtonIconType = 'check' | 'expandMore'
+
+interface ButtonProps {
+ onPress?: () => void
+ disabled?: boolean
+ style?: StyleProp
+ testID?: string
+ type: ButtonType
+ size: ButtonSize
+ leftIcon?: ButtonIconType
+ rightIcon?: ButtonIconType
+}
+
+export const Button = forwardRef<
+ TouchableOpacity,
+ ButtonProps & PropsWithChildren
+>(
+ (
+ {
+ type,
+ size,
+ leftIcon,
+ rightIcon,
+ disabled,
+ style,
+ children,
+ testID,
+ ...rest
+ },
+ ref
+ ) => {
+ const { theme } = useTheme()
+
+ const tintColor = useMemo(
+ // todo: please remove the ts-ignore comments after we address this issue
+ // https://ava-labs.atlassian.net/browse/CP-9297
+ // @ts-ignore
+ () => getTintColor(type, theme, disabled),
+ [disabled, type, theme]
+ )
+
+ const backgroundColor = useMemo(
+ // todo: please remove the ts-ignore comments after we address this issue
+ // https://ava-labs.atlassian.net/browse/CP-9297
+ // @ts-ignore
+ () => getBackgroundColor(type, theme, disabled),
+ [type, theme, disabled]
+ )
+
+ const iconWidth = { large: 20, medium: 16, small: 16 }[size]
+ const textVariant = {
+ large: 'buttonMedium',
+ medium: 'buttonMedium',
+ small: 'buttonSmall'
+ }[size] as TextVariant
+
+ const shouldUseBlurWrapper = type === 'secondary' && !disabled
+ const WrapperComponent = shouldUseBlurWrapper ? GlassView : View
+
+ return (
+
+
+
+
+ {leftIcon ? (
+ getIcon(leftIcon, {
+ width: iconWidth,
+ height: iconWidth,
+ color: tintColor,
+ style: { marginRight: 8 }
+ })
+ ) : rightIcon ? (
+
+ ) : null}
+
+ {children}
+
+ {rightIcon ? (
+ getIcon(rightIcon, {
+ width: iconWidth,
+ height: iconWidth,
+ color: tintColor,
+ style: { marginLeft: 8 }
+ })
+ ) : leftIcon ? (
+
+ ) : null}
+
+
+
+
+ )
+ }
+)
+
+const sizeStyles = StyleSheet.create({
+ large: {
+ paddingHorizontal: 12,
+ minHeight: 42
+ },
+ medium: {
+ paddingHorizontal: 12,
+ minHeight: 36
+ },
+ small: {
+ paddingHorizontal: 8,
+ minHeight: 27
+ }
+})
+
+const iconComponents = {
+ check: Icons.Navigation.Check,
+ expandMore: Icons.Navigation.ExpandMore
+}
+
+const getIcon = (
+ type: ButtonIconType,
+ iconProps: {
+ width: number
+ height: number
+ color: string
+ style?: ViewStyle
+ }
+): JSX.Element | undefined => {
+ const IconComponent = iconComponents[type]
+ return
+}
+
+const getBackgroundColor = (
+ type: ButtonType,
+ theme: K2AlpineTheme,
+ disabled: boolean | undefined
+): string | undefined => {
+ if (disabled) {
+ return theme.isDark
+ ? overlayColor(
+ alpha(lightModeColors.$surfacePrimary, 0.3),
+ darkModeColors.$surfacePrimary
+ )
+ : overlayColor(
+ alpha(darkModeColors.$surfaceSecondary, 0.3),
+ lightModeColors.$surfacePrimary
+ )
+ }
+
+ switch (type) {
+ case 'primary':
+ return theme.isDark
+ ? lightModeColors.$surfacePrimary
+ : darkModeColors.$surfacePrimary
+ case 'secondary':
+ return undefined
+ case 'tertiary':
+ return theme.colors.$surfacePrimary
+ }
+}
+
+const getTintColor = (
+ type: ButtonType,
+ theme: K2AlpineTheme,
+ disabled: boolean | undefined
+): string => {
+ if (disabled) {
+ return theme.isDark
+ ? lightModeColors.$textPrimary
+ : darkModeColors.$textPrimary
+ }
+ switch (type) {
+ case 'primary':
+ return theme.isDark
+ ? lightModeColors.$textPrimary
+ : darkModeColors.$textPrimary
+ case 'secondary':
+ case 'tertiary':
+ return theme.colors.$textPrimary
+ }
+}
+
+Button.displayName = 'Button'
diff --git a/packages/k2-alpine/src/components/GlassView/GlassView.tsx b/packages/k2-alpine/src/components/GlassView/GlassView.tsx
new file mode 100644
index 0000000000..5fc2ec2cb1
--- /dev/null
+++ b/packages/k2-alpine/src/components/GlassView/GlassView.tsx
@@ -0,0 +1,55 @@
+import { BlurView } from 'expo-blur'
+import React, { FC, PropsWithChildren, useMemo } from 'react'
+import { ViewStyle } from 'react-native'
+import { alpha } from '../../utils'
+
+export type GlassType = 'light' | 'light2' | 'dark' | 'dark2' | 'dark3'
+
+export const GlassView: FC<
+ {
+ style?: ViewStyle
+ glassType?: GlassType
+ } & PropsWithChildren
+> = ({ style, glassType, children }): JSX.Element => {
+ const backgroundColor = useMemo(() => {
+ if (!glassType) return undefined
+
+ switch (glassType) {
+ case 'light':
+ return alpha('#FFFFFF', 0.6)
+ case 'light2':
+ return alpha('#A1A1AA', 0.25)
+ case 'dark':
+ return alpha('#28282E', 0.85)
+ case 'dark2':
+ return alpha('#818189', 0.6)
+ case 'dark3':
+ return alpha('#C5C5C8', 0.25)
+ }
+ }, [glassType])
+
+ const tint = useMemo(() => {
+ switch (glassType) {
+ case 'light':
+ case 'light2':
+ return 'light'
+ case 'dark':
+ case 'dark2':
+ case 'dark3':
+ return 'dark'
+ }
+ }, [glassType])
+
+ return (
+
+ {children}
+
+ )
+}
diff --git a/packages/k2-alpine/src/components/Primitives.ts b/packages/k2-alpine/src/components/Primitives.ts
index d2b8587dc5..485748ffd0 100644
--- a/packages/k2-alpine/src/components/Primitives.ts
+++ b/packages/k2-alpine/src/components/Primitives.ts
@@ -2,7 +2,6 @@ import {
styled,
Text as DripsyText,
ScrollView as DripsyScrollView,
- View as DripsyView,
FlatList as DripsyFlatList,
SafeAreaView as DripsySafeAreaView
} from 'dripsy'
@@ -31,13 +30,6 @@ export const ScrollView = styled(
backgroundColor: '$surfacePrimary'
})
-export const View = styled(
- DripsyView,
- {}
-)({
- backgroundColor: '$surfacePrimary'
-})
-
export const FlatList = styled(
DripsyFlatList,
{}
@@ -52,4 +44,4 @@ export const SafeAreaView = styled(
backgroundColor: '$surfacePrimary'
})
-export { TextInput, Image, Pressable, ActivityIndicator } from 'dripsy'
+export { View, TextInput, Image, Pressable, ActivityIndicator } from 'dripsy'
diff --git a/packages/k2-alpine/src/components/index.ts b/packages/k2-alpine/src/components/index.ts
index 16238a9931..34b3b3eb47 100644
--- a/packages/k2-alpine/src/components/index.ts
+++ b/packages/k2-alpine/src/components/index.ts
@@ -1 +1,3 @@
export * from './Primitives'
+export * from './GlassView/GlassView'
+export * from './Button/Button'
diff --git a/packages/k2-alpine/src/index.ts b/packages/k2-alpine/src/index.ts
index b25b922423..03039a1b20 100644
--- a/packages/k2-alpine/src/index.ts
+++ b/packages/k2-alpine/src/index.ts
@@ -2,4 +2,5 @@ export { useDripsyTheme as useTheme } from 'dripsy'
export type { SxProp, Sx } from 'dripsy'
export * from './components'
export * from './theme/ThemeProvider'
+export { Icons } from './theme/tokens/Icons'
export * from './utils'
diff --git a/packages/k2-alpine/src/theme/theme.ts b/packages/k2-alpine/src/theme/theme.ts
index a9d5490756..85e530ff7f 100644
--- a/packages/k2-alpine/src/theme/theme.ts
+++ b/packages/k2-alpine/src/theme/theme.ts
@@ -8,12 +8,14 @@ export const darkTheme = makeTheme({
reactNativeTypesOnly: true
},
colors: darkModeColors,
- text
+ text,
+ isDark: true
})
export const lightTheme = {
...darkTheme,
- colors: lightModeColors
+ colors: lightModeColors,
+ isDark: false
}
export type K2AlpineTheme = typeof darkTheme
diff --git a/packages/k2-alpine/src/theme/tokens/Colors.stories.tsx b/packages/k2-alpine/src/theme/tokens/Colors.stories.tsx
index b08d36952b..796b984fb3 100644
--- a/packages/k2-alpine/src/theme/tokens/Colors.stories.tsx
+++ b/packages/k2-alpine/src/theme/tokens/Colors.stories.tsx
@@ -1,13 +1,15 @@
import React from 'react'
import tinycolor from 'tinycolor2'
import { useColorScheme } from 'react-native'
+import { LinearGradient } from 'expo-linear-gradient'
import { View, Text, FlatList } from '../../components/Primitives'
import Link from '../../utils/Link'
import { useTheme } from '../..'
+import { GlassView, GlassType } from '../../components/GlassView/GlassView'
import { colors } from './colors'
const FIGMA_LINK =
- 'https://www.figma.com/design/opZ4C1UGzcoGRjxE4ZIE3J/K2-Alpine?node-id=781-3507&node-type=frame&t=J5mVaf37BsbqucdK-0'
+ 'https://www.figma.com/design/opZ4C1UGzcoGRjxE4ZIE3J/K2-Alpine?node-id=1-721&node-type=frame&t=JNmtjxX2p2CadPSd-11'
export default {
title: 'Colors'
@@ -103,3 +105,59 @@ export const Colors = (): JSX.Element => {
/>
)
}
+
+export const Glasses = (): JSX.Element => {
+ const types: GlassType[] = ['light', 'light2', 'dark', 'dark2', 'dark3']
+
+ return (
+
+
+
+
+ }
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ renderItem={({ item }: { item: any }) => (
+
+
+ {item}
+
+
+ )}
+ />
+
+ )
+}
diff --git a/packages/k2-alpine/src/theme/tokens/Icons.stories.tsx b/packages/k2-alpine/src/theme/tokens/Icons.stories.tsx
new file mode 100644
index 0000000000..32d95e3de7
--- /dev/null
+++ b/packages/k2-alpine/src/theme/tokens/Icons.stories.tsx
@@ -0,0 +1,61 @@
+import React from 'react'
+
+import { FlatList } from 'react-native'
+import { SvgProps } from 'react-native-svg'
+import Link from '../../utils/Link'
+import { useTheme } from '../..'
+import { Icons } from './Icons'
+
+export default {
+ title: 'Icons'
+}
+
+export const All = (): JSX.Element => {
+ return (
+
+ )
+}
+
+const Template = ({
+ icons,
+ resourceURL
+}: {
+ icons: React.FC[]
+ resourceURL: string
+}): JSX.Element => {
+ const {
+ theme: { colors }
+ } = useTheme()
+ const renderItem = ({ item }: { item: React.FC }): JSX.Element => {
+ const IconComponent = item
+
+ return
+ }
+
+ return (
+
+ }
+ />
+ )
+}
+
+export const Navigation = (): JSX.Element =>
+ Template({
+ icons: [Icons.Navigation.Check, Icons.Navigation.ExpandMore],
+ resourceURL:
+ 'https://www.figma.com/file/hDSl4OUgXorDAtqPZtCUhB/K2-Foundation?type=design&node-id=378-5642&mode=design&t=HOIixbVhKpxGrRwG-4'
+ })
diff --git a/packages/k2-alpine/src/theme/tokens/Icons.ts b/packages/k2-alpine/src/theme/tokens/Icons.ts
new file mode 100644
index 0000000000..7440cac53c
--- /dev/null
+++ b/packages/k2-alpine/src/theme/tokens/Icons.ts
@@ -0,0 +1,13 @@
+import IconCheck from '../../assets/icons/check.svg'
+import IconExpandMore from '../../assets/icons/expand_more.svg'
+import IconBackArrowCustom from '../../assets/icons/back_arrow_custom.svg'
+
+export const Icons = {
+ Navigation: {
+ Check: IconCheck,
+ ExpandMore: IconExpandMore
+ },
+ Custom: {
+ BackArrowCustom: IconBackArrowCustom
+ }
+}
diff --git a/packages/k2-alpine/src/theme/tokens/text.ts b/packages/k2-alpine/src/theme/tokens/text.ts
index 98eb7402d7..a757598085 100644
--- a/packages/k2-alpine/src/theme/tokens/text.ts
+++ b/packages/k2-alpine/src/theme/tokens/text.ts
@@ -62,6 +62,21 @@ export const text = {
fontFamily: 'DejaVuSansMono',
fontSize: 12,
lineHeight: 16
+ },
+ buttonLarge: {
+ fontFamily: 'Inter-SemiBold',
+ fontSize: 18,
+ lineHeight: 18
+ },
+ buttonMedium: {
+ fontFamily: 'Inter-SemiBold',
+ fontSize: 15,
+ lineHeight: 18
+ },
+ buttonSmall: {
+ fontFamily: 'Inter-SemiBold',
+ fontSize: 12,
+ lineHeight: 14
}
}
diff --git a/packages/k2-alpine/src/utils/alpha.ts b/packages/k2-alpine/src/utils/alpha.ts
deleted file mode 100644
index 0e29623603..0000000000
--- a/packages/k2-alpine/src/utils/alpha.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-import tinycolor from 'tinycolor2'
-
-export function alpha(color: string, value: number): string {
- return tinycolor(color).setAlpha(value).toString()
-}
diff --git a/packages/k2-alpine/src/utils/colors.ts b/packages/k2-alpine/src/utils/colors.ts
new file mode 100644
index 0000000000..f3cad9a9de
--- /dev/null
+++ b/packages/k2-alpine/src/utils/colors.ts
@@ -0,0 +1,24 @@
+import tinycolor from 'tinycolor2'
+
+export function alpha(color: string, value: number): string {
+ return tinycolor(color).setAlpha(value).toString()
+}
+
+export function overlayColor(colorA: string, colorB: string): string {
+ const _colorA = tinycolor(colorA).toRgb()
+ const _colorB = tinycolor(colorB).toRgb()
+
+ const combinedAlpha = _colorA.a + _colorB.a * (1 - _colorA.a)
+
+ const r =
+ (_colorA.r * _colorA.a + _colorB.r * _colorB.a * (1 - _colorA.a)) /
+ combinedAlpha
+ const g =
+ (_colorA.g * _colorA.a + _colorB.g * _colorB.a * (1 - _colorA.a)) /
+ combinedAlpha
+ const b =
+ (_colorA.b * _colorA.a + _colorB.b * _colorB.a * (1 - _colorA.a)) /
+ combinedAlpha
+
+ return tinycolor({ r, g, b, a: combinedAlpha }).toRgbString()
+}
diff --git a/packages/k2-alpine/src/utils/index.ts b/packages/k2-alpine/src/utils/index.ts
index 8675b145ce..67b2602ea5 100644
--- a/packages/k2-alpine/src/utils/index.ts
+++ b/packages/k2-alpine/src/utils/index.ts
@@ -1 +1 @@
-export * from './alpha'
+export * from './colors'
diff --git a/packages/k2-mobile/src/theme/K2ThemeProvider.tsx b/packages/k2-mobile/src/theme/K2ThemeProvider.tsx
index 5e20d96f5d..6b0b7398c3 100644
--- a/packages/k2-mobile/src/theme/K2ThemeProvider.tsx
+++ b/packages/k2-mobile/src/theme/K2ThemeProvider.tsx
@@ -3,5 +3,8 @@ import { DripsyProvider } from 'dripsy'
import { theme } from './theme'
export const K2ThemeProvider: React.FC = ({ children }) => {
+ // todo: please remove the ts-ignore comments after we address this issue
+ // https://ava-labs.atlassian.net/browse/CP-9297
+ // @ts-ignore
return {children}
}
diff --git a/yarn.lock b/yarn.lock
index 7a59e57722..4a244338b6 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -285,6 +285,7 @@ __metadata:
ethers: 6.8.1
events: 3.3.0
expo: 50.0.21
+ expo-blur: 12.9.2
expo-constants: 15.4.6
expo-linking: 6.2.2
expo-router: 3.4.10
@@ -498,7 +499,9 @@ __metadata:
eslint: 9.9.1
eslint-plugin-avalabs-mobile: "workspace:*"
expo: 50.0.21
+ expo-blur: 12.9.2
expo-font: 11.10.3
+ expo-linear-gradient: 12.7.2
expo-splash-screen: 0.27.6
expo-status-bar: 1.12.1
json-stringify-pretty-compact: 4.0.0
@@ -508,6 +511,8 @@ __metadata:
react-native: 0.73.7
react-native-reanimated: 3.8.0
react-native-safe-area-context: 4.11.0
+ react-native-svg: 15.7.1
+ react-native-svg-transformer: 1.5.0
tinycolor2: 1.6.0
typescript: 5.6.3
peerDependencies:
@@ -16748,6 +16753,15 @@ __metadata:
languageName: node
linkType: hard
+"expo-blur@npm:12.9.2":
+ version: 12.9.2
+ resolution: "expo-blur@npm:12.9.2"
+ peerDependencies:
+ expo: "*"
+ checksum: 56be7adc400d01a541ba92a8f35efa4295e57750f0736c73b2890a006ce873f646df3b08c822073fc7b34c984cb213aef135f133b0fc97a28c4eb89afb4676bd
+ languageName: node
+ linkType: hard
+
"expo-constants@npm:15.4.6, expo-constants@npm:~15.4.0, expo-constants@npm:~15.4.3":
version: 15.4.6
resolution: "expo-constants@npm:15.4.6"
@@ -16788,6 +16802,15 @@ __metadata:
languageName: node
linkType: hard
+"expo-linear-gradient@npm:12.7.2":
+ version: 12.7.2
+ resolution: "expo-linear-gradient@npm:12.7.2"
+ peerDependencies:
+ expo: "*"
+ checksum: afe4daf423dcaa02900a1252eb670a75089b9c9837bff2bd7f76199b7ad76f4b48efadaeec773b4d328456d9e8e3d56f68f9f665312681e1537adadbd97b54ff
+ languageName: node
+ linkType: hard
+
"expo-linking@npm:6.2.2":
version: 6.2.2
resolution: "expo-linking@npm:6.2.2"
@@ -25550,7 +25573,7 @@ react-native-webview@ava-labs/react-native-webview:
peerDependencies:
react: "*"
react-native: "*"
- checksum: d396f3dea807077e8789e1d463c87024e1633481d3dff53c0650c82a08d8b7d699db97ceab4e8d2c9de85c3d5378d192c968487254c62edadff77e82a9b8c929
+ checksum: a187edd718e1ea3a6b1e5da167744e6ee324bc3c3e492bcb0a9d028ab68a82907f053f37c23aa4229d6a9091541cee3c73549c3c850056e4cf5eb5b3cb2c9ffc
languageName: node
linkType: hard