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