dex/src/components/Nav.js
chris 1125278f76 Easter egg: give the mini-game a real mobile trigger
.nav__brand is display:none below 1024px, so "tap the wordmark" was
desktop-only. Add a shared onTapCode() helper (src/lib/tap-code.js) and
put the 7-tap shortcut on the dex feed's game-title (.feed-head__id),
which is visible on every screen size. Keeps the wordmark tap for desktop.

3 tests for onTapCode (count, window reset, unbind).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Ve7HLspzeG2xDPtJQ8vmu
2026-09-10 12:47:15 -04:00

76 lines
2.5 KiB
JavaScript

import { el } from '../lib/dom.js';
import { openGameSheet } from './GameSheet.js';
import { settings } from '../store/settings.js';
import { onTapCode } from '../lib/tap-code.js';
const ITEMS = [
{ label: 'Dex', icon: '▦', href: '#/', match: (h) => h === '#/' || h === '' || h === '#' },
{
label: 'Team',
icon: '⛨',
href: '#/team',
match: (h) => h.startsWith('#/team'),
optional: 'showTeamNav',
},
{ label: 'Games', icon: '◉', action: openGameSheet },
{ label: 'Search', icon: '⌕', href: '#/search', match: (h) => h.startsWith('#/search') },
{ label: 'Settings', icon: '⚙', href: '#/settings', match: (h) => h.startsWith('#/settings') },
];
/**
* One nav element, styled by CSS into a bottom bar on phones and a sidebar
* on wide screens. The Games item summons an overlay; optional items (Team)
* can be hidden from Settings.
*/
export function Nav() {
const nav = el('nav', { class: 'nav', 'aria-label': 'Primary' });
let links = [];
function build() {
const st = settings.get();
const items = ITEMS.filter((it) => !it.optional || st[it.optional]);
links = items.map((item) => {
const inner = [
el('span', { class: 'nav__icon', 'aria-hidden': 'true' }, item.icon),
el('span', { class: 'nav__label' }, item.label),
];
return item.action
? el(
'button',
{ class: 'nav__link', type: 'button', onclick: () => item.action() },
...inner,
)
: el('a', { class: 'nav__link', href: item.href }, ...inner);
});
// Easter egg: the wordmark only shows on wide screens; on mobile the
// same shortcut lives on the dex feed's game title (see DexGrid).
const brand = el('span', { class: 'nav__brand' }, 'Pocketdex');
onTapCode(brand, () => {
if ((location.hash || '') !== '#/whos-that') location.hash = '#/whos-that';
});
nav.replaceChildren(brand, ...links);
nav._items = items;
sync();
}
function sync() {
const hash = location.hash || '#/';
(nav._items || []).forEach((item, i) => {
if (!item.match) return;
links[i].classList.toggle('is-active', item.match(hash));
links[i].setAttribute('aria-current', item.match(hash) ? 'page' : 'false');
});
}
build();
let lastShowTeam = settings.get().showTeamNav;
settings.subscribe((s) => {
if (s.showTeamNav !== lastShowTeam) {
lastShowTeam = s.showTeamNav;
build();
}
});
window.addEventListener('hashchange', sync);
return nav;
}