Skip to content

List Rendering

This example shows how index helps when repeated HTML elements share state but still need individual DOM updates.

Open this demo in a new tab

<section data-tabs>
<div role="tablist">
<button type="button" data-tab>Overview</button>
<button type="button" data-tab>Usage</button>
<button type="button" data-tab>API</button>
</div>
<section data-panel>Overview content</section>
<section data-panel hidden>Usage content</section>
<section data-panel hidden>API content</section>
</section>
import { defineComponent } from "ornata";
export const Tabs = defineComponent({
name: "Tabs",
state: {
activeIndex: { default: 0, type: Number },
},
elements: {
tabs: { queryAll: "[data-tab]", min: 2 },
panels: { queryAll: "[data-panel]", min: 2 },
},
render: {
tabs({ index }) {
const currentIndex = index ?? 0;
const isActive = currentIndex === this.state.activeIndex;
return {
attributes: {
"aria-selected": String(isActive),
},
classes: {
"is-active": isActive,
},
events: {
click: () => {
this.state.activeIndex = currentIndex;
},
},
};
},
panels({ index }) {
const currentIndex = index ?? 0;
return {
attributes: {
hidden: currentIndex !== this.state.activeIndex,
},
};
},
},
});

Without index, each repeated element would need more custom plumbing.

With it, each tab and panel can respond to shared component state while still rendering individually.