Build a Disclosure
This tutorial walks through a small disclosure component from plain HTML to reusable interactive behavior.
Step 1: Write the baseline HTML
Section titled “Step 1: Write the baseline HTML”<section data-disclosure> <button type="button" aria-expanded="false" data-disclosure-button > More details </button>
<div hidden data-disclosure-panel> This content exists in the page markup from the start. </div></section>This is the important starting point: the content is already in the document.
Step 2: Define the state
Section titled “Step 2: Define the state”state: { open: { default: false, type: Boolean },}The disclosure only needs one reactive property: open.
Step 3: Resolve the important elements
Section titled “Step 3: Resolve the important elements”elements: { button: { query: "[data-disclosure-button]" }, panel: { query: "[data-disclosure-panel]" },}Step 4: Add a method
Section titled “Step 4: Add a method”methods: { toggle() { this.state.open = !this.state.open; },}Step 5: Render the state into the DOM
Section titled “Step 5: Render the state into the DOM”render: { button() { return { attributes: { "aria-expanded": String(this.state.open), }, events: { click: () => this.methods.toggle(), }, }; }, panel() { return { attributes: { hidden: !this.state.open, }, }; },}Full component
Section titled “Full component”import { defineComponent } from "ornata";
export const Disclosure = defineComponent({ name: "Disclosure", state: { open: { default: false, type: Boolean }, }, elements: { button: { query: "[data-disclosure-button]" }, panel: { query: "[data-disclosure-panel]" }, }, methods: { toggle() { this.state.open = !this.state.open; }, }, render: { button() { return { attributes: { "aria-expanded": String(this.state.open), }, events: { click: () => this.methods.toggle(), }, }; }, panel() { return { attributes: { hidden: !this.state.open, }, }; }, },});Step 6: Mount it
Section titled “Step 6: Mount it”Disclosure.mount("[data-disclosure]");What this tutorial shows
Section titled “What this tutorial shows”- the HTML stays meaningful on its own
- state drives interaction
- render output updates existing DOM
- methods keep imperative logic tidy
That is the core Ornata workflow in a very small example.