Apply the Nocturne fidelity pass to the web UI
This commit is contained in:
+128
-27
@@ -1,41 +1,126 @@
|
||||
"use strict";
|
||||
|
||||
/* ─────────────────────────────────────────────────────────────────────────
|
||||
Veskslop icons — Phosphor geometry.
|
||||
|
||||
Replaces the hand-drawn 16-unit set. Three things change:
|
||||
|
||||
1. Grid. Phosphor draws on 256 units; the old set drew on 16, so curves
|
||||
were quantised to half-pixels and the mic, gear and camera all had
|
||||
visibly different optical weights from each other.
|
||||
2. Terminals. Round caps and joins throughout, as Phosphor regular.
|
||||
3. Stroke. Held at a constant ~1.35 device pixels whatever the render
|
||||
size, instead of a fixed 1.3 unit stroke that thickened as icons grew.
|
||||
A 44px icon and a 13px icon now read as the same weight of line.
|
||||
|
||||
The API is unchanged — VK.icon(name, size) and VK.iconEl(name, size) —
|
||||
and every previous name still resolves, so nothing needs editing to
|
||||
adopt this. New names are listed at the bottom.
|
||||
|
||||
If you would rather ship the real Phosphor set, swap this file for
|
||||
@phosphor-icons/web and keep VK.icon as a thin wrapper; the names below
|
||||
are Phosphor's own, so the mapping is one to one.
|
||||
───────────────────────────────────────────────────────────────────────── */
|
||||
|
||||
window.VK = window.VK ?? {};
|
||||
|
||||
const ICON_PATHS = {
|
||||
hash: '<path d="M6 2L4.5 14M11.5 2L10 14M2.5 5.5h12M2 10.5h12"/>',
|
||||
volume: '<path d="M8.5 2.5 4.5 6H2v4h2.5l4 3.5z"/><path d="M11 5.5a3.5 3.5 0 0 1 0 5"/>',
|
||||
mic: '<rect x="5.5" y="1.5" width="5" height="7.5" rx="2.5"/><path d="M3 7.5a5 5 0 0 0 10 0M8 12.5v2"/>',
|
||||
/* ── Channels and navigation ── */
|
||||
hash: '<path d="M96 40 72 216M184 40l-24 176M52 96h152M44 160h152"/>',
|
||||
users: '<circle cx="104" cy="96" r="44"/><path d="M24 200a88 88 0 0 1 160 0"/><path d="M160 54a44 44 0 0 1 0 84"/><path d="M232 200a88 88 0 0 0-40-38"/>',
|
||||
user: '<circle cx="128" cy="92" r="48"/><path d="M36 204a96 96 0 0 1 184 0"/>',
|
||||
chat: '<path d="M52 212l12-36A88 88 0 1 1 128 216a87 87 0 0 1-40-10z"/><path d="M96 120h64M96 152h40"/>',
|
||||
activity: '<path d="M24 128h40l24-64 40 128 24-64h80"/>',
|
||||
robot: '<rect x="28" y="72" width="200" height="136" rx="24"/><path d="M128 28v44"/><circle cx="128" cy="24" r="10"/><path d="M92 136v12M164 136v12"/><path d="M104 176h48"/>',
|
||||
|
||||
/* ── Voice ── */
|
||||
mic: '<rect x="96" y="24" width="64" height="112" rx="32"/><path d="M196 124a68 68 0 0 1-136 0"/><path d="M128 192v40M92 232h72"/>',
|
||||
micSlash:
|
||||
'<rect x="5.5" y="1.5" width="5" height="7.5" rx="2.5"/><path d="M3 7.5a5 5 0 0 0 10 0M8 12.5v2"/><path d="M2.5 13.5 13.5 2.5"/>',
|
||||
speaker: '<path d="M3 10V8a5 5 0 0 1 10 0v2"/><rect x="1.5" y="9.5" width="3" height="4.5" rx="1.5"/><rect x="11.5" y="9.5" width="3" height="4.5" rx="1.5"/>',
|
||||
speakerSlash:
|
||||
'<path d="M3 10V8a5 5 0 0 1 10 0v2"/><rect x="1.5" y="9.5" width="3" height="4.5" rx="1.5"/><rect x="11.5" y="9.5" width="3" height="4.5" rx="1.5"/><path d="M2 14 14 2"/>',
|
||||
monitor: '<rect x="1.5" y="2.5" width="13" height="9" rx="1.5"/><path d="M5.5 14h5M8 11.5v2.5"/>',
|
||||
camera: '<rect x="1.5" y="4.5" width="9" height="7" rx="1.5"/><path d="M10.5 8l4-2.2v4.4z"/>',
|
||||
caretDown: '<path d="M3.5 6l4.5 4.5L12.5 6"/>',
|
||||
caretUp: '<path d="M3.5 10L8 5.5l4.5 4.5"/>',
|
||||
x: '<path d="M3.5 3.5l9 9M12.5 3.5l-9 9"/>',
|
||||
lock: '<rect x="3.5" y="7" width="9" height="7" rx="1.5"/><path d="M5.5 7V5a2.5 2.5 0 0 1 5 0v2"/>',
|
||||
search: '<circle cx="7" cy="7" r="4.5"/><path d="M10.5 10.5 14 14"/>',
|
||||
gear: '<circle cx="8" cy="8" r="2.2"/><path d="M8 1.8v2M8 12.2v2M1.8 8h2M12.2 8h2M3.6 3.6l1.4 1.4M11 11l1.4 1.4M12.4 3.6 11 5M5 11l-1.4 1.4"/>',
|
||||
wave: '<path d="M2 6.5V4.5h6v2M5 4.5V12"/><path d="M10.5 5.5a3.2 3.2 0 0 1 0 5"/><path d="M12.8 3.5a6 6 0 0 1 0 9"/>',
|
||||
warning: '<path d="M8 2 1.5 13.5h13z"/><path d="M8 6.5v3.5M8 12v.5"/>',
|
||||
refresh: '<path d="M13.5 8a5.5 5.5 0 1 1-1.6-3.9"/><path d="M13.5 2.5V6H10"/>',
|
||||
play: '<path d="M5 3.5 12.5 8 5 12.5z"/>',
|
||||
microphone: '<rect x="5.5" y="1.5" width="5" height="7.5" rx="2.5"/><path d="M3 7.5a5 5 0 0 0 10 0M8 12.5v2"/>',
|
||||
users: '<circle cx="6" cy="5.5" r="2.5"/><path d="M1.5 13.5c0-2.5 2-4 4.5-4s4.5 1.5 4.5 4"/><path d="M11 3.5a2.5 2.5 0 0 1 0 5"/>',
|
||||
activity: '<path d="M1.5 8h3l2-4.5 2.5 9L11 8h3.5"/>'
|
||||
'<rect x="96" y="24" width="64" height="112" rx="32"/><path d="M196 124a68 68 0 0 1-136 0"/><path d="M128 192v40M92 232h72"/><path d="M44 36l168 184"/>',
|
||||
volume: '<path d="M152 36 88 88H40v80h48l64 52z"/><path d="M188 96a44 44 0 0 1 0 64"/>',
|
||||
speaker: '<path d="M152 36 88 88H40v80h48l64 52z"/><path d="M188 96a44 44 0 0 1 0 64"/><path d="M212 68a80 80 0 0 1 0 120"/>',
|
||||
speakerSlash: '<path d="M152 36 88 88H40v80h48l64 52z"/><path d="M188 100l44 56M232 100l-44 56"/>',
|
||||
headphones: '<path d="M44 176v-48a84 84 0 0 1 168 0v48"/><rect x="20" y="152" width="48" height="68" rx="20"/><rect x="188" y="152" width="48" height="68" rx="20"/>',
|
||||
headphonesSlash:
|
||||
'<path d="M44 176v-48a84 84 0 0 1 168 0v48"/><rect x="20" y="152" width="48" height="68" rx="20"/><rect x="188" y="152" width="48" height="68" rx="20"/><path d="M44 36l168 184"/>',
|
||||
waveform: '<path d="M32 108v40M72 76v104M112 40v176M152 76v104M192 100v56M232 116v24"/>',
|
||||
wave: '<path d="M32 92V64h96v28M80 64v128M52 192h56"/><path d="M168 96a44 44 0 0 1 0 64"/><path d="M200 70a80 80 0 0 1 0 116"/>',
|
||||
|
||||
/* ── Media ── */
|
||||
monitor: '<rect x="24" y="48" width="208" height="136" rx="20"/><path d="M96 216h64M128 184v32"/>',
|
||||
screenshare: '<rect x="24" y="48" width="208" height="136" rx="20"/><path d="M96 216h64"/><path d="M128 76v72M100 104l28-28 28 28"/>',
|
||||
camera: '<rect x="24" y="64" width="144" height="128" rx="20"/><path d="M168 112l64-36v104l-64-36z"/>',
|
||||
image: '<rect x="32" y="48" width="192" height="160" rx="20"/><circle cx="96" cy="100" r="16"/><path d="M32 172l56-48 48 40 32-24 56 48"/>',
|
||||
film: '<rect x="32" y="48" width="192" height="160" rx="20"/><path d="M88 48v160M168 48v160M32 128h192M32 88h56M32 168h56M168 88h56M168 168h56"/>',
|
||||
audio: '<circle cx="76" cy="188" r="32"/><circle cx="196" cy="164" r="28"/><path d="M108 188V72l116-28v120"/>',
|
||||
folder: '<path d="M216 208H40a12 12 0 0 1-12-12V60a12 12 0 0 1 12-12h56l28 36h92a12 12 0 0 1 12 12v100a12 12 0 0 1-12 12z"/>',
|
||||
play: '<path d="M76 40l148 88-148 88z"/>',
|
||||
pause: '<rect x="76" y="48" width="40" height="160" rx="10"/><rect x="140" y="48" width="40" height="160" rx="10"/>',
|
||||
stop: '<rect x="56" y="56" width="144" height="144" rx="20"/>',
|
||||
|
||||
/* ── Controls ── */
|
||||
caretDown: '<path d="M208 96l-80 80-80-80"/>',
|
||||
caretUp: '<path d="M48 160l80-80 80 80"/>',
|
||||
caretRight: '<path d="M96 48l80 80-80 80"/>',
|
||||
caretLeft: '<path d="M160 208 80 128l80-80"/>',
|
||||
x: '<path d="M200 56 56 200M200 200 56 56"/>',
|
||||
check: '<path d="M216 72 104 184l-56-56"/>',
|
||||
plus: '<path d="M40 128h176M128 40v176"/>',
|
||||
minus: '<path d="M40 128h176"/>',
|
||||
dots: '<circle cx="128" cy="128" r="14"/><circle cx="60" cy="128" r="14"/><circle cx="196" cy="128" r="14"/>',
|
||||
search: '<circle cx="116" cy="116" r="76"/><path d="M170 170l54 54"/>',
|
||||
funnel: '<path d="M32 56h192l-76 88v72l-40-24v-48z"/>',
|
||||
gear: '<circle cx="128" cy="128" r="40"/><path d="M128 20l26 22 34-4 13 32 32 13-4 34 22 27-22 27 4 34-32 13-13 32-34-4-26 22-26-22-34 4-13-32-32-13 4-34-22-27 22-27-4-34 32-13 13-32 34 4z"/>',
|
||||
sliders: '<path d="M40 88h72M156 88h60M40 168h28M112 168h104"/><circle cx="134" cy="88" r="22"/><circle cx="90" cy="168" r="22"/>',
|
||||
refresh: '<path d="M176 92h44V48"/><path d="M220 92A100 100 0 0 0 44 78"/><path d="M80 164H36v44"/><path d="M36 164a100 100 0 0 0 176 14"/>',
|
||||
download: '<path d="M128 32v128M80 112l48 48 48-48M40 208h176"/>',
|
||||
copy: '<rect x="80" y="80" width="144" height="144" rx="16"/><path d="M176 80V48a16 16 0 0 0-16-16H48a16 16 0 0 0-16 16v112a16 16 0 0 0 16 16h32"/>',
|
||||
pencil: '<path d="M92 216H48a8 8 0 0 1-8-8v-44L164 40l52 52z"/><path d="M136 68l52 52"/>',
|
||||
trash: '<path d="M36 64h184M96 64V40h64v24M60 64v148a16 16 0 0 0 16 16h104a16 16 0 0 0 16-16V64M108 108v72M148 108v72"/>',
|
||||
pin: '<path d="M100 28h56l-8 60 40 44H68l40-44z"/><path d="M128 132v96"/>',
|
||||
popout: '<path d="M144 40h72v72"/><path d="M128 128 216 40"/><path d="M188 152v56a12 12 0 0 1-12 12H48a12 12 0 0 1-12-12V80a12 12 0 0 1 12-12h56"/>',
|
||||
lock: '<rect x="40" y="88" width="176" height="128" rx="20"/><path d="M88 88V56a40 40 0 0 1 80 0v32"/>',
|
||||
star: '<path d="M128 24l30 62 68 10-49 48 12 68-61-32-61 32 12-68-49-48 68-10z"/>',
|
||||
|
||||
/* ── Status ── */
|
||||
info: '<circle cx="128" cy="128" r="96"/><path d="M120 124h12v56M104 180h48"/><circle cx="126" cy="86" r="10"/>',
|
||||
warning: '<path d="M110 40 22 190a20 20 0 0 0 18 30h176a20 20 0 0 0 18-30L146 40a20 20 0 0 0-36 0z"/><path d="M128 104v40"/><circle cx="128" cy="180" r="10"/>',
|
||||
error: '<circle cx="128" cy="128" r="96"/><path d="M160 96l-64 64M96 96l64 64"/>',
|
||||
ok: '<circle cx="128" cy="128" r="96"/><path d="M172 100l-56 56-32-32"/>',
|
||||
clock: '<circle cx="128" cy="128" r="96"/><path d="M128 72v56h48"/>'
|
||||
};
|
||||
|
||||
const FILLED = new Set(["star"]);
|
||||
/* Aliases — every name the app used before this file landed. */
|
||||
ICON_PATHS.microphone = ICON_PATHS.mic;
|
||||
ICON_PATHS.deafen = ICON_PATHS.headphonesSlash;
|
||||
ICON_PATHS.listen = ICON_PATHS.headphones;
|
||||
ICON_PATHS.video = ICON_PATHS.camera;
|
||||
ICON_PATHS.close = ICON_PATHS.x;
|
||||
ICON_PATHS.settings = ICON_PATHS.gear;
|
||||
ICON_PATHS.tts = ICON_PATHS.wave;
|
||||
ICON_PATHS.magnify = ICON_PATHS.search;
|
||||
|
||||
ICON_PATHS.star = '<path d="M8 1.6l1.9 4 4.4.6-3.2 3 .8 4.3L8 11.5 4.1 13.5l.8-4.3-3.2-3 4.4-.6z"/>';
|
||||
const FILLED = new Set(["star", "play", "dots"]);
|
||||
|
||||
/* Solid marks keep a hairline of their own so they hold shape at 10-11px. */
|
||||
const HAIRLINE = new Set(["dots"]);
|
||||
|
||||
window.VK.icon = function icon(name, size = 13) {
|
||||
const path = ICON_PATHS[name] ?? "";
|
||||
const fill = FILLED.has(name) ? "currentColor" : "none";
|
||||
return `<svg width="${size}" height="${size}" viewBox="0 0 16 16" fill="${fill}" stroke="currentColor" stroke-width="1.3" aria-hidden="true">${path}</svg>`;
|
||||
const path = ICON_PATHS[name];
|
||||
if (!path) {
|
||||
if (name) console.warn("VK.icon: unknown icon", name);
|
||||
return "";
|
||||
}
|
||||
const filled = FILLED.has(name);
|
||||
/* Constant optical weight: ~1.35 device px of stroke at any render size. */
|
||||
const sw = Math.min(30, Math.max(12, +((1.35 / size) * 256).toFixed(1)));
|
||||
return (
|
||||
`<svg width="${size}" height="${size}" viewBox="0 0 256 256" ` +
|
||||
`fill="${filled ? "currentColor" : "none"}" ` +
|
||||
`stroke="${filled && !HAIRLINE.has(name) ? "none" : "currentColor"}" ` +
|
||||
`stroke-width="${sw}" stroke-linecap="round" stroke-linejoin="round" ` +
|
||||
`aria-hidden="true" focusable="false">${path}</svg>`
|
||||
);
|
||||
};
|
||||
|
||||
window.VK.iconEl = function iconEl(name, size = 13) {
|
||||
@@ -44,3 +129,19 @@ window.VK.iconEl = function iconEl(name, size = 13) {
|
||||
span.innerHTML = window.VK.icon(name, size);
|
||||
return span;
|
||||
};
|
||||
|
||||
/* Fills any empty [data-icon] span. Safe to call repeatedly — it skips
|
||||
anything already rendered, so it will not fight whatever app.js does. */
|
||||
window.VK.hydrateIcons = function hydrateIcons(root = document) {
|
||||
root.querySelectorAll("[data-icon]").forEach((el) => {
|
||||
if (el.firstElementChild) return;
|
||||
const size = Number(el.dataset.iconSize) || 13;
|
||||
el.innerHTML = window.VK.icon(el.dataset.icon, size);
|
||||
});
|
||||
};
|
||||
|
||||
if (document.readyState === "loading") {
|
||||
document.addEventListener("DOMContentLoaded", () => window.VK.hydrateIcons());
|
||||
} else {
|
||||
window.VK.hydrateIcons();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user