diff --git a/odoo-community-developers/index.html b/odoo-community-developers/index.html index 9021b81..622b2f8 100644 --- a/odoo-community-developers/index.html +++ b/odoo-community-developers/index.html @@ -552,14 +552,33 @@ margin: 0.1rem 0 0; color: var(--ink-soft); } + /* Profile links are LOGO ONLY — no visible name. One uniform monochrome SVG set, + inlined (zero requests). The link's accessible name comes from its aria-label. + Each hit area is 36px around a 24px mark, so the row clears the WCAG 2.2 24px + target-size minimum with room to spare. */ .dev-links { margin: 0; - font-size: 0.85rem; - color: var(--ink-soft); + display: flex; + align-items: center; + flex-wrap: wrap; + gap: 0.3rem; } .dev-links a { - color: var(--brass-deep); + color: var(--midnight); + display: inline-flex; + align-items: center; + justify-content: center; + width: 36px; + height: 36px; + border-radius: 50%; + line-height: 0; } + .dev-links a:hover { color: var(--brass-deep); } + .dev-links a:focus-visible { + outline: 3px solid var(--brass-deep); + outline-offset: 2px; + } + .dev-links svg { display: block; width: 24px; height: 24px; } /* The "Ask question anonymously" trigger — added by script only while its route is set. Styled as a link so it sits in the links row where the mailto chip was. */ .dev-links button { @@ -2461,7 +2480,10 @@ // Our own count — rendered ONCE, with weight, never a score. var clients = parseInt(rec.odoo4projects_clients, 10); - if (!isNaN(clients)) { + // A count of 0 — or an absent count — shows NO line at all. Not "0 clients", + // not a dash: 0 is not a fact worth printing about a freelancer. The plural + // rules for >= 1 are unchanged ("1 client" / "N clients", the plain number). + if (!isNaN(clients) && clients >= 1) { var p = liveEl("p", "dev-clients"); p.appendChild(liveEl("span", "dev-clients-n", String(clients))); p.appendChild(document.createTextNode(" ")); @@ -2495,11 +2517,18 @@ [["Linkedin", "LinkedIn"], ["github", "GitHub"], ["upwork", "Upwork"], ["fiverr", "Fiverr"]].forEach(function (pair) { var val = String(rec[pair[0]] || "").trim(); + var label = pair[1]; if (isLink(val)) { - var a = liveEl("a", null, pair[1]); + // Logo only: the visible content is the SVG, so the link keeps its name in + // the accessibility tree (aria-label + title) and never ships as an empty or + // unnamed anchor. A null/blank value renders NO anchor at all. + var a = liveEl("a", null); a.href = val; a.target = "_blank"; a.rel = "noopener nofollow"; + a.setAttribute("aria-label", label + " profile"); + a.setAttribute("title", label + " profile"); + a.innerHTML = LINK_ICONS[label]; // a static constant, never data from a record links.push(a); } }); @@ -2510,10 +2539,7 @@ if (canAsk(rec)) card.setAttribute("data-relay", "1"); if (links.length) { var row = liveEl("p", "dev-links"); - links.forEach(function (a, i) { - if (i) row.appendChild(document.createTextNode(" \u00b7 ")); - row.appendChild(a); - }); + links.forEach(function (a) { row.appendChild(a); }); card.appendChild(row); } if (!canAsk(rec)) { @@ -2784,6 +2810,17 @@ ' stroke-linejoin="round">' + ''; + /* The four profile marks — ONE uniform monochrome SVG set (Simple Icons, 24 x 24: + same grid, same internal padding, same weight), self-hosted copies in + static/icons/. Inlined so the row makes NO request and the mark inherits + currentColor. The mark is decorative (aria-hidden); the link carries the name. */ + var LINK_ICONS = { + LinkedIn: '', + GitHub: '', + Upwork: '', + Fiverr: '' + }; + /* Add the self-service controls to one card, in ONE row ABOVE the links so the contact action comes first: · "Ask question anonymously" — only while its route is set AND the card is diff --git a/static/icons/README.md b/static/icons/README.md new file mode 100644 index 0000000..7201fff --- /dev/null +++ b/static/icons/README.md @@ -0,0 +1,22 @@ +# static/icons — the profile-link icon set + +Four monochrome brand marks shown in the freelancer directory card's links row +(`/odoo-community-developers/`): LinkedIn, GitHub, Upwork, Fiverr. + +**Source:** [Simple Icons](https://simpleicons.org) v13 — one uniform set, so the four +share one visual language by construction: the same 24 × 24 grid, the same internal +padding, the same monochrome mass, single-path art. Nothing here is hand-drawn and +nothing is fetched from a third party at runtime. + +**How the page uses them.** The card inlines the same path data (see `LINK_ICONS` in the +page's script and in `work/build-directory.py`), so the links row makes **zero requests** +and each mark inherits the link's `currentColor`. These files are the self-hosted, +drop-in copy of that set — identical geometry — for any host that prefers a file over an +inline ``. + +**Brand rule.** A brand mark is never redrawn and never restyled beyond a single +monochrome fill. The one styling the page applies is `fill="currentColor"`. + +The `role`/`aria-label` here are for standalone use; the card strips them and marks the +inline SVG `aria-hidden="true" focusable="false"`, putting the accessible name on the +link (`aria-label` + `title`, e.g. "GitHub profile"). diff --git a/static/icons/fiverr.svg b/static/icons/fiverr.svg new file mode 100644 index 0000000..aedb320 --- /dev/null +++ b/static/icons/fiverr.svg @@ -0,0 +1 @@ + diff --git a/static/icons/github.svg b/static/icons/github.svg new file mode 100644 index 0000000..c755337 --- /dev/null +++ b/static/icons/github.svg @@ -0,0 +1 @@ + diff --git a/static/icons/linkedin.svg b/static/icons/linkedin.svg new file mode 100644 index 0000000..119fdf7 --- /dev/null +++ b/static/icons/linkedin.svg @@ -0,0 +1 @@ + diff --git a/static/icons/upwork.svg b/static/icons/upwork.svg new file mode 100644 index 0000000..0595fe0 --- /dev/null +++ b/static/icons/upwork.svg @@ -0,0 +1 @@ +