diff --git a/packages/app-mobile/components/checkbox.js b/packages/app-mobile/components/checkbox.js
new file mode 100644
index 0000000000..b6919841dc
--- /dev/null
+++ b/packages/app-mobile/components/checkbox.js
@@ -0,0 +1,78 @@
+const React = require('react');
+const Component = React.Component;
+const { View, TouchableHighlight } = require('react-native');
+const Icon = require('react-native-vector-icons/Ionicons').default;
+Icon.loadFont();
+
+const styles = {
+ checkboxIcon: {
+ fontSize: 20,
+ height: 22,
+ // marginRight: 10,
+ },
+};
+
+class Checkbox extends Component {
+ constructor() {
+ super();
+ this.state = {
+ checked: false,
+ };
+ }
+
+ UNSAFE_componentWillMount() {
+ this.setState({ checked: this.props.checked });
+ }
+
+ UNSAFE_componentWillReceiveProps(newProps) {
+ if ('checked' in newProps) {
+ this.setState({ checked: newProps.checked });
+ }
+ }
+
+ onPress() {
+ const newChecked = !this.state.checked;
+ this.setState({ checked: newChecked });
+ if (this.props.onChange) this.props.onChange(newChecked);
+ }
+
+ render() {
+ const iconName = this.state.checked ? 'md-checkbox-outline' : 'md-square-outline';
+
+ const style = this.props.style ? Object.assign({}, this.props.style) : {};
+ style.justifyContent = 'center';
+ style.alignItems = 'center';
+
+ const checkboxIconStyle = Object.assign({}, styles.checkboxIcon);
+ if (style.color) checkboxIconStyle.color = style.color;
+
+ if (style.paddingTop) checkboxIconStyle.marginTop = style.paddingTop;
+ if (style.paddingBottom) checkboxIconStyle.marginBottom = style.paddingBottom;
+ if (style.paddingLeft) checkboxIconStyle.marginLeft = style.paddingLeft;
+ if (style.paddingRight) checkboxIconStyle.marginRight = style.paddingRight;
+
+ const thStyle = {
+ justifyContent: 'center',
+ alignItems: 'center',
+ };
+
+ if (style && style.display === 'none') return ;
+
+ // if (style.display) thStyle.display = style.display;
+
+ return (
+ this.onPress()}
+ style={thStyle}
+ accessibilityRole="checkbox"
+ accessibilityState={{
+ checked: this.state.checked,
+ }}
+ accessibilityLabel={this.props.accessibilityLabel ?? ''}>
+
+
+ );
+ }
+}
+
+module.exports = { Checkbox };
diff --git a/packages/app-mobile/components/global-style.js b/packages/app-mobile/components/global-style.js
new file mode 100644
index 0000000000..a6f42d1597
--- /dev/null
+++ b/packages/app-mobile/components/global-style.js
@@ -0,0 +1,105 @@
+const Setting = require('@joplin/lib/models/Setting').default;
+const { Platform } = require('react-native');
+const { themeById } = require('@joplin/lib/theme');
+
+const baseStyle = {
+ appearance: 'light',
+ fontSize: 16,
+ noteViewerFontSize: 16,
+ margin: 15, // No text and no interactive component should be within this margin
+ itemMarginTop: 10,
+ itemMarginBottom: 10,
+ fontSizeSmaller: 14,
+ disabledOpacity: 0.2,
+ lineHeight: '1.6em',
+};
+
+const themeCache_ = {};
+
+function addExtraStyles(style) {
+ style.marginRight = style.margin;
+ style.marginLeft = style.margin;
+ style.marginTop = style.margin;
+ style.marginBottom = style.margin;
+
+ style.icon = {
+ color: style.color,
+ fontSize: 30,
+ };
+
+ style.lineInput = {
+ color: style.color,
+ backgroundColor: style.backgroundColor,
+ borderBottomWidth: 1,
+ borderColor: style.dividerColor,
+ paddingBottom: 0,
+ };
+
+ if (Platform.OS === 'ios') {
+ delete style.lineInput.borderBottomWidth;
+ delete style.lineInput.borderColor;
+ }
+
+ style.buttonRow = {
+ flexDirection: 'row',
+ borderTopWidth: 1,
+ borderTopColor: style.dividerColor,
+ paddingTop: 10,
+ };
+
+ style.normalText = {
+ color: style.color,
+ fontSize: style.fontSize,
+ };
+
+ style.urlText = {
+ color: style.urlColor,
+ fontSize: style.fontSize,
+ };
+
+ style.headerStyle = {
+ color: style.color,
+ fontSize: style.fontSize * 1.2,
+ fontWeight: 'bold',
+ };
+
+ style.headerWrapperStyle = {
+ backgroundColor: style.headerBackgroundColor,
+ };
+
+ style.keyboardAppearance = style.appearance;
+
+ return style;
+}
+
+function editorFont(fontId) {
+ // IMPORTANT: The font mapping must match the one in Setting.js
+ const fonts = {
+ [Setting.FONT_DEFAULT]: null,
+ [Setting.FONT_MENLO]: 'Menlo',
+ [Setting.FONT_COURIER_NEW]: 'Courier New',
+ [Setting.FONT_AVENIR]: 'Avenir',
+ [Setting.FONT_MONOSPACE]: 'monospace',
+ };
+ if (!fontId) {
+ // console.warn('Editor font not set! Falling back to default font."');
+ fontId = Setting.FONT_DEFAULT;
+ }
+ return fonts[fontId];
+}
+
+function themeStyle(theme) {
+ if (!theme) {
+ console.warn('Theme not set! Defaulting to Light theme.');
+ theme = Setting.THEME_LIGHT;
+ }
+
+ const cacheKey = [theme].join('-');
+ if (themeCache_[cacheKey]) return themeCache_[cacheKey];
+
+ const output = Object.assign({}, baseStyle, themeById(theme));
+ themeCache_[cacheKey] = addExtraStyles(output);
+ return themeCache_[cacheKey];
+}
+
+module.exports = { themeStyle, editorFont };