mirror of
https://github.com/luxfi/safe-wallet.git
synced 2026-11-02 15:28:09 +00:00
* chore(mobile): upgrade Tamagui from v1 to v2 Upgrade all @tamagui/* packages from v1 (^1.126.3) to v2 (2.0.0-rc.26). Replace deprecated @tamagui/animations-moti with animations-reanimated. Rewrite SafeButton to use v2 compound component pattern (Button.Text) with correct font weight, disabled state, and icon coloring. Patch @tamagui/image for style override bug (upstream fix merged but not yet on npm: https://github.com/tamagui/tamagui/pull/3966). * fix(mobile): resolve Tamagui tokens in Loader before passing to SVG The Loader component passes color directly to react-native-progress (CircleSnail), which uses react-native-svg internally. SVG doesn't understand Tamagui theme tokens like "$color", causing repeated "not a valid color or brush" console warnings. * fix(mobile): center nav bar title in scrollable headers Remove flex: 1 from headerTitle Animated.View so the native stack header centers the title element itself. Add headerTitleAlign: 'center' and match right spacer width (40px) to the back button circle. * fix(mobile): fix Tamagui v2 component API breakages - SafeButton: rewrite with Button.Text compound pattern, add textColor prop for forced light-mode overrides, restore fontWeight 700 default - SafeInput: replace removed `editable` prop with `readOnly`, use GetProps<StyledInput> to fix type conflicts, cast theme tokens - SafeCard: use `src` instead of `source`, `objectFit` instead of `resizeMode` for Tamagui v2 Image - ParametersButton: migrate from raw Button to SafeButton - Badge: fix dark mode background token (backgroundMain → borderLight) - Raw Buttons: move fontWeight to Button.Text in ImportSigner/Ledger - Onboarding: migrate color prop to textColor for dark mode fix - Assets errors: use secondary variant + textColor instead of inline bg * fix(mobile): preserve element children and text-button accent color in SafeButton - Only wrap string/number children in Button.Text; render element children (ActivityIndicator, Loader) directly to avoid invalid text-child nesting on native. - Use theme.primary for the text variant so text-style buttons retain their accent color instead of blending with body text. * fix(mobile): replace raw Tamagui Button with SafeButton in ImportSuccess The Copy button on the signer import success screen was broken after the Tamagui v2 upgrade because it used a raw Tamagui Button. Replace it with SafeButton (secondary, $sm) for consistent styling and v2 compatibility. * fix(mobile): fix Jest transform config for Tamagui v2 and update snapshots Add tamagui and @tamagui/* to transformIgnorePatterns so Jest can parse the ESM exports in Tamagui v2. Update 22 snapshots reflecting the new style output and remove stale fontFamily assertion in DataRow test. --------- Co-authored-by: Hanzo Dev <[email protected]>
140 lines
4.2 KiB
TypeScript
140 lines
4.2 KiB
TypeScript
import type { Preview } from '@storybook/react'
|
|
import { useColorScheme } from 'react-native'
|
|
import { NavigationContainer, NavigationIndependentTree } from '@react-navigation/native'
|
|
import { StorybookThemeProvider } from '@/src/theme/provider/storybookTheme'
|
|
import { SafeToastProvider } from '@/src/theme/provider/toastProvider'
|
|
import { SafeAreaProvider } from 'react-native-safe-area-context'
|
|
import { PortalProvider, View } from 'tamagui'
|
|
import { createNavigationContainerRef } from '@react-navigation/native'
|
|
import { Provider } from 'react-redux'
|
|
import { configureStore } from '@reduxjs/toolkit'
|
|
import { rootReducer } from '@/src/store'
|
|
import { FLUSH, PAUSE, PERSIST, PURGE, REGISTER, REHYDRATE } from 'redux-persist'
|
|
import { cgwClient } from '@safe-global/store/gateway/cgwClient'
|
|
import { web3API } from '@/src/store/signersBalance'
|
|
import { TOKEN_LISTS } from '@/src/store/settingsSlice'
|
|
import { chainsAdapter } from '@safe-global/store/gateway/chains'
|
|
import { mockChain } from '@/src/tests/mocks'
|
|
import { CONFIG_SERVICE_KEY } from '@/src/config/constants'
|
|
|
|
const navigationRef = createNavigationContainerRef()
|
|
|
|
// Create a mock Redux store for Storybook
|
|
const createStorybookStore = () => {
|
|
const mockChainsState = chainsAdapter.setAll(chainsAdapter.getInitialState(), [mockChain])
|
|
|
|
return configureStore({
|
|
reducer: rootReducer,
|
|
middleware: (getDefaultMiddleware) =>
|
|
getDefaultMiddleware({
|
|
serializableCheck: {
|
|
ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
|
|
},
|
|
}).concat(cgwClient.middleware, web3API.middleware),
|
|
preloadedState: {
|
|
settings: {
|
|
onboardingVersionSeen: '',
|
|
themePreference: 'light',
|
|
currency: 'usd',
|
|
tokenList: TOKEN_LISTS.TRUSTED,
|
|
env: {
|
|
rpc: {},
|
|
tenderly: {
|
|
url: '',
|
|
accessToken: '',
|
|
},
|
|
},
|
|
},
|
|
activeSafe: {
|
|
chainId: '1',
|
|
address: '0x1234567890123456789012345678901234567890',
|
|
threshold: 1,
|
|
owners: [],
|
|
nonce: 0,
|
|
version: '1.3.0',
|
|
},
|
|
[cgwClient.reducerPath]: {
|
|
queries: {
|
|
[`getChainsConfigV2("${CONFIG_SERVICE_KEY}")`]: {
|
|
status: 'fulfilled',
|
|
data: mockChainsState,
|
|
},
|
|
},
|
|
},
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
} as any,
|
|
})
|
|
}
|
|
|
|
const storybookStore = createStorybookStore()
|
|
|
|
// Navigation wrapper component for Storybook
|
|
// Uses NavigationIndependentTree to isolate from any parent navigation
|
|
const NavigationWrapper = ({ children }: { children: React.ReactNode }) => {
|
|
return (
|
|
<NavigationIndependentTree>
|
|
<NavigationContainer
|
|
ref={navigationRef}
|
|
documentTitle={{
|
|
enabled: false,
|
|
}}
|
|
>
|
|
{children}
|
|
</NavigationContainer>
|
|
</NavigationIndependentTree>
|
|
)
|
|
}
|
|
|
|
const preview: Preview = {
|
|
parameters: {
|
|
controls: {
|
|
matchers: {
|
|
color: /(background|color)$/i,
|
|
date: /Date$/,
|
|
},
|
|
},
|
|
},
|
|
globalTypes: {
|
|
theme: {
|
|
description: 'Global theme for components',
|
|
defaultValue: '',
|
|
toolbar: {
|
|
title: 'Theme',
|
|
icon: 'circlehollow',
|
|
items: [
|
|
{ value: 'light', icon: 'circlehollow', title: 'Light' },
|
|
{ value: 'dark', icon: 'circle', title: 'Dark' },
|
|
],
|
|
dynamicTitle: true,
|
|
},
|
|
},
|
|
},
|
|
tags: ['autodocs'],
|
|
decorators: [
|
|
(Story, context) => {
|
|
const colorScheme = useColorScheme()
|
|
const theme = context.globals.theme || colorScheme || 'light'
|
|
|
|
return (
|
|
<Provider store={storybookStore}>
|
|
<PortalProvider shouldAddRootHost>
|
|
<NavigationWrapper>
|
|
<SafeAreaProvider>
|
|
<StorybookThemeProvider theme={theme}>
|
|
<SafeToastProvider>
|
|
<View style={{ padding: 16, flex: 1 }} backgroundColor={'$background'}>
|
|
<Story />
|
|
</View>
|
|
</SafeToastProvider>
|
|
</StorybookThemeProvider>
|
|
</SafeAreaProvider>
|
|
</NavigationWrapper>
|
|
</PortalProvider>
|
|
</Provider>
|
|
)
|
|
},
|
|
],
|
|
}
|
|
|
|
export default preview
|