footer: add slim single-line mode for fixed-height app shells
Full block footer steals ~230px in fixed app layouts (iamthelaw et al). New data-mode="slim" renders a compact accent-matched one-line bar. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
7a3b684203
commit
2afb56d93d
1 changed files with 39 additions and 5 deletions
44
footer.js
44
footer.js
|
|
@ -7,8 +7,10 @@
|
||||||
- Self-contained: injects itself into <body>, styles live in a Shadow DOM
|
- Self-contained: injects itself into <body>, styles live in a Shadow DOM
|
||||||
so nothing leaks in or out of the host page's CSS.
|
so nothing leaks in or out of the host page's CSS.
|
||||||
- Central: edit this one file, every site updates. No per-repo redeploy.
|
- Central: edit this one file, every site updates. No per-repo redeploy.
|
||||||
- Two modes, chosen via a data attribute on the script tag:
|
- Three modes, chosen via a data attribute on the script tag:
|
||||||
(default) full footer bar at the end of the page.
|
(default) full footer bar at the end of the page.
|
||||||
|
data-mode="slim" compact single-line bar (~40px) — for fixed-height
|
||||||
|
app shells where the full block would steal layout.
|
||||||
data-mode="pill" compact fixed corner badge — for full-screen apps
|
data-mode="pill" compact fixed corner badge — for full-screen apps
|
||||||
(maps, games) where a block footer would be hidden.
|
(maps, games) where a block footer would be hidden.
|
||||||
Optional: data-accent="#ff0099" to match a site's own accent.
|
Optional: data-accent="#ff0099" to match a site's own accent.
|
||||||
|
|
@ -22,7 +24,8 @@
|
||||||
document.currentScript ||
|
document.currentScript ||
|
||||||
document.querySelector('script[src*="footer.js"]');
|
document.querySelector('script[src*="footer.js"]');
|
||||||
var ds = (self && self.dataset) || {};
|
var ds = (self && self.dataset) || {};
|
||||||
var mode = ds.mode === 'pill' ? 'pill' : 'bar';
|
var mode =
|
||||||
|
ds.mode === 'pill' ? 'pill' : ds.mode === 'slim' ? 'slim' : 'bar';
|
||||||
var accent = ds.accent || '#ff2d55';
|
var accent = ds.accent || '#ff2d55';
|
||||||
var here = location.hostname; // don't link a site back to itself
|
var here = location.hostname; // don't link a site back to itself
|
||||||
|
|
||||||
|
|
@ -90,6 +93,37 @@
|
||||||
'<div class="rf-btm"><span>© 2026 The Radical Party</span><span>Radical by default</span></div>' +
|
'<div class="rf-btm"><span>© 2026 The Radical Party</span><span>Radical by default</span></div>' +
|
||||||
'</div>';
|
'</div>';
|
||||||
|
|
||||||
|
// Slim: one compact line. Renders as a normal block bar (NOT fixed), so it
|
||||||
|
// sits as a ~40px flex child at the bottom of an app shell without stealing
|
||||||
|
// the layout the way the full block does, and still flows fine on a scrolling
|
||||||
|
// page. Accent-matched so it reads as part of the host app, not a foreign box.
|
||||||
|
var slimCSS =
|
||||||
|
':host{all:initial}' +
|
||||||
|
'*{margin:0;padding:0;box-sizing:border-box;font-family:"IBM Plex Mono",ui-monospace,SFMono-Regular,Menlo,monospace}' +
|
||||||
|
'.rf{background:#0B0B09;color:#8b8b85;border-top:1px solid rgba(255,255,255,.08);' +
|
||||||
|
'box-shadow:0 -1px 0 ' + accent + '22;padding:9px 18px;display:flex;align-items:center;' +
|
||||||
|
'gap:8px 22px;flex-wrap:wrap;line-height:1}' +
|
||||||
|
'.rf-logo{display:inline-flex;align-items:center;gap:8px;text-decoration:none;flex:none}' +
|
||||||
|
'.rf-dot{width:9px;height:9px;border-radius:50%;background:' + accent + ';box-shadow:0 0 10px ' + accent + '99;flex:none}' +
|
||||||
|
'.rf-word{font-family:"Syne","IBM Plex Mono",monospace;font-weight:800;font-size:13px;letter-spacing:.14em;' +
|
||||||
|
'color:#F0EDE6;text-transform:uppercase}' +
|
||||||
|
'.rf-nav{display:flex;flex-wrap:wrap;align-items:center;gap:6px 16px;flex:1;min-width:0}' +
|
||||||
|
'.rf a{color:#b7b7b0;text-decoration:none;font-size:12px;letter-spacing:.02em;transition:color .15s;white-space:nowrap}' +
|
||||||
|
'.rf a:hover{color:' + accent + '}' +
|
||||||
|
'.rf-logo:hover .rf-word{color:' + accent + '}' +
|
||||||
|
'.rf-vvv{font-size:9px;letter-spacing:.28em;text-transform:uppercase;color:' + accent + ';flex:none;white-space:nowrap}' +
|
||||||
|
'@media(max-width:640px){.rf{padding:9px 14px;gap:8px 14px}.rf-vvv{display:none}}';
|
||||||
|
|
||||||
|
var slimHTML =
|
||||||
|
'<div class="rf">' +
|
||||||
|
'<a class="rf-logo" href="' + HOME + '"><span class="rf-dot"></span><span class="rf-word">Radical</span></a>' +
|
||||||
|
'<nav class="rf-nav">' +
|
||||||
|
flagLinks +
|
||||||
|
'<a href="' + HUB + '">All Projects ↗</a>' +
|
||||||
|
'</nav>' +
|
||||||
|
'<span class="rf-vvv">Vibe · Vote · Veto</span>' +
|
||||||
|
'</div>';
|
||||||
|
|
||||||
var pillCSS =
|
var pillCSS =
|
||||||
':host{all:initial}' +
|
':host{all:initial}' +
|
||||||
'*{margin:0;padding:0;box-sizing:border-box;font-family:"IBM Plex Mono",ui-monospace,monospace}' +
|
'*{margin:0;padding:0;box-sizing:border-box;font-family:"IBM Plex Mono",ui-monospace,monospace}' +
|
||||||
|
|
@ -107,9 +141,9 @@
|
||||||
'<span class="rf-txt">Part of <b>The Radical Party</b></span>' +
|
'<span class="rf-txt">Part of <b>The Radical Party</b></span>' +
|
||||||
'<span class="rf-arrow">↗</span></a>';
|
'<span class="rf-arrow">↗</span></a>';
|
||||||
|
|
||||||
shadow.innerHTML =
|
var css = mode === 'pill' ? pillCSS : mode === 'slim' ? slimCSS : barCSS;
|
||||||
'<style>' + (mode === 'pill' ? pillCSS : barCSS) + '</style>' +
|
var html = mode === 'pill' ? pillHTML : mode === 'slim' ? slimHTML : barHTML;
|
||||||
(mode === 'pill' ? pillHTML : barHTML);
|
shadow.innerHTML = '<style>' + css + '</style>' + html;
|
||||||
|
|
||||||
function mount() {
|
function mount() {
|
||||||
if (document.getElementById('radical-footer-root')) return;
|
if (document.getElementById('radical-footer-root')) return;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue