doxa-maps/library/components/poster
Doxa Maps 36f2818b37 Every animating library component now honours prefers-reduced-motion itself
17 of 25 library components that ship motion carried no reduced-motion rule, so
they animated regardless of the reader's OS setting.

The reason it cannot be fixed once, centrally: a @media (prefers-reduced-motion)
rule in the host document does not cross a shadow boundary, and these render
inside one. Measured while surveying: NO generated leaf page ships such a rule
at all — 0 occurrences across the whole built tree — so there was not even a
page rule to inherit. Each component owns its own.

CSS-ONLY AND ADDITIVE. Nothing but new @media blocks; no existing rule changed.
Verified by diff: 0 real removals across 17 files. The two lines git reports as
removed are a trailing comma moving as a new string was chained onto an existing
concatenation, and both original rules are still present — checked by grepping
for them, not by reading the diff.

WHERE MOTION CARRIES MEANING, it is kept rather than hidden:
  · SemanticTreeLegend's spinner MEANS "loading". Stopped dead it is a static
    ring that says nothing, so it is slowed to a step crawl (2.4s, steps(8)) —
    visibly working, no smooth spin.
  · LegendProgressBar's only motion is a hover filter, so it simply stops; the
    bar's FILL is geometry, not animation, and still reports its value.

The rule goes where each component's styles actually go, and that varies more
than expected: 13 append into a useShadowStyles template literal, 3 into
string-concatenated sheets, and VerticalTabsLayout into its VTL_SHADOW_CSS
constant AND its duplicate <style> block, because its own header says the two
copies must stay identical.

check:reduced-motion asserts both halves, each mutation-tested to fail before I
trusted a pass: strip the rule from an animating component and it fails; move a
rule from the injected sheet into a <style> block and it fails too, because on a
useShadowStyles component that rule would never reach the shadow root. Both
mutated files restored byte-identical.

Two of my own errors caught by tooling rather than by review, and worth naming:
my first patch asserted useShadowStyles existed in every target and RAISED on
VerticalTabsLayout instead of silently skipping it — the assert-the-anchor habit
from the last registration failure working as intended. Then I appended CSS
after the label argument on two concat-built sheets, corrupting the injection
key; check:shadow-css-parses named both files and the fix was to insert before
the label. A gate I did not write caught what I got wrong.

Registered in all three places and verified by re-reading the parsed
package.json.
2026-09-29 01:38:07 +00:00
..
slots consolidate docs into documentation/ and deployment shells into deployment/ 2026-09-21 23:23:23 +00:00
PosterDialog.vue PosterDialog prints by default instead of downloading, like PosterWall 2026-09-28 05:30:58 +00:00
PosterPreview.vue The last of the shared-library English: legend, poster preview and tab loading states 2026-09-26 13:04:16 +00:00
PosterWall.vue Every animating library component now honours prefers-reduced-motion itself 2026-09-29 01:38:07 +00:00
README.md consolidate docs into documentation/ and deployment shells into deployment/ 2026-09-21 23:23:23 +00:00

library/components/poster/ — poster export UI

The dialog and preview surfaces that turn a live map into a printable poster. Used by research-map.vue.

  PosterDialog.vue   ← pick size, orientation, title → export
  PosterPreview.vue  ← live preview, updates as you change settings
  PosterWall.vue     ← grid of poster previews
  slots/             ← the composable regions of a poster (own README)
        fed by useMapPoster() · sizes from constants/posterSizes.js
  • Open/close state comes from inject('uiStore'); the preview is fed by useMapPoster().
  • Page sizes: library/constants/posterSizes.js. Defaults: library/constants/posterDefaults.js.

Full wiring + slot contract: ../../../documentation/architecture/components.md.