React Native Web UI Components is a library of customized React Native/React Native Web components for mobile and web UI. This library is used by React Native Web Jsonschema Form.
- See this library in production at https://www.carelulu.com
- Skeleton project using React Native Web UI Components at https://www.carelulu.com/react-native-web-example/ and https://github.com/CareLuLu/react-native-web-skeleton
- Documentation
- Setup
- Usage
- Class Names
- Components
- Alert
- Autocomplete
- Banner
- Bold
- Box
- BoxHeader
- BoxItem
- BoxTitle
- Button
- Carousel
- Checkbox
- Column
- Confirm
- Container
- Datepicker
- Draggable
- Dropzone
- Helmet
- HideShowText
- Hr
- Icon
- IconLink
- IconText
- Image
- Link
- Loading
- MainContainer
- NavLink
- Popup
- Radiobox
- ReadMoreLessLink
- Router
- Row
- Screen
- ScrollView
- Select
- Sidebar
- Spinner
- StylePropType
- Switch
- TagInput
- Text
- TextInput
- TimeRangePicker
- Title
- Tooltip
- View
- WebOnly
- WebView
- Theme
- License
Coming soon!
React Native Web UI Components was created to facilitate the development of write once, run anywhere
web and mobile apps. In order to accomplish that, this library is heavily based on React Native and React Native Web.
First you need to install react ^16.8.3 (this library uses react-hooks).
yarn add react
If you're using Expo, they use a custom version of react-native and therefore you need to check what is the React Native repository for the Expo version you're using. For Expo v33.x.x you'd run:
yarn add https://github.com/expo/react-native/archive/sdk-33.0.0.tar.gz
If your project is also being used for web, please install React Native Web. Make sure your babel/webpack build replace all react-native
imports with react-native-web
(details here). If you used React Create App, aliasing is already taken care off for you.
yarn add react-dom react-native-web
Install the library using yarn
or npm
.
yarn add react-native-web-ui-components
- Example using
react-router
:
import React from 'react';
import { StyleSheet } from 'react-native';
import { useHistory } from 'react-router';
import { Router, Switch } from 'react-router-native';
import { UIProvider } from 'react-native-web-ui-components';
const theme = {
input: {
focused: StyleSheet.create({
border: {
borderColor: 'yellow',
},
}),
},
};
const Theme = (props) => {
const history = useHistory();
return (
<UIProvider theme={theme} history={history}>
<EntryScreen {...props} />
</UIProvider>
);
};
const App = props = (
<Router>
<Switch>
<Theme {...props} />
</Switch>
</Router>
);
export default App;
- Example using
react-navigation
:
import React from 'react';
import { StyleSheet } from 'react-native';
import { NavigationContainer, useNavigation } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import { UIProvider } from 'react-native-web-ui-components';
const theme = {
input: {
focused: StyleSheet.create({
border: {
borderColor: 'yellow',
},
}),
},
};
const Stack = createStackNavigator();
const Theme = (props) => {
const navigation = useNavigation();
const history = {
location: {
pathname: () => navigation.state.routeName,
},
push: routeName => navigation.navigate(routeName),
replace: routeName => navigation.dispatch(
StackActions.replace(routeName),
),
};
return (
<UIProvider theme={theme} history={history}>
<EntryScreen {...props} />
</UIProvider>
);
};
const App = props = (
<NavigationContainer>
<Stack.Navigator>
<Theme {...props} />
</Stack.Navigator>
</NavigationContainer>
);
export default App;
import React from 'react';
import { StyleSheet } from 'react-native';
import { useHistory } from 'react-router';
import { Router, Switch } from 'react-router-dom';
import { UIProvider } from 'react-native-web-ui-components';
const theme = {
input: {
focused: StyleSheet.create({
border: {
borderColor: 'yellow',
},
}),
},
};
const Theme = (props) => {
const history = useHistory();
return (
<UIProvider theme={theme} history={history}>
<EntryScreen {...props} />
</UIProvider>
);
};
const App = props = (
<Router>
<Switch>
<Theme {...props} />
</Switch>
</Router>
);
export default App;
This library was built with Google's new standard Accelerated Mobile Page in mind. Although most components exported are AMP compatible by default, some components will have different implementations for AMP and non-AMP pages. This usually happens when the usabability would be degraded by complying with AMP requirements. If you're using server-side rendering (SSR), set amp
to true
for AMP pages.
// App.js
import React from 'react';
import { StyleSheet } from 'react-native';
import { useHistory } from 'react-router';
import { StaticRouter, Switch } from 'react-router-dom';
import { UIProvider } from 'react-native-web-ui-components';
const theme = {
input: {
focused: StyleSheet.create({
border: {
borderColor: 'yellow',
},
}),
},
};
const Theme = (props) => {
const history = useHistory();
const { amp } = props;
return (
<UIProvider theme={theme} history={history} amp={amp}>
<EntryScreen {...props} />
</UIProvider>
);
};
const App = (props) = {
const { pathname, context } = props;
return (
<StaticRouter location={pathname} context={context}>
<Switch>
<Theme {...props} />
</Switch>
</StaticRouter>
);
};
export default App;
// index.js
import Koa from 'koa';
import ReactDOMServer from 'react-dom/server';
import { AppRegistry } from 'react-native';
import { Helmet } from 'react-helmet';
import App from './App';
const app = new Koa();
AppRegistry.registerComponent('App', () => App);
const renderer = async (ctx) => {
const context = {};
const pathname = ctx.request.path;
const amp = /^\/amp/.test(pathname);
const initialProps = { pathname, context, amp };
const { element, getStyleElement } = AppRegistry.getApplication(
'App',
{ initialProps },
);
let body;
try {
body = await ReactDOMServer.renderToString(App);
} catch (err) {
ctx.status = 500;
return ctx.redirect('/500');
}
if (context.url) {
if (/^\/404/.test(context.url)) {
ctx.status = 404;
}
return ctx.redirect(context.url);
}
const helmet = Helmet.renderStatic();
const markup = ReactDOMServer.renderToStaticMarkup(getStyleElement());
ctx.body = `
<!DOCTYPE html>
<html ${helmet.htmlAttributes.toString()}>
<head>
${helmet.title.toString()}
${helmet.meta.toString()}
${helmet.link.toString()}
${markup}
${helmet.style.toString()}
</head>
<body ${helmet.bodyAttributes.toString()}>
<div id="root">
${body}
</div>
</body>
</html>
`;
};
app.use(renderer);
app.listen(3000);
React Native Web UI Components was developed with file size in mind and therefore exports individual components without the need of using the entire library.
import Autocomplete from 'react-native-web-ui-components/Autocomplete';
While mobile components are indiferent to the className
property, that is very useful for the web. React Native Web components no longer accept class names but for convenience, this library accepts the className
property for all exported components. Please note that class names are converted into data-class
attribute.
import React from 'react';
import { Row } from 'react-native-web-ui-components';
// You must use the Helmet export by this library to avoid conflicts.
import Helmet, { style } from 'react-native-web-ui-components/Helmet';
const MyComponent = () => (
<React.Fragment>
<Helmet>
<style>
{`
[data-class~="MyComponent__Row"] {
width: calc(100% - 20px);
}
`}
</style>
</Helmet>
<Row className="MyComponent__Row" />
</React.Fragment>
);
Opens an Alert popup. This library uses React Modal to display modals for web.
Displays a text input with autocomplete functionality.
Displays a banner/background image that adjusts with the screen size. You can display other components within the banner.
Same as Text but using the bold font defined in the theme fontFamily.bold
.
Container used to wrap BoxHeader and BoxItem.
Displays a header within the Box.
Displays an item within the Box.
Displays the title of the BoxHeader.
Displays a button.
Displays a carousel. If amp
is true
, then it will automatically use Google AMP Carousel.
Displays a checkbox.
Column is a View with flexDirection: "column"
that follows Bootstrap's grid system. You can define the percentage of the width that should be used in different screen sizes. For example:
<Row>
<Column xs={12} sm={4} md={3} lg={2} style={{ backgroundColor: 'red', height: 25 }} />
<Column xs={12} sm={4} md={3} lg={2} style={{ backgroundColor: 'green', height: 25 }} />
<Column xs={12} sm={4} md={3} lg={2} style={{ backgroundColor: 'blue', height: 25 }}/>
<Column xs={12} sm={4} md={3} lg={2} style={{ backgroundColor: 'purple', height: 25 }} />
<Column xs={12} sm={4} md={3} lg={2} style={{ backgroundColor: 'yellow', height: 25 }} />
<Column xs={12} sm={4} md={3} lg={2} style={{ backgroundColor: 'pink', height: 25 }} />
</Row>
Opens a confirmation popup. This library uses React Modal to render modals for web.
Container is a useful grid structure for mobile and web. It is a view that for reduced screens (xs
and sm
), it uses 95%
of the width. For larger screens (md
and lg
) it uses up to 960px
.
Displays a text input with datepicker functionality. This library uses React Datepicker and React Native Datepicker to render datepickers for web and mobile respectively.
Turns a component into a draggable component. This library uses React Draggable to render draggable components for web.
Displays a dropzone to upload files. This library uses React Dropzone to render the dropzone containers for web.
This library exports React Helmet. For mobile, Helmet won't do anything.
import React from 'react';
import { Row } from 'react-native-web-ui-components';
// You must use the Helmet export by this library to avoid conflicts.
import Helmet, { style } from 'react-native-web-ui-components/Helmet';
const MyComponent = () => (
<React.Fragment>
<Helmet>
<style>
{`
[data-class~="MyComponent__Row"] {
width: calc(100% - 20px);
}
`}
</style>
</Helmet>
<Row className="MyComponent__Row" />
</React.Fragment>
);
Displays summary of a text with a link to show more.
Displays a horizontal rule.
Displays an icon. This library uses React Fontawesome and Expo Vector Icons to render icons for web and mobile respectively.
Displays a link with an icon. This library uses React Fontawesome and Expo Vector Icons to render icons for web and mobile respectively.
Displays a text with an icon. This library uses React Fontawesome and Expo Vector Icons to render icons for web and mobile respectively.
Displays an image. This library uses react-native-expo-image-cache and <amp-img>
to render images for mobile and AMP pages respectively.
Displays a link. This library uses React Router to render links.
Displays a popup with a loading spinner. This library uses React Modal to display modals for web.
Displays a Row
that uses the entire window height.
Displays a link with active/inactive state (useful for menus). This library uses React Router to render links.
Displays a popup.
Displays a radiobox.
Row is a View with flexDirection: "row"
that follows Bootstrap's grid system. You can define the percentage of the width that should be used in different screen sizes. For example:
<Row>
<Row xs={12} sm={4} md={3} lg={2} style={{ backgroundColor: 'red', height: 25 }} />
<Row xs={12} sm={4} md={3} lg={2} style={{ backgroundColor: 'green', height: 25 }} />
<Row xs={12} sm={4} md={3} lg={2} style={{ backgroundColor: 'blue', height: 25 }}/>
<Row xs={12} sm={4} md={3} lg={2} style={{ backgroundColor: 'purple', height: 25 }} />
<Row xs={12} sm={4} md={3} lg={2} style={{ backgroundColor: 'yellow', height: 25 }} />
<Row xs={12} sm={4} md={3} lg={2} style={{ backgroundColor: 'pink', height: 25 }} />
</Row>
Helper to get screen properties.
See React Native's ScrollView. For mobile, the ScrollView exported by this library automatically dismiss the keyboard on scroll.
Displays a select input.
Displays a sidebar. This library uses React Sidebar and React Native Side Menu to render sidebars for web and mobile respectively.
Displays a spinner.
Prop type for styles.
import { StylePropType } from 'react-native-web-ui-components';
// ...
MyComponent.propTypes = {
style: StylePropType.isRequired,
};
See React Router's Switch.
Displays a tag input.
Displays a text. It automatically parses [tag](url)
into Link
components.
Displays a text input.
Displays a time range picker.
Displays a title text.
Displays a tooltip when hovering over a component. This library uses Tippy.js React to render tooltips for web. For mobile, this component is ignored.
See React Native's View.
Shows a component only for web platforms.
See React Native's WebView. For web, this component is ignored.
React Native Web UI Components theme can be customized at a globally and for each individual component. Please access https://github.com/CareLuLu/react-native-web-ui-components for the complete theme documentation.
A set of theme attributes can be defined globally and components will use these definitions as necessary.
const theme = {
// All components will receive the prop fontFamily
'*': {
fontFamily: {
regular: 'Lucida Sans',
bold: 'Lucida Sans Bold',
},
},
}
Themes can be overwritten by platform.
const theme = {
// All components will receive the prop fontFamily
'*': {
fontFamily: {
regular: 'Lucida Sans',
bold: 'Lucida Sans Bold',
},
},
platform: {
// When running on web, the fontFamily property will be overwritten by the following.
web: {
'*': {
fontFamily: {
regular: '"Lucida Sans Unicode","Lucida Grande",Arial,Helvetica,clean,sans-serif',
bold: '"Lucida Grande", "Lucida Sans Unicode","Lucida Grande",Arial,Helvetica,clean,sans-serif',
},
},
},
},
}
Themes can be overwritten by component.
const theme = {
// All components will receive the prop fontFamily
'*': {
fontFamily: {
regular: 'Lucida Sans',
bold: 'Lucida Sans Bold',
},
},
Title: {
// Title will receive the following fontFamily.
fontFamily: {
regular: 'Arial',
bold: 'Arial Bold',
},
},
}