diff --git a/public/css/admin-style.css b/public/css/admin-style.css index b3da6df..1a75278 100644 --- a/public/css/admin-style.css +++ b/public/css/admin-style.css @@ -58,22 +58,20 @@ } /* Additional Properties */ +#neusta_areabrick_config ul.additional-properties { + padding: 0; +} + #neusta_areabrick_config ul.additional-properties li { list-style-type: none; - margin-left: 5px; - width: 150px; + width: 100%; padding: 2px 4px; border-radius: 3px; display: inline-block; - color: #ffffff; -} - -#neusta_areabrick_config ul.additional-properties li.tag { - background-color: #2a6f9c; } -#neusta_areabrick_config ul.additional-properties li.group { - background-color: #194567; +#neusta_areabrick_config ul.additional-properties li + li { + margin-top: 3px; } #neusta_areabrick_config ul.additional-properties li.empty { diff --git a/public/js/areabrick-overview.js b/public/js/areabrick-overview.js index 11c7b7f..40b2435 100644 --- a/public/js/areabrick-overview.js +++ b/public/js/areabrick-overview.js @@ -38,12 +38,14 @@ neusta.areabrick_config.areabrick_overview = Class.create({ html: response.responseText, autoScroll: true, }); + + this.colorizeAdditionalProperties(); }.bind(this), }); this.handleClick('#neusta_areabrick_config a[data-page-id]', el => { pimcore.helpers.openDocument(el.dataset.pageId, el.dataset.pageType); - }) + }); } return this.panel; @@ -59,4 +61,83 @@ neusta.areabrick_config.areabrick_overview = Class.create({ }); }, + colorizeAdditionalProperties: function () { + document.getElementById(this.tabId) + .querySelectorAll('#neusta_areabrick_config ul.additional-properties > li:not(.empty)') + .forEach(el => { + const name = el.querySelector('span').textContent; + const rgb = this.hslToRgb(this.textToHSL(name, { + hue: [190,220], + sat: [60,80], + lit: [30,70], + })); + + el.style.backgroundColor = `rgb(${rgb.r}, ${rgb.g}, ${rgb.b})`; + el.style.color = this.contrastingColor(rgb); + }); + }, + + // https://gist.github.com/0x263b/2bdd90886c2036a1ad5bcf06d6e6fb37#hsl + textToHSL: function (string, opts = {}) { + const hash = [...string].reduce((s, c) => Math.imul(31, s) + c.charCodeAt(0) | 0, 0); + const { + hue = [0, 360], + sat = [0, 100], + lit = [0, 100], + } = opts; + + function range(num, min, max) { + const diff = max - min; + + return (((num % diff) + diff) % diff) + min; + } + + return { + h: range(hash, hue[0], hue[1]), + s: range(hash, sat[0], sat[1]), + l: range(hash, lit[0], lit[1]), + }; + }, + + // https://en.wikipedia.org/wiki/HSL_and_HSV#HSL_to_RGB_alternative + hslToRgb: function (hsl) { + const h = hsl.h; + const s = hsl.s / 100; + const l = hsl.l / 100; + + function f(n) { + const k = (n + h / 30) % 12; + const a = s * Math.min(l, 1 - l); + + return l - a * Math.max(-1, Math.min(k - 3, 9 - k, 1)); + } + + return { + r: Math.round(f(0) * 255), + g: Math.round(f(8) * 255), + b: Math.round(f(4) * 255), + }; + }, + + // https://www.w3.org/TR/WCAG21/#dfn-relative-luminance + rgbToRelativeLuminance: function (rgb) { + const srgb = this.mapObject(rgb, c => c / 255); + const {r, g, b} = this.mapObject(srgb, c => { + return c <= 0.04045 + ? c / 12.92 + : ((c + 0.055) / 1.055) ** 2.4; + }); + + return 0.2126 * r + 0.7152 * g + 0.0722 * b; + }, + + // https://dev.to/louis7/how-to-choose-the-font-color-based-on-the-background-color-402a + contrastingColor: function (rgb) { + return this.rgbToRelativeLuminance(rgb) > 0.179 ? '#000' : '#fff'; + }, + + mapObject: function (obj, func) { + return Object.fromEntries(Object.entries(obj).map(([k, v]) => [k, func(v)])); + }, + }); diff --git a/templates/bricks/overview.html.twig b/templates/bricks/overview.html.twig index 34d8aaf..10fdd32 100644 --- a/templates/bricks/overview.html.twig +++ b/templates/bricks/overview.html.twig @@ -52,10 +52,8 @@ {% if hasAdditionalProperties %}