Skip to content

Commit 79666ab

Browse files
Merge pull request #3 from react-declarative/docs
Docs
2 parents 6d1c245 + ccbf03e commit 79666ab

16 files changed

+243
-18
lines changed

Diff for: README.md

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
55
![screencast](./assets/screencast.gif)
66

7+
The howto guide available [by the link](https://github.com/react-declarative/rn-declarative/tree/master/docs/HOWTO.md)
8+
79
## Installation
810

911
The package is split into two parts: [rn-declarative](https://www.npmjs.com/package/rn-declarative) and [rn-declarative-eva](https://www.npmjs.com/package/rn-declarative-eva). The `rn-declarative` manage the core part: It independent from any UI Kit and can be easely installed to any project. The `rn-declarative-eva` contains bindings to the [UI Kitten](https://akveo.github.io/react-native-ui-kitten/) - an open source ui components for `react-native` build on top of [Eva Design](https://eva.design/). By replacing `rn-declarative-eva` package you can connect the `rn-declarative` to any UI kit, for example, [react-native-paper](https://reactnativepaper.com/)

Diff for: assets/bottom_baseline.png

15.1 KB
Loading

Diff for: assets/bottom_baseline_issue.png

21.9 KB
Loading

Diff for: assets/dex.png

545 KB
Loading

Diff for: assets/fold.png

1.66 MB
Loading

Diff for: assets/top_baseline.png

22.8 KB
Loading

Diff for: assets/top_baseline_issue.png

9.17 KB
Loading

Diff for: demo/package-lock.json

+8-8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: demo/package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
"react-native": "0.74.1",
1111
"react-native-svg": "15.2.0",
1212
"react-native-web": "~0.19.6",
13-
"rn-declarative": "^0.0.53",
14-
"rn-declarative-eva": "^0.0.41"
13+
"rn-declarative": "^0.0.54",
14+
"rn-declarative-eva": "^0.0.42"
1515
},
1616
"devDependencies": {
1717
"@babel/core": "^7.19.3",

Diff for: docs/HOWTO.md

+219
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
# Responsive Layout in React Native
2+
3+
> The challenges encountered when porting a classic React application to React Native are discussed in this article. It focuses on supporting various device form factors, including the Galaxy Fold.
4+
5+
## Проблема
6+
7+
Some time ago, I started developing a mobile application with React Native. The issue is that the application needs to support both the Galaxy Fold and Samsung DeX.
8+
9+
![fold](../assets/fold.png)
10+
11+
As a result, the question of implementing adaptive layout forms arose. The same application needs to render forms in a single column mode on phones and two columns in tablet mode. If different layout codes are written, it would require duplicating form logic; at the very least, a new field would be added twice.
12+
![dex](../assets/dex.png)
13+
14+
Yoga Layout, the layout engine from React Native, only supports flexbox. Consequently, implementing layouts correctly while avoiding excessive nesting of Views is a non-trivial task: nested groups must be displayed from the top edge of the parent, and input fields must align to the bottom edge of the display line (baseline).
15+
16+
![top_baseline](../assets/top_baseline.png)
17+
18+
Ignoring the rule of binding field groups to the top edge results in an ugly layout.
19+
20+
![bottom_baseline_issue](../assets/bottom_baseline_issue.png)
21+
22+
Fields within a group should be bound to the bottom edge of the row.
23+
24+
![bottom_baseline](../assets/bottom_baseline.png)
25+
26+
The ugliness of having a top baseline for fields is not immediately obvious but becomes very noticeable when using standard fields from Material 1 on Android 4.
27+
28+
![top_baseline_issue](../assets/top_baseline_issue.png)
29+
30+
## Solution
31+
32+
To delegate the complex task of proper form layout to a less specialized developer, a templating system was developed that generates layouts according to the rules mentioned above from a JSON template. An example template is shown in the code block below:
33+
34+
```tsx
35+
import { One, FieldType, TypedField } from 'rn-declarative';
36+
37+
import { Text } from '@ui-kitten/components';
38+
import { ScrollView } from 'react-native';
39+
40+
const fields: TypedField[] = [
41+
{
42+
type: FieldType.Component,
43+
style: {
44+
justifyContent: 'center',
45+
width: '100%',
46+
height: 125,
47+
},
48+
element: () => (
49+
<Text category='h4'>
50+
Adaptive columns
51+
</Text>
52+
),
53+
},
54+
{
55+
type: FieldType.Group,
56+
style: {
57+
width: '100%',
58+
},
59+
fields: [
60+
{
61+
type: FieldType.Group,
62+
phoneStyle: {
63+
width: '100%',
64+
},
65+
tabletStyle: {
66+
width: '50%',
67+
},
68+
desktopStyle: {
69+
width: '25%',
70+
},
71+
fields: [
72+
{
73+
type: FieldType.Component,
74+
style: {
75+
width: '100%',
76+
},
77+
element: () => (
78+
<Text category='h6'>
79+
FieldType.Text
80+
</Text>
81+
),
82+
},
83+
{
84+
type: FieldType.Text,
85+
style: {
86+
width: '100%',
87+
},
88+
name: 'text',
89+
title: 'Text',
90+
description: 'Single line',
91+
},
92+
{
93+
type: FieldType.Text,
94+
style: {
95+
width: '100%',
96+
},
97+
validation: {
98+
required: true,
99+
},
100+
dirty: true,
101+
name: 'text_invalid',
102+
title: 'Text',
103+
description: 'Invalid',
104+
},
105+
{
106+
type: FieldType.Text,
107+
style: {
108+
width: '100%',
109+
},
110+
inputMultiline: true,
111+
name: 'text',
112+
title: 'Text',
113+
description: 'Multi line',
114+
},
115+
],
116+
},
117+
118+
...
119+
120+
];
121+
122+
export const MainPage = () => {
123+
return (
124+
<ScrollView>
125+
<One fields={fields} onChange={console.log} />
126+
</ScrollView>
127+
);
128+
};
129+
130+
export default MainPage;
131+
```
132+
133+
The library is divided into two modules: [rn-declarative](https://www.npmjs.com/package/rn-declarative) and [rn-declarative-eva](https://www.npmjs.com/package/rn-declarative-eva) . The first contains the core logic and does not depend on a UI kit: it can be installed in any project regardless of the `react-native` version or framework (both `Expo` and `react-native-community` starter kits are supported). Besides `react` and `react-native`, there are no other dependencies.
134+
135+
```tsx
136+
import { useMediaContext } from 'rn-declarative'
137+
138+
...
139+
140+
const { isPhone, isTablet, isDesktop } = useMediaContext();
141+
```
142+
143+
Layout and field widths are configured using `phoneStyle`, `tabletStyle`, and `desktopStyle` properties. If you don't want to change the style based on the device form factor, you can just use `style`. Connecting a UI Kit is done through the context with slots `<OneSlotFactory />` for implementing `FieldType`.
144+
145+
```tsx
146+
import { Toggle } from '@ui-kitten/components';
147+
import { OneSlotFactory, ISwitchSlot } from 'rn-declarative';
148+
149+
export const Switch = ({
150+
disabled,
151+
value,
152+
onChange,
153+
onFocus,
154+
onBlur,
155+
title,
156+
}: ISwitchSlot) => {
157+
return (
158+
<Toggle
159+
checked={Boolean(value)}
160+
disabled={disabled}
161+
onChange={() => onChange(!value)}
162+
onFocus={onFocus}
163+
onBlur={onBlur}
164+
>
165+
{title}
166+
</Toggle>
167+
);
168+
};
169+
170+
...
171+
172+
const defaultSlots = {
173+
CheckBox,
174+
Combo,
175+
Items,
176+
Radio,
177+
Button,
178+
Text,
179+
Switch,
180+
YesNo,
181+
};
182+
183+
...
184+
185+
<OneSlotFactory
186+
{...defaultSlots}
187+
>
188+
{children}
189+
</OneSlotFactory>
190+
```
191+
192+
P.S. Any other component or custom layout can be seamlessly integrated through `FieldType.Component` (with `onChange` and `value`) or `FieldType.Layout`.
193+
194+
```tsx
195+
{
196+
type: FieldType.Component,
197+
element: () => (
198+
<Text category='h4'>
199+
Sample component
200+
</Text>
201+
),
202+
},
203+
204+
...
205+
206+
{
207+
type: FieldType.Layout,
208+
customLayout: ({ children }) => (
209+
<ScrollView>
210+
{children}
211+
</ScrollView>
212+
),
213+
},
214+
```
215+
216+
The component code is published on GitHub and can be viewed at:
217+
[https://github.com/react-declarative/rn-declarative/](https://github.com/react-declarative/rn-declarative/)
218+
219+
Thank you for your attention!

Diff for: packages/rn-declarative-eva/README.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
> Responsive layout for the `react-native`
44
5-
![screencast](https://github.com/react-declarative/rn-declarative/blob/HEAD/assets/screencast.gif)
5+
![screencast](./assets/screencast.gif)
6+
7+
The howto guide available [by the link](https://github.com/react-declarative/rn-declarative/tree/master/docs/HOWTO.md)
68

79
## Installation
810

Diff for: packages/rn-declarative-eva/package-lock.json

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: packages/rn-declarative-eva/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "rn-declarative-eva",
3-
"version": "0.0.41",
3+
"version": "0.0.42",
44
"description": "A responsive layout for the react-native",
55
"private": false,
66
"author": {

Diff for: packages/rn-declarative/README.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
> Responsive layout for the `react-native`
44
5-
![screencast](https://github.com/react-declarative/rn-declarative/blob/HEAD/assets/screencast.gif)
5+
![screencast](./assets/screencast.gif)
6+
7+
The howto guide available [by the link](https://github.com/react-declarative/rn-declarative/tree/master/docs/HOWTO.md)
68

79
## Installation
810

Diff for: packages/rn-declarative/package-lock.json

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: packages/rn-declarative/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "rn-declarative",
3-
"version": "0.0.53",
3+
"version": "0.0.54",
44
"description": "A responsive layout for the react-native",
55
"private": false,
66
"author": {

0 commit comments

Comments
 (0)