@freva-org/freva-badge
v2608.0.0-beta.0
Published
The Freva footer badge: a static mark that opens a panel, with a bird that flies in and lands on it.
Downloads
108
Readme
@freva-org/freva-badge
The Freva footer badge, vendored as its optimized runtime. A static mark that opens a panel, with a bird that flies in, lands on the mark and walks along its rim.
This package is the badge's implementation. Nothing outside it draws the badge, animates it, or styles it. A host mounts it and tells it where its assets live; everything else - the markup, the motion, the copy, the CSS - is here.
dist/
freva-badge.js the runtime; hand maintained, no build step
freva-badge-content.js copy, links, organisations; no logic
freva-badge.css all of the badge's styling, scoped under `.fb`
assets/ mark, story sheet, motion chunks and manifestsMounting
window.FrevaBadgeOptions = { assetBase: "/site/_badge/assets/" };
// then load freva-badge-content.js, then freva-badge.js
FrevaBadge.mount(element);| Option | Meaning |
| ----------- | --------------------------------------------------------------------------- |
| assetBase | Where assets/ was published. Must end in /. |
| quality | "auto" (default) picks 1x or 2x by display density; "standard" pins 1x. |
The loading lifecycle, which is the point of this package
- about 70 KB of code plus the static mark at page load, and nothing else;
- the footer story sheet and the flight and walk sprites only once someone hovers, focuses, touches or opens the badge - never before;
- and the story only plays when the visitor closes the panel. A mark that ran its whole story on every page load was motion nobody asked for;
- a visitor who asked for reduced motion, or whose browser reports Save-Data, gets the still asset and no sprite sheet at all;
- drawing surfaces are sized to the animation, allocated on open and released on close; nothing paints while the badge is closed or the document is hidden.
Do not add preload hints for the bridge or ground assets. They would defeat all of the above.
What is not here
masters/, tools/, results/, demo/ and the original PNG atlases are not
vendored: they are the inputs to the assets in dist/assets, not something a
portal serves. Asset regeneration happens upstream, against the masters archive,
and lands here as a new dist/.
Local changes to the vendored runtime
Eight, kept here so a future asset drop does not become a portal change. Each one is a host-integration fix - none changes what the badge draws, how it moves, or what it says:
quality: "standard"inFrevaBadgeOptions, which pins the motion assets to the 1x set instead of choosing by device pixel ratio.- Every selector in the stylesheet is scoped under
.fb, the root the runtime already builds. Mechanical, no declaration touched, and load-bearing in both directions: the badge cannot restyle a host, and a host cannot restyle the badge. It is not hypothetical - the Data Browser ships a global.pop { display: none }for its own popovers, which hid this one entirely on any page that mounted it..fb .popnow states its owndisplay: blockfor the same reason: scoping raises specificity, but only for properties the badge actually declares, and this was not one of them. - The badge's own typography is stated on
.fbrather than inherited, and restated asfont-family: inheriton the element types a host stylesheet can name. Scoping stops the badge reaching the host; this is the other direction. The panel's headline is an<h2>, so a portal'sh1, h2, h3, h4rule reached straight into the mark: every size inside the panel is a fraction of--pop-w, so a face with different metrics rewrapped the headline from two lines to four and pushed the organisation strip out of the circle. Measured against the package's own demo page, the panel's computed styles now differ in four places, all of them intended: the asset origin, the shadow colour the badge takes from the page by design, the marquee's animation phase, and an icon-only button's font. - The footer story sheet is loaded straight from its own same-origin URL.
Upstream fetched it as bytes and handed CSS an object URL to keep the uncached
case at one request; a host with an ordinary
img-src 'self' data:refuses ablob:URL, so the sheet silently never became ready and the badge kept its static mark forever. One request either way - thefetchis gone, not moved - and a portal needs noblob:in its policy. - The story sheet moved behind the intent gate, and arriving no longer means playing. Upstream fetched it on an idle callback and played it the moment it landed, so 765 kB arrived on every page load and the mark ran its whole 260-frame story in the corner of every documentation page, unprompted. It is fetched now with the motion - on hover, focus, touch or open - and it plays when the panel closes. The at-rest cost is the 70 kB the lifecycle above claims, and the mark at rest is the still, which is the same artwork: the story's own last frame.
- Three host-facing lengths -
--fb-ftr-h,--fb-insetand--fb-pop-drop- in place of hard-coded offsets, so the mark lines up with a page's own gutter and the open panel overlaps a footer rather than balancing on top of it. - No scrim. A draft of this integration dimmed the whole portal while the panel was open; a credit line should not read like a modal, and opening it now changes nothing behind it.
About uspoints athttps://freva-org.github.io/.- Three mark layers instead of two, and the resting state is a state. A host
can lend the badge an animated mark through
FrevaBadgeOptions.liveMark; that is what shows when nobody has touched the badge. Upstream had a one-way door - once the story sheet loaded, the still was hidden for good and the sheet's last frame became the mark - so the story could only ever be the resting state. Now the sheet is shown while the story runs and put away when the bird has landed, and the mark goes back to living. A reduced-motion visitor is never shown either: they keep the package's own still. --fb-mark-lift, so the disc can stand on the page's bottom edge instead of floating 20px above it. The artwork carries about 3px of clear space below it inside the 158x63 box, which is why the portal sets-3px.- The organisation strip carries real marks: each chip is a link when the
organisation has a home, the slot is a white tile rather than a translucent
one - most of these logos are dark navy and 20% white over a dark blue panel
showed nothing - and the tile is larger, at the cost of tightening the
strip's own margins so the panel's copy keeps its air. The duplicate group
that makes the marquee seamless stays
aria-hiddenand unlinked, so nothing is announced or tabbed twice.
