diff --git a/dist/app.js b/dist/app.js index 80f5048..6e55a87 100644 --- a/dist/app.js +++ b/dist/app.js @@ -572,10 +572,19 @@ var found = (tasks && tasks.lists || []).filter(function (l) { return l.name === name; })[0]; return found || { name: name, icon: 'list', person: false, color: '' }; } + // A person's initial on their colour. The letter takes whichever ink reads better on that colour, white or the night + // surface's near-black (--mono-on-dark, --mono-on-light in tokens.css): white on every person colour fell to 2.8:1 on + // the palette's orange. With no colour it sits on --ink-2 in --mono-ink. + var MONO_ON_DARK = [255, 255, 255], MONO_ON_LIGHT = [12, 17, 29]; + function monogram(name, color) { + var c = /^#[0-9a-f]{6}$/i.test(color || '') ? [1, 3, 5].map(function (i) { return parseInt(color.slice(i, i + 2), 16); }) : null; + var a = node('span', c ? 'avatar ' + (contrast(MONO_ON_DARK, c) >= contrast(MONO_ON_LIGHT, c) ? 'on-dark' : 'on-light') : 'avatar', name.charAt(0).toUpperCase()); + if (c) a.style.backgroundColor = color; + return a; + } // A person, as their initial in the color their calendar uses: the mark their own list carries. function personMark(name, color, label) { - var a = node('span', 'avatar', name.charAt(0).toUpperCase()); - if (color) a.style.backgroundColor = color; + var a = monogram(name, color); a.setAttribute('title', name); a.setAttribute('aria-label', label); return a; } @@ -593,7 +602,7 @@ } function listMark(name) { var l = listOf(name), svg; - if (l.person) { var a = node('span', 'avatar', l.name.charAt(0).toUpperCase()); if (l.color) a.style.backgroundColor = l.color; a.setAttribute('aria-hidden', 'true'); return a; } + if (l.person) { var a = monogram(l.name, l.color); a.setAttribute('aria-hidden', 'true'); return a; } svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); svg.setAttribute('class', 'glyph'); svg.setAttribute('viewBox', '0 0 24 24'); svg.setAttribute('aria-hidden', 'true'); (GLYPHS[l.icon] || GLYPHS.list).forEach(function (d) { var p = document.createElementNS('http://www.w3.org/2000/svg', 'path'); p.setAttribute('d', d); svg.appendChild(p); }); return svg; diff --git a/dist/style.css b/dist/style.css index cc1f0c6..2d18f4d 100644 --- a/dist/style.css +++ b/dist/style.css @@ -319,7 +319,7 @@ body[data-rest] .photo-card{border-radius:0} .forecast{display:flex;align-items:center;height:3.2rem;margin:.7rem 0 1.1rem;padding-bottom:1rem;box-sizing:content-box;border-bottom:.0625rem solid var(--line);font-size:1.45rem;color:var(--ink-2);font-variant-numeric:tabular-nums;white-space:nowrap} .forecast .wx,.agenda-wx .wx{flex:none;width:2.6rem;margin-right:.6rem;display:flex;flex-direction:column;align-items:center} .forecast .wx-icon,.agenda-wx .wx-icon{width:2.4rem;height:2.4rem;color:var(--ink-2)} -.forecast small,.agenda-wx small{font-size:1.05rem;line-height:1;font-weight:600;color:var(--rain);margin-top:-.1rem} +.forecast small,.agenda-wx small{font-size:1.05rem;line-height:1;font-weight:600;color:var(--rain-ink);margin-top:-.1rem} .forecast b{color:var(--ink);font-weight:600;margin-right:.45rem} .day-items{flex:1;min-height:0;overflow:hidden} .day .item{margin-bottom:calc(1.15rem*var(--ts))} @@ -440,7 +440,8 @@ button.item:active{opacity:.6} .day .candle{width:.511em;height:.876em;margin-right:.36em;vertical-align:-.073em} /* A list's mark: a glyph for a household list, a monogram in the person's color for a person's list. */ .glyph{flex:none;width:1.75rem;height:1.75rem;fill:none;stroke:currentColor;stroke-width:1.9;stroke-linecap:round;stroke-linejoin:round} -.avatar{flex:none;display:flex;align-items:center;justify-content:center;width:1.9rem;height:1.9rem;border-radius:50%;background:var(--ink-2);color:#fff;font:700 1.05rem/1 var(--text);letter-spacing:0} +.avatar{flex:none;display:flex;align-items:center;justify-content:center;width:1.9rem;height:1.9rem;border-radius:50%;background:var(--ink-2);color:var(--mono-ink);font:700 1.05rem/1 var(--text);letter-spacing:0} +.avatar.on-dark{color:var(--mono-on-dark)}.avatar.on-light{color:var(--mono-on-light)} .tabs .label{margin-left:.6rem} .item-title .avatar{display:inline-flex;width:1.7rem;height:1.7rem;font-size:.95rem;vertical-align:.1em} .item-title .avatar+.avatar{margin-left:.3rem} diff --git a/dist/tokens.css b/dist/tokens.css index 935a755..12c8484 100644 --- a/dist/tokens.css +++ b/dist/tokens.css @@ -31,13 +31,17 @@ } /* The same in both themes. The sky is only a default: app.js paints --sky-* on every minute. --sky-rule is the - hairline drawn on the sky: a mid-grey, so it reads on any sky. */ + hairline drawn on the sky: a mid-grey, so it reads on any sky. --rain is the drops of a rain icon. A monogram on a + person's colour takes whichever of the two --mono-on-* inks reads better there (app.js decides, DESIGN.md → Rain and + monograms reach 4.8:1). */ :root{ --sky-top:var(--sky-day-top);--sky-bottom:var(--sky-day-bottom);--sky-ink:var(--navy-900);--sky-rule:var(--grey-a35); --sun:var(--yellow-sun);--rain:var(--blue-rain);--moon:var(--cream-moon); + --mono-on-dark:var(--mist-0);--mono-on-light:var(--slate-900); } -/* Light. --selected, --shade, --tint and --star are the wall's; --bad and --good are the phone's (the wall has no +/* Light. --selected, --shade, --tint, --star, --rain-ink (the rain chance as text) and --mono-ink (the letter of a + monogram with no colour of its own, on --ink-2) are the wall's; --bad and --good are the phone's (the wall has no error colour). The phone's card shadow is its own, rgba(16,38,63,.08) in setup.css, not --shade. */ :root,.theme-light{ --surface:var(--mist-100);--card:var(--mist-0);--ink:var(--navy-800);--ink-2:var(--navy-600);--line:var(--mist-300); @@ -46,6 +50,7 @@ --selected:var(--mist-0); --shade:rgba(16,38,63,.14);--tint:rgba(16,38,63,.028); --star:var(--ember-600);--bad:var(--red-600);--good:var(--green-600); + --rain-ink:var(--blue-600);--mono-ink:var(--mist-0); } /* Dark, for the phone. Keep in step with .theme-dark below. */ @@ -55,6 +60,7 @@ --selected:var(--slate-500); --shade:rgba(0,0,0,.5);--tint:rgba(255,255,255,.025); --star:var(--ember-300);--bad:var(--red-300);--good:var(--green-300); + --rain-ink:var(--blue-rain);--mono-ink:var(--slate-900); }} /* Dark, for the wall. Keep in step with the block above. */ @@ -64,4 +70,5 @@ --selected:var(--slate-500); --shade:rgba(0,0,0,.5);--tint:rgba(255,255,255,.025); --star:var(--ember-300);--bad:var(--red-300);--good:var(--green-300); + --rain-ink:var(--blue-rain);--mono-ink:var(--slate-900); } diff --git a/site/index.html b/site/index.html index bdeacb7..b2cbfd6 100644 --- a/site/index.html +++ b/site/index.html @@ -313,7 +313,7 @@
Kept by Gingham, or in Todoist, Google Tasks, Microsoft To Do, Home Assistant or a CalDAV server such as Nextcloud or Fastmail. Check things off with a moment to undo. A phone reaches Gingham’s own lists on the home Wi‑Fi, or from anywhere when they live on a server with https. The others go wherever their own apps go.
+Kept by Gingham, or in Todoist, Home Assistant, a CalDAV server such as Nextcloud or Fastmail, or Google Tasks once you register a Google app of your own. Check things off with a moment to undo. A phone reaches Gingham’s own lists on the home Wi‑Fi, or from anywhere when they live on a server with https. The others go wherever their own apps go.