diff --git a/dist/hpl-toolbox-0.1.8.exe b/dist/hpl-toolbox-0.1.8.exe index dd15348..f0c3545 100644 Binary files a/dist/hpl-toolbox-0.1.8.exe and b/dist/hpl-toolbox-0.1.8.exe differ diff --git a/dist/hpl-toolbox-0.1.8.vsix b/dist/hpl-toolbox-0.1.8.vsix index e584dfc..fcde2d0 100644 Binary files a/dist/hpl-toolbox-0.1.8.vsix and b/dist/hpl-toolbox-0.1.8.vsix differ diff --git a/standalone/layout.go b/standalone/layout.go index 55d7f91..8069d53 100644 --- a/standalone/layout.go +++ b/standalone/layout.go @@ -25,30 +25,110 @@ const SharedCSS = ` html { min-height: 100%; } body { min-height: 100vh; - display: flex; - flex-direction: column; + display: grid; + grid-template-columns: var(--sidebar-width, 236px) minmax(0, 1fr); font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; background: #1e1e1e; color: #ddd; margin: 0; padding: 0; } - .topbar { - display: flex; align-items: center; gap: 8px; - padding: 8px 16px; background: #252526; border-bottom: 1px solid #333; + body.sidebar-collapsed { --sidebar-width: 56px; } + .sidebar { + position: sticky; + top: 0; + height: 100vh; + display: flex; + flex-direction: column; + gap: 8px; + padding: 10px 8px; + background: #252526; + border-right: 1px solid #333; font-size: 13px; + overflow: hidden; } - .topbar .nav-link { + .sidebar-header { + display: flex; + align-items: center; + gap: 8px; + min-height: 32px; + padding: 0 2px 6px; + border-bottom: 1px solid #333; + } + .sidebar-title { + min-width: 0; + flex: 1; + color: #ddd; + font-size: 12px; + font-weight: 700; + letter-spacing: 0.45px; + text-transform: uppercase; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + .sidebar-toggle { + width: 32px; + height: 28px; + padding: 0; + display: grid; + place-items: center; + background: transparent; + color: #ddd; + border: 1px solid #444; + border-radius: 4px; + font-size: 16px; + line-height: 1; + } + .sidebar-toggle:hover { background: #2a2d2e; } + .sidebar-nav { + display: flex; + flex-direction: column; + gap: 4px; + min-height: 0; + overflow: auto; + } + .sidebar .nav-link { + width: 100%; + min-height: 34px; + display: grid; + grid-template-columns: 28px minmax(0, 1fr); + align-items: center; + gap: 8px; background: transparent; color: #ddd; border: 0; - padding: 5px 10px; + padding: 4px 8px 4px 4px; border-radius: 4px; cursor: pointer; font: inherit; + text-align: left; + } + .sidebar .nav-link:hover { background: #2a2d2e; } + .sidebar .nav-link.active { background: #094771; color: #fff; } + .nav-icon { + width: 28px; + height: 26px; + display: grid; + place-items: center; + border-radius: 4px; + background: rgba(128,128,128,0.12); + color: #ddd; + font-size: 11px; + font-weight: 700; + letter-spacing: 0; + } + .nav-text { + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; } - .topbar .nav-link:hover { background: #2a2d2e; } - .topbar .nav-link.active { background: #094771; color: #fff; } .beta-pill { margin-left: 4px; padding: 1px 4px; border: 1px solid #555; border-radius: 3px; font-size: 10px; opacity: 0.7; text-transform: uppercase; } - .topbar-spacer { margin-left: auto; } + .app-shell { + min-width: 0; + min-height: 100vh; + display: flex; + flex-direction: column; + } .content { flex: 1; width: 100%; padding: 18px; max-width: 1100px; margin: 0 auto; } .app-footer { width: 100%; @@ -78,6 +158,28 @@ const SharedCSS = ` .app-footer-version { opacity: 0.75; text-align: center; white-space: nowrap; } .app-footer-link { justify-self: end; padding: 0; background: transparent; color: #a7a7a7; border: 0; cursor: pointer; font: inherit; opacity: 0.72; } .app-footer-link:hover { background: transparent; opacity: 1; text-decoration: underline; } + body.sidebar-collapsed .sidebar { align-items: stretch; } + body.sidebar-collapsed .sidebar-title, + body.sidebar-collapsed .nav-text, + body.sidebar-collapsed .beta-pill { display: none; } + body.sidebar-collapsed .sidebar .nav-link { + grid-template-columns: 28px; + justify-content: center; + padding: 4px; + } + body.sidebar-collapsed .sidebar-header { justify-content: center; padding-left: 0; padding-right: 0; } + body.sidebar-collapsed .sidebar-toggle { width: 38px; } + @media (max-width: 760px) { + body { grid-template-columns: 1fr; } + .sidebar { + position: static; + height: auto; + max-height: 48vh; + border-right: 0; + border-bottom: 1px solid #333; + } + body.sidebar-collapsed .sidebar { max-height: 50px; } + } h2 { margin: 0; font-size: 18px; line-height: 1.25; font-weight: 600; } .tool-header { margin-bottom: var(--tool-gap-lg); } .tool-title { margin: 0; font-size: 18px; line-height: 1.25; font-weight: 600; } @@ -366,6 +468,34 @@ func betaToolCount() int { return count } +func navInitials(label string) string { + switch label { + case "Base64 Scanner": + return "B64" + case "AppLovin Playable Preview": + return "APP" + case "Mintegral Checker": + return "MiC" + } + words := strings.Fields(label) + if len(words) == 0 { + return "?" + } + if len(words) == 1 { + r := []rune(words[0]) + if len(r) == 0 { + return "?" + } + return strings.ToUpper(string(r[0])) + } + first := []rune(words[0]) + second := []rune(words[1]) + if len(first) == 0 || len(second) == 0 { + return strings.ToUpper(string([]rune(label)[0])) + } + return strings.ToUpper(string(first[0]) + string(second[0])) +} + func Page(activePath, title, body string) string { cfg := LoadConfig() betaToolsEnabled := cfg.BetaToolsEnabled @@ -379,7 +509,7 @@ func Page(activePath, title, body string) string { if n.Beta { label += `Beta` } - tabs.WriteString(``) + tabs.WriteString(``) } betaButtonLabel := "Show beta" @@ -394,14 +524,29 @@ func Page(activePath, title, body string) string { -
` + tabs.String() + `
-
` + body + `
-