List Rendering
This example shows how index helps when repeated HTML elements share state but still need individual DOM updates.
Live Demo
Section titled “Live Demo”<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>Component
Section titled “Component”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, }, }; }, },});import { defineComponent } from "ornata";
export const Tabs = defineComponent<{ state: { activeIndex: number; }; elements: { tabs: HTMLButtonElement[]; panels: HTMLElement[]; };}>({ name: "Tabs", state: { activeIndex: { default: 0, type: Number }, }, elements: { tabs: { resolve(root) { return Array.from( root.querySelectorAll("[data-tab]") ) as HTMLButtonElement[]; }, min: 2, }, panels: { resolve(root) { return Array.from( root.querySelectorAll("[data-panel]") ) as HTMLElement[]; }, 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, }, }; }, },});Why index matters
Section titled “Why index matters”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.