QHTML Component Examples

This page is now mostly HTML. Each example is a plain <q-editor> with inline QHTML source.

The sidebar is built with a small navigation script that links to each example section anchor.

q-keyword syntax usage

Scoped keyword remapping with direct-only alias rules.

q-keyword component { q-component } q-style tiny-card-style { q-style-class { w3-round-large w3-border } background-color: #eef4ff color: #0f172a border: 1px solid #bfd0ea } q-theme tiny-card-theme { .tiny-card-shell { tiny-card-style } } component tiny-card { tiny-card-theme { div.tiny-card-shell.w3-card.w3-padding { text { Tiny Card } } } } tiny-card { }

q-form.qhtml usage

Use form templates for quick input layouts.

q-import { ../dist/q-components/q-form.qhtml } q-style form-shell-custom { background-color: #fff7ed border-color: #fdba74 color: #7c2d12 } q-style form-input-custom { background-color: #fffaf0 border-color: #fed7aa } q-style form-submit-custom { background-color: #ea580c border: 1px solid #c2410c color: #f8fafc } q-theme form-demo-theme { q-form-theme { } .q-form-root { form-shell-custom } .q-form-input { form-input-custom } .q-form-submit { form-submit-custom } } form-demo-theme { q-form contactForm { url: "pages/submit.php" type: "GET" h3 { text { Quick Form } } q-form-input-textbox nameField { name: "name" label: "Name" placeholder: "Name" } q-form-input-email emailField { name: "email" label: "Email" placeholder: "Email" } q-form-input-textarea projectNotes { name: "notes" label: "Project notes" placeholder: "Tell us what you are building..." } q-form-input-submit sendButton { name: "submit" label: "Send" } } }

q-layout usage

Use the built-in q-layout, q-row, and q-col objects instead of the removed grid helper component.

q-style layout-cell-a-style { background-color: #eff6ff color: #1e3a8a border: 1px solid #93c5fd } q-style layout-cell-b-style { background-color: #ecfeff color: #155e75 border: 1px solid #67e8f9 } q-style layout-cell-c-style { background-color: #f0fdf4 color: #166534 border: 1px solid #86efac } q-style layout-cell-style { minHeight: 90px padding: 14px display: flex alignItems: center justifyContent: center } q-theme layout-cells-theme { .layout-cell { layout-cell-style } .cell-a { layout-cell-a-style } .cell-b { layout-cell-b-style } .cell-c { layout-cell-c-style } } layout-cells-theme { q-layout { width: "100%" gap: "10px" q-row { gap: "10px" q-col { div.layout-cell.cell-a.w3-round-large { text { Cell A } } } q-col { div.layout-cell.cell-b.w3-round-large { text { Cell B } } } q-col { div.layout-cell.cell-c.w3-round-large { text { Cell C } } } } } }

q-modal.qhtml usage

Use built-in q-modal-theme defaults, then layer an external theme override.

q-import { ../dist/q-components/q-modal.qhtml } q-import { ../dist/q-components/dark-theme.qhtml } dark-theme { q-modal mymodal { id: "mymodal" visible: false title { div,span,text { System Configuration } } body { h3 { text { My Dialog Main Title } } div { text { Here is the main dialog content. } } span { text { This area scrolls while the titlebar, header, and footer remain visible. } } } footer { text { Custom Footer } button { text { Close } onclick { mymodal.visible = false; } } } } button { text { Open Modal } onclick { mymodal.visible = true; } } }

q-sidebar.qhtml usage

Use one theme: include q-sidebar-theme defaults, then apply targeted overrides.

q-import { ../dist/q-components/q-sidebar.qhtml } q-style sidebar-toggle-override-style { background-color: #16a34a color: #f8fafc border: 1px solid #15803d } q-style sidebar-panel-override-style { background-color: #ffedd5 color: #7c2d12 border-color: #fb923c } q-style sidebar-toggle-strong-style { background-color: #ef4444 color: #f8fafc border: 1px solid #7f1d1d } q-style sidebar-content-card-style { background-color: #dbeafe color: #1e3a8a border: 1px solid #60a5fa } q-style sidebar-nav-link-style { background-color: #fef3c7 color: #92400e border: 1px solid #f59e0b } q-theme sidebar-demo-theme { q-sidebar-theme { } .q-sidebar-panel { sidebar-panel-override-style } .q-sidebar-toggle { sidebar-toggle-override-style sidebar-toggle-strong-style } .sidebar-content-pane { sidebar-content-card-style } .sidebar-nav-btn { sidebar-nav-link-style } } sidebar-demo-theme { div.w3-container.w3-border.w3-round-large { style { position: relative; height: 240px; overflow: hidden; padding: 8px; } button.w3-button.w3-margin-bottom { text { Toggle Sidebar } onclick { demoSidebar.toggle(); } } q-sidebar demoSidebar { sidebarWidth: "280" collapsedWidth: "2vw" open: "1" content { div.sidebar-content-pane.w3-bar-block.w3-padding.w3-border { h4 { text { Sidebar } } a.sidebar-nav-btn.w3-bar-item.w3-button { text { Nav Item 1 } } a.sidebar-nav-btn.w3-bar-item.w3-button { text { Nav Item 2 } } } } main { div.w3-padding { h4 { text { Main Content } } p { text { q-sidebar uses an in-container grid layout (sidebar + main). } } } } } } }

lcars-sidebar.qhtml usage

LCARS-style sidebar shell with a Houdini-painted curved top, vertical rail buttons, and slotted main content.

q-import { ../dist/q-components/lcars-sidebar.qhtml } lcars-sidebar { sidebar { lcars-sidebar-buttons { buttons { lcars-sidebar-button { buttonColor: "#f59a38" buttonText { text { Ops } } onclick { alert("Ops channel selected"); } } lcars-sidebar-button { buttonColor: "#d97706" buttonText { text { Sensors } } onclick { alert("Sensors selected"); } } lcars-sidebar-button { buttonColor: "#ef4444" buttonText { a { href: "https://www.google.com" target: "_blank" text { Google } } } onclick { console.log("LCARS external link button"); } } } } } main { div { style { display: grid; gap: 12px; color: #f8fafc; } h3 { text { LCARS Command Surface } } p { text { The left rail is projected through the sidebar slot. Main content remains arbitrary QHTML. } } div { style { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; } div { style { background: #172033; padding: 12px; } text { Navigation } } div { style { background: #172033; padding: 12px; } text { Telemetry } } div { style { background: #172033; padding: 12px; } text { Actions } } } } } }

q-popup-menu.qhtml usage

Minimal popup menu using popup-contents, oncontextmenu, and show(x, y, event).

q-import { ../dist/q-components/q-popup-menu.qhtml } div.w3-container.w3-border.w3-round-large.w3-padding { h4 { text { Right-click inside the dashed area } } div#ctx-zone.w3-panel.w3-border-dashed.w3-round-large { style { min-height: 140px; background-color: #f8fafc; color: #0f172a; border: 1px dashed #94a3b8; } oncontextmenu { event.preventDefault(); ctxUsage.show(event.clientX, event.clientY, event); var ctxLog = document.querySelector("#ctx-log"); if (ctxLog) { ctxLog.textContent = "Last open: " + String(event.clientX) + ", " + String(event.clientY); } } p { text { This context menu uses explicit show(event.clientX, event.clientY, event). } } q-popup-menu ctxUsage { id: "ctx-usage" popup-contents { ul.w3-ul.w3-small.w3-card { li { text { Rename } } li { text { Duplicate } } hr { } li { text { Archive } } li { text { Delete } } } } } } p#ctx-log { class: "w3-small" style { color: #334155; } text { Last open: none } } }

q-tabs.qhtml usage

Instantiate tabs and switch via showTab(index).

q-import { ../dist/q-components/q-tabs.qhtml } q-style tabs-show-btn-style { background-color: #334155 color: #f8fafc border: 1px solid #1e293b } q-style tabs-nav-override-style { background-color: #ffedd5 } q-style tabs-panel-override-style { background-color: #fffaf0 } q-theme tabs-demo-theme { .tabs-show-btn { tabs-show-btn-style } .q-tabs-container { tabs-nav-override-style } .q-tab-panel { tabs-panel-override-style } } tabs-demo-theme { button.tabs-show-btn.w3-button.w3-margin-bottom { text { Show Tab 3 } onclick { tabsUsage.showTab(2); } } q-tabs tabsUsage { id: "tabs-usage" q-tab { name { text { Overview } } body { p { text { Overview content } } } } q-tab { name { text { Details } } body { p { text { Details content } } } } q-tab { name { text { Logs } } body { p { text { Logs content } } } } } }

dynamicTabWidget

Model-driven tabs using declarative composition: q-tabs + for.

q-import { ../dist/q-components/q-tabs.qhtml } q-component dynamicTabWidget { div.w3-margin-bottom { button.w3-button.w3-small.w3-border.w3-round { text { Add runtime tab } onclick { var index = dynamicTabs.querySelectorAll(".q-tab-button").length + 1; dynamicTabs.addTab({ name: "Runtime Tab " + String(index), body: "This tab was appended through dynamicTabs.addTab(tabObject)." }); } } button.w3-button.w3-small.w3-border.w3-round.w3-margin-left { text { Remove runtime tab } onclick { dynamicTabs.removeTab(); } } } q-tabs dynamicTabs { id: "dynamic-tabs" q-tab { name { text { Tab 1 } } body { div { text { hello world } } } } q-tab { name { text { Tab 2 } } body { div { text { test 123 } } } } } onready { setTimeout(function() { if (dynamicTabs && typeof dynamicTabs.addTab === "function" && !dynamicTabs.querySelector("[tabName='Ready Tab']")) { dynamicTabs.addTab({ name: "Ready Tab", body: "This tab was added from dynamicTabWidget.onready." }); } }, 0); } } dynamicTabWidget { }

q-tree-view quick usage

Collapsible tree using HTML5 details/summary from inline JSON-style object data.

q-import { ../dist/q-components/q-tree-view.qhtml } q-style tree-list-style { margin: 0.25rem 0 padding-left: 1.25rem } q-style tree-item-style { display: block position: relative } q-style tree-leaf-item-style { display: flex align-items: center gap: 0.32rem position: relative margin-left: 0.2rem padding: 0.12rem 0 } q-style tree-leaf-connector-style { display: inline-block width: 0.7rem height: 0.01rem border-left: 2.0px solid #0ea5e9 border-bottom: 0.75px solid #0ea5e9 box-sizing: border-box padding-bottom: 0.25rem; } q-style tree-children-style { margin: 0.25rem 0 0.25rem 0.5rem padding-left: 1rem } q-style tree-marker-style { border-radius: 2px } q-style tree-marker-open-style { background-color: #16a34a color: #f8fafc border-color: #166534 } q-style tree-marker-closed-style { background-color: #2563eb color: #f8fafc border-color: #1d4ed8 } q-style tree-connector-style { color: #0ea5e9 border-left-style: solid border-left-width: 1.25px border-left-color: #0ea5e9 } q-style tree-connector-last-style { border-left-color: transparent } q-style tree-summary-style { color: #0f172a display: flex align-items: center gap: 0.35rem cursor: pointer } q-style tree-branch-style { display: block } q-style tree-label-style { color: #0369a1 } q-style tree-leaf-style { color: #1e3a8a } q-theme tree-demo-theme { .q-tree-list { tree-list-style } .q-tree-item { tree-item-style } .q-tree-branch-item { tree-item-style } .q-tree-leaf-item { tree-leaf-item-style } .q-tree-children { tree-children-style } .q-tree-branch { tree-branch-style } .q-tree-marker { tree-marker-style } .q-tree-marker-open { tree-marker-open-style } .q-tree-marker-closed { tree-marker-closed-style } .q-tree-connector { tree-connector-style } .q-tree-branch-item.q-tree-connector-last { tree-connector-last-style } .q-tree-summary { tree-summary-style } .q-tree-label { tree-label-style } .q-tree-leaf-connector { tree-leaf-connector-style } .q-tree-leaf-label { tree-leaf-style } } tree-demo-theme { q-tree-view#my-view { treeModel: { src: ["index.js", "parser.js", { utils: ["path.js", "net.js"] }], docs: ["README.md", "MODULE-API.md"] } } }

q-list-view.qhtml usage

Render a simple list from JSON-style array data using for.

q-import { ../dist/q-components/q-list-view.qhtml } q-component demo-list-view extends q-list-view { q-property model: [ "hello world", "item 2", "item 3" ] } demo-list-view#my-list { }

e-store component suite demo

Integrated demo using q-estore-pricebox and q-checkout-modal.

q-import { ../dist/q-components/q-estore.qhtml } button.w3-button.w3-small.w3-border.w3-round { text { Load Alternate Products } onclick { demoestore.setProducts([ { SKU: "ALT-001", name: "Travel Bottle", description: "Insulated stainless steel", price: "29.00" }, { SKU: "ALT-002", name: "Desk Mat", description: "Felt anti-slip surface", price: "22.50" }, { SKU: "ALT-003", name: "Pen Set", description: "Fine-tip gel pens", price: "12.99" }, { SKU: "ALT-004", name: "Cable Kit", description: "USB-C and Lightning pack", price: "18.75" } ]); } } q-estore demoestore { id: "demo-estore" }

q-spritesheet [alpha] usage

Declarative spritesheet player with frame range, speed, size, and interpolation controls.

q-import { ../dist/q-components/q-spritesheet.qhtml } q-component sprite-demo-status { q-property textValue: "frame: 0" div.w3-small.w3-text-indigo { text { ${this.textValue} } } } div.w3-container.w3-border.w3-round-large.w3-padding { sprite-demo-status demoStatus { } q-spritesheet demoSheet { source: "assets/test-ss.png" frameCount: 18 frameStart: 0 frameStop: 17 frameDuration: 70 frameWidth: 32 frameHeight: 32 repeat: true running: false interpolate: true onframechanged(frameIndex) { demoStatus.textValue = "frame: " + String(frameIndex); } } div.w3-margin-top { button.w3-button.w3-border.w3-round.w3-small { text { Start } onclick { demoSheet.start(); } } button.w3-button.w3-border.w3-round.w3-small.w3-margin-left { text { Stop } onclick { demoSheet.stop(); } } button.w3-button.w3-border.w3-round.w3-small.w3-margin-left { text { Toggle Interpolate } onclick { demoSheet.interpolate = !demoSheet.interpolate; } } } }

onPaintBackground / onPaintBorder / onPaintMask demo

Three component-local CSS Houdini painters using QHTML7 paint handlers and q-property paint variable lists.

q-component paint-background-card { q-property width: 220px q-property height: 92px q-property hotColor: "#ff006e" q-property warmColor: "#ffd60a" q-property coolColor: "#00d1ff" q-property greenColor: "#00f5a0" q-property inkColor: "#111827" q-property paintvars: [this.width, this.height, this.hotColor, this.warmColor, this.coolColor, this.greenColor, this.inkColor] onPaintBackground(paintvars) { var w = this.geom.width; var h = this.geom.height; this.clearRect(transparent); this.setFill(this.hotColor); this.drawRect(0, 0, w, h); this.setFill(this.warmColor); this.drawRect(0, 0, w * 0.5, h * 0.5); this.setFill(this.coolColor); this.drawRect(w * 0.5, h * 0.5, w * 0.5, h * 0.5); this.setFill(this.greenColor); this.drawRect(0, h * 0.58, w, h * 0.16); this.setFill(this.inkColor); this.drawRect(w * 0.46, 0, w * 0.08, h); } div { style { width: 220px; height: 92px; display: inline-flex; align-items: center; justify-content: center; color: #0f172a; font-weight: 700; font-family: monospace; letter-spacing: 0.02em; border: 1px solid #334155; border-radius: 10px; box-sizing: border-box; } text { background painter } } } q-component paint-border-card { q-property width: 220px q-property height: 92px q-property outerColor: "#ff0033" q-property middleColor: "#00e5ff" q-property innerColor: "#000000" q-property stripeColor: "#f6ff00" q-property paintvars: [this.width, this.height, this.outerColor, this.middleColor, this.innerColor, this.stripeColor] onPaintBorder(paintvars) { var w = this.geom.width; var h = this.geom.height; var band = Math.max(6, Math.floor(Math.min(w, h) * 0.12)); this.setFill(this.outerColor); this.drawRect(0, 0, w, h); this.setFill(this.middleColor); this.drawRect(band, band, w - (band * 2), h - (band * 2)); this.setFill(this.innerColor); this.drawRect(band * 2, band * 2, w - (band * 4), h - (band * 4)); this.setFill(this.stripeColor); this.drawRect(0, h * 0.42, w, h * 0.16); this.drawRect(w * 0.42, 0, w * 0.16, h); } div { style { width: 220px; height: 92px; display: inline-flex; align-items: center; justify-content: center; color: #0f172a; font-weight: 700; font-family: monospace; border: 18px solid transparent; border-radius: 10px; box-sizing: border-box; background-color: #f8fafc; } text { border painter } } } q-component paint-mask-card { q-property width: 220px q-property height: 92px q-property topWidth: 62 q-property topHeight: 34 q-property paintvars: [this.width, this.height, this.topWidth, this.topHeight] onPaintMask(paintvars) { var w = this.geom.width; var h = this.geom.height; var tw = Number(this.topWidth || 62); var th = Number(this.topHeight || 34); if (!Number.isFinite(tw) || tw < 10) { tw = 10; } if (tw > 95) { tw = 95; } if (!Number.isFinite(th) || th < 10) { th = 10; } if (th > 90) { th = 90; } var topWidth = w * tw / 100; var left = (w - topWidth) / 2; this.clearRect(transparent); this.ctx.fillStyle = black; this.ctx.beginPath(); this.ctx.moveTo(left, 0); this.ctx.lineTo(w - left, 0); this.ctx.lineTo(w, h * th / 100); this.ctx.lineTo(w * 0.5, h); this.ctx.lineTo(0, h * th / 100); this.ctx.closePath(); this.ctx.fill(); } div { style { width: 220px; height: 92px; display: inline-flex; align-items: center; justify-content: center; color: #0f172a; font-weight: 700; font-family: monospace; border: 1px solid #334155; border-radius: 10px; box-sizing: border-box; background: linear-gradient(90deg, #ff006e 0%, #ffd60a 20%, #00d1ff 40%, #00f5a0 60%, #8b5cf6 80%, #111827 100%); } text { mask painter } } } q-style paintHostStyle { display: inline-block marginRight: 10px marginBottom: 10px borderRadius: 10px background-repeat: no-repeat background-size: 100% 100% mask-repeat: no-repeat mask-size: 100% 100% mask-position: center -webkit-mask-repeat: no-repeat -webkit-mask-size: 100% 100% -webkit-mask-position: center } q-theme painterTriptychTheme { paint-background-card { paintHostStyle } paint-border-card { paintHostStyle } paint-mask-card { paintHostStyle } } painterTriptychTheme { div.w3-container.w3-border.w3-round-large.w3-padding { paint-background-card bgPanel { id: "ptri-bg" } paint-border-card borderPanel { id: "ptri-border" } paint-mask-card maskPanel { id: "ptri-mask" } p#ptri-status.w3-small.w3-text-indigo { text { painter status: checking... } } } } onready { var support = !!(CSS && CSS.paintWorklet && typeof CSS.paintWorklet.addModule === "function"); var bg = document.querySelector("#ptri-bg"); var border = document.querySelector("#ptri-border"); var mask = document.querySelector("#ptri-mask"); var out = document.querySelector("#ptri-status"); var bgStyle = bg ? String(bg.style.backgroundImage || "").trim() : ""; var borderStyle = border ? String(border.style.borderImageSource || "").trim() : ""; var maskStyle = mask ? String(mask.style.maskImage || mask.style.webkitMaskImage || "").trim() : ""; if (out) { out.textContent = "painter support=" + String(support ? 1 : 0) + " | background=" + bgStyle + " | border=" + borderStyle + " | mask=" + maskStyle; } }

q-tech-panel Houdini panel showcase

Five large direct child divs using different clipped corners, top dents, border widths, shadows, and grid patterns.

q-import { ../dist/q-components/q-tech-panel.qhtml } q-style tech-panel-stage { display: grid gridTemplateColumns: repeat(auto-fit, minmax(320px, 1fr)) gap: 22px padding: 18px background: #07111f } q-style tech-panel-box { minHeight: 24vh height: 260px padding: 30px 34px color: #e6fbff fontFamily: monospace fontWeight: 700 letterSpacing: 0.04em display: flex alignItems: center justifyContent: center textAlign: center } q-theme techPanelDemoTheme { .tech-stage { tech-panel-stage } .tech-box { tech-panel-box } } techPanelDemoTheme { div.tech-stage { q-tech-panel { borderWidth: "8px" borderColor: "#6ee7ff" shadowColor: "#00ff99" topLeft: "34px" bottomRight: "42px" topDent: "30px" topDentLength: "24%" patternSize: "22px" div.tech-box { text { CYAN COMMAND PANEL } } } q-tech-panel { borderWidth: "5px" borderColor: "#ffcc66" shadowColor: "#ff7a18" topRight: "54px" bottomLeft: "48px" topDent: "46px" topDentLength: "34%" patternShift: "20px 36px" patternSize: "28px" percentage: "0.35" div.tech-box { text { AMBER REACTOR SLOT } } } q-tech-panel { borderWidth: "4px" borderColor: "#d8b4fe" shadowColor: "#a855f7" topLeft: "58px 38px" topRight: "38px 58px" bottomRight: "70px 44px" bottomLeft: "44px 70px" topDent: "26px" topDentLength: "42%" patternSize: "18px" percentage: "0.55" div.tech-box { text { VIOLET SYMMETRY FRAME } } } q-tech-panel { borderWidth: "2px" borderColor: "#86efac" shadowColor: "#22c55e" topLeft: "20px" topRight: "72px" bottomRight: "32px" bottomLeft: "86px" topDent: "54px" topDentLength: "18%" patternShift: "-18px 26px" patternSize: "34px" percentage: "0.2" div.tech-box { text { GREEN HEAVY ARMOR PANEL } } } q-tech-panel { borderWidth: "1px" borderColor: "#fca5a5" shadowColor: "#ef4444" topLeft: "46px" topRight: "18px" bottomRight: "58px" bottomLeft: "28px" topDent: "18px" topDentLength: "30%" patternShift: "12px -18px" patternSize: "20px" percentage: "0.48" div.tech-box { text { RED THIN SIGNAL PANEL } } } } }

q-toolbar + q-toolbutton usage

Floating, draggable, resizable toolbar with square toolbuttons that auto-scale from container resize events.

q-import { ../dist/q-components/q-toolbar.qhtml } q-import { ../dist/q-components/q-toolbutton.qhtml } div.w3-container.w3-border.w3-round-large.w3-padding { h4 { text { Toolbar Demo } } p { text { Drag from the top edge, resize from bottom-right corner, and click X to close. } } button.w3-button.w3-small.w3-border { text { Re-open toolbar } onclick { toolboxMain.showToolbar(); } } q-toolbar toolboxMain { id: "toolbox-main" title: "Quick Tools" x: 160 y: 120 width: 360 height: 72 q-toolbutton { src: "../dist/q-components/expand-collapse.svg" label: "Open File" onclick { alert("file open clicked") } } q-toolbutton { src: "../dist/q-components/expand-collapse.svg" label: "Save" onclick { alert("save clicked") } } q-toolbutton { src: "../dist/q-components/expand-collapse.svg" label: "Settings" onclick { alert("settings clicked") } } } }

Unified Commerce Ops Hub

One integrated control surface combining navigation, storefront, monitoring, and quick actions with typed named instances.

q-import { ../dist/q-components/q-sidebar.qhtml } q-import { ../dist/q-components/q-tabs.qhtml } q-import { ../dist/q-components/q-modal.qhtml } q-import { ../dist/q-components/q-popup-menu.qhtml } q-import { ../dist/q-components/q-toolbar.qhtml } q-import { ../dist/q-components/q-toolbutton.qhtml } q-import { ../dist/q-components/q-estore.qhtml } q-import { ../dist/q-components/q-spritesheet.qhtml } q-import { ../dist/q-components/q-form.qhtml } q-import { ../dist/q-components/q-list-view.qhtml } q-import { ../dist/q-components/q-tree-view.qhtml } q-import { ../dist/q-components/q-tech-tag.qhtml } q-component hub-status-pill { q-property textValue: "frame: 0" div.w3-small.w3-padding-small.w3-round.w3-border.w3-pale-blue { text { ${this.textValue} } } } q-component hub-activity-list extends q-list-view { q-property model: [ "hub initialized", "catalog loaded", "sprite ready" ] } q-modal hubInfoModal { id: "hubInfoModal" visible: false titlebar { text { Hub Command Summary } } header { text { Command Surface } } main { p { text { This unified hub combines storefront controls, runtime observability, and quick command actions. } } p { text { Use the left navigation, floating toolbar, and context menu to drive one shared workspace. } } } footer { button.w3-button.w3-border.w3-round { text { Close } onclick { $("#hubInfoModal").hide(); } } } } q-popup-menu hubContextMenu { id: "hub-context-menu" popup-contents { ul.w3-ul.w3-small.w3-card { li { text { Open Overview } onclick { hubTabs.showTab(0); } } li { text { Open Store } onclick { hubTabs.showTab(1); } } li { text { Start Sprite } onclick { hubSprite.start(); } } hr { } li { text { Open Summary Modal } onclick { $("#hubInfoModal").show(); } } } } } div.w3-container.w3-border.w3-round-large.w3-padding { h4 { text { Commerce Operations Hub } } p.w3-small { text { Right-click inside the workspace to open the command menu. } } hub-status-pill hubFrameStatus { } q-tech-tag.w3-tag.w3-blue.w3-round.w3-small.w3-margin-left { text { unified-demo } } q-sidebar hubSidebar { sidebarWidth: "250" collapsedWidth: "40px" open: "1" content { div.w3-padding.w3-small { h5 { text { Navigation } } button.w3-button.w3-small.w3-border.w3-round.w3-margin-bottom { text { Overview } onclick { hubTabs.showTab(0); } } button.w3-button.w3-small.w3-border.w3-round.w3-margin-bottom { text { Storefront } onclick { hubTabs.showTab(1); } } button.w3-button.w3-small.w3-border.w3-round.w3-margin-bottom { text { Runtime } onclick { hubTabs.showTab(2); } } button.w3-button.w3-small.w3-border.w3-round { text { Hub Summary } onclick { $("#hubInfoModal").show(); } } } } main { div#hub-workspace.w3-padding.w3-round-large.w3-border { oncontextmenu { event.preventDefault(); hubContextMenu.show(event.clientX, event.clientY, event); } q-tabs hubTabs { q-tab { name { text { Overview } } body { q-spritesheet hubSprite { source: "assets/test-ss.png" frameCount: 18 frameStart: 0 frameStop: 17 frameDuration: 90 frameWidth: 32 frameHeight: 32 repeat: true running: false interpolate: false onframechanged(frameIndex) { hubFrameStatus.textValue = "frame: " + String(frameIndex); } } div.w3-margin-top { button.w3-button.w3-small.w3-border.w3-round { text { Start Sprite } onclick { hubSprite.start(); } } button.w3-button.w3-small.w3-border.w3-round.w3-margin-left { text { Stop Sprite } onclick { hubSprite.stop(); } } } div.w3-row-padding.w3-margin-top { div.w3-third { div.w3-panel.w3-border.w3-round { text { active frame: ${hubSprite.currentFrame} } } } div.w3-third { div.w3-panel.w3-border.w3-round { text { frame count: ${hubSprite.frameCount} } } } div.w3-third { div.w3-panel.w3-border.w3-round { text { playback: ${hubSprite.running} } } } } } } q-tab { name { text { Storefront } } body { button.w3-button.w3-small.w3-border.w3-round.w3-margin-bottom { text { Load Alternate Products } onclick { hubStore.setProducts([ { SKU: "ALT-001", name: "Travel Bottle", description: "Insulated stainless steel", price: "29.00" }, { SKU: "ALT-002", name: "Desk Mat", description: "Felt anti-slip surface", price: "22.50" }, { SKU: "ALT-003", name: "Pen Set", description: "Fine-tip gel pens", price: "12.99" }, { SKU: "ALT-004", name: "Cable Kit", description: "USB-C and Lightning pack", price: "18.75" } ]); } } q-estore hubStore { } } } q-tab { name { text { Runtime } } body { q-tree-view { treeModel: { storefront: ["catalog", "checkout", "orders"], runtime: ["signals", "timers", "workers"], assets: ["spritesheet", "icons", "theme"] } } hub-activity-list hubLog { } q-form runtimeNotes { url: "#" type: "GET" h4 { text { Runtime Notes } } q-form-input-textbox operatorName { name: "operator" label: "Operator" placeholder: "Operator" } q-form-input-textarea runtimeNote { name: "note" label: "Note" placeholder: "Enter a runtime note..." } div.q-form-actions { button.q-form-submit { type: "button" text { Add Activity Entry } onclick { hubLog.model.push("note captured at frame " + String(hubSprite.currentFrame)); } } } } } } } } } } q-toolbar hubTools { id: "hub-tools" title: "Hub Tools" x: 140 y: 140 width: 320 height: 70 q-toolbutton { src: "../dist/q-components/expand-collapse.svg" label: "Overview" onclick { hubTabs.showTab(0); } } q-toolbutton { src: "../dist/q-components/expand-collapse.svg" label: "Store" onclick { hubTabs.showTab(1); } } q-toolbutton { src: "../dist/q-components/expand-collapse.svg" label: "Start" onclick { hubSprite.start(); } } q-toolbutton { src: "../dist/q-components/expand-collapse.svg" label: "Stop" onclick { hubSprite.stop(); } } q-toolbutton { src: "../dist/q-components/expand-collapse.svg" label: "Summary" onclick { $("#hubInfoModal").show(); } } } }

q-tech-tag.qhtml usage

Placeholder usage for currently empty file.

q-import { ../dist/q-components/q-tech-tag.qhtml } q-style tech-note-style { background-color: #eef4ff color: #334155 border: 1px solid #c7d8ef } q-theme tech-tag-theme { .tech-note { tech-note-style } } tech-tag-theme { q-tech-tag { text { Extend this tag by adding definitions inside q-tech-tag.qhtml. } } div.tech-note.w3-panel.w3-small.w3-border { text { q-tech-tag.qhtml currently has no built-in definitions. } } }