Name Date Size #Lines LOC

..26-Sep-2023-

babel/H26-Sep-2023-196165

build/H26-Sep-2023-1,123936

src/H26-Sep-2023-2,7962,410

.eslintrc.jsH A D26-Sep-2023103 31

.npmignoreH A D26-Sep-202328 33

CHANGELOG.mdH A D26-Sep-20231.3 KiB4825

README.mdH A D26-Sep-202333.3 KiB849636

babel.config.jsH A D26-Sep-2023104 31

babel.jsH A D26-Sep-20233.4 KiB143120

package.jsonH A D26-Sep-20231.5 KiB6362

tsconfig.jsonH A D26-Sep-2023217 109

README.md

1<h1 align="center">@expo/html-elements</h1>
2
3<img alt="Product: demo" src="https://dev-to-uploads.s3.amazonaws.com/i/xoc3yx7qfqf6e1w6mm2e.png" />
4
5<p align="center">
6  <!-- iOS -->
7  <img alt="Supports Expo iOS" longdesc="Supports Expo iOS" src="https://img.shields.io/badge/iOS-4630EB.svg?style=flat-square&logo=APPLE&labelColor=999999&logoColor=fff" />
8  <!-- Android -->
9  <img alt="Supports Expo Android" longdesc="Supports Expo Android" src="https://img.shields.io/badge/Android-4630EB.svg?style=flat-square&logo=ANDROID&labelColor=A4C639&logoColor=fff" />
10  <!-- Web -->
11  <img alt="Supports Expo Web" longdesc="Supports Expo Web" src="https://img.shields.io/badge/web-4630EB.svg?style=flat-square&logo=GOOGLE-CHROME&labelColor=4285F4&logoColor=fff" />
12  <a aria-label="Circle CI" href="https://circleci.com/gh/expo/expo/tree/main">
13    <img alt="Circle CI" src="https://flat.badgen.net/circleci/github/expo/expo?label=Circle%20CI&labelColor=555555&icon=circleci">
14  </a>
15</p>
16
17Simple, light-weight, and well tested, universal semantic HTML elements as React components for iOS, Android, web, and desktop apps!
18
19We at Expo recommend using platform agnostic primitives like `View`, `Image`, and `Text` whenever possible but sometimes that's not easy. Some primitives like Tables, and Footers are native to web only and currently have no way of easily accessing. This package aims to solve that while still being an optimal UI package for iOS, and Android.
20
21### What you get
22
23- Using `@expo/html-elements` will optimize your website for SEO and accessibility. Meaning your websites are indexed more accurately and your native apps better accommodate physically impaired users.
24  - This package takes full advantage of [`react-native-web` a11y rules](https://github.com/necolas/react-native-web/blob/master/packages/docs/src/guides/accessibility.stories.mdx) whenever possible.
25  - For example, the `H1` component will render an `<h1 />` on web, a `UILabel` on iOS, and a `TextView` on Android.
26- Every component can accept styles from the `StyleSheet` API.
27- TypeScript works for iOS, Android, and web, no more having to create monkey patches to use `href` on a `Text` element.
28- Every component is tested render **tested universally** for iOS, Android, and Web using the package [`jest-expo-enzyme`](https://www.npmjs.com/package/jest-expo-enzyme). Each element is also **E2E tested** on iOS with Detox, and web with [`jest-expo-puppeteer`](https://www.npmjs.com/package/jest-expo-puppeteer).
29- This package is completely side-effect free!
30
31## Setup
32
33Install:
34
35```
36yarn add @expo/html-elements
37```
38
39Import and use the package:
40
41```tsx
42import { H1 } from '@expo/html-elements';
43```
44
45# Components
46
47Here is a list of all the currently supported elements and the web feature they map to. Not all HTML elements are supported. There are some HTML elements that mostly overlap with some universal modules, you should always try to use the universal modules whenever possible. All supported components are a capitalized variation of the semantic HTML they implement/emulate.
48
49| HTML                                |      `@expo/html-elements`      |
50| ----------------------------------- | :-----------------------------: |
51| [`<a />`][html-a]                   |          [`<A />`](#a)          |
52| [`<article />`][html-article]       |    [`<Article />`](#article)    |
53| [`<aside />`][html-aside]           |      [`<Aside />`](#aside)      |
54| [`<b />`][html-b]                   |          [`<B />`](#b)          |
55| [`<blockquote />`][html-blockquote] | [`<BlockQuote />`](#blockquote) |
56| [`<br />`][html-br]                 |         [`<BR />`](#br)         |
57| [`<caption />`][html-caption]       |    [`<Caption />`](#caption)    |
58| [`<code />`][html-code]             |       [`<Code />`](#code)       |
59| [`<del />`][html-del]               |        [`<Del />`](#del)        |
60| [`<div />`][html-div]               |        [`<Div />`](#div)        |
61| [`<em />`][html-em]                 |         [`<EM />`](#em)         |
62| [`<footer />`][html-footer]         |     [`<Footer />`](#footer)     |
63| [`<h1 />`][html-h1]                 |         [`<H1 />`](#h1)         |
64| [`<h2 />`][html-h2]                 |         [`<H2 />`](#h2)         |
65| [`<h3 />`][html-h3]                 |         [`<H3 />`](#h3)         |
66| [`<h4 />`][html-h4]                 |         [`<H4 />`](#h4)         |
67| [`<h5 />`][html-h5]                 |         [`<H5 />`](#h5)         |
68| [`<h6 />`][html-h6]                 |         [`<H6 />`](#h6)         |
69| [`<header />`][html-header]         |     [`<Header />`](#header)     |
70| [`<hr />`][html-hr]                 |         [`<HR />`](#hr)         |
71| [`<i />`][html-i]                   |          [`<I />`](#i)          |
72| [`<main />`][html-main]             |       [`<Main />`](#main)       |
73| [`<mark />`][html-mark]             |       [`<Mark />`](#mark)       |
74| [`<nav />`][html-nav]               |        [`<Nav />`](#nav)        |
75| [`<p />`][html-p]                   |          [`<P />`](#p)          |
76| [`<pre />`][html-pre]               |        [`<Pre />`](#pre)        |
77| [`<q />`][html-q]                   |          [`<Q />`](#q)          |
78| [`<s />`][html-s]                   |          [`<S />`](#s)          |
79| [`<section />`][html-section]       |    [`<Section />`](#section)    |
80| [`<span />`][html-span]             |       [`<Span />`](#span)       |
81| [`<strong />`][html-strong]         |     [`<Strong />`](#strong)     |
82| [`<table />`][html-table]           |      [`<Table />`](#table)      |
83| [`<tbody />`][html-tbody]           |      [`<TBody />`](#tbody)      |
84| [`<td />`][html-td]                 |         [`<TD />`](#td)         |
85| [`<tfoot />`][html-tfoot]           |      [`<TFoot />`](#tfoot)      |
86| [`<th />`][html-th]                 |         [`<TH />`](#th)         |
87| [`<thead />`][html-thead]           |      [`<THead />`](#thead)      |
88| [`<time />`][html-time]             |       [`<Time />`](#time)       |
89| [`<tr />`][html-tr]                 |         [`<TR />`](#tr)         |
90| [`<ul />`][html-ul]                 |         [`<UL />`](#ul)         |
91| [`<li />`][html-li]                 |         [`<LI />`](#li)         |
92| [`<details />`][html-details]       |            ⏱ Pending            |
93| [`<summary />`][html-summary]       |            ⏱ Pending            |
94| [`<progress />`][html-progress]     |            ⏱ Pending            |
95| [`<select />`][html-select]         |            ⏱ Pending            |
96| [`<picture />`][html-picture]       |            ⏱ Pending            |
97| [`<figure />`][html-figure]         |            ⏱ Pending            |
98| [`<figcaption />`][html-figcaption] |            ⏱ Pending            |
99| [`<form />`][html-form]             |            ⏱ Pending            |
100| [`<label />`][html-label]           |            ⏱ Pending            |
101
102## External
103
104Other features not implemented in this package can be found in different parts of the Expo ecosystem.
105
106| HTML                            |      Universal       |                                                        Package                                                         |
107| ------------------------------- | :------------------: | :--------------------------------------------------------------------------------------------------------------------: |
108| `<audio />`                     |       `Audio`        |                                                 [`expo-av`][ex-audio]                                                  |
109| `<button />`                    |     `<Button />`     |                                                     `react-native`                                                     |
110| `<input type="text" />`         |   `<TextInput />`    |                                                     `react-native`                                                     |
111| `<input type="file" />`         |    `ImagePicker`     |                                            [`expo-image-picker`][ex-ipick]                                             |
112| `<input type="file" />`         |   `DocumentPicker`   |                                           [`expo-document-picker`][ex-dpick]                                           |
113| `<canvas />`                    |     `<GLView />`     |                                     [`expo-gl`][ex-gl] & [Expo Canvas][ex-canvas]                                      |
114| `<iframe />`                    |    `<WebView />`     | [`<WebView />`][ex-webview]. `@react-native-community/web-view` is not maintained by Expo and doesn't have web support |
115| [`<link />`][html-link]         |         None         |              Eject the `index.html` with `npx expo customize` and link resources directly with `<link />`              |
116| [`<noscript />`][html-noscript] |         None         |                Eject the `index.html` with `npx expo customize` and use `<noscript />` directly as HTML                |
117| `<div />`                       |      `<View />`      |                                                     `react-native`                                                     |
118| `<img />`                       |     `<Image />`      |                                                     `react-native`                                                     |
119| `<span />`                      |      `<Text />`      |                                                     `react-native`                                                     |
120| `<video />`                     |     `<Video />`      |                                                  [`expo-av`][ex-vid]                                                   |
121| `style="backdrop-filter"`       |    `<BlurView />`    |                                                 [`expo-blur`][ex-blur]                                                 |
122| `style="linear-gradient()"`     | `<LinearGradient />` |                                         [`expo-linear-gradient`][ex-gradient]                                          |
123
124[ex-gradient]: https://docs.expo.dev/versions/latest/sdk/linear-gradient/
125[ex-webview]: https://docs.expo.dev/versions/latest/sdk/webview/
126[ex-audio]: https://docs.expo.dev/versions/latest/sdk/audio
127[ex-gl]: https://docs.expo.dev/versions/latest/sdk/gl-view
128[ex-canvas]: https://github.com/expo/expo-2d-context
129[html-noscript]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/noscript
130[html-link]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link
131[ex-blur]: https://docs.expo.dev/versions/latest/sdk/blur-view/
132[ex-vid]: https://docs.expo.dev/versions/latest/sdk/video/
133[ex-ipick]: https://docs.expo.dev/versions/latest/sdk/imagepicker/
134[ex-dpick]: https://docs.expo.dev/versions/latest/sdk/document-picker/
135
136## Headings
137
138Header elements will use the expected [font size and margins from web](http://trac.webkit.org/browser/trunk/Source/WebCore/css/html.css) universally. You can see how the native CSS units (rem, and em) are transformed in [css/units](src/css/units.ts).
139
140```tsx
141import { H1, H2, H3, H4, H5, H6 } from '@expo/html-elements';
142```
143
144### `<H1/>`
145
146```tsx
147import { H1 } from '@expo/html-elements';
148export default () => <H1>Example<H1/>
149```
150
151| Platform | Output                                                 |
152| -------- | ------------------------------------------------------ |
153| Web      | `<h1 aria-level="1" dir="auto" role="heading" />`      |
154| Native   | `<Text accessibilityRole="header" style={[Custom]} />` |
155
156### `<H2/>`
157
158```tsx
159import { H2 } from '@expo/html-elements';
160export default () => <H2>Example<H2/>
161```
162
163| Platform | Output                                                 |
164| -------- | ------------------------------------------------------ |
165| Web      | `<h2 aria-level="2" dir="auto" role="heading" />`      |
166| Native   | `<Text accessibilityRole="header" style={[Custom]} />` |
167
168### `<H3/>`
169
170```tsx
171import { H3 } from '@expo/html-elements';
172export default () => <H3>Example<H3/>
173```
174
175| Platform | Output                                                 |
176| -------- | ------------------------------------------------------ |
177| Web      | `<h3 aria-level="3" dir="auto" role="heading" />`      |
178| Native   | `<Text accessibilityRole="header" style={[Custom]} />` |
179
180### `<H4/>`
181
182```tsx
183import { H4 } from '@expo/html-elements';
184export default () => <H4>Example<H4/>
185```
186
187| Platform | Output                                                 |
188| -------- | ------------------------------------------------------ |
189| Web      | `<h4 aria-level="4" dir="auto" role="heading" />`      |
190| Native   | `<Text accessibilityRole="header" style={[Custom]} />` |
191
192### `<H5/>`
193
194```tsx
195import { H5 } from '@expo/html-elements';
196export default () => <H5>Example<H5/>
197```
198
199| Platform | Output                                                 |
200| -------- | ------------------------------------------------------ |
201| Web      | `<h5 aria-level="5" dir="auto" role="heading" />`      |
202| Native   | `<Text accessibilityRole="header" style={[Custom]} />` |
203
204### `<H6/>`
205
206```tsx
207import { H6 } from '@expo/html-elements';
208export default () => <H6>Example<H6/>
209```
210
211| Platform | Output                                                 |
212| -------- | ------------------------------------------------------ |
213| Web      | `<h6 aria-level="6" dir="auto" role="heading" />`      |
214| Native   | `<Text accessibilityRole="header" style={[Custom]} />` |
215
216## Link
217
218### `<A/>`
219
220You can use the anchor element with href prop to open links. On native this will attempt to use the `Linking` API to open the `href`.
221
222- The CSS style is fully normalized to match `<Text />`
223- For pseudo-class effects like hover and focus states check out the package [`react-native-web-hooks`](https://www.npmjs.com/package/react-native-web-hooks) | [tutorial](https://blog.expo.dev/css-pseudo-class-effects-in-expo-for-web-56649f88eb6b)
224
225```tsx
226import { A } from '@expo/html-elements';
227
228export default () => <A href="#" target="_blank" />;
229}
230```
231
232| Platform | Output                                                                          |
233| -------- | ------------------------------------------------------------------------------- |
234| Web      | `<a data-focusable="{true}" dir="auto" href="#" role="link" target="_blank" />` |
235| Native   | `<Text accessibilityRole="link" onPress={[Function]} />`                        |
236
237## Layout
238
239You can use layout elements like Header, Main, Footer, Section, Nav, etc. as a drop-in replacement for `View`s in your existing app.
240
241#### Default Layout style
242
243All layout HTML elements inherit the shared style of `<View />` to accommodate the [Yoga layout engine][yoga] which we use on native for iOS, and Android.
244
245- `display` is always `flex`. This is because [Yoga][yoga] only implements `display: flex`.
246- `flex-direction` is always `column` instead of `row`.
247
248#### Why use Layout elements
249
250Consider the following: in your app you have a basic element at the top which wraps the buttons and title. A screen reader doesn't understand that this is a header, and mostly neither does a web crawler. But if you replace the encasing view with a `<Header />` the following happens:
251
252- **iOS**: `UIView` uses [`UIAccessibilityTraitHeader`](https://developer.apple.com/documentation/uikit/uiaccessibilitytraitheader?language=objc).
253- **Android**: `View` will use the proper [`AccessibilityNodeInfoCompat.CollectionItemInfoCompat`](https://github.com/facebook/react-native/blob/7428271995adf21b2b31b188ed83b785ce1e9189/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactAccessibilityDelegate.java#L370-L372) | [docs](https://developer.android.com/reference/android/support/v4/view/accessibility/AccessibilityNodeInfoCompat.CollectionItemInfoCompat).
254- **web**: render an HTML 5 [`<header />`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/header) with the ARIA `role` set to [`"banner"`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/Banner_role).
255
256Some elements like `Footer` and `Main` have no iOS, or Android enhancements, but they'll still improve web. Using the proper HTML 5 elements will make your layout compliant with the [HTML5 outline algorithm](https://html.spec.whatwg.org/multipage/sections.html#outlines).
257
258### `<Div/>`
259
260Renders a `<div />` on web and a `View` with no ARIA set on mobile.
261
262```tsx
263import { Div } from '@expo/html-elements';
264
265export default () => (
266    <Div>
267      <P>Some content in the main element</P>
268    </Div>
269  );
270)
271```
272
273| Platform | Output     |
274| -------- | ---------- |
275| Web      | `<div />`  |
276| Native   | `<View />` |
277
278### `<Nav/>`
279
280```tsx
281import { Nav } from '@expo/html-elements';
282
283export default () => <Nav />;
284```
285
286| Platform | Output                         |
287| -------- | ------------------------------ |
288| Web      | `<nav style="display:flex" />` |
289| Native   | `<View />`                     |
290
291### `<Header/>`
292
293Renders a `<header />` on web with ARIA set to [`banner`][aria-banner] and a `View` with ARIA set to `header` on mobile.
294
295```tsx
296import { Header } from '@expo/html-elements';
297
298export default () => <Header />;
299```
300
301| Platform | Output                                                                                                              |
302| -------- | ------------------------------------------------------------------------------------------------------------------- |
303| Web      | [`<header role="banner" />`][html-header]                                                                           |
304| Native   | `<View />`                                                                                                          |
305| iOS      | `UIView` uses [`UIAccessibilityTraitHeader`][uiatheader].                                                           |
306| Android  | `View` will use the proper [`AccessibilityNodeInfoCompat.CollectionItemInfoCompat`][anicompat] [docs][anicompatdoc] |
307
308[uiatheader]: https://developer.apple.com/documentation/uikit/uiaccessibilitytraitheader?language=objc
309[anicompat]: https://github.com/facebook/react-native/blob/7428271995adf21b2b31b188ed83b785ce1e9189/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactAccessibilityDelegate.java#L370-L372
310[anicompatdoc]: https://developer.android.com/reference/android/support/v4/view/accessibility/AccessibilityNodeInfoCompat.CollectionItemInfoCompat
311
312### `<Main/>`
313
314Renders a `<main />` on web with ARIA `role` set to `main` and a `View` with no ARIA set on mobile.
315
316```tsx
317import { Main } from '@expo/html-elements';
318
319export default () => (
320    <Main>
321      <P>Some content in the main element</P>
322    </Main>
323  );
324)
325```
326
327| Platform | Output                                      |
328| -------- | ------------------------------------------- |
329| Web      | `<main role="main" style="display:flex" />` |
330| Native   | `<View />`                                  |
331
332### `<Section/>`
333
334Renders a `<section />` on web with ARIA set to `region` and a `View` with ARIA set to `summary` on mobile.
335
336```tsx
337import { Section } from '@expo/html-elements';
338
339export default () => <Section />;
340```
341
342| Platform | Output                                           |
343| -------- | ------------------------------------------------ |
344| Web      | `<section role="region" style="display:flex" />` |
345| Native   | `<View accessibilityRole="summary" />`           |
346
347### `<Article/>`
348
349Renders an `<article />` on web and a `View` everywhere else.
350
351```tsx
352import { Article } from '@expo/html-elements';
353
354export default () => <Article />;
355```
356
357| Platform | Output                       |
358| -------- | ---------------------------- |
359| Web      | `<article role="article" />` |
360| Native   | `<View />`                   |
361
362### `<Aside/>`
363
364```tsx
365import { Aside } from '@expo/html-elements';
366
367export default () => <Aside />;
368```
369
370| Platform | Output                           |
371| -------- | -------------------------------- |
372| Web      | `<aside role="complementary" />` |
373| Native   | `<View />`                       |
374
375### `<Footer/>`
376
377Renders an `<footer />` on web and a `View` everywhere else.
378
379```tsx
380import { Footer } from '@expo/html-elements';
381
382export default () => <Footer />;
383```
384
385| Platform | Output                          |
386| -------- | ------------------------------- |
387| Web      | `<footer role="contentinfo" />` |
388| Native   | `<View />`                      |
389
390## Text
391
392Text elements currently use `Text` universally rendering either a `div` or `span` to emulate Yoga style properly.
393
394- Style is modified to match web.
395- All font styles are reset (minus `Code`, and `Pre`).
396- All elements accept styles from `StyleSheet` API.
397
398```tsx
399import { P, B, S, I, BR, Code } from '@expo/html-elements';
400
401export default () => (
402  <>
403    <P>
404      Hello<B>World (in bold)</B>
405    </P>
406    <S>strike text</S>
407    <BR />
408    <I>Italic</I>
409    <Code>const foo = true</Code>
410  </>
411);
412```
413
414### `<P/>`
415
416Standard paragraph element.
417
418| Platform  | Output                                                     |
419| --------- | ---------------------------------------------------------- |
420| Universal | `<Text style={{ fontSize: 14, marginVertical: '1em' }} />` |
421
422### `<B/>`
423
424Bold text text.
425
426| Platform  | Output                                    |
427| --------- | ----------------------------------------- |
428| Universal | `<Text style={{ fontWeight: 'bold' }} />` |
429
430### `<Strong/>`
431
432Alternate bold text.
433
434| Platform  | Output                                    |
435| --------- | ----------------------------------------- |
436| Universal | `<Text style={{ fontWeight: 'bold' }} />` |
437
438### `<Span/>`
439
440Inline text element.
441
442| Platform  | Output     |
443| --------- | ---------- |
444| Universal | `<Text />` |
445
446### `<S/>`
447
448Strike through text.
449
450| Platform  | Output                                                    |
451| --------- | --------------------------------------------------------- |
452| Universal | `<Text style={{ textDecorationLine: 'line-through' }} />` |
453
454### `<Del/>`
455
456Alternate strike through text.
457
458| Platform  | Output                                                    |
459| --------- | --------------------------------------------------------- |
460| Universal | `<Text style={{ textDecorationLine: 'line-through' }} />` |
461
462### `<I/>`
463
464Italic text.
465
466| Platform  | Output                                     |
467| --------- | ------------------------------------------ |
468| Universal | `<Text style={{ fontStyle: 'italic' }} />` |
469
470### `<EM/>`
471
472Alternate italic text.
473
474| Platform  | Output                                     |
475| --------- | ------------------------------------------ |
476| Universal | `<Text style={{ fontStyle: 'italic' }} />` |
477
478### `<Code/>`
479
480Inline code block with `fontFamily: 'Courier'` on iOS and Web, `fontFamily: 'monospace'` on Android.
481
482| Platform  | Output                      |
483| --------- | --------------------------- |
484| Universal | `<Text style={[Custom]} />` |
485
486### `<Pre/>`
487
488Render a preformatted code block with `fontFamily: 'Courier'` on iOS and Web, `fontFamily: 'monospace'` on Android.
489
490```jsx
491<Pre>{`
492body {
493  color: red;
494}
495`}</Pre>
496
497// Or pass views
498
499<Pre>
500  <Code>{`const val = true`}</Code>
501</Pre>
502```
503
504| Platform  | Output                                    |
505| --------- | ----------------------------------------- |
506| Universal | `<Text style={[Custom]} />` \| `<View />` |
507
508### `<Mark/>`
509
510Highlight text.
511
512| Platform  | Output                                                           |
513| --------- | ---------------------------------------------------------------- |
514| Universal | `<Text style={{ backgroundColor: 'yellow', color: 'black' }} />` |
515
516### `<Q/>`
517
518Quoted text.
519
520| Platform  | Output                                             |
521| --------- | -------------------------------------------------- |
522| Universal | `<Text style={[Custom]}>"{props.children}"</Text>` |
523
524### `<BlockQuote/>`
525
526| Platform  | Output                      |
527| --------- | --------------------------- |
528| Universal | `<View style={[Custom]} />` |
529
530### `<Time/>`
531
532- `dateTime` prop is supported on web and stripped on native.
533
534| Platform  | Output                      |
535| --------- | --------------------------- |
536| Universal | `<Text style={[Custom]} />` |
537
538## Lists
539
540Lists can be used to create basic bulleted or numbered lists. You should try and use universal `FlatList` or `SectionList` components for long scrolling lists instead of these.
541
542### `<UL/>`
543
544Create an unordered (bulleted) list `<ul />` on web, and emulates the style with a `<View />` on native.
545
546- [x] Resets font styles everywhere.
547- [ ] Supports i18n by reversing format on iOS and Android
548- [ ] Supports custom bullets
549
550```tsx
551import { UL, LI } from '@expo/html-elements';
552
553export default () => (
554  <UL>
555    <LI>oranges</LI>
556    <LI>apples</LI>
557    <UL>
558      <LI>green</LI>
559      <LI>red</LI>
560    </UL>
561  </UL>
562);
563```
564
565| Platform | Output                      |
566| -------- | --------------------------- |
567| Web      | `<ul />`                    |
568| Native   | `<View style={[Custom]} />` |
569
570### `<LI/>`
571
572Create a standard list item `<li />` on web and a native view on mobile which can render text or views inside it.
573
574| Platform | Output                                                     |
575| -------- | ---------------------------------------------------------- |
576| Web      | `<li />`                                                   |
577| Native   | `<Text style={[Custom]} />` \| `<View style={[Custom]} />` |
578
579## Rules
580
581### `<HR/>`
582
583Renders a `<View>` everywhere. Style is modified to match web.
584
585```tsx
586import { HR } from '@expo/html-elements';
587
588export default () => <HR />;
589```
590
591| Platform | Output                      |
592| -------- | --------------------------- |
593| Web      | `<hr />`                    |
594| Native   | `<View style={[Custom]} />` |
595
596### `<BR/>`
597
598Create a line break.
599
600| Platform | Output                                   |
601| -------- | ---------------------------------------- |
602| Web      | `<br />`                                 |
603| Native   | `<View style={{height: 8, width: 0}} />` |
604
605## Tables
606
607Create tables universally.
608
609- Each element renders to the expected type on web.
610- `padding` is removed from all table elements.
611- Text **can only** be rendered in `TH` and `TD` on mobile.
612- `colSpan` and `rowSpan` are currently web-only (PRs welcome).
613
614```tsx
615import { Table, THead, TH, TBody, TFoot, TR, TD, Caption } from '@expo/html-elements';
616import { Text } from 'react-native';
617
618export default () => (
619  <Table>
620    <Caption>Caption</Caption>
621    <THead>
622      <TR>
623        <TH colSpan="2">The table header</TH>
624      </TR>
625    </THead>
626    <TBody>
627      <TR>
628        <TD>The table body</TD>
629        <TD>with two columns</TD>
630      </TR>
631    </TBody>
632    <TFoot>
633      <TR>
634        <TD>
635          <Text>This is the table footer</Text>
636        </TD>
637      </TR>
638    </TFoot>
639  </Table>
640);
641```
642
643#### Table example output web
644
645```html
646<table>
647  <caption>
648    Caption
649  </caption>
650  <thead>
651    <tr>
652      <th colspan="2">The table header</th>
653    </tr>
654  </thead>
655  <tbody>
656    <tr>
657      <td>The table body</td>
658      <td>with two columns</td>
659    </tr>
660  </tbody>
661  <tfoot>
662    <tr>
663      <td><div>The table body</div></td>
664    </tr>
665  </tfoot>
666</table>
667```
668
669### `<Table/>`
670
671Base element for creating a Table.
672
673| Platform | Output                      |
674| -------- | --------------------------- |
675| Web      | `<table />`                 |
676| Native   | `<View style={[Custom]} />` |
677
678### `<THead/>`
679
680Header element in a Table.
681
682| Platform | Output                      |
683| -------- | --------------------------- |
684| Web      | `<thead />`                 |
685| Native   | `<View style={[Custom]} />` |
686
687### `<TBody/>`
688
689Body element in a Table.
690
691| Platform | Output                      |
692| -------- | --------------------------- |
693| Web      | `<tbody />`                 |
694| Native   | `<View style={[Custom]} />` |
695
696### `<TFoot/>`
697
698Footer element in a Table.
699
700| Platform | Output                      |
701| -------- | --------------------------- |
702| Web      | `<tfoot />`                 |
703| Native   | `<View style={[Custom]} />` |
704
705### `<TH/>`
706
707Used to display text in the Header.
708
709- `colSpan` and `rowSpan` are currently web-only.
710
711| Platform | Output                      |
712| -------- | --------------------------- |
713| Web      | `<th />`                    |
714| Native   | `<Text style={[Custom]} />` |
715
716### `<TR/>`
717
718Used to create a Row in a Table.
719
720| Platform | Output                      |
721| -------- | --------------------------- |
722| Web      | `<tr />`                    |
723| Native   | `<View style={[Custom]} />` |
724
725### `<TD/>`
726
727Create a cell in a Table.
728
729- `colSpan` and `rowSpan` are currently web-only.
730
731| Platform | Output                      |
732| -------- | --------------------------- |
733| Web      | `<td />`                    |
734| Native   | `<View style={[Custom]} />` |
735
736### `<Caption/>`
737
738Used to caption your table. Excepts text as a child.
739
740| Platform | Output                      |
741| -------- | --------------------------- |
742| Web      | `<caption />`               |
743| Native   | `<Text style={[Custom]} />` |
744
745# TODO
746
747- Improve relative imports for better tree-shaking.
748
749# Babel
750
751You can write `react-dom` elements in your code and use the babel plugin to transform them to `@expo/html-elements` elements.
752
753```js
754// babel.config.js
755module.exports = {
756  plugins: ['@expo/html-elements/babel'],
757};
758```
759
760## Input
761
762```js
763export default function Page() {
764  return (
765    <div>
766      <h1>Hello World</h1>
767    </div>
768  );
769}
770```
771
772## Output
773
774The import is automatically added if it's not already present. All props are passed through without any additional transforms.
775
776```js
777import { Div, H1 } from '@expo/html-elements';
778
779export default function Page() {
780  return (
781    <Div>
782      <H1>Hello World</H1>
783    </Div>
784  );
785}
786```
787
788# Contributing
789
790Contributions are very welcome! Please refer to guidelines described in the [contributing guide](https://github.com/expo/expo#contributing).
791
792[yoga]: https://yogalayout.com/
793
794<!-- HTML element links -->
795
796[html-a]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a
797[html-article]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/article
798[html-aside]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/aside
799[html-b]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/b
800[html-blockquote]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/blockquote
801[html-br]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/br
802[html-caption]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/caption
803[html-code]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/code
804[html-del]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/del
805[html-div]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/div
806[html-em]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/em
807[html-footer]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/footer
808[html-form]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form
809[html-h1]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h1
810[html-h2]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h2
811[html-h3]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h3
812[html-h4]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h4
813[html-h5]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h5
814[html-h6]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h6
815[html-header]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/header
816[html-hr]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/hr
817[html-i]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/i
818[html-main]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/main
819[html-mark]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/mark
820[html-nav]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/nav
821[html-ol]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ol
822[html-p]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/p
823[html-pre]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/pre
824[html-q]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/q
825[html-s]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/s
826[html-section]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/section
827[html-span]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/span
828[html-small]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/small
829[html-strong]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/strong
830[html-table]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/table
831[html-tbody]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tbody
832[html-td]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/td
833[html-tfoot]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tfoot
834[html-th]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/th
835[html-thead]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/thead
836[html-time]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/time
837[html-tr]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tr
838[html-ul]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ul
839[html-li]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/li
840[html-label]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label
841[html-details]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details
842[html-summary]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/summary
843[html-progress]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/progress
844[html-select]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select
845[html-picture]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/picture
846[html-figure]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/figure
847[html-figcaption]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/figcaption
848[aria-banner]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/Banner_role
849