doxa-maps/library/components/map-controls
Doxa Maps 5c9c1fd36b Two maps placed their share menu correctly because they were named in a string literal
DRV1650-SHARE-MENU-MOBILE-OFFSCREEN. On mobile the share/embed menu opens off-screen to
the right on Cities with Internet and Gospel Resources, while Simple Research and Prayer
Progress are correct.

THE SPLIT IS NOT A PLUGIN DIFFERENCE. MapControlMenu resolved the area it places inside
with closest('.dsm-map-area, .rm-map-area, .dm-map-area, [data-map-area]') -- three
hardcoded plugin class names. doxa-simple-map and research-map are on that list. Everyone
else resolved `|| null`, and place() answers a null area by returning an EMPTY STYLE,
which leaves .mcm{position:absolute} at its STATIC position: below-and-right of a button
already at the top right. Off the page.

So the two maps that worked worked because they were named in a string in another
component, and the bug was decided by a literal rather than by geometry. It is also the
SAME failure the 2026-09-22 dashboard fix documents twenty lines below -- not "a wrong
side was chosen" but "nothing chose anything" -- returning through a different door.

MEASURED: cities-internet, gospel-resources, key-cities and upg-neighbor carry no
map-area class and no data-map-area, so FOUR plugins were unanchored. The Driver reported
two. A fix aimed at the two he named would have left the other two, and a gate written
around them would have passed.

The named area is still preferred, because it is a real map's walls and a menu must not
outgrow them. When a plugin declares none, the anchor falls back to the toolbar's own
offsetParent -- the containing block this menu is absolutely positioned against, so
placing against it is correct by definition rather than by registration. A plugin that
adopts a class later simply gets the better anchor; nothing has to be registered anywhere
for a menu to be on screen.

check-map-menu-anchor asserts the PROPERTY rather than the list: that the resolution
cannot produce null from a real toolbar, that place() still guards a genuinely absent
one, and that a declared map area is still preferred over the fallback. Negative-tested:
restoring the allowlist-only resolution turns it red.

NEEDS EYES: this is rendered geometry and I work headless. What I can prove is that the
anchor is no longer decided by a name; whether the menu now sits correctly at 390px on
all four is rega's to measure.
2026-09-28 17:40:34 +00:00
..
FullscreenButton.vue A lazy view that fails to load says so and offers Retry; map controls carry data-control 2026-09-28 11:42:54 +00:00
GeocoderComponent.vue Every runtime CDN script and stylesheet is an exact version with an integrity hash 2026-09-26 05:50:24 +00:00
HamburgerButton.vue doxa-maps — portable bundler for embeddable JAMstack maps 2026-09-10 01:53:07 +00:00
HelpButton.vue A lazy view that fails to load says so and offers Retry; map controls carry data-control 2026-09-28 11:42:54 +00:00
index.js doxa-maps — portable bundler for embeddable JAMstack maps 2026-09-10 01:53:07 +00:00
LocationButton.vue A lazy view that fails to load says so and offers Retry; map controls carry data-control 2026-09-28 11:42:54 +00:00
MapControlButton.vue A lazy view that fails to load says so and offers Retry; map controls carry data-control 2026-09-28 11:42:54 +00:00
MapControlMenu.vue Two maps placed their share menu correctly because they were named in a string literal 2026-09-28 17:40:34 +00:00
MapToolbar.vue Square panel: no child brings its own outline 2026-09-27 23:23:42 +00:00
README.md consolidate docs into documentation/ and deployment shells into deployment/ 2026-09-21 23:23:23 +00:00
ShareButton.vue A lazy view that fails to load says so and offers Retry; map controls carry data-control 2026-09-28 11:42:54 +00:00
ThemeToggleButton.vue A lazy view that fails to load says so and offers Retry; map controls carry data-control 2026-09-28 11:42:54 +00:00
ZoomInButton.vue A lazy view that fails to load says so and offers Retry; map controls carry data-control 2026-09-28 11:42:54 +00:00
ZoomOutButton.vue A lazy view that fails to load says so and offers Retry; map controls carry data-control 2026-09-28 11:42:54 +00:00

library/components/map-controls/ — toolbar buttons

Each file is a single, focused button or input that mounts inside the map's control area. Replaces the older monolithic MapControlsComponent.vue.

  MapToolbar.vue  (container)
   ├─ ZoomInButton · ZoomOutButton · LocationButton
   ├─ FullscreenButton · HamburgerButton · ThemeToggleButton
   ├─ HelpButton · ShareButton
   └─ GeocoderComponent   (all built on MapControlButton.vue)
  • Every button takes a size prop (sm | md | lg) and follows the MapControlButton shape.
  • Click handlers go through inject('mapStore') or getMap() — never a captured Mapbox instance.
  • To add one: copy ZoomInButton.vue and register it in MapToolbar.vue.

Full conventions + catalog: ../../../documentation/architecture/components.md.