Files
FixIt/assets/js/modules/menu.ts
T
Cell 17d7bc1781 refactor(assets): SCSS variables with hugo:vars and module setup standardization (#788)
* feat(assets): refactor SCSS variables with Hugo config via hugo:vars

Use Hugo's hugo:vars mechanism (v0.161.0+) to configure SCSS variables
via [params.appearance] in hugo.toml, replacing the override.scss file.

- Add [params.appearance] config section in hugo.toml
- Create scss-vars.html partial for SCSS default values
- Pass vars to toCSS via head/index.html
- Rewrite _variables.scss to use @use "hugo:vars" as h with !default
- Update all 20 consumer files from @use "override" to @use "variables"
- Delete override.scss
- Add admonition mixin in core/mixins/_admonition.scss
- Update deprecation detection to use fileExists

* refactor(assets): standardize module setup() and simplify main.ts init

- Add setup() method to all modules (menu, theme, search, enc, misc, events)
- Rename initMenu to setup, initMenuDesktop/initMenuMobile to initDesktop/initMobile
- Rename initSearch, initFixItDecryptor to setup
- Standardize setup() position at end of each module class and interface
- Simplify main.ts init sequence to uniform setup() calls

* refactor(assets): replace config.template.scss with hugo:vars/internal

- Delete config.template.scss and its ExecuteAsTemplate pipeline
- Pass internal config (base URL, logo, loading) via hugo:vars/internal namespace
- Move CSS custom properties to _root.scss using set-fi-vars mixin
- Simplify _variables.scss by removing config namespace dependency
- Update CLAUDE.md to reflect new SCSS architecture

* style(i18n): fix spacing in Korean translation strings

* fix(assets): resolve dead SCSS config keys and deduplicate defaults

- Wire up 5 config keys with v.$ references: menu-active-color,
  tag-cloud-start, tag-cloud-end, tag-cloud-end-dark,
  pagination-link-color-dark (were reading from SCSS vars, ignoring
  hugo:vars overrides)
- Remove dead !default flags from all v.$ references (hugo:vars
  always provides values, making !default unreachable)
- Compute derived defaults in scss-vars.html from base values instead
  of hardcoding duplicates
- Extract admonition mixin set-fi-vars map to shared $vars variable
2026-06-22 02:43:35 +08:00

58 lines
2.1 KiB
TypeScript

import type { CoreService, MenuService } from '../core/tokens'
/**
* Menu module — desktop dropdown and mobile drawer navigation.
*
* Responsibilities:
* - Desktop header dropdown menu interactions.
* - Mobile header drawer menu open/close/toggle.
* - Sync menu state with mask overlay.
*/
export class MenuModule implements MenuService {
constructor(private readonly core: CoreService) {}
/** Set min-width on desktop sub-menus to match parent item width. */
initDesktop() {
document.querySelectorAll<HTMLElement>('.has-children').forEach(($item) => {
$item.querySelector<HTMLElement>('.sub-menu')!.style.minWidth = `${$item.offsetWidth - 8}px`
})
}
/** Initialize mobile drawer menu with mask overlay and nested toggles. */
initMobile() {
const $menuToggleMobile = document.getElementById('menu-toggle-mobile')
const $menuMobile = document.getElementById('menu-mobile')
if (!$menuToggleMobile || !$menuMobile)
return
this.core.registerMaskOverlay('menu-mobile', {
isActive: () => $menuMobile.classList.contains('active'),
onOpen: () => {
$menuToggleMobile.classList.add('active')
$menuMobile.classList.add('active')
$menuToggleMobile.setAttribute('aria-expanded', 'true')
},
onClose: () => {
$menuToggleMobile.classList.remove('active')
$menuMobile.classList.remove('active')
$menuToggleMobile.setAttribute('aria-expanded', 'false')
},
})
$menuToggleMobile.addEventListener('click', () => {
this.core.toggleMaskOverlay('menu-mobile')
}, false)
// add nested menu toggler
document.querySelectorAll<HTMLElement>('.menu-item>.nested-item').forEach(($nestedItem) => {
$nestedItem.addEventListener('click', function (this: HTMLElement) {
(this.parentNode as HTMLElement).querySelector('.sub-menu')!.classList.toggle('open')
this.querySelector('.dropdown-icon')!.classList.toggle('open')
})
})
}
/** Initialize both desktop and mobile menus. */
setup() {
this.initDesktop()
this.initMobile()
}
}