← back to Quadrille Showroom
public/js/furniture-styles.js
117 lines
/* ============================================================================
* furniture-styles.js — The Quadrille House: FURNITURE STYLE SELECTOR.
*
* A bottom-left chip-tray with the four procedural furniture styles
* (Contemporary / Traditional / Transitional / Brutalist). Clicking a chip calls
* window._qh.swapFurniture(styleKey, { includeExtras }). A "+ Decor" toggle opts
* the set into its optional decor extras (onload stays minimal = table + chair).
* The chosen style persists in localStorage (via swapFurniture) so it survives a
* reload; the tray reflects the active style read back from window._qh.
*
* Matches the hamburger-dock visual language (gold #c9a96e on smoked glass,
* Georgia eyebrow). Its own #qh-style-tray id is NOT in dock.js's stow lists, so
* it stays permanently visible like the guided pager.
* ========================================================================== */
(function () {
'use strict';
var LS_EXTRAS = 'qh_furniture_extras_ui'; // remembers ONLY the toggle's UI state
var extrasOn = false;
function injectStyles() {
if (document.getElementById('qh-style-styles')) return;
var st = document.createElement('style');
st.id = 'qh-style-styles';
st.textContent = [
'#qh-style-tray{position:fixed;left:16px;bottom:16px;z-index:8800;',
'display:flex;flex-direction:column;gap:7px;padding:10px 11px;',
'background:rgba(14,14,20,0.90);border:1px solid rgba(201,169,110,0.30);border-radius:14px;',
'backdrop-filter:blur(12px);box-shadow:0 18px 50px -12px rgba(0,0,0,0.8);',
'font-family:Georgia,serif;max-width:250px;}',
'.qh-style-eyebrow{font-size:10px;letter-spacing:1.5px;text-transform:uppercase;',
'color:#8c8678;font-weight:700;padding:0 2px 1px;}',
'.qh-style-chips{display:flex;flex-wrap:wrap;gap:6px;}',
'.qh-style-chip{cursor:pointer;padding:7px 12px;border-radius:9px;',
'background:rgba(255,255,255,0.04);border:1px solid rgba(201,169,110,0.20);',
'color:#e8e2d4;font-size:12.5px;font-weight:600;letter-spacing:.2px;',
'transition:background .12s,border-color .12s,color .12s;white-space:nowrap;}',
'.qh-style-chip:hover{background:rgba(201,169,110,0.18);border-color:#c9a96e;}',
'.qh-style-chip.active{background:rgba(201,169,110,0.28);border-color:#c9a96e;color:#fbf4e3;}',
'.qh-style-decor{display:flex;align-items:center;justify-content:space-between;gap:8px;',
'margin-top:1px;padding:6px 10px;border-radius:9px;cursor:pointer;',
'background:rgba(255,255,255,0.03);border:1px solid rgba(201,169,110,0.16);',
'color:#cfc7b4;font-size:11.5px;font-weight:600;letter-spacing:.3px;',
'transition:background .12s,border-color .12s,color .12s;}',
'.qh-style-decor:hover{border-color:#c9a96e;color:#f0e6cf;}',
'.qh-style-decor.on{background:rgba(201,169,110,0.22);border-color:#c9a96e;color:#fbf4e3;}',
'.qh-style-decor .qh-decor-dot{width:9px;height:9px;border-radius:50%;flex:0 0 auto;',
'background:rgba(201,169,110,0.35);transition:background .12s;}',
'.qh-style-decor.on .qh-decor-dot{background:#c9a96e;}'
].join('\n');
document.head.appendChild(st);
}
var tray;
function reflect() {
if (!tray || !window._qh) return;
var active = window._qh.furnitureStyle;
tray.querySelectorAll('.qh-style-chip').forEach(function (c) {
c.classList.toggle('active', c.getAttribute('data-style') === active);
});
var decor = tray.querySelector('.qh-style-decor');
if (decor) decor.classList.toggle('on', extrasOn);
}
function build() {
var order = (window._qh && window._qh.FURNITURE_STYLE_ORDER) || [];
injectStyles();
tray = document.createElement('div');
tray.id = 'qh-style-tray';
var html = '<div class="qh-style-eyebrow">Furniture Style</div><div class="qh-style-chips">';
order.forEach(function (key) {
var label = window._qh.furnitureStyleLabel ? window._qh.furnitureStyleLabel(key) : key;
html += '<button class="qh-style-chip" data-style="' + key + '">' + label + '</button>';
});
html += '</div>' +
'<div class="qh-style-decor" role="button" tabindex="0">' +
'<span>Add Decor</span><span class="qh-decor-dot"></span></div>';
tray.innerHTML = html;
document.body.appendChild(tray);
tray.querySelector('.qh-style-chips').addEventListener('click', function (e) {
var chip = e.target.closest('.qh-style-chip'); if (!chip) return;
window._qh.swapFurniture(chip.getAttribute('data-style'), { includeExtras: extrasOn });
reflect();
});
var decor = tray.querySelector('.qh-style-decor');
function toggleDecor() {
extrasOn = !extrasOn;
try { localStorage.setItem(LS_EXTRAS, extrasOn ? '1' : '0'); } catch (e) {}
window._qh.swapFurniture(window._qh.furnitureStyle, { includeExtras: extrasOn });
reflect();
}
decor.addEventListener('click', toggleDecor);
decor.addEventListener('keydown', function (e) {
if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); toggleDecor(); }
});
reflect();
}
function boot(tries) {
tries = tries || 0;
// Wait until showroom.js has booted its furniture API + built the first set.
if (!window._qh || !window._qh.FURNITURE_STYLE_ORDER || !window._qh.furniturePresent) {
if (tries > 200) return; // give up after ~12s
return setTimeout(function () { boot(tries + 1); }, 60);
}
build();
}
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', function () { boot(0); });
else boot(0);
})();