diff options
| author | Kyren223 <contact@kyren.codes> | 2026-10-08 19:44:46 +0300 |
|---|---|---|
| committer | Kyren223 <contact@kyren.codes> | 2026-10-08 19:44:46 +0300 |
| commit | 9b03d2790b8b8db1b5a6755b6130f37e5f7f2455 (patch) | |
| tree | a84f6e9cfe2b8aaf087d55830c938443f6be683e /public | |
| parent | 6e70fe447ec9504757fbdc152b5b3697c9af8def (diff) | |
WIP
Diffstat (limited to 'public')
| -rw-r--r-- | public/copy.js | 14 | ||||
| -rw-r--r-- | public/main.css | 5 | ||||
| -rw-r--r-- | public/my_uptime.js | 18 | ||||
| -rw-r--r-- | public/scrollbar.js | 52 | ||||
| -rw-r--r-- | public/style.css | 376 | ||||
| -rw-r--r-- | public/styles/terminal.css | 23 |
6 files changed, 404 insertions, 84 deletions
diff --git a/public/copy.js b/public/copy.js new file mode 100644 index 0000000..751f2ae --- /dev/null +++ b/public/copy.js @@ -0,0 +1,14 @@ +document.addEventListener("click", async (e) => { + const el = e.target.closest("[data-copy]"); + if (!el) return; + try { + await navigator.clipboard.writeText(el.dataset.copy); + } catch (err) { + console.error("copy failed:", err); + return; + } + const scope = el.closest("[data-copy-scope]") ?? el; + scope.setAttribute("data-copied", ""); + clearTimeout(scope._copyTimer); + scope._copyTimer = setTimeout(() => scope.removeAttribute("data-copied"), 1500); +}); diff --git a/public/main.css b/public/main.css index f93965c..772f896 100644 --- a/public/main.css +++ b/public/main.css @@ -5,3 +5,8 @@ @source "../**/*.go"; @source "../**/*.templ"; + +@keyframes pop { 50% { transform: scale(1.3); } } +[data-copied] svg { animation: pop 0.25s; } + +@keyframes bump { 50% { transform: scale(1.03); } } diff --git a/public/my_uptime.js b/public/my_uptime.js new file mode 100644 index 0000000..25f549a --- /dev/null +++ b/public/my_uptime.js @@ -0,0 +1,18 @@ +async function updateUptime() { + try { + const res = await fetch("/api/my-uptime"); + if (!res.ok) return; + const data = await res.json(); + + const text = document.getElementById("Uptime"); + + if (text && text.textContent !== data.uptime) { + text.textContent = data.uptime; + } + } catch (e) {} +} + +// Run on page load after all DOM elements loaded +DOMContentLoaded(updateUptime()); + +setInterval(updateUptime, 5 * 1000); // in ms diff --git a/public/scrollbar.js b/public/scrollbar.js new file mode 100644 index 0000000..da6aded --- /dev/null +++ b/public/scrollbar.js @@ -0,0 +1,52 @@ +function initScrollbox(box) { + const area = box.querySelector("[data-scroll-area]"); + const track = box.querySelector("[data-scroll-track]"); + const thumb = box.querySelector("[data-scroll-thumb]"); + + const inset = () => parseFloat(getComputedStyle(thumb).left) || 0; + + const update = () => { + const pad = inset(); + const room = track.clientHeight - pad * 2; + const maxScroll = area.scrollHeight - area.clientHeight; + const ratio = Math.min(1, area.clientHeight / area.scrollHeight); + const height = Math.max(room * ratio, thumb.clientWidth); + const progress = maxScroll > 0 ? area.scrollTop / maxScroll : 0; + thumb.style.height = `${height}px`; + thumb.style.top = `${pad + progress * (room - height)}px`; + }; + + thumb.addEventListener("pointerdown", (e) => { + e.preventDefault(); + thumb.setPointerCapture(e.pointerId); + const startY = e.clientY; + const startTop = parseFloat(thumb.style.top) || 0; + + const move = (ev) => { + const pad = inset(); + const room = track.clientHeight - pad * 2 - thumb.offsetHeight; + const top = Math.min( + Math.max(startTop - pad + ev.clientY - startY, 0), + room, + ); + const progress = room > 0 ? top / room : 0; + area.scrollTop = progress * (area.scrollHeight - area.clientHeight); + }; + const stop = () => { + thumb.removeEventListener("pointermove", move); + thumb.removeEventListener("pointerup", stop); + thumb.removeEventListener("pointercancel", stop); + }; + thumb.addEventListener("pointermove", move); + thumb.addEventListener("pointerup", stop); + thumb.addEventListener("pointercancel", stop); + }); + + area.addEventListener("scroll", update, { passive: true }); + const observer = new ResizeObserver(update); + observer.observe(area); + for (const child of area.children) observer.observe(child); + update(); +} + +document.querySelectorAll("[data-scrollbox]").forEach(initScrollbox); diff --git a/public/style.css b/public/style.css index d1e775f..c555b7d 100644 --- a/public/style.css +++ b/public/style.css @@ -13,6 +13,8 @@ --text-3xl--line-height: calc(2.25 / 1.875); --font-weight-normal: 400; --font-weight-bold: 700; + --default-transition-duration: 150ms; + --default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); --default-font-family: var(--font-sans); --default-mono-font-family: var(--font-mono); } @@ -178,18 +180,54 @@ .fixed { position: fixed; } + .relative { + position: relative; + } .static { position: static; } + .inset-x-\[0\.3rem\] { + inset-inline: 0.3rem; + } + .top-1 { + top: var(--spacing); + } + .top-1\/2 { + top: calc(1 / 2 * 100%); + } .top-\[-0\.7em\] { top: -0.7em; } + .top-\[-0\.75rem\] { + top: -0.75rem; + } + .top-\[0\.6rem\] { + top: 0.6rem; + } + .right-\[0\.6rem\] { + right: 0.6rem; + } + .right-full { + right: 100%; + } .bottom-\[-0\.7em\] { bottom: -0.7em; } + .bottom-\[-0\.75rem\] { + bottom: -0.75rem; + } .left-\[0\.5em\] { left: 0.5em; } + .left-\[0\.625rem\] { + left: 0.625rem; + } + .col-span-2 { + grid-column: span 2 / span 2; + } + .-m-\[0\.4rem\] { + margin: calc(0.4rem * -1); + } .m-0 { margin: 0px; } @@ -217,6 +255,9 @@ .my-\[5vw\] { margin-block: 5vw; } + .mt-\[0\.5rem\] { + margin-top: 0.5rem; + } .mt-\[0\.625vw\] { margin-top: 0.625vw; } @@ -229,6 +270,9 @@ .mt-\[10vw\] { margin-top: 10vw; } + .mr-2 { + margin-right: calc(var(--spacing) * 2); + } .mr-\[0\.1vw\] { margin-right: 0.1vw; } @@ -241,21 +285,24 @@ .mb-6 { margin-bottom: calc(var(--spacing) * 6); } - .mb-6\.25 { - margin-bottom: calc(var(--spacing) * 6.25); - } - .mb-\[1\.5625rem\] { - margin-bottom: 1.5625rem; + .mb-\[0\.30rem\] { + margin-bottom: 0.30rem; } .mb-\[1\.5625vw\] { margin-bottom: 1.5625vw; } + .mb-\[1rem\] { + margin-bottom: 1rem; + } .mb-\[5vw\] { margin-bottom: 5vw; } .mb-\[7vw\] { margin-bottom: 7vw; } + .-ml-\[0\.1rem\] { + margin-left: calc(0.1rem * -1); + } .ml-\[-4vw\] { margin-left: -4vw; } @@ -280,6 +327,9 @@ .h-0 { height: 0px; } + .h-38 { + height: calc(var(--spacing) * 38); + } .h-\[9\.5vw\] { height: 9.5vw; } @@ -307,42 +357,24 @@ .max-h-\[80svh\] { max-height: 80svh; } + .min-h-0 { + min-height: 0px; + } .w-0 { width: 0px; } - .w-300 { - width: calc(var(--spacing) * 300); + .w-8 { + width: calc(var(--spacing) * 8); } .w-\[30\%\] { width: 30%; } - .w-\[40rem\] { - width: 40rem; - } .w-\[67\%\] { width: 67%; } .w-\[70\%\] { width: 70%; } - .w-\[75\.0rem\] { - width: 75.0rem; - } - .w-\[75\.001rem\] { - width: 75.001rem; - } - .w-\[75\.1rem\] { - width: 75.1rem; - } - .w-\[75\.12rem\] { - width: 75.12rem; - } - .w-\[75\.13rem\] { - width: 75.13rem; - } - .w-\[75\.123rem\] { - width: 75.123rem; - } .w-\[75rem\] { width: 75rem; } @@ -364,18 +396,41 @@ .flex-1 { flex: 1; } + .flex-shrink { + flex-shrink: 1; + } + .shrink-0 { + flex-shrink: 0; + } .border-collapse { border-collapse: collapse; } + .-translate-y-1 { + --tw-translate-y: calc(var(--spacing) * -1); + translate: var(--tw-translate-x) var(--tw-translate-y); + } + .-translate-y-1\/2 { + --tw-translate-y: calc(calc(1 / 2 * 100%) * -1); + translate: var(--tw-translate-x) var(--tw-translate-y); + } .transform { transform: var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,); } + .cursor-grab { + cursor: grab; + } .cursor-pointer { cursor: pointer; } + .touch-none { + touch-action: none; + } .resize { resize: both; } + .\[scrollbar-width\:none\] { + scrollbar-width: none; + } .grid-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); } @@ -385,6 +440,9 @@ .grid-cols-5 { grid-template-columns: repeat(5, minmax(0, 1fr)); } + .grid-cols-\[29\%_1fr\] { + grid-template-columns: 29% 1fr; + } .flex-col { flex-direction: column; } @@ -394,21 +452,24 @@ .justify-between { justify-content: space-between; } + .gap-4 { + gap: calc(var(--spacing) * 4); + } .gap-10 { gap: calc(var(--spacing) * 10); } .gap-16 { gap: calc(var(--spacing) * 16); } - .gap-20 { - gap: calc(var(--spacing) * 20); - } .gap-\[1\.25vw\] { gap: 1.25vw; } .gap-\[1ch\] { gap: 1ch; } + .gap-x-8 { + column-gap: calc(var(--spacing) * 8); + } .gap-x-\[5vw\] { column-gap: 5vw; } @@ -417,6 +478,9 @@ margin-inline-start: calc(1.25vw * var(--tw-space-x-reverse)); margin-inline-end: calc(1.25vw * calc(1 - var(--tw-space-x-reverse))); } + .gap-y-4 { + row-gap: calc(var(--spacing) * 4); + } .truncate { overflow: hidden; text-overflow: ellipsis; @@ -434,29 +498,16 @@ .overflow-y-auto { overflow-y: auto; } - .border { - border-style: var(--tw-border-style); - border-width: 1px; - } - .border-0 { - border-style: var(--tw-border-style); - border-width: 0px; + .rounded-\[0\.4rem\] { + border-radius: 0.4rem; } - .border-1 { + .border { border-style: var(--tw-border-style); border-width: 1px; } - .border-2 { - border-style: var(--tw-border-style); - border-width: 2px; - } - .border-3 { - border-style: var(--tw-border-style); - border-width: 3px; - } - .border-10 { + .border-\[0\.1rem\] { border-style: var(--tw-border-style); - border-width: 10px; + border-width: 0.1rem; } .border-\[0\.1vw\] { border-style: var(--tw-border-style); @@ -466,10 +517,6 @@ border-style: var(--tw-border-style); border-width: 0.2rem; } - .border-\[0\.25rem\] { - border-style: var(--tw-border-style); - border-width: 0.25rem; - } .border-\[0\.25vh\] { border-style: var(--tw-border-style); border-width: 0.25vh; @@ -494,6 +541,15 @@ .border-\[var\(--alt\)\] { border-color: var(--alt); } + .bg-\(--background\) { + background-color: var(--background); + } + .bg-\(--secondary\) { + background-color: var(--secondary); + } + .bg-\[var\(--background\)\] { + background-color: var(--background); + } .fill-\[\#7ed4fb\]\/50 { fill: color-mix(in oklab, #7ed4fb 50%, transparent); } @@ -509,57 +565,57 @@ .p-0 { padding: 0px; } - .p-2 { - padding: calc(var(--spacing) * 2); - } - .p-3 { - padding: calc(var(--spacing) * 3); - } .p-4 { padding: calc(var(--spacing) * 4); } .p-8 { padding: calc(var(--spacing) * 8); } - .p-10 { - padding: calc(var(--spacing) * 10); + .p-\[0\.4rem\] { + padding: 0.4rem; } .p-\[0\.8em\] { padding: 0.8em; } - .p-\[2\.0rem\] { - padding: 2.0rem; - } - .p-\[2\.2rem\] { - padding: 2.2rem; + .p-\[1rem\] { + padding: 1rem; } .p-\[2\.2svh\] { padding: 2.2svh; } - .p-\[2\.5rem\] { - padding: 2.5rem; - } - .p-\[2\.rem\] { - padding: 2.rem; - } - .p-\[2rem\] { - padding: 2rem; - } .p-\[3vw\] { padding: 3vw; } + .px-3 { + padding-inline: calc(var(--spacing) * 3); + } + .px-3\.5 { + padding-inline: calc(var(--spacing) * 3.5); + } .px-\[0\.1vw\] { padding-inline: 0.1vw; } + .px-\[0\.4rem\] { + padding-inline: 0.4rem; + } .px-\[0\.5em\] { padding-inline: 0.5em; } + .px-\[0\.625rem\] { + padding-inline: 0.625rem; + } + .py-\(--ypad\) { + padding-block: var(--ypad); + } .py-16 { padding-block: calc(var(--spacing) * 16); } .py-\[0\.625vw\] { padding-block: 0.625vw; } + .pt-3 { + padding-top: calc(var(--spacing) * 3); + } .pt-\[1\.0625em\] { padding-top: 1.0625em; } @@ -569,6 +625,9 @@ .pt-\[5vw\] { padding-top: 5vw; } + .pt-\[calc\(var\(--ypad\)\+0\.0625rem\)\] { + padding-top: calc(var(--ypad) + 0.0625rem); + } .pr-\[1\.25vw\] { padding-right: 1.25vw; } @@ -584,19 +643,24 @@ .font-mono { font-family: var(--font-mono); } - .text-3xl { - font-size: var(--text-3xl); - line-height: var(--tw-leading, var(--text-3xl--line-height)); + .text-\[0\.8rem\] { + font-size: 0.8rem; } .text-\[0\.96vw\] { font-size: 0.96vw; } + .text-\[0\.675rem\] { + font-size: 0.675rem; + } .text-\[1\.125rem\] { font-size: 1.125rem; } .text-\[1\.375rem\] { font-size: 1.375rem; } + .text-\[1rem\] { + font-size: 1rem; + } .text-\[2\.5vw\] { font-size: 2.5vw; } @@ -618,6 +682,14 @@ .text-\[130\%\] { font-size: 130%; } + .leading-\[normal\] { + --tw-leading: normal; + line-height: normal; + } + .font-\[150\%\] { + --tw-font-weight: 150%; + font-weight: 150%; + } .font-bold { --tw-font-weight: var(--font-weight-bold); font-weight: var(--font-weight-bold); @@ -626,18 +698,60 @@ --tw-font-weight: var(--font-weight-normal); font-weight: var(--font-weight-normal); } + .wrap-anywhere { + overflow-wrap: anywhere; + } + .whitespace-nowrap { + white-space: nowrap; + } + .text-\(--accent\) { + color: var(--accent); + } + .text-\(--alt\) { + color: var(--alt); + } + .text-\(--extra\) { + color: var(--extra); + } .text-\(--primary\) { color: var(--primary); } + .text-\(--secondary\) { + color: var(--secondary); + } + .text-\[\#54D7A9\] { + color: #54D7A9; + } + .text-\[\#D8C44B\] { + color: #D8C44B; + } + .text-\[\#F16265\] { + color: #F16265; + } + .text-\[--\] { + color: --; + } + .text-\[--accent\] { + color: --accent; + } + .text-\[--extra\] { + color: --extra; + } + .text-\[--secondary\] { + color: --secondary; + } + .text-\[color\:var\(--alt\)\] { + color: var(--alt); + } .text-\[var\(--accent\)\] { color: var(--accent); } - .text-\[var\(--primary\)\] { - color: var(--primary); - } .text-\[var\(--secondary\)\] { color: var(--secondary); } + .no-underline { + text-decoration-line: none; + } .underline { text-decoration-line: underline; } @@ -648,6 +762,27 @@ outline-style: var(--tw-outline-style); outline-width: 1px; } + .transition-colors { + transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to; + transition-timing-function: var(--tw-ease, var(--default-transition-timing-function)); + transition-duration: var(--tw-duration, var(--default-transition-duration)); + } + .select-text { + -webkit-user-select: text; + user-select: text; + } + .\[--border-py\:0\.5rem\] { + --border-py: 0.5rem; + } + .\[--border-py\:0\.75rem\] { + --border-py: 0.75rem; + } + .\[--border-py\:0\.875rem\] { + --border-py: 0.875rem; + } + .\[--ypad\:var\(--border-py\,0\.875rem\)\] { + --ypad: var(--border-py,0.875rem); + } @media (hover: hover) { .group-hover\:text-\[var\(--alt\)\]:is(:where(.group):hover *) { color: var(--alt); @@ -658,10 +793,29 @@ .group-hover\:underline:is(:where(.group):hover *) { text-decoration-line: underline; } - .hover\:text-\(--accent\):hover { - color: var(--accent); + } + .group-data-copied\:block:is(:where(.group)[data-copied] *) { + display: block; + } + .group-data-copied\/copy\:block:is(:where(.group\/copy)[data-copied] *) { + display: block; + } + .group-data-copied\/copy\:bg-\(--primary\)\/25\!:is(:where(.group\/copy)[data-copied] *) { + background-color: var(--primary) !important; + @supports (color: color-mix(in lab, red, red)) { + background-color: color-mix(in oklab, var(--primary) 25%, transparent) !important; } - .hover\:text-\[var\(--accent\)\]:hover { + } + @media (hover: hover) { + .hover\:bg-\(--alt\)\/25:hover { + background-color: var(--alt); + } + @supports (color: color-mix(in lab, red, red)) { + .hover\:bg-\(--alt\)\/25:hover { + background-color: color-mix(in oklab, var(--alt) 25%, transparent); + } + } + .hover\:text-\(--accent\):hover { color: var(--accent); } .hover\:text-\[var\(--alt\)\]:hover { @@ -673,6 +827,18 @@ .hover\:text-gray-700:hover { color: var(--color-gray-700); } + .hover\:no-underline:hover { + text-decoration-line: none; + } + } + .data-copied\:animate-\[bump_0\.25s\][data-copied] { + animation: bump 0.25s; + } + .data-copied\:bg-\(--primary\)\/25\![data-copied] { + background-color: var(--primary) !important; + @supports (color: color-mix(in lab, red, red)) { + background-color: color-mix(in oklab, var(--primary) 25%, transparent) !important; + } } @media (width >= 40rem) { .sm\:invisible { @@ -835,6 +1001,40 @@ grid-template-columns: repeat(1, minmax(0, 1fr)); } } + .\[\&\:\:-webkit-scrollbar\]\:hidden::-webkit-scrollbar { + display: none; + } + .\[\&\>\*\+\*\]\:mt-\[-0\.1rem\] > * + * { + margin-top: -0.1rem; + } +} +@keyframes pop { + 50% { + transform: scale(1.3); + } +} +[data-copied] svg { + animation: pop 0.25s; +} +@keyframes bump { + 50% { + transform: scale(1.03); + } +} +@property --tw-translate-x { + syntax: "*"; + inherits: false; + initial-value: 0; +} +@property --tw-translate-y { + syntax: "*"; + inherits: false; + initial-value: 0; +} +@property --tw-translate-z { + syntax: "*"; + inherits: false; + initial-value: 0; } @property --tw-rotate-x { syntax: "*"; @@ -866,6 +1066,10 @@ inherits: false; initial-value: solid; } +@property --tw-leading { + syntax: "*"; + inherits: false; +} @property --tw-font-weight { syntax: "*"; inherits: false; @@ -878,6 +1082,9 @@ @layer properties { @supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) { *, ::before, ::after, ::backdrop { + --tw-translate-x: 0; + --tw-translate-y: 0; + --tw-translate-z: 0; --tw-rotate-x: initial; --tw-rotate-y: initial; --tw-rotate-z: initial; @@ -885,6 +1092,7 @@ --tw-skew-y: initial; --tw-space-x-reverse: 0; --tw-border-style: solid; + --tw-leading: initial; --tw-font-weight: initial; --tw-outline-style: solid; } diff --git a/public/styles/terminal.css b/public/styles/terminal.css index f44bcd0..e0e80aa 100644 --- a/public/styles/terminal.css +++ b/public/styles/terminal.css @@ -45,3 +45,26 @@ body { color: var(--accent); } } + +.scrollbox::-webkit-scrollbar { + width: 1.5rem; +} +.scrollbox::-webkit-scrollbar-track { + background: transparent; + border-left: 0.1rem solid var(--alt); +} +.scrollbox::-webkit-scrollbar-thumb { + background: var(--primary); + border: 0.3rem solid transparent; + background-clip: padding-box; + border-radius: 0; +} +.scrollbox::-webkit-scrollbar-thumb:hover { + background: var(--accent); +} + +@supports not selector(::-webkit-scrollbar) { + .scrollbox { + scrollbar-color: var(--primary) transparent; + } +} |
