# `BootOptions.el`

> Contract 2.0.0 · package sha256 `a857eca95b35921109faf997094bb4192f12527d9d0fcd4be7e97f06425bad6e` · generated from `configurator-runtime.d.ts` by `services/onsite-scripter/scripts/build-contract-docs.mjs`; edit the source, not this file.

Property of [`BootOptions`](BootOptions.md) · stable · since 2.0.0

```ts
el: HTMLElement;
```

The host element. One session per element. The runtime owns its shadow root; style it only
through `::part()`. It attaches that root at the element's first boot and reuses it at every
later boot; [`destroy()`](Session.destroy.md), the boot signal's abort and a failed boot leave it empty. `el` must be
able to host a shadow root (the DOM standard's `attachShadow` list: `div`, `section`, `span`
and the like, or an autonomous custom element), carry none the runtime did not attach, and be
in the document at the call (`isConnected`; one the page removes while the session starts is
HoloBootError 'disconnected'); otherwise [`boot`](boot.md) rejects HoloInputError ('invalid-input', path
'el') at once, before any request (spec section 5.1).
Children of `el` are not rendered: mount your own overlays in a sibling.
Give `el` a CSS size: the runtime draws at its size. With no CSS height it takes the view's
default 2:1 height (360 × 180 for a 360 px wide `div`); under 64 CSS px on a side, or under
`display: none`, it shows next to nothing and records 'host-unsized'.
One session per product on screen: each holds a WebGL context, and browsers keep about 16 live
per page, losing the oldest past that. A grid of products shows one session and swaps its
model ([`collection(name).load`](Collection.load.md), [`setSceneModel`](Writer.setSceneModel.md)), or boots a card's session on hover and
destroys it after. Every session on the page comes from one runtime module: another
configurator runtime on the page (a 1.x embed, a runtime from another URL) makes [`boot`](boot.md)
reject HoloBootError 'other' ([`BootOptions`](BootOptions.md)).
While the display is held or gated, the runtime sets `aria-busy="true"` on it and removes it
at the reveal (spec section 6.6). When removing the focused badge leaves no badge, the runtime
focuses `el`, with `tabindex="-1"` until its next `blur` if it has no `tabindex`
([`Overlays.hotspots`](Overlays.hotspots.md)); from the focused `el`, Tab enters the badges. Never give `el` a negative
`tabindex` yourself: a shadow host with `tabindex="-1"` takes its whole shadow tree, the badges
included, out of the Tab order. Put a programmatic focus target on a wrapper. The runtime's canvas is `aria-hidden="true"`; its badges and
ruler labels are the only content it exposes. Name the view on `el` or a wrapper with
`role="group"` and `aria-label`, or `aria-describedby` pointing at your own text summary of
the configured product. Never put `role="img"` on `el` or an ancestor while badges are set:
an image's children are presentational, so the badges leave the accessibility tree. `label`
items are pixels only, so put what they say in DOM too.

## Generic-API test (spec 3.1)

| Rule | Result |
| --- | --- |
| 1. Neutral name | pass: `el` names no product |
| 2. A precedent | not recorded: no ledger row (coverage.json) names this member or its owner |
| 3. Two apps, or labs | pass: 28 apps (fleet cross-check: app-04c2774145, app-0c773a4ee3, app-37356bf09f, app-378d190f1b, app-4762caacdc, app-4f16d2f6da, app-4fd23bc869, app-510d750508 and 20 more) |
| 4. The cheaper fix first | not recorded per member (Appendix B decides it per need) |
