From 5205c5cef94d23a3266326a86ab6b94502d0f0f0 Mon Sep 17 00:00:00 2001 From: Sam <64147848+yungsamd17@users.noreply.github.com> Date: Mon, 26 Oct 2026 14:21:37 +0000 Subject: [PATCH 1/2] style(ui): button/link hover treatments, disabled states, icon alignment, search FAB --- src/styles/global.css | 19 ++++-- src/styles/tool.css | 101 ++++++++++++++++++++++++++------ src/styles/tools/icon-maker.css | 13 +++- 3 files changed, 108 insertions(+), 25 deletions(-) diff --git a/src/styles/global.css b/src/styles/global.css index 3fb7375..34ff058 100644 --- a/src/styles/global.css +++ b/src/styles/global.css @@ -266,8 +266,17 @@ a:focus-visible { } .github-link:hover { - background: var(--accent); - color: var(--primary); + background: var(--accent-dim); + border-color: var(--accent); + color: var(--primary-text); +} + +/* GitHub-link icons stay aligned with the label and inherit its color */ +.github-link svg { + flex-shrink: 0; + display: inline-flex; + align-items: center; + color: inherit; } /* ═══════════════════════════════════════════════════ @@ -445,8 +454,10 @@ a:focus-visible { press still speak in accent, like every other bar control. */ .search-fab { position: fixed; - top: max(1.15rem, env(safe-area-inset-top)); - right: max(1.15rem, env(safe-area-inset-right)); + /* Match the topbar's hamburger button: centered in the 3.75rem bar + (center at 1.875rem) and inset to the 900px page column's right edge. */ + top: max(0.675rem, env(safe-area-inset-top)); + right: calc(max(0px, (100vw - 900px) / 2) + max(1.25rem, env(safe-area-inset-right))); z-index: 40; display: inline-flex; align-items: center; diff --git a/src/styles/tool.css b/src/styles/tool.css index 7e9b59d..d1ceb54 100644 --- a/src/styles/tool.css +++ b/src/styles/tool.css @@ -72,6 +72,19 @@ a { text-underline-offset: 2px; } +/* .link-secondary with a permanent underline (privacy/terms links) */ +.link-secondary-permanent { + color: var(--secondary-text); + text-decoration: underline; + text-underline-offset: 2px; +} + +.link-secondary-permanent:hover { + color: var(--primary-text); + text-decoration: underline; + text-underline-offset: 2px; +} + .link-ghost { color: inherit; font-weight: bold; @@ -764,8 +777,9 @@ input[type='range']::-moz-range-thumb { } .btn:hover { - background: var(--accent); - color: var(--primary); + background: var(--accent-dim); + border-color: var(--accent); + color: var(--primary-text); } .btn:disabled { @@ -775,19 +789,40 @@ input[type='range']::-moz-range-thumb { .btn:disabled:hover { background: var(--btn-bg); + border-color: transparent; color: var(--secondary-text); } +/* Button icons: stay aligned with the label and inherit its color in every + state (never a separate accent tint). */ +.btn svg, +.btn-sm svg, +.choice-btn svg, +.source-btn svg, +.style-btn svg, +.shape-btn svg, +.preset-btn svg, +.angle-btn svg, +.result-dl svg, +.dl-all-btn svg, +.more-tools-btn svg { + flex-shrink: 0; + display: inline-flex; + align-items: center; + color: inherit; +} + /* Accent state once the action has something to work on */ .btn.ready { - background: var(--accent); + background: var(--accent-dim); border-color: var(--accent); - color: var(--primary); + color: var(--primary-text); } .btn.ready:hover { - background: var(--accent-hover); + background: rgba(255, 65, 54, 0.24); border-color: var(--accent-hover); + color: var(--primary-text); } /* Inline / small button */ @@ -810,9 +845,9 @@ input[type='range']::-moz-range-thumb { } .btn-sm:hover { - background: var(--accent); + background: var(--accent-dim); border-color: var(--accent); - color: var(--primary); + color: var(--primary-text); } .btn-sm:disabled { @@ -820,6 +855,12 @@ input[type='range']::-moz-range-thumb { cursor: not-allowed; } +.btn-sm:disabled:hover { + background: var(--surface-2); + border-color: var(--border); + color: var(--secondary-text); +} + /* Small selectable option (size presets, format pickers, …). Shared recipe — icon-maker families (.source/.style/.shape/.preset/ .angle-btn) reuse it and add only their own layout/typography. */ @@ -877,6 +918,16 @@ input[type='range']::-moz-range-thumb { cursor: not-allowed; } +.choice-btn:disabled:hover, +.source-btn:disabled:hover, +.style-btn:disabled:hover, +.shape-btn:disabled:hover, +.preset-btn:disabled:hover, +.angle-btn:disabled:hover { + border-color: var(--border); + color: var(--secondary-text); +} + /* Two-column export row */ .btn-row { display: grid; @@ -888,13 +939,15 @@ input[type='range']::-moz-range-thumb { .btn-fmt { font-family: Aldrich, sans-serif; font-size: 0.85rem; - color: var(--accent); + color: inherit; transition: color var(--t); + display: inline-flex; + align-items: center; + vertical-align: middle; + transform: translateY(1.5px); } -.btn:hover .btn-fmt { - color: var(--primary); -} +/* .btn-fmt inherits the button's text color in every state */ /* ═══════════════════════════════════════════════════ STATUS / ERROR MESSAGE @@ -1005,9 +1058,9 @@ input[type='range']::-moz-range-thumb { } .result-dl:hover { - background: var(--accent); + background: var(--accent-dim); border-color: var(--accent); - color: var(--primary); + color: var(--primary-text); } .result-dl:disabled { @@ -1015,6 +1068,12 @@ input[type='range']::-moz-range-thumb { cursor: not-allowed; } +.result-dl:disabled:hover { + background: none; + border-color: var(--border); + color: var(--secondary-text); +} + /* Full-width Download All — accent */ .dl-all-btn { display: inline-flex; @@ -1024,10 +1083,10 @@ input[type='range']::-moz-range-thumb { width: 100%; margin-bottom: 1rem; padding: 0.75rem 1.4rem; - background: var(--accent); + background: var(--accent-dim); border: 1px solid var(--accent); border-radius: var(--radius); - color: var(--primary); + color: var(--primary-text); font-size: 1rem; font-family: Verdana, sans-serif; cursor: pointer; @@ -1041,7 +1100,7 @@ input[type='range']::-moz-range-thumb { } .dl-all-btn:hover { - background: var(--accent-hover); + background: rgba(255, 65, 54, 0.24); border-color: var(--accent-hover); } @@ -1050,6 +1109,11 @@ input[type='range']::-moz-range-thumb { cursor: not-allowed; } +.dl-all-btn:disabled:hover { + background: var(--accent-dim); + border-color: var(--accent); +} + /* ZIP packing progress */ .zip-progress-wrap { display: none; @@ -1139,8 +1203,9 @@ input[type='range']::-moz-range-thumb { } .more-tools-btn:hover { - background: var(--accent); - color: var(--primary); + background: var(--accent-dim); + border-color: var(--accent); + color: var(--primary-text); } /* ═══════════════════════════════════════════════════ diff --git a/src/styles/tools/icon-maker.css b/src/styles/tools/icon-maker.css index 094be9c..4152fa1 100644 --- a/src/styles/tools/icon-maker.css +++ b/src/styles/tools/icon-maker.css @@ -409,9 +409,9 @@ input.text-input { } .modal-btn.primary:hover { - background: var(--accent); - border-color: var(--accent); - color: var(--primary); + background: rgba(255, 65, 54, 0.24); + border-color: var(--accent-hover); + color: var(--primary-text); } #icon-scale { @@ -681,6 +681,13 @@ input.text-input { border-color: rgba(61, 220, 132, 0.22); } +.android-btn svg { + flex-shrink: 0; + display: inline-flex; + align-items: center; + color: inherit; +} + .android-label { font-family: Aldrich, sans-serif; font-size: 0.85rem; From 29370b7243a5f28f0761a9df327c90ee1bfe3eb2 Mon Sep 17 00:00:00 2001 From: Sam <64147848+yungsamd17@users.noreply.github.com> Date: Mon, 26 Oct 2026 14:21:39 +0000 Subject: [PATCH 2/2] refactor(ui): markup spacing, convert-button ready removal, privacy/terms link class --- src/components/ToolLayout.astro | 2 +- src/pages/design.astro | 10 ++++++++-- src/pages/index.astro | 4 ++-- src/pages/privacy.astro | 6 +++--- src/pages/terms.astro | 8 ++++---- src/pages/tools/icon-maker.astro | 4 ++-- src/pages/tools/image-resizer.astro | 14 +++----------- src/pages/tools/svg-to-png.astro | 2 +- src/scripts/tools/image-resizer.ts | 1 - src/scripts/tools/lib.ts | 4 ++-- src/scripts/tools/svg-to-png.ts | 1 - 11 files changed, 26 insertions(+), 30 deletions(-) diff --git a/src/components/ToolLayout.astro b/src/components/ToolLayout.astro index 07e3870..eeb9ac7 100644 --- a/src/components/ToolLayout.astro +++ b/src/components/ToolLayout.astro @@ -46,7 +46,7 @@ const {

More s17 Labs Tools

Discover more free, browser-based utilities designed for creators and developers.

- View More Tools + View More Tools diff --git a/src/pages/design.astro b/src/pages/design.astro index 56a4161..2e6fe21 100644 --- a/src/pages/design.astro +++ b/src/pages/design.astro @@ -333,6 +333,12 @@ const textFonts = [ Ghost + icon

+
+ .link-secondary-permanent — privacy/terms links +

+ Permanent underline +

+
.tool-item icon variants — glyph · artwork · emoji
@@ -402,8 +408,8 @@ const textFonts = [
.dl-all-btn · .more-tools-btn · .android-btn (icon-maker) - -
View More Tools
+ +
View More Tools
diff --git a/src/pages/privacy.astro b/src/pages/privacy.astro index 204129f..4818f97 100644 --- a/src/pages/privacy.astro +++ b/src/pages/privacy.astro @@ -61,12 +61,12 @@ const description =

Questions

Something unclear? Reach out on - GitHub - or X. + GitHub + or X.

Canonical text: - docs/PRIVACY.md. + docs/PRIVACY.md.

diff --git a/src/pages/terms.astro b/src/pages/terms.astro index f3918e3..e771b59 100644 --- a/src/pages/terms.astro +++ b/src/pages/terms.astro @@ -38,7 +38,7 @@ const description = 'Terms of use for the s17 Labs website and browser tools.';

The site, the tools, and the s17 Labs name and artwork belong to s17 Labs. Open-source projects under the - s17labs org + s17labs org carry their own licenses — check each repo.

@@ -60,12 +60,12 @@ const description = 'Terms of use for the s17 Labs website and browser tools.';

These terms may change as the site grows; continued use means you accept the current version. Questions? Reach out on - GitHub - or X. + GitHub + or X.

Canonical text: - docs/TERMS.md. + docs/TERMS.md.

diff --git a/src/pages/tools/icon-maker.astro b/src/pages/tools/icon-maker.astro index 8f70228..a3a8026 100644 --- a/src/pages/tools/icon-maker.astro +++ b/src/pages/tools/icon-maker.astro @@ -227,8 +227,8 @@ const tagline =
- - + +
@@ -58,7 +58,7 @@ const tagline = 'Batch resize images directly in your browser — your data neve @@ -175,13 +175,5 @@ const tagline = 'Batch resize images directly in your browser — your data neve color: var(--primary-text); } - /* Resize button idle state */ - .btn:not(.ready):not(:disabled) { - color: var(--accent); - } - - .btn:not(.ready):not(:disabled):hover { - background: var(--accent); - color: var(--primary); - } + /* Resize button uses the shared .btn treatment (no accent idle state) */ diff --git a/src/pages/tools/svg-to-png.astro b/src/pages/tools/svg-to-png.astro index 05007de..533bfe1 100644 --- a/src/pages/tools/svg-to-png.astro +++ b/src/pages/tools/svg-to-png.astro @@ -32,7 +32,7 @@ const tagline = 'Convert SVG vectors to transparent PNG files locally — batch
diff --git a/src/scripts/tools/image-resizer.ts b/src/scripts/tools/image-resizer.ts index 30be59d..d63a3a3 100644 --- a/src/scripts/tools/image-resizer.ts +++ b/src/scripts/tools/image-resizer.ts @@ -82,7 +82,6 @@ function addFiles(newFiles: File[]): void { renderUploadPreview(); clearResults(); resizeBtn.disabled = false; - resizeBtn.classList.add('ready'); } // ── Upload preview grid ──────────────────────────────────────────────────── diff --git a/src/scripts/tools/lib.ts b/src/scripts/tools/lib.ts index 347f9cd..b2189e3 100644 --- a/src/scripts/tools/lib.ts +++ b/src/scripts/tools/lib.ts @@ -333,7 +333,7 @@ export function makeResultItem({ const dlBtn = document.createElement('button'); dlBtn.className = 'result-dl'; dlBtn.type = 'button'; - dlBtn.innerHTML = `${downloadIconHtml} Save`; + dlBtn.innerHTML = `${downloadIconHtml}Save`; dlBtn.addEventListener('click', onDownload); item.append(thumb, info, dlBtn); @@ -354,7 +354,7 @@ export function makePlaceholderItem(opts: {
${opts.statusHtml}
- `; + `; item.querySelector('.result-name')!.textContent = opts.fileName; return item; } diff --git a/src/scripts/tools/svg-to-png.ts b/src/scripts/tools/svg-to-png.ts index 36a35e7..6c47fbe 100644 --- a/src/scripts/tools/svg-to-png.ts +++ b/src/scripts/tools/svg-to-png.ts @@ -79,7 +79,6 @@ function addFiles(newFiles: File[]): void { renderUploadPreview(); clearResults(); convertBtn.disabled = false; - convertBtn.classList.add('ready'); } function renderUploadPreview(): void {