Skip to content

Commit 48f0cd9

Browse files
committed
docs(blog): update draft 6.2 release notes blog post
1 parent 8a88457 commit 48f0cd9

File tree

1 file changed

+150
-31
lines changed

1 file changed

+150
-31
lines changed

apps/website/blog/2021-09-27-6-2-updates.mdx

Lines changed: 150 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
title: Announcing the 6.2 Release, Featuring Enhanced Model Rendering and Accessibility!
2+
title: What's New in v6.2?
33
author: Jules Sam. Randolph
44
author_title: Developer of React Native Render HTML v6
55
author_url: https://github.com/jsamr/
@@ -12,22 +12,36 @@ draft: true
1212
---
1313

1414
import APIReference from '@site/src/components/APIReference';
15+
import Reference from '@site/src/components/Reference';
1516

1617
It has been over two months since the first final version of the Foundry
17-
released has been made public.
18+
released has been made public. This new release focuses on two areas of
19+
improvements:
20+
21+
1. Accessibility;
22+
2. Richer model-based rendering.
23+
24+
As you will discover through this reading, both are somehow related. Let's find out how!
25+
26+
<!--truncate-->
1827

1928
## You Might not Need a Custom Component Renderer
2029

21-
Model-based custom rendering via <APIReference name="RenderHTMLProps"
30+
Model-based rendering via <APIReference name="RenderHTMLProps"
2231
member="customHTMLElementModels"/> prop has been a lightweight alternative to
2332
custom (component) renderers since the early stages of the Foundry release.
2433
However, it was limited to setting user agent styles (<APIReference
2534
name="HTMLElementModel" member="mixedUAStyles" />),
2635
although those styles could be derived from the DOM node element attributes
27-
(<APIReference name="HTMLElementModel" member="getUADerivedStyleFromAttributes" />).
36+
(the now-deprecated <APIReference name="HTMLElementModel" member="getUADerivedStyleFromAttributes" />).
37+
The below example is a reminder of how those element models can be defined, for instance to
38+
register a new `<blue-circle>` tag which renders to a 50 by 50 blue circle!
2839

2940
```js title="An Example of Model-Based Rendering"
30-
import RenderHTML, { HTMLElementModel } from 'react-native-render-html';
41+
import RenderHTML, {
42+
HTMLElementModel,
43+
HTMLContentModel
44+
} from 'react-native-render-html';
3145

3246
// The eponym prop to pass to RenderHTML
3347
const customHTMLElementModels = {
@@ -49,12 +63,14 @@ const customHTMLElementModels = {
4963
Keep in mind that <APIReference name="HTMLElementModel" member="mixedUAStyles"
5064
/> has a lower specificity than styles passed to `RenderHTML` such as
5165
&ZeroWidthSpace;<APIReference name="RenderHTMLProps" member="tagsStyles" />.
66+
See the [CSS Processing guide](/docs/flow/css-processing#specificity) section
67+
related to specificity for a refresher.
5268
:::
5369

5470
Version 6.2 ships with a bunch of new fields for HTML element models which
55-
should make model-based custom rendering more popular. Let's take a tour!
71+
should make model-based rendering more popular. Let's take a tour!
5672

57-
### `getMixedUAStyles` almost features CSS selectors!
73+
### `getMixedUAStyles` Tickles CSS Selectors!
5874

5975
This field deprecates <APIReference name="HTMLElementModel" member="getUADerivedStyleFromAttributes"/>; it's basically the same
6076
but its signature has changed: it receives the target `tnode` and DOM `element`, which lets us implement CSS-selector-like behaviors:
@@ -81,6 +97,11 @@ const customHTMLElementModels = {
8197
};
8298
```
8399

100+
However and as stated before, those styles will have a lower specificity than tags, classes and
101+
ID styles and as such, these are not "real" CSS selectors. Hopefully, CSS selectors will be
102+
implemented at some point, [you can upvote the feature request here](https://native-html.canny.io/features/p/support-complex-css-like-selectors-eg-div-button)!
103+
The hard challenge is that these should not impede performances. I am planning to explore this issue next year.
104+
84105
:::warning
85106
Beware that this `tnode` is an instance of <APIReference name="TNodeDescriptor"
86107
/>, which is a minimal `tnode` shape available during the Transient Render
@@ -93,15 +114,15 @@ to query the DOM and create your conditional styling rules.
93114

94115
### `reactNativeProps`
95116

96-
This field will set props to the native component during the rendering phase. It is an object with three optional properties:
117+
This field will set props to the native component during the rendering phase.
118+
It is an object with three optional properties (for reference, the shape of
119+
this object is a <APIReference name="ReactNativePropsDefinitions" />):
97120

98121
1. `text`, to pass native props to the `Text` component when the renderer is textual;
99122
2. `view`, to pass native props to the `View` component when the renderer is block;
100123
3. `native`, to pass props to either `View` or `Text` components, irrespective of the renderer type.
101124

102-
The type definition for this object is <APIReference name="ReactNativePropsDefinitions" />.
103-
104-
In the below example, we are defining a custom tag, `nav-widget`, and setting
125+
In the next snippet, we are defining a custom tag, `<nav-widget>`, and setting
105126
accessibility props to any underlying native component for the render phase. We
106127
can also define `onPress`, which will cause the renderer to use the
107128
&ZeroWidthSpace;<APIReference name="RenderHTMLProps" member="GenericPressable" /> instead of
@@ -143,21 +164,23 @@ name="ReactNativePropsDefinitions" />).
143164

144165
In the example below, a custom `nav-widget` tag is registered. This time, we
145166
are handling `onPress` events conditionally, based on attributes of the
146-
`tnode`. The snippets uses a phony API, `appNavigatorControler`, to navigate
167+
`tnode`. The snippets uses a phony API, `appNavigatorController`, to navigate
147168
between screens. Such API is easy to implement with a globally-defined ref to a
148-
`react-navigation` "navigation" object.
169+
[`react-navigation`](https://reactnavigation.org) "navigation" object.
149170

150171
:::important
151-
It is worth noting that you cannot use React hooks in any of element models functions. But you can use
152-
any ad-hoc API to emit events. If you really need React hooks, add a custom component renderer.
172+
It is worth noting that you cannot use React hooks in those element models
173+
functions. But you can use any ad-hoc API to emit events, and glue that logic
174+
to hooks. If you really need React hooks, it might be simple to [create a custom
175+
component renderer](/docs/guides/custom-renderers#component-based-custom-rendering).
153176
:::
154177

155178
```js title="Defining React Native props based on the TNode in an HTML element model"
156179
import RenderHTML, {
157180
HTMLContentModel,
158181
HTMLElementModel
159182
} from 'react-native-render-html';
160-
import appNavigatorControler from './appNavigatorControler';
183+
import appNavigatorController from './appNavigatorController';
161184

162185
// The eponym prop to pass to RenderHTML
163186
const customHTMLElementModels = {
@@ -171,7 +194,7 @@ const customHTMLElementModels = {
171194
onPress() {
172195
const targetScreen = tnode.attributes['data-target'];
173196
const targetParams = tnode.attributes['data-params'];
174-
appNavigatorControler.navigate(
197+
appNavigatorController.navigate(
175198
targetScreen,
176199
targetParams ? JSON.parse(targetParams) : null
177200
);
@@ -189,18 +212,46 @@ Don't forget that you can mix model-based and component-based rendering!
189212

190213
## A Focus on Accessibility
191214

192-
### Support for `aria-label` and `aria-role` Attributes
215+
Screen readers integration has been worked on sparsely since the Foundry
216+
release, by addressing issues raised by the community, but until v6.2 there has
217+
not been structural improvements to cover the full range of required features.
218+
Thanks to the new Transient Render Engine, it has become very easy to define
219+
translations from HTML attributes to React Native props within the engine.
220+
Let's find out what's new!
221+
222+
### Support for `aria-label` and `role` Attributes
223+
224+
On one hand, <Reference type="html-attr" url="https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-label_attribute" name="aria-label" />
225+
is used to hint screen readers on how a specific node **and all its descendants** should be read out loud. It is especially
226+
useful to handle icons which don't have inner semantic meanings. This attribute has a React Native prop equivalent, namely
227+
[`accessibilityLabel`](https://reactnative.dev/docs/accessibility#accessibilitylabel), which serves the same purpose.
228+
On the other hand, <Reference type="html-attr" url="https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles" name="role" />
229+
informs the screen reader of the target element nature and how a user might interact with it.
230+
This attributes roughly maps to React Native [`accessibilityRole`](https://reactnative.dev/docs/accessibility#accessibilityrole)
231+
prop, although the set of allowed values slightly differs.
232+
See [all supported roles and their mapping
233+
here](https://github.com/native-html/core/blob/00c0cd1034c4cb721e991d5c02b232c4d64eae3d/packages/transient-render-engine/src/tree/TNodeCtor.ts#L33).
234+
235+
:::warning
236+
Remember that a majority of interactive elements will not be rendered by this library. You must change their
237+
content model to <APIReference name="HTMLContentModel" member="block" /> in order for them to be rendered.
238+
Nevertheless, those interactive element models are already shipped with the appropriate `accessibilityRole` prop.
239+
:::
240+
241+
The new Transient Render Engine will from now on
242+
translate both attributes to their React Native counterparts.
193243

194-
`aria-label` and `aria-role` HTML attributes roughly map to
195-
`accessibilityLabel` and `accessibilityRole` React Native props. The new
196-
Transient Render Engine which features React Native props generation will from now on
197-
translate both attributes to their React Native counterparts. The mapping rules
198-
for `aria-role` have been extracted from `react-native-web`.
244+
:::info Midly relevant
245+
The mapping rules from the `role` HTML attribute to React Native props has
246+
been greatly influenced by those of
247+
[`react-native-web`](https://github.com/necolas/react-native-web/blob/66d01734ce3ffcfea61e05aa1b45015658b3f2af/packages/react-native-web/src/modules/AccessibilityUtil/propsToAriaRole.js),
248+
the other way round!
249+
:::
199250

200251
### Accessible `<a>` Tags
201252

202253
`<a>` tags now receive an `accessibilityRole="link"` prop when their `href`
203-
attribute is non-empty. Let's see now how we could set a custom generic hint by
254+
attribute is non-empty. Let's see now how we could set [an accessibility hint](https://reactnative.dev/docs/accessibility#accessibilityhint) by
204255
extending the HTML model:
205256

206257
```ts
@@ -217,9 +268,13 @@ const customHTMLElementModels = {
217268
};
218269
```
219270

271+
Notice that <APIReference full name="HTMLElementModel" member="extend" />
272+
method can now take a generator function. Pretty convenient to merge
273+
nested fields!
274+
220275
:::warning
221276
Because of a [React Native
222-
limitation](https://github.com/facebook/react-native/issues/32004), nested
277+
bug](https://github.com/facebook/react-native/issues/32004), nested
223278
`Text` elements are not accessible, which means that the screen reader will not
224279
be able to identify `<a>` tags as links when grouped with other textual
225280
elements. Below is an example:
@@ -233,9 +288,8 @@ elements. Below is an example:
233288

234289
Luke Walczak from Callstack [explains how to circumvent this issue in a great
235290
post](https://callstack.com/blog/react-native-android-accessibility-tips/).
236-
Unfortunately, this workaround is not generalizable and we will have to wait
291+
Unfortunately, this workaround cannot be genericized and we will have to wait
237292
for an upstream fix.
238-
239293
:::
240294

241295
### Enhanced Accessibility for `<img>` Tags
@@ -254,7 +308,7 @@ image container, to make it independent of the internal state.
254308
### Accessible `<h1-6>` Tags
255309

256310
React Native has a “header” accessibility role which screen reader users depend
257-
on a lot to identify efficiently the content hierarchy of a screen. Until this
311+
on widely to identify quickly the content hierarchy of a screen. Until this
258312
release, `react-native-render-html` did not pass this role to heading tags.
259313

260314
## Other Enhancements
@@ -277,20 +331,85 @@ Please not that this is not full support. The TRE will map `user-select: none;`
277331
any other value to `selectable={true}`.
278332
:::
279333

280-
### `getNativePropsForTnode` Function
334+
## Bonus: Version 6.1 Features
281335

282-
## Bonus: Notes on Version 6.1
336+
### `renderIndex` and `renderLength` Props to Custom Component Renderers
283337

284-
### `renderIndex` and `renderLength` Props to `TDefaultRenderer`
338+
Those props passed to custom component renderers give you positional
339+
information regarding this element in the render tree. `renderIndex` will often
340+
coincide with `tnode.index` but there are subtle differences.
285341

286342
### `enableExperimentalBRCollapsing` Prop
287343

344+
This **recommended prop** allows consumers to circumvent a bug in the Foundry
345+
release where line breaks (`<br>`) would be printed erroneously, such
346+
as at the end of a paragraph. It will be enabled by default in the next major
347+
release.
348+
349+
:::tip learn more
350+
Read the complete explanation for this prop [in the textual content guide](/docs/content/textual#line-breaks).
351+
:::
352+
288353
### `enableExperimentalGhostLinesPrevention` Prop
289354

355+
This **recommended prop** allows to circumvent [a React Native bug](https://github.com/facebook/react-native/issues/32062) where empty
356+
`Text` elements would be printed as ghost lines of fixed height (around 20 dpi).
357+
358+
:::tip learn more
359+
Read the complete explanation for this prop [in the textual content guide](/docs/content/textual#empty-tags).
360+
:::
361+
290362
### `provideEmbeddedHeaders` Prop
291363

292364
This is a function prop which allows consumer to generate HTTP headers for
293365
remote resources. It currently works with `<img>` and `<iframe>` tags (from the
294366
`@native-html/iframe-plugin` lib).
295367

368+
:::tip learn more
369+
See for example how it can be used with images [in the image content guide](/docs/content/images#providing-headers).
370+
:::
371+
296372
### `bypassAnonymousTPhrasingNodes` Prop
373+
374+
This prop makes the React rendering layer omit grouping (anonymous) `TPhrasing`
375+
nodes which have only one child. It is best learn by example. For instance, the
376+
following HTML snippet:
377+
378+
```html
379+
<p>A sentence.</p>
380+
```
381+
382+
will produce the below Transient Render Tree:
383+
384+
```xml
385+
<TBlock tagName="p">
386+
<TPhrasing>
387+
<TText>A sentence.</TText>
388+
</TPhrasing>
389+
</TBlock>
390+
```
391+
392+
which by default rendering rules, would be translated to the below React render tree:
393+
394+
```xml
395+
<View>
396+
<Text>
397+
<Text>A sentence.</Text>
398+
</Text>
399+
</View>
400+
```
401+
402+
However, when `bypassAnonymousTPhrasingNodes` prop is `true` (the default),
403+
the render tree will be simplified to:
404+
405+
```xml
406+
<View>
407+
<Text>A sentence.</Text>
408+
</View>
409+
```
410+
411+
This behavior is preferred for many reasons. The most simple one is that it
412+
simplifies the render tree. The less React element there is, the best it is
413+
performance-wise. Moreover, there are a lot of React Native bugs implying
414+
nested `Text` nodes, so this simplification limits the number of occurrences
415+
of those bugs.

0 commit comments

Comments
 (0)