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-grid.qhtml usage
Create a simple grid with declarative columns.
q-import { q-components.qhtml }
q-style cell-a-style {
background-color: #eff6ff
color: #1e3a8a
border: 1px solid #93c5fd
}
q-style cell-b-style {
background-color: #ecfeff
color: #155e75
border: 1px solid #67e8f9
}
q-style cell-c-style {
background-color: #f0fdf4
color: #166534
border: 1px solid #86efac
}
q-theme grid-cells-theme {
.cell-a { cell-a-style }
.cell-b { cell-b-style }
.cell-c { cell-c-style }
}
grid-cells-theme {
q-grid {
columns: 3;
div.cell-a.w3-panel.w3-border { text { Cell A } }
div.cell-b.w3-panel.w3-border { text { Cell B } }
div.cell-c.w3-panel.w3-border { text { Cell C } }
}
}
q-modal.qhtml usage
Use built-in q-modal-theme defaults, then layer an external theme override.
q-import { q-components.qhtml }
q-style modal-open-button-style {
background-color: #16a34a
color: #f8fafc
border: 1px solid #15803d
}
q-style modal-container-override-style {
background-color: #ffedd5
color: #7c2d12
}
q-style modal-titlebar-override-style {
background-color: #ef4444
color: #f8fafc
}
q-style modal-close-override-style {
background-color: #7f1d1d
color: #f8fafc
}
q-style modal-title-override-style {
background-color: #fb923c
color: #111827
}
q-style modal-content-override-style {
background-color: #dbeafe
color: #1e3a8a
}
q-style modal-footer-override-style {
background-color: #fde047
color: #713f12
}
q-theme modal-demo-theme {
q-modal-theme { }
.modal-open-btn { modal-open-button-style }
.q-modal-container { modal-container-override-style }
.q-modal-titlebar { modal-titlebar-override-style }
.q-modal-closebutton { modal-close-override-style }
.q-modal-title { modal-title-override-style }
.q-modal-content { modal-content-override-style }
.q-modal-footer { modal-footer-override-style }
button { modal-open-button-style }
}
modal-demo-theme {
button.modal-open-btn.w3-button {
text { Open Modal }
onclick { modalUsage.show(); }
}
q-modal modalUsage {
id: "modal-usage"
title { h3 { text { q-modal Usage } } }
body {
p { text { Modal default colors are overridden externally via q-theme composition. } }
button.w3-button { text { In-modal button override } }
}
footer {
button.w3-button {
text { Close }
onclick { this.component.hide(); }
}
}
}
}
q-tabs.qhtml usage
Instantiate tabs and switch via showTab(index).
q-import { q-components.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-content-override-style {
background-color: #fffaf0
}
q-theme tabs-demo-theme {
.tabs-show-btn { tabs-show-btn-style }
.q-tabs-nav { tabs-nav-override-style }
.q-tabs-content-themed { tabs-content-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 } } content { p { text { Overview content } } } }
q-tab { name { text { Details } } content { p { text { Details content } } } }
q-tab { name { text { Logs } } content { p { text { Logs content } } } }
}
}
q-tree-view quick usage
Collapsible tree using HTML5 details/summary from a q-model.
q-import { q-components.qhtml }
q-model my-tree {
q-map {
src: q-array { "index.js", "parser.js", q-map { utils: q-array { "path.js", "net.js" } } }
docs: q-array { "README.md", "MODULE-API.md" }
}
}
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 {
model: "my-tree"
}
}
q-list-view.qhtml usage
Render a simple list from a q-array model using for.
q-import { q-components.qhtml }
q-component demo-list-view extends q-list-view {
q-property model: q-array {
"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 { q-components.qhtml }
button.w3-button.w3-small.w3-border.w3-round {
text { Load Alternate Products }
onclick {
demoestore.products = QArray([
{ 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 { q-components.qhtml }
q-component sprite-demo-status {
q-property textValue: "frame: 0"
div.w3-small.w3-text-indigo {
text { ${this.component.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; }
}
}
}
q-painter border/background/mask demo
Three unique painters mapped to border, background, and mask using declarative q-style-painter.
q-painter painterBackground {
onpaint {
var w = this.width;
var h = this.height;
this.fillStyle = "#ff006e";
this.fillRect(0, 0, w, h);
this.fillStyle = "#ffd60a";
this.fillRect(0, 0, w * 0.5, h * 0.5);
this.fillStyle = "#00d1ff";
this.fillRect(w * 0.5, h * 0.5, w * 0.5, h * 0.5);
this.fillStyle = "#00f5a0";
this.fillRect(0, h * 0.58, w, h * 0.16);
this.fillStyle = "#111827";
this.fillRect(w * 0.46, 0, w * 0.08, h);
}
}
q-painter painterBorder {
onpaint {
var w = this.width;
var h = this.height;
var band = Math.max(6, Math.floor(Math.min(w, h) * 0.12));
this.fillStyle = "#ff0033";
this.fillRect(0, 0, w, h);
this.fillStyle = "#00e5ff";
this.fillRect(band, band, w - (band * 2), h - (band * 2));
this.fillStyle = "#000000";
this.fillRect(band * 2, band * 2, w - (band * 4), h - (band * 4));
this.fillStyle = "#f6ff00";
this.fillRect(0, h * 0.42, w, h * 0.16);
this.fillRect(w * 0.42, 0, w * 0.16, h);
}
}
q-painter painterMask {
q-property topWidth: 62
q-property topHeight: 34
onpaint {
var w = this.width;
var h = this.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(0, 0, w, h);
this.fillStyle = "black";
this.beginPath();
this.moveTo(left, 0);
this.lineTo(w - left, 0);
this.lineTo(w, h * th / 100);
this.lineTo(w * 0.5, h);
this.lineTo(0, h * th / 100);
this.closePath();
this.fill();
}
}
q-style painterPanelBase {
width: 220px
height: 92px
borderRadius: 10px
display: inline-flex
alignItems: center
justifyContent: center
marginRight: 10px
marginBottom: 10px
color: #0f172a
fontWeight: 700
fontFamily: monospace
letterSpacing: 0.02em
border: 1px solid #334155
}
q-style panelBackgroundStyle {
width: 220px
height: 92px
borderRadius: 10px
border: 1px solid #334155
display: inline-flex
alignItems: center
justifyContent: center
color: #0f172a
fontWeight: 700
fontFamily: monospace
background-repeat: no-repeat
background-size: 100% 100%
q-style-painter {
background { painterBackground }
}
}
q-style panelBorderStyle {
width: 220px
height: 92px
borderRadius: 10px
border: 18px solid transparent
border-image-slice: 0
backgroundColor: #f8fafc
display: inline-flex
alignItems: center
justifyContent: center
color: #0f172a
fontWeight: 700
fontFamily: monospace
q-style-painter {
border { painterBorder }
}
}
q-style panelMaskStyle {
width: 220px
height: 92px
borderRadius: 10px
border: 1px solid #334155
background: linear-gradient(90deg, #ff006e 0%, #ffd60a 20%, #00d1ff 40%, #00f5a0 60%, #8b5cf6 80%, #111827 100%)
display: inline-flex
alignItems: center
justifyContent: center
color: #0f172a
fontWeight: 700
fontFamily: monospace
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-style-painter {
mask { painterMask }
}
}
q-theme painterTriptychTheme {
.panel-background { panelBackgroundStyle }
.panel-border { panelBorderStyle }
.panel-mask { panelMaskStyle }
}
painterTriptychTheme {
div.w3-container.w3-border.w3-round-large.w3-padding {
div#ptri-bg.panel-background { text { background painter } }
div#ptri-border.panel-border { text { border painter } }
div#ptri-mask.panel-mask { text { mask painter } }
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 { q-components.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 } }
}
}
}
Unified Commerce Ops Hub
One integrated control surface combining navigation, storefront, monitoring, and quick actions with typed named instances.
q-import { q-components/q-sidebar.qhtml?v=drawer-width }
q-import { q-components/q-tabs.qhtml }
q-import { q-components/q-modal.qhtml }
q-import { q-components/q-popup-menu.qhtml?v=popup-redesign-6 }
q-import { q-components/q-toolbar.qhtml }
q-import { q-components/q-estore.qhtml }
q-import { q-components/q-spritesheet.qhtml?v=6.3.2 }
q-import { q-components/q-grid.qhtml }
q-import { q-components/q-form.qhtml }
q-import { q-components/q-list-view.qhtml }
q-import { q-components/q-tree-view.qhtml?v=tree-css-28 }
q-import { q-components/q-tech-tag.qhtml }
q-model hubTreeModel {
q-map {
storefront: q-array { "catalog", "checkout", "orders" }
runtime: q-array { "signals", "timers", "workers" }
assets: q-array { "spritesheet", "icons", "theme" }
}
}
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.component.textValue} }
}
}
q-component hub-activity-list extends q-list-view {
q-property model: q-array {
"hub initialized",
"catalog loaded",
"sprite ready"
}
}
q-modal hubInfoModal {
title { h4 { text { Hub Command Summary } } }
body {
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(); }
}
}
onready { this.component.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(); } }
}
}
onready { this.closest("q-popup-menu").style.display = "none"; }
}
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 + "px", event.clientY + "px");
}
q-tabs hubTabs {
q-tab {
name { text { Overview } }
content {
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(); }
}
}
q-grid {
columns: 3
div.w3-panel.w3-border.w3-round { text { active frame: ${hubSprite.currentFrame} } }
div.w3-panel.w3-border.w3-round { text { frame count: ${hubSprite.frameCount} } }
div.w3-panel.w3-border.w3-round { text { playback: ${hubSprite.running} } }
}
}
}
q-tab {
name { text { Storefront } }
content {
button.w3-button.w3-small.w3-border.w3-round.w3-margin-bottom {
text { Load Alternate Products }
onclick {
hubStore.products = QArray([
{ 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 } }
content {
q-tree-view {
model: "hubTreeModel"
}
hub-activity-list hubLog { }
q-form {
h4 { text { Runtime Notes } }
q-input { placeholder: "Operator" }
q-textarea { text { Enter a runtime note... } }
q-submit {
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: "q-components/expand-collapse.svg"
label: "Overview"
onclick { hubTabs.showTab(0); }
}
q-toolbutton {
src: "q-components/expand-collapse.svg"
label: "Store"
onclick { hubTabs.showTab(1); }
}
q-toolbutton {
src: "q-components/expand-collapse.svg"
label: "Start"
onclick { hubSprite.start(); }
}
q-toolbutton {
src: "q-components/expand-collapse.svg"
label: "Stop"
onclick { hubSprite.stop(); }
}
q-toolbutton {
src: "q-components/expand-collapse.svg"
label: "Summary"
onclick { hubInfoModal.show(); }
}
}
}
q-tech-tag.qhtml usage
Placeholder usage for currently empty file.
q-import { 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. } }
}