From c4bb12970e024e2c4c3793e76844dbcee03a5eb7 Mon Sep 17 00:00:00 2001 From: JungHwan Jang Date: Thu, 31 Oct 2024 17:16:15 -0400 Subject: [PATCH] CP-9316: Buttons and Glasses (#2033) --- packages/core-mobile/AppSwitcher.tsx | 13 +- .../app/new/components/BlurBackgroundView.tsx | 19 -- .../components/navigation/BackBarButton.tsx | 12 +- .../navigation/BlurredBackgroundView.tsx | 16 ++ .../navigation/HeaderBackground.tsx | 20 -- .../navigation/TabBarBackground.tsx | 20 -- .../(signedIn)/(modals)/settings/account.tsx | 8 +- .../(signedIn)/(modals)/settings/index.tsx | 8 +- .../new/routes/(signedIn)/(tabs)/_layout.tsx | 4 +- .../(signedIn)/(tabs)/portfolio/index.tsx | 11 +- packages/core-mobile/app/new/routes/index.tsx | 14 +- .../app/new/routes/signup/index.tsx | 7 +- .../new/utils/navigation/screenOptions.tsx | 4 +- packages/core-mobile/ios/Podfile.lock | 6 + packages/core-mobile/package.json | 1 + packages/k2-alpine/declarations.d.ts | 6 + packages/k2-alpine/metro.config.js | 15 ++ packages/k2-alpine/package.json | 6 +- .../src/assets/icons/back_arrow_custom.svg | 11 + packages/k2-alpine/src/assets/icons/check.svg | 3 + .../src/assets/icons/expand_more.svg | 3 + .../src/components/Button/Button.stories.tsx | 138 ++++++++++ .../src/components/Button/Button.tsx | 237 ++++++++++++++++++ .../src/components/GlassView/GlassView.tsx | 55 ++++ .../k2-alpine/src/components/Primitives.ts | 10 +- packages/k2-alpine/src/components/index.ts | 2 + packages/k2-alpine/src/index.ts | 1 + packages/k2-alpine/src/theme/theme.ts | 6 +- .../src/theme/tokens/Colors.stories.tsx | 60 ++++- .../src/theme/tokens/Icons.stories.tsx | 61 +++++ packages/k2-alpine/src/theme/tokens/Icons.ts | 13 + packages/k2-alpine/src/theme/tokens/text.ts | 15 ++ packages/k2-alpine/src/utils/alpha.ts | 5 - packages/k2-alpine/src/utils/colors.ts | 24 ++ packages/k2-alpine/src/utils/index.ts | 2 +- .../k2-mobile/src/theme/K2ThemeProvider.tsx | 3 + yarn.lock | 25 +- 37 files changed, 759 insertions(+), 105 deletions(-) delete mode 100644 packages/core-mobile/app/new/components/BlurBackgroundView.tsx create mode 100644 packages/core-mobile/app/new/components/navigation/BlurredBackgroundView.tsx delete mode 100644 packages/core-mobile/app/new/components/navigation/HeaderBackground.tsx delete mode 100644 packages/core-mobile/app/new/components/navigation/TabBarBackground.tsx create mode 100644 packages/k2-alpine/declarations.d.ts create mode 100644 packages/k2-alpine/metro.config.js create mode 100644 packages/k2-alpine/src/assets/icons/back_arrow_custom.svg create mode 100644 packages/k2-alpine/src/assets/icons/check.svg create mode 100644 packages/k2-alpine/src/assets/icons/expand_more.svg create mode 100644 packages/k2-alpine/src/components/Button/Button.stories.tsx create mode 100644 packages/k2-alpine/src/components/Button/Button.tsx create mode 100644 packages/k2-alpine/src/components/GlassView/GlassView.tsx create mode 100644 packages/k2-alpine/src/theme/tokens/Icons.stories.tsx create mode 100644 packages/k2-alpine/src/theme/tokens/Icons.ts delete mode 100644 packages/k2-alpine/src/utils/alpha.ts create mode 100644 packages/k2-alpine/src/utils/colors.ts 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