What I like to use to build my projects:
- ⚛️ React
- 📳 React Native
- 🖥️ Next.js
- 📱 SwiftUI
Buy me a coffee if you like my work!
Bringing SwiftUI features to your React Native app. It's like if React Native and SwiftUI had a child.
Home Page: swiftui-react-native.vercel.app
License: MIT License
Is your libary compatible with expo?
Thank you
UIColor
object. This is an object you can import that has dark
and light
properties. Inside those, there are each individual colors.
useUIColor
hook. this hook returns a dynamic form of the above UIColor object that decides between dark and light based on the current color scheme.
You can also just pass in a hex value or any of the built in react native color values.
Pass in the name of the swiftui color (as a string) that will map to the correct hex value. This will provide autocomplete and users won't need to use the hook or object.
example:
backgroundColor=“systemBlue”
where,
type backgroundColor = keyof UIColor.light | string
or something like that.
The logic would go something like this:
In order to incorporate dark mode, we would have to use the useColorScheme
hook internally within each component rather than having the user use it (I like this better - less work for the user).
utils/colors
const getColor = (color: string, colorScheme: 'dark' | 'light') => {
const palette = UIColor[colorScheme];
if (palette[color]) return palette[color]
return color
};
then in each component
const colorScheme = useColorSheme();
…getColor(backgroundColor, colorScheme),
Open questions:
So the UIColor
object currently in the project, contains only light mode colors. This is fine for light mode, but we have to consider dark mode as well.
To fix this:
DynamicColorIOS
or PlatformColor
which can handle light/dark variants automatically.What do you think @andrew-levy
(This is a "nice to have", just proposing at this time)
I have been thinking that putting the example in this repository and using something like nodemon
would greatly improve my efficiency.
On swiftui-react-native
:
yarn run clean-build
On swiftui-react-native-example
rm -rf node_modules && yarn install && yarn start --reset-cache
R
to reload simulator(s).Hi again! I've continued testing the library and found that text does not support number of lines, it just has a ellipsis trailing and wrapping doesn't work fine. The video situation is the following: adding string literal's new line doesn't work straight up, it requires to add two new lines.
Once SwiftUI views are supported in the module api (early 2023 maybe?), I would like to switch some components over to it rather than using javascript implementations. Good candidates include:
Maybe:
Notice this list doesn't include any container views like Stacks, this is because there currently isn't an easy way to pass children from RN to the SwiftUI view. This will likely come in later iterations of the module api.
Questions:
Track PR: expo/expo#19888
There is a HeaderScrollContext
context variable in the NavigationViewManager
component that eventually gets consumed by the ScrollView
component to update the amount the user has scrolled (triggering the header animation). When these components are compiled using Rollup, it is not correctly passing the context from navigation.js
(created here) to main.js
(consumed here). Instead, navigation.js
is creating its own context var, and no data is being shared between the two components.
In main.js
line 248,
Current:
const HeaderScrollContext = React.createContext(null);
I think it should be doing something like this:
const HeaderScrollContext = require('./navigation').HeaderScrollContext
so that we can use the context that was created in the other file.
I also see that var stack = require('@react-navigation/stack');
is being required in main.js
and stack.createStackNavigator();
is being called randomly. Maybe I messed up my import/export somewhere? The only reference to navigation stuff should be the context var.
I am actively trying to fix this, which has been making me think about how navigation components fit into this project. Ideally, I would like to keep the navigation components (I think?), but I am open to either making them platform agnostic or moving them to a completely different project. Here are some options:
Do nothing. Leave them in this project with the current setup (which works nicely). Just would need to fix this small issue mentioned above.
Keep the navigation components, but make them framework agnostic. They would have much less functionality and a lot would be simplified, but we could allow the user to pass in props depending on if they are using react-navigation, react-native-navigation, etc. You could imagine something like this
<NavigationLink text='Go to SomeView' action={use whatever navigation function you want here} />
Don't change any of the navigation components, but move them to a separate project (something like swiftui-react-native-navigation
). This could be an optional package that is a wrapper of react-navigation (and maybe more in the future). I definitely want to keep a lot of the animation magic that has been built out in these components already. If you haven't seen some of the animations yet, here is a quick demo:
I'm open to more solutions, but these are the 3 that come to mind.
@sallar tagging you if you have any ideas! Just wanted to create an issue to keep track of this.
Here are my thoughts on building navigation related swiftui views:
I built a solid prototype that seems to be working really well for me. Need to decide where its going to live tho.
First, wrap your app with a NavigationProvider
to enable navigation. For basic navigation (going from screen to screen and back), use the Navigation
component. Its first and only child should be the initial view you want to show.
<NavigationProvider>
<Navigation>
<Home user={{ name: "Andrew" }} />
</Navigation>
</NavigationProvider>
Moving along to the actual screen we want to render. Like SwiftUI, we wrap our screen in a NavigationView
which will allow the user to customize the navigation bar like displayMode, title, etc. We use the NavigationLink
component to navigate to another view.
const Home = ({ user }) => (
<NavigationView navigationTitle="Welcome" navigationTitleDisplayMode="large">
<VStack>
<Text>Welcome {user}</Text>
<NavigationLink label="To Settings" destination={<Settings theme="dark" />} />
</VStack>
</NavigationView>
)
Another feature we want to support is TabView
. Similar to the above example, wrap the app in a NavigationProvider
. Then as children, render a TabItem
for each tab you want. You can supply the following props: label
, icon
, view
. You can also send in props via props
.
<NavigationProvider>
<TabView>
<TabItem label="Home" icon={homeIcon} >
<Home />
</TabItem>
<TabItem label="Settings" icon={settingsIcon} >
<Settings />
</TabItem>
<TabView>
</NavigationProvider>
Like in the basic navigation example above, Home
and Settings
are screens where the screen content is wrapped in a NavigationView
:
const Home = () => (
<NavigationView navigationTitle="Welcome">
<VStack>
<Text>Home Screen</Text>
<NavigationLink label="To Settings" destination={<Settings />} />
</VStack>
</NavigationView>
)
At this point, we are able to navigate between tabs, but what if we want to navigate to a details screen under the Home
tab? Well instead of providing <Home />
as a child of <TabItem>
, we can pass a <Navigation>
stack like so:
const HomeNavigation = () => <Navigation><Home /></Navigation>
<NavigationProvider>
<TabView>
<TabItem label="Home" icon={homeIcon} >
<HomeNavigation />
</TabItem>
<TabItem label="Settings" icon={settingsIcon} >
<Settings />
</TabItem>
<TabView>
</NavigationProvider>
Hi! I've got to refactor some of my components since I was using v5, and I noticed 2 issues:
Should be similar to SwiftUI for the VStack
VStack()
.padding()
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(.black)
For the Button, it should respect the order as well, but it doesn't (because of this I can't have full width buttons, it seems)
My code:
const { height, width } = useWindowDimensions();
const { stateNavigator } = useContext(NavigationContext);
return (
<VStack padding frame={{ width, height }} background="black">
<Image systemName="face.smiling" fontSize={50} />
<Text font="title" foregroundStyle="white">
Hello World!
</Text>
<Button
title="Profile"
tint="purple"
buttonStyle="borderedProminent"
frame={{ width }}
action={() => stateNavigator.navigate('profile')}
/>
</VStack>
);
Hi!
I was thinking about making something like this, because I love SwiftUI too and I was searching to see if anybody else has done anything similar.
This project is fantastic, however I have one question/concern:
Why do you use styled-components for this? In my experience it's a very heavy and unnecessary dependency for a project like this. Everything here can be achieved nicely via normal RN styles and it would be lighter and more performant.
Also another issue is, styled-components uses units like px
which doesnt apply to RN, since everything needs to be unitless, but if you do that, styled-components throws a warning.
Are you interested in removing this dependency? It's ok if you're set on it, in that case I would still be making my own version.
Thanks again!
I've been searching for iOS-style React Native component library for a while and this is just what I want. Thanks for the awesome project!
While using Link
component in a List, I found that the chevron icon on the right side is missing. The screenshots in README shows a Link component with chevron icon, but it does not appear in my app nor the example app.
Is there any way to add this in the latest version of swiftui-react-native? Thanks!
P.S. I've tried something like this but it looks much different with the native UITableViewCell.AccessoryType.disclosureIndicator
.
<Button action={() => navigation.navigate('Drawing')}>
<Text alignment="leading">Button</Text>
<Image systemName="chevron.forward" />
</Button>
I keep getting this error when trying to use any of the components. I'm fairly certain I have installed all the dependencies correctly. Here's my package.json:
"dependencies": {
"@gorhom/bottom-sheet": "^3",
"@react-native-community/masked-view": "^0.1.11",
"@react-native-mapbox-gl/maps": "^8.2.0-beta2",
"@react-navigation/bottom-tabs": "^5.11.11",
"@react-navigation/native": "^5.9.4",
"@react-navigation/stack": "^5.14.5",
"react": "17.0.1",
"react-native": "0.64.2",
"react-native-gesture-handler": "^1.10.3",
"react-native-reanimated": "^2.2.0",
"react-native-safe-area-context": "^3.2.0",
"react-native-screens": "^3.3.0",
"react-native-vector-icons": "^8.1.0",
"swiftui-react-native": "^1.9.3"
},
and I'm attempting to just use very simple components as a test,
import {Text} from 'swiftui-react-native';
....
<Text font="title">Some cool text</Text>
I've tried a few components and they all produce the same error. Any ideas? Here's the error
ERROR TypeError: null is not an object (evaluating '_useColorScheme.colorScheme')
This error is located at:
in Text (at MapButtons.js:65)
in RCTView (at View.js:34)
in View (at createAnimatedComponent.js:448)
in AnimatedComponent(View) (at createAnimatedComponent.js:459)
in AnimatedComponentWrapper (at BottomSheetDraggableView.tsx:74)
in PanGestureHandler (at BottomSheetDraggableView.tsx:62)
in BottomSheetDraggableView (at BottomSheet.tsx:948)
in RCTView (at View.js:34)
in View (at createAnimatedComponent.js:448)
in AnimatedComponent(View) (at createAnimatedComponent.js:459)
in AnimatedComponentWrapper (at BottomSheet.tsx:943)
in RCTView (at View.js:34)
in View (at createAnimatedComponent.js:448)
in AnimatedComponent(View) (at createAnimatedComponent.js:459)
in AnimatedComponentWrapper (at BottomSheet.tsx:930)
in RCTView (at View.js:34)
in View (at BottomSheetContainer.tsx:40)
in BottomSheetContainer (at BottomSheet.tsx:924)
in BottomSheet (created by BottomSheet)
in PortalHost (at PortalProvider.tsx:13)
in PortalProvider (at BottomSheetModalProvider.tsx:186)
in BottomSheetModalProviderWrapper (at HomeScreen.js:224)
in HomeScreen (at SceneView.tsx:122)
in StaticContainer
in EnsureSingleNavigator (at SceneView.tsx:114)
in SceneView (at useDescriptors.tsx:153)
in RCTView (at View.js:34)
in View (at BottomTabView.tsx:55)
in SceneContent (at BottomTabView.tsx:172)
in RNSScreen (at createAnimatedComponent.js:217)
in AnimatedComponent (at createAnimatedComponent.js:278)
in AnimatedComponentWrapper (at src/index.native.tsx:147)
in Screen (at ResourceSavingScene.tsx:30)
in ResourceSavingScene (at BottomTabView.tsx:166)
in RNSScreenContainer (at src/index.native.tsx:186)
in ScreenContainer (at BottomTabView.tsx:146)
in RNCSafeAreaProvider (at SafeAreaContext.tsx:76)
in SafeAreaProvider (at SafeAreaProviderCompat.tsx:42)
in SafeAreaProviderCompat (at BottomTabView.tsx:145)
in BottomTabView (at createBottomTabNavigator.tsx:45)
in BottomTabNavigator (at App.js:20)
in EnsureSingleNavigator (at BaseNavigationContainer.tsx:409)
in BaseNavigationContainer (at NavigationContainer.tsx:91)
in ThemeProvider (at NavigationContainer.tsx:90)
in NavigationContainer (at App.js:19)
in App (at renderApplication.js:47)
in RCTView (at View.js:34)
in View (at AppContainer.js:107)
in RCTView (at View.js:34)
in View (at AppContainer.js:134)
in AppContainer (at renderApplication.js:40)
Use Flex Gap for spacing now that its available in RN 0.71
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.