Skip to content

Commit 239c69e

Browse files
feat: mobile UX overhaul, theme flash prevention and build cleanup (#474)
* feat: mobile UX overhaul, theme flash prevention and build cleanup UI/UX (mostly mobile): - Prevent white flash on load: pre-paint inline style + script in index.html applies the persisted theme before first paint. - Match browser chrome to the app background: theme-color meta kept in sync for Android/older iOS, and body background pinned to the Layout color for Safari 26+, which ignores theme-color and samples the page. - Make the document the app's scroller instead of n-layout's nested container: single scrollbar, native iOS tap-status-bar-to-scroll-top, natural toolbar collapsing; desktop sider becomes sticky and router scrollBehavior restores/resets scroll on navigation. - Full-width mobile menu that fades in under an always-visible sticky top bar, seamless app background without the hero gradient, closes on navigation (including About while already on /about), scroll-locked behind, symmetric spacing around the title block and icon row. - Language selector and theme toggle become icon dropdowns; theme supports System/Light/Dark via useColorMode (same storage as before). - Route-change loading spinner scoped to the page area so the nav bar stays visible; spinner remains cosmetic-only (350ms delay). - Halve content padding on small screens; reduce home top padding. - Full-width expand/collapse tools button so its width doesn't jump. - No sticky hover styles on touch devices (hover gated behind @media (hover: hover)). Build: - Rename deprecated rolldown output.advancedChunks to codeSplitting. - Fix unocss 'unmatched utility' warnings in the pretty-scrollbar shortcut; override js-sha256 to 0.11.x (drops eval); bump javascript-obfuscator to 5.4.6. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TNayL5ianBBucVapfkM8CC * Remove unnecessary comment * Refresh lockfile, remove releaseage ignore Signed-off-by: Sebastian Danielsson <sebastian.danielsson@proton.me> * chore: remove unused LocaleSelector component Language selection moved into the NavbarButtons dropdown; nothing references this component anymore. Its i18n keys are left in place. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TNayL5ianBBucVapfkM8CC --------- Signed-off-by: Sebastian Danielsson <sebastian.danielsson@proton.me> Co-authored-by: Claude <noreply@anthropic.com>
1 parent 7460423 commit 239c69e

20 files changed

Lines changed: 394 additions & 116 deletions

index.html

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,25 @@
22
<html lang="en">
33
<head>
44
<meta charset="UTF-8" />
5+
<meta name="theme-color" content="#f1f5f9" />
6+
<style>
7+
html { color-scheme: light; }
8+
html.dark { color-scheme: dark; }
9+
html, body { background-color: #f1f5f9; }
10+
html.dark, html.dark body { background-color: #1c1c1c; }
11+
</style>
12+
<script>
13+
(function () {
14+
try {
15+
var mode = localStorage.getItem('vueuse-color-scheme') || 'auto';
16+
if (mode === 'dark' || (mode === 'auto' && matchMedia('(prefers-color-scheme: dark)').matches)) {
17+
document.documentElement.classList.add('dark');
18+
document.querySelector('meta[name="theme-color"]').setAttribute('content', '#1c1c1c');
19+
}
20+
}
21+
catch (e) {}
22+
})();
23+
</script>
524
<link rel="icon" href="favicon.ico" />
625
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
726
<title>IT Tools - Handy online tools for developers</title>
@@ -14,7 +33,6 @@
1433
<link rel="mask-icon" href="safari-pinned-tab.svg" color="#18a058" />
1534

1635
<meta name="msapplication-TileColor" content="#da532c" />
17-
<meta name="theme-color" content="#ffffff" />
1836

1937
<meta property="og:url" content="https://sharevb-it-tools.vercel.app/" />
2038
<meta property="og:type" content="website" />

locales/en.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,10 @@ home:
114114
lightMode: Light mode
115115
mode: Toggle dark/light mode
116116
aboutLabel: About
117+
language: Language
118+
themeSystem: System
119+
themeLight: Light
120+
themeDark: Dark
117121
page:
118122
text:
119123
collection-of-handy-online-tools-for-developers-with-great-ux-it-tools-is-a-free-and-open-source-collection-of-handy-online-tools-for-developers-and-people-working-in-it: >-

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "it-tools",
33
"type": "module",
44
"version": "2026.1.4",
5-
"packageManager": "pnpm@11.10.0+sha512.0b7f8b98060031904c017e3a41eb187a16d40eeb829b95c4f8cb03681761fc4ab53dd219115b9b447f4dce1a05a214764461e7d3703392a9f32f9511ce8c86c8",
5+
"packageManager": "pnpm@11.11.0+sha512.4463f65fd80ed80d69bc1d4bf163ee94f605c7380fc318bb5b2ebe15f8cd12d49c51a4d59e951b401e764d3b6ca751cbf51bc50ed7001a6bcb4935e684c34882",
66
"description": "Collection of handy online tools for developers, with great UX. ",
77
"author": "Corentin Th <corentin.thomasset74+it-tools@gmail.com> (https://corentin.tech)",
88
"license": "GNU GPLv3",
@@ -238,7 +238,7 @@
238238
"isbn3": "^2.0.2",
239239
"iso-639-1": "^3.1.5",
240240
"jasypt": "^1.0.7",
241-
"javascript-obfuscator": "^5.1.0",
241+
"javascript-obfuscator": "^5.4.6",
242242
"javastack.js": "^1.0.3",
243243
"jks-js": "^1.1.4",
244244
"jose": "5.10.0",

pnpm-lock.yaml

Lines changed: 14 additions & 13 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pnpm-workspace.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ overrides:
1313
isolated-vm: file:./stubs/empty-stub
1414
onnxruntime-node: file:./stubs/empty-stub
1515
elliptic: ^6.6.1
16+
# @it-tools/bip39 pins ^0.9.0, whose Node fallback uses eval("require('crypto')")
17+
# and triggers rolldown EVAL build warnings; 0.11.x dropped the eval.
18+
js-sha256: ^0.11.1
1619
xlsx: https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz
1720

1821
patchedDependencies:

src/App.vue

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,17 +78,19 @@ body {
7878
min-height: 100%;
7979
margin: 0;
8080
padding: 0;
81+
/* The document scrolls vertically (see MenuLayout.vue); never horizontally */
82+
overflow-x: hidden;
8183
-webkit-overflow-scrolling: touch;
8284
}
8385
8486
* {
8587
box-sizing: border-box;
8688
}
8789
90+
/* No transform/contain here: they would make .app-root the containing block
91+
for position:fixed descendants (the mobile menu), and the old inner-scroll
92+
perf rationale no longer applies now that the document is the scroller. */
8893
.app-root {
89-
contain: layout style paint;
90-
-webkit-transform: translateZ(0);
91-
transform: translateZ(0);
9294
-webkit-overflow-scrolling: touch;
9395
}
9496
@@ -97,13 +99,24 @@ body .vld-container {
9799
left: 0;
98100
top: 0;
99101
width: 100%;
100-
height: 100vh;
101102
background-color: var(--loading-background-color);
102-
z-index: 9999;
103103
text-align: center;
104104
pointer-events: none;
105105
}
106106
107+
/* Fullscreen fallback: overlay mounted on <body> (first navigation) */
108+
body > .vld-container {
109+
height: 100vh;
110+
z-index: 9999;
111+
}
112+
113+
/* Route-change overlay scoped to the page area (see router.ts) */
114+
.page-content > .vld-container {
115+
height: 100%;
116+
min-height: 350px;
117+
z-index: 100;
118+
}
119+
107120
body .vld-container.vl-active {
108121
pointer-events: auto;
109122
}

src/components/CollapsibleToolMenu.vue

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -139,8 +139,10 @@ const themeVars = useThemeVars();
139139
</script>
140140

141141
<template>
142-
<div class="top-controls" mb-12px ml-12px>
143-
<c-button :disabled="isToggling" @click="toggleAllCategories">
142+
<!-- Full width: the label changes between expand/collapse, and a
143+
hug-content button would jump in width on every toggle -->
144+
<div class="top-controls" mb-12px mx-12px>
145+
<c-button w-full :disabled="isToggling" @click="toggleAllCategories">
144146
<span v-if="isToggling">
145147
{{ areAllCollapsed ? $t('collapsibleToolMenu.text.expanding') : $t('collapsibleToolMenu.text.collapsing') }}
146148
</span>
@@ -198,18 +200,23 @@ const themeVars = useThemeVars();
198200
text-align: left;
199201
user-select: none;
200202
201-
&:hover {
202-
background-color: v-bind('themeVars.buttonColor2Hover');
203-
opacity: 0.8;
203+
// Hover only on hover-capable devices; on touch it sticks after tapping
204+
@media (hover: hover) {
205+
&:hover {
206+
background-color: v-bind('themeVars.buttonColor2Hover');
207+
opacity: 0.8;
208+
}
204209
}
205210
206211
&.category-active {
207212
background-color: color-mix(in srgb, v-bind('themeVars.primaryColor') 40%, transparent);
208213
opacity: 1;
209214
color: white;
210215
211-
&:hover {
212-
background-color: color-mix(in srgb, v-bind('themeVars.primaryColorHover') 50%, transparent);
216+
@media (hover: hover) {
217+
&:hover {
218+
background-color: color-mix(in srgb, v-bind('themeVars.primaryColorHover') 50%, transparent);
219+
}
213220
}
214221
}
215222
}
@@ -264,8 +271,10 @@ const themeVars = useThemeVars();
264271
left: 14px;
265272
}
266273
267-
&:hover {
268-
opacity: 0.5;
274+
@media (hover: hover) {
275+
&:hover {
276+
opacity: 0.5;
277+
}
269278
}
270279
}
271280
}

src/components/ColoredCard.vue

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,10 @@ const { icon, title } = toRefs(props);
4848
font-weight: bold;
4949
transition: color ease 0.2s;
5050
51-
&:hover {
52-
color: rgb(20, 20, 20);
51+
@media (hover: hover) {
52+
&:hover {
53+
color: rgb(20, 20, 20);
54+
}
5355
}
5456
}
5557
}

0 commit comments

Comments
 (0)