Base64 tool: add editor-style menubar (File via ToolFileMenu, Encode/Decode toggles, Help + Tour right-aligned) #92

Closed
opened 2026-05-09 20:27:50 +00:00 by spikerj · 1 comment
Owner

Summary

The Base64 Encoder / Decoder at /tools/(tools:base64) (Base64Component in @spikersoft/feature-dev-tools-encoding) currently uses a header block with slide toggles and stroked buttons for help/tour, plus a separate mode section for Encode/Decode. It does not use the same CDK menubar pattern as the JavaScript playground’s app-js-debugger-toolbar (libraries/features/dev-tools-javascript-runner/src/lib/js-debugger-toolbar.component.*editor-menubar, cdkMenuBar, menubar-trigger, menubar-spacer, etc.; see also Gitea #32 in code comments).

We want a single top menubar for Base64 that feels consistent with those tools and with the JSON QuickType input bar (/tools/(tools:json), quick-type.component.htmlcdkMenuBar + File / Edit / Format dropdowns).

Desired layout

  1. lib-tool-file-menu (@spikersoft/platform-tool-file-menuToolFileMenuComponent) under a top-level File menu trigger, with the standard four operations (same contract as RegEx and other tools):

    • Save to Browser
    • Download to Device
    • Load from Browser
    • Load from Device

    Host provides ToolStorageConfig, serialize(), and handles ToolFileMenuEvent (loaded → apply string into input / state; saved optional extra UX). Reference implementations: reg-ex.component.ts (ToolFileMenuComponent + onFileMenuEvent), and the JSON tool’s File dropdown UX in quick-type.component.html (manual menu today — prefer the shared component for Base64 for consistency with RegEx).

  2. Encode / Decode as root-level controls on the menubar (e.g. mat-button-toggle-group or two menubar-trigger actions), not buried only in the old standalone “mode section” — visually comparable to primary actions on js-debugger-toolbar.

  3. Toggle Help and Guided Tour moved into the menubar, pulled right (after menubar-spacer), mirroring the right-aligned cluster pattern used on the debugger toolbar (status / trailing controls). Today these live in base64.component.html header-actions (mat-slide-toggle + mat-stroked-button).

References (code)

  • Route: projects/spikersoft/src/routes.tspath: "base64", Base64Component.
  • Current UI: libraries/features/dev-tools-encoding/src/lib/base64/base64.component.{ts,html,scss}.
  • Menubar pattern: libraries/features/dev-tools-javascript-runner/src/lib/js-debugger-toolbar.component.html + _editor-menubar.scss / editor-menubar partial from theme.
  • JSON tool menubar: libraries/features/dev-tools-quick-type/src/lib/quick-type.component.html (data-tour="json-input-menu").
  • Shared file menu: libraries/platform/tool-file-menu/src/lib/tool-file-menu.component.ts.

Acceptance criteria

  • Base64 shows an editor-menubar (cdkMenuBar) with File using lib-tool-file-menu and the four standard file operations.
  • Encode and Decode are visible as root-level menubar controls.
  • Toggle Help and Guided Tour are in the menubar, right-aligned (spacer before them).
  • Existing intro.js / IntroTourProvider / data-tour anchors updated or preserved so tours still target the right elements.
  • @nx/enforce-module-boundaries: feature-dev-tools-encoding may depend on platform-tool-file-menu and platform-tool-storage as needed.
  • Unit tests updated (base64.component.spec.ts) for any new wiring.

Notes

  • Pick a dedicated ToolStorageConfig dbName / file naming for Base64 so saves do not collide with other tools.
  • Serialization shape: at minimum persist the text input, mode (encode | decode), and any flags the tool already tracks (liveMode, fromFile / file-derived state if still supported); document briefly in README.md for dev-tools-encoding if the payload is non-obvious.
## Summary The Base64 Encoder / Decoder at `/tools/(tools:base64)` (`Base64Component` in `@spikersoft/feature-dev-tools-encoding`) currently uses a **header block** with slide toggles and stroked buttons for help/tour, plus a separate **mode section** for Encode/Decode. It does **not** use the same **CDK menubar** pattern as the JavaScript playground’s `app-js-debugger-toolbar` (`libraries/features/dev-tools-javascript-runner/src/lib/js-debugger-toolbar.component.*` — `editor-menubar`, `cdkMenuBar`, `menubar-trigger`, `menubar-spacer`, etc.; see also Gitea #32 in code comments). We want a **single top menubar** for Base64 that feels consistent with those tools and with the JSON QuickType input bar (`/tools/(tools:json)`, `quick-type.component.html` — `cdkMenuBar` + File / Edit / Format dropdowns). ## Desired layout 1. **`lib-tool-file-menu`** (`@spikersoft/platform-tool-file-menu` — `ToolFileMenuComponent`) under a top-level **File** menu trigger, with the standard four operations (same contract as RegEx and other tools): - Save to Browser - Download to Device - Load from Browser - Load from Device Host provides `ToolStorageConfig`, `serialize()`, and handles `ToolFileMenuEvent` (`loaded` → apply string into input / state; `saved` optional extra UX). Reference implementations: `reg-ex.component.ts` (`ToolFileMenuComponent` + `onFileMenuEvent`), and the JSON tool’s File dropdown UX in `quick-type.component.html` (manual menu today — prefer the **shared** component for Base64 for consistency with RegEx). 2. **Encode / Decode** as **root-level** controls on the menubar (e.g. `mat-button-toggle-group` or two `menubar-trigger` actions), **not** buried only in the old standalone “mode section” — visually comparable to primary actions on `js-debugger-toolbar`. 3. **Toggle Help** and **Guided Tour** moved **into the menubar**, **pulled right** (after `menubar-spacer`), mirroring the right-aligned cluster pattern used on the debugger toolbar (status / trailing controls). Today these live in `base64.component.html` `header-actions` (`mat-slide-toggle` + `mat-stroked-button`). ## References (code) - Route: `projects/spikersoft/src/routes.ts` — `path: "base64"`, `Base64Component`. - Current UI: `libraries/features/dev-tools-encoding/src/lib/base64/base64.component.{ts,html,scss}`. - Menubar pattern: `libraries/features/dev-tools-javascript-runner/src/lib/js-debugger-toolbar.component.html` + `_editor-menubar.scss` / `editor-menubar` partial from theme. - JSON tool menubar: `libraries/features/dev-tools-quick-type/src/lib/quick-type.component.html` (`data-tour="json-input-menu"`). - Shared file menu: `libraries/platform/tool-file-menu/src/lib/tool-file-menu.component.ts`. ## Acceptance criteria - [ ] Base64 shows an `editor-menubar` (`cdkMenuBar`) with **File** using `lib-tool-file-menu` and the four standard file operations. - [ ] **Encode** and **Decode** are visible as root-level menubar controls. - [ ] **Toggle Help** and **Guided Tour** are in the menubar, **right-aligned** (spacer before them). - [ ] Existing intro.js / `IntroTourProvider` / `data-tour` anchors updated or preserved so tours still target the right elements. - [ ] `@nx/enforce-module-boundaries`: `feature-dev-tools-encoding` may depend on `platform-tool-file-menu` and `platform-tool-storage` as needed. - [ ] Unit tests updated (`base64.component.spec.ts`) for any new wiring. ## Notes - Pick a dedicated `ToolStorageConfig` `dbName` / file naming for Base64 so saves do not collide with other tools. - Serialization shape: at minimum persist the text input, mode (`encode` | `decode`), and any flags the tool already tracks (`liveMode`, `fromFile` / file-derived state if still supported); document briefly in `README.md` for `dev-tools-encoding` if the payload is non-obvious.
Author
Owner

Implemented and shipped together with #93 — the two tools now share an identical menubar pattern.

What changed

  • Replaced the Base64 tool's stacked header-section (Toggle Help + Guided Tour) and standalone mode-section (Encode/Decode) with a single editor-menubar (cdkMenuBar) at the top of base64.component.html, mirroring the JS debugger toolbar / JSON QuickType / new JWT bar.
  • File is a lib-tool-file-menu on the left of the bar with the standard four operations. Backed by a dedicated ToolStorageConfig with dbName: "SpikerSoftBase64Storage" so saves never collide with the JWT sibling.
  • Encode / Decode are root-level mat-button-toggle controls on the menubar.
  • Toggle Help and Guided Tour are right-aligned after <span class="menubar-spacer">.
  • data-tour="base64-header" and data-tour="base64-mode" migrated to the menubar wrapper / toggle group respectively, so existing intro.js steps keep working.
  • Saved-file payload is a versioned { version: 1, mode, input, liveMode, showEducation } envelope. File-mode payloads (fromFile, fileEncoded) are intentionally NOT persisted — round-tripping a 5 MB data URL through IndexedDB / disk has weird semantics and balloons the saved snapshot. Loading a snapshot always lands the user in text mode; re-upload is a one-step recovery. Documented in the lib README under "Saved-file envelope convention".

Shared abstractions with #93

Done in one pass to share the encoding-lib infrastructure (peer deps, styleIncludePaths, test target). The two tools' menubar markup is intentionally NOT extracted into a shared component — it's only ~20 lines of HTML, the controls have different mode labels/icons/order, and the future trajectories likely diverge (Base64 may want Text/File toggles in the bar; JWT may want Demo Token / claims toggle). Documented as a convention in the lib README rather than a generic component.

Tests

  • 4 new tests in base64.component.spec.ts covering File menu integration: round-trip serialize+load, file-mode reset on load, non-JSON guard, no apply on saved events.
  • Existing 28 tests preserved. nx test feature-dev-tools-encoding passes 60/60 (Base64 + JWT combined).

Verification

  • nx build feature-dev-tools-encoding
  • nx lint feature-dev-tools-encoding
  • nx test feature-dev-tools-encoding 60/60

Closing.

Implemented and shipped together with #93 — the two tools now share an identical menubar pattern. **What changed** - Replaced the Base64 tool's stacked `header-section` (Toggle Help + Guided Tour) and standalone `mode-section` (Encode/Decode) with a single `editor-menubar` (`cdkMenuBar`) at the top of `base64.component.html`, mirroring the JS debugger toolbar / JSON QuickType / new JWT bar. - **File** is a `lib-tool-file-menu` on the left of the bar with the standard four operations. Backed by a dedicated `ToolStorageConfig` with `dbName: "SpikerSoftBase64Storage"` so saves never collide with the JWT sibling. - **Encode** / **Decode** are root-level `mat-button-toggle` controls on the menubar. - **Toggle Help** and **Guided Tour** are right-aligned after `<span class="menubar-spacer">`. - `data-tour="base64-header"` and `data-tour="base64-mode"` migrated to the menubar wrapper / toggle group respectively, so existing intro.js steps keep working. - Saved-file payload is a versioned `{ version: 1, mode, input, liveMode, showEducation }` envelope. **File-mode payloads (`fromFile`, `fileEncoded`) are intentionally NOT persisted** — round-tripping a 5 MB data URL through IndexedDB / disk has weird semantics and balloons the saved snapshot. Loading a snapshot always lands the user in text mode; re-upload is a one-step recovery. Documented in the lib README under "Saved-file envelope convention". **Shared abstractions with #93** Done in one pass to share the encoding-lib infrastructure (peer deps, `styleIncludePaths`, `test` target). The two tools' menubar markup is intentionally NOT extracted into a shared component — it's only ~20 lines of HTML, the controls have different mode labels/icons/order, and the future trajectories likely diverge (Base64 may want Text/File toggles in the bar; JWT may want Demo Token / claims toggle). Documented as a convention in the lib README rather than a generic component. **Tests** - 4 new tests in `base64.component.spec.ts` covering File menu integration: round-trip serialize+load, file-mode reset on load, non-JSON guard, no apply on `saved` events. - Existing 28 tests preserved. `nx test feature-dev-tools-encoding` passes 60/60 (Base64 + JWT combined). **Verification** - `nx build feature-dev-tools-encoding` ✅ - `nx lint feature-dev-tools-encoding` ✅ - `nx test feature-dev-tools-encoding` ✅ 60/60 Closing.
Sign in to join this conversation.