diff options
author | JJ <nicetry@noemail.com> | 2025-03-30 20:56:01 +0100 |
---|---|---|
committer | JJ <nicetry@noemail.com> | 2025-03-30 20:56:01 +0100 |
commit | d518beb637e7c2776d84e87c63cc201c101ca89c (patch) | |
tree | abbfc7933285f829a23afeae09655e5d2106849b /static | |
parent | aa931dddf30700b6458a269389291b632a848ccb (diff) |
styling, sub instructions
Diffstat (limited to 'static')
-rw-r--r-- | static/images/bars.svg | 52 | ||||
-rw-r--r-- | static/scripts/htmx-targets.js | 129 | ||||
-rw-r--r-- | static/scripts/index.js | 11 | ||||
-rw-r--r-- | static/style/style.css | 27 |
4 files changed, 207 insertions, 12 deletions
diff --git a/static/images/bars.svg b/static/images/bars.svg new file mode 100644 index 0000000..64dd5a8 --- /dev/null +++ b/static/images/bars.svg @@ -0,0 +1,52 @@ +<svg width="16" height="16" viewBox="0 0 135 140" xmlns="http://www.w3.org/2000/svg" fill="#fff"> + <rect y="10" width="15" height="120" rx="6"> + <animate attributeName="height" + begin="0.5s" dur="1s" + values="120;110;100;90;80;70;60;50;40;140;120" calcMode="linear" + repeatCount="indefinite" /> + <animate attributeName="y" + begin="0.5s" dur="1s" + values="10;15;20;25;30;35;40;45;50;0;10" calcMode="linear" + repeatCount="indefinite" /> + </rect> + <rect x="30" y="10" width="15" height="120" rx="6"> + <animate attributeName="height" + begin="0.25s" dur="1s" + values="120;110;100;90;80;70;60;50;40;140;120" calcMode="linear" + repeatCount="indefinite" /> + <animate attributeName="y" + begin="0.25s" dur="1s" + values="10;15;20;25;30;35;40;45;50;0;10" calcMode="linear" + repeatCount="indefinite" /> + </rect> + <rect x="60" width="15" height="140" rx="6"> + <animate attributeName="height" + begin="0s" dur="1s" + values="120;110;100;90;80;70;60;50;40;140;120" calcMode="linear" + repeatCount="indefinite" /> + <animate attributeName="y" + begin="0s" dur="1s" + values="10;15;20;25;30;35;40;45;50;0;10" calcMode="linear" + repeatCount="indefinite" /> + </rect> + <rect x="90" y="10" width="15" height="120" rx="6"> + <animate attributeName="height" + begin="0.25s" dur="1s" + values="120;110;100;90;80;70;60;50;40;140;120" calcMode="linear" + repeatCount="indefinite" /> + <animate attributeName="y" + begin="0.25s" dur="1s" + values="10;15;20;25;30;35;40;45;50;0;10" calcMode="linear" + repeatCount="indefinite" /> + </rect> + <rect x="120" y="10" width="15" height="120" rx="6"> + <animate attributeName="height" + begin="0.5s" dur="1s" + values="120;110;100;90;80;70;60;50;40;140;120" calcMode="linear" + repeatCount="indefinite" /> + <animate attributeName="y" + begin="0.5s" dur="1s" + values="10;15;20;25;30;35;40;45;50;0;10" calcMode="linear" + repeatCount="indefinite" /> + </rect> +</svg> diff --git a/static/scripts/htmx-targets.js b/static/scripts/htmx-targets.js new file mode 100644 index 0000000..26fffc3 --- /dev/null +++ b/static/scripts/htmx-targets.js @@ -0,0 +1,129 @@ +(function() { + /** @type {import("../htmx").HtmxInternalApi} */ + var api + + var attrPrefix = 'hx-target-' + + // IE11 doesn't support string.startsWith + function startsWith(str, prefix) { + return str.substring(0, prefix.length) === prefix + } + + /** + * @param {HTMLElement} elt + * @param {number} respCode + * @returns {HTMLElement | null} + */ + function getRespCodeTarget(elt, respCodeNumber) { + if (!elt || !respCodeNumber) return null + + var respCode = respCodeNumber.toString() + + // '*' is the original syntax, as the obvious character for a wildcard. + // The 'x' alternative was added for maximum compatibility with HTML + // templating engines, due to ambiguity around which characters are + // supported in HTML attributes. + // + // Start with the most specific possible attribute and generalize from + // there. + var attrPossibilities = [ + respCode, + + respCode.substring(0, 2) + '*', + respCode.substring(0, 2) + 'x', + + respCode.substring(0, 1) + '*', + respCode.substring(0, 1) + 'x', + respCode.substring(0, 1) + '**', + respCode.substring(0, 1) + 'xx', + + '*', + 'x', + '***', + 'xxx' + ] + if (startsWith(respCode, '4') || startsWith(respCode, '5')) { + attrPossibilities.push('error') + } + + for (var i = 0; i < attrPossibilities.length; i++) { + var attr = attrPrefix + attrPossibilities[i] + var attrValue = api.getClosestAttributeValue(elt, attr) + if (attrValue) { + if (attrValue === 'this') { + return api.findThisElement(elt, attr) + } else { + return api.querySelectorExt(elt, attrValue) + } + } + } + + return null + } + + /** @param {Event} evt */ + function handleErrorFlag(evt) { + if (evt.detail.isError) { + if (htmx.config.responseTargetUnsetsError) { + evt.detail.isError = false + } + } else if (htmx.config.responseTargetSetsError) { + evt.detail.isError = true + } + } + + htmx.defineExtension('response-targets', { + + /** @param {import("../htmx").HtmxInternalApi} apiRef */ + init: function(apiRef) { + api = apiRef + + if (htmx.config.responseTargetUnsetsError === undefined) { + htmx.config.responseTargetUnsetsError = true + } + if (htmx.config.responseTargetSetsError === undefined) { + htmx.config.responseTargetSetsError = false + } + if (htmx.config.responseTargetPrefersExisting === undefined) { + htmx.config.responseTargetPrefersExisting = false + } + if (htmx.config.responseTargetPrefersRetargetHeader === undefined) { + htmx.config.responseTargetPrefersRetargetHeader = true + } + }, + + /** + * @param {string} name + * @param {Event} evt + */ + onEvent: function(name, evt) { + if (name === 'htmx:beforeSwap' && + evt.detail.xhr && + evt.detail.xhr.status !== 200) { + if (evt.detail.target) { + if (htmx.config.responseTargetPrefersExisting) { + evt.detail.shouldSwap = true + handleErrorFlag(evt) + return true + } + if (htmx.config.responseTargetPrefersRetargetHeader && + evt.detail.xhr.getAllResponseHeaders().match(/HX-Retarget:/i)) { + evt.detail.shouldSwap = true + handleErrorFlag(evt) + return true + } + } + if (!evt.detail.requestConfig) { + return true + } + var target = getRespCodeTarget(evt.detail.requestConfig.elt, evt.detail.xhr.status) + if (target) { + handleErrorFlag(evt) + evt.detail.shouldSwap = true + evt.detail.target = target + } + return true + } + } + }) +})() diff --git a/static/scripts/index.js b/static/scripts/index.js new file mode 100644 index 0000000..65c3c12 --- /dev/null +++ b/static/scripts/index.js @@ -0,0 +1,11 @@ +const modal = document.querySelector("dialog"); +const showModalBtn = document.querySelector("#show-modal"); +const closeModalBtn = document.querySelector("#close-modal"); + +showModalBtn.addEventListener("click", () => { + modal.showModal(); +}); + +closeModalBtn.addEventListener("click", () => { + modal.close(); +}); diff --git a/static/style/style.css b/static/style/style.css index 36a4373..748e8dd 100644 --- a/static/style/style.css +++ b/static/style/style.css @@ -1,11 +1,21 @@ :root { - --bg-colour: #1d1f27; - --font-colour: #c9d1d9; - --accent-colour: #8cc2dd; + --bg-colour: #fff; + --font-colour: #1d1f27; + --accent-colour: #3273dc; + --border-color: #ccc; --success: #4bb543; --error: #ff3333; } +/* Helpers */ +.error { + color: var(--error); +} + +.success { + color: var(--success); +} + body, html { min-height: 100%; @@ -14,7 +24,7 @@ html { body { background-color: var(--bg-colour); color: var(--font-colour); - font-family: "Verdana"; + font-family: "DM Sans", sans-serif; max-width: 900px; margin: 0 auto; padding: 15px; @@ -70,7 +80,7 @@ button { } hr { - border: 1px dashed #fff; + border: 1px dashed var(--border-color); margin: 20px 0; } @@ -118,10 +128,3 @@ figure figcaption { font-weight: 400; } -.error { - color: var(--error); -} - -.success { - color: var(--success); -} |