wayBetter for X 1.0.2
This commit is contained in:
parent
660531daeb
commit
6f6721d32d
212 changed files with 10208 additions and 2345 deletions
400
apps/desktop/src/inject/packs/retro.ts
Normal file
400
apps/desktop/src/inject/packs/retro.ts
Normal file
|
|
@ -0,0 +1,400 @@
|
|||
// Retro icon packs for the wayBetter Store (not bundled in the app: they are installed from the
|
||||
// Store, the same way as any pack). Both are our own drawings; nothing is traced or extracted from
|
||||
// Windows, from X or from any icon archive (the Windows icon archives on the web carry Microsoft's
|
||||
// copyright, and the plan bans them). The look is the idea of the era, drawn from scratch.
|
||||
// retro-98 16 by 16 pixel art on the 98 desktop palette: black outline, silver, navy, teal.
|
||||
// retro-xp vector glyphs in the manner of 2001: gel fills, a dark edge, a lit top.
|
||||
// Both draw every name X's left rail uses (home .. compose, and the .active forms) and the action bar.
|
||||
// Generated into store/x/icons/<id>/ by scripts/build-store-icons.mjs.
|
||||
|
||||
import { sanitizeIconPack, type IconGlyph, type IconName, type IconPack } from '../../../../../waybetter/packages/runtime/src/themeIcons.ts';
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
// retro-98: rows of 16 letters, `.` is transparent
|
||||
|
||||
const P98: Record<string, string> = {
|
||||
k: '#000000', w: '#ffffff', s: '#c0c0c0', g: '#808080', n: '#000080', b: '#0000ff', c: '#008080', t: '#00ffff',
|
||||
y: '#ffff00', d: '#808000', r: '#ff0000', m: '#800000', p: '#ff80c0', e: '#00a000', o: '#ff8000', u: '#800080',
|
||||
};
|
||||
|
||||
/** Rows to a glyph of 1.5px squares on the 24px box; same-colored cells are merged into rectangles; the outline is drawn last. */
|
||||
export function rasterGlyph(name: string, rows: readonly string[]): IconGlyph {
|
||||
if (rows.length !== 16) throw new Error(`${name}: ${rows.length} rows, 16 needed`);
|
||||
rows.forEach((row, y) => {
|
||||
if (row.length !== 16) throw new Error(`${name}: row ${y} has ${row.length} cells, 16 needed (${row})`);
|
||||
for (const ch of row) if (ch !== '.' && !P98[ch]) throw new Error(`${name}: row ${y} has an unknown color "${ch}"`);
|
||||
});
|
||||
const taken = rows.map(() => new Array<boolean>(16).fill(false));
|
||||
const byColor = new Map<string, string[]>();
|
||||
const f = (n: number) => +(n * 1.5).toFixed(1);
|
||||
for (let y = 0; y < 16; y++) {
|
||||
for (let x = 0; x < 16; x++) {
|
||||
const key = rows[y]![x]!;
|
||||
if (key === '.' || taken[y]![x]) continue;
|
||||
let w = 1;
|
||||
while (x + w < 16 && rows[y]![x + w] === key && !taken[y]![x + w]) w++;
|
||||
let h = 1;
|
||||
grow: while (y + h < 16) {
|
||||
for (let i = 0; i < w; i++) if (rows[y + h]![x + i] !== key || taken[y + h]![x + i]) break grow;
|
||||
h++;
|
||||
}
|
||||
for (let j = 0; j < h; j++) for (let i = 0; i < w; i++) taken[y + j]![x + i] = true;
|
||||
const list = byColor.get(key) ?? [];
|
||||
list.push(`M${f(x)} ${f(y)}h${f(w)}v${f(h)}h-${f(w)}z`);
|
||||
byColor.set(key, list);
|
||||
}
|
||||
}
|
||||
const keys = [...byColor.keys()].sort((a, b) => (a === 'k' ? 1 : 0) - (b === 'k' ? 1 : 0));
|
||||
if (keys.length > 6) throw new Error(`${name}: ${keys.length} colors, a glyph has 6 layers at most`);
|
||||
return { layers: keys.map(key => ({ d: byColor.get(key)!.join(''), fill: P98[key]! })) };
|
||||
}
|
||||
|
||||
const ART98: Record<string, readonly string[]> = {
|
||||
home: [
|
||||
'................', '.......kk.......', '......krrk......', '.....krrrrk.....', '....krrrrrrk....', '...krrrrrrrrk...', '..krrrrrrrrrrk..', '.kkkkkkkkkkkkkk.',
|
||||
'..kwwwwwwwwwwk..', '..kwbbbwwbbbwk..', '..kwbbbwwbbbwk..', '..kwwwwkkkkwwk..', '..kwwwwkmmkwwk..', '..kwwwwkmmkwwk..', '..kkkkkkkkkkkk..', '................',
|
||||
],
|
||||
search: [
|
||||
'................', '...kkkkkk.......', '..kwwwwwwk......', '.kwwwwwwwwk.....', '.kwtwwwwwwk.....', '.kwtwwwwwwk.....', '.kwwwwwwwwk.....', '.kwwwwwwwwk.....',
|
||||
'..kwwwwwwkk.....', '...kkkkkksgk....', '........kgggk...', '.........kgggk..', '..........kgggk.', '...........kgk..', '............k...', '................',
|
||||
],
|
||||
bell: [
|
||||
'................', '.......kk.......', '......kyyk......', '.....kywyyk.....', '....kywyyyyk....', '....kywyyyyk....', '....kyyyyyyk....', '...kyyyyyyyyk...',
|
||||
'...kyyyyyyyyk...', '..kyyyyyyyyyyk..', '..kddddddddddk..', '..kkkkkkkkkkkk..', '.....kkddkk.....', '......kddk......', '.......kk.......', '................',
|
||||
],
|
||||
mail: [
|
||||
'................', '................', '.kkkkkkkkkkkkkk.', '.kwwwwwwwwwwwwk.', '.kkwwwwwwwwwwkk.', '.kwkwwwwwwwwkwk.', '.kwwkwwwwwwkwwk.', '.kwwwkwwwwkwwwk.',
|
||||
'.kwwwwkwwkwwwwk.', '.kwwwwwkkwwwwwk.', '.kwwwwwwwwwwwwk.', '.kssssssssssssk.', '.kssssssssssssk.', '.kkkkkkkkkkkkkk.', '................', '................',
|
||||
],
|
||||
monitor: [
|
||||
'................', '..kkkkkkkkkkkk..', '..kssssssssssk..', '..ksnnnnnnnnsk..', '..ksnttnnnnnsk..', '..ksnttnnnwnsk..', '..ksnnnnnwwwsk..', '..ksnnnnnnwnsk..',
|
||||
'..ksnnnnnnnnsk..', '..kssssssssssk..', '..kkkkkggkkkkk..', '......kssk......', '....kkssssk.....', '...kssssssssk...', '...kkkkkkkkkk...', '................',
|
||||
],
|
||||
folder: [
|
||||
'................', '................', '..kkkkk.........', '.kyyyyyk........', '.kyyyyyykkkkkkk.', '.kywwwwwwwwwwyk.', '.kywyyyyyyyyyyk.', '.kyyyyyyyyyyyyk.',
|
||||
'.kyyyyyyyyyyyyk.', '.kyyyyyyyyyyyyk.', '.kyyyyyyyyyyyyk.', '.kyyyyyyyyyyyyk.', '.kddddddddddddk.', '.kkkkkkkkkkkkkk.', '................', '................',
|
||||
],
|
||||
notepad: [
|
||||
'................', '..kkkkkkkkkkk...', '..kwwwwwwwwwk...', '..kwkkkkkkkwk...', '..kwwwwwwwwwk...', '..kwkkkkkkkwk...', '..kwwwwwwwwwk...', '..kwkkkkkkwwk...',
|
||||
'..kwwwwwwwwwk...', '..kwkkkkkkkwk...', '..kwwwwwwwwwk...', '..kwkkkkwwwwk...', '..kwwwwwwwwwk...', '..kkkkkkkkkkk...', '................', '................',
|
||||
],
|
||||
people: [
|
||||
'................', '...kkkk..kkkk...', '..kyyyyk.kyyyk..', '..kykkyk.kkyyk..', '..kyyyyk.kyyyk..', '...kkkk..kkkk...', '..kccccck.kuuuk.', '.kcccccccckuuuuk',
|
||||
'.kccccccckkuuuuk', '.kcccccccckuuuuk', '.kkkkkkkkkkkkkkk', '................', '................', '................', '................', '................',
|
||||
],
|
||||
badge: [
|
||||
'................', '.......kk.......', '......kyyk......', '.....kyyyyk.....', '.kkkkkywyykkkk..', '.kyyyyywyyyyyk..', '..kyyyyyyyyyk...', '...kyyyyyyyk....',
|
||||
'...kyyywyyyk....', '..kyyywwwyyyk...', '..kyyywyywyyk...', '.kyyyk..kyyyk...', '.kkkk....kkkk...', '................', '................', '................',
|
||||
],
|
||||
person: [
|
||||
'................', '......kkkk......', '.....kyyyyk.....', '....kyyyyyyk....', '....kykyykyk....', '....kyyyyyyk....', '....kyykkyyk....', '.....kyyyyk.....',
|
||||
'....kkkkkkkk....', '...kcccccccck...', '..kcccccccccck..', '..kcccccccccck..', '..kcccccccccck..', '..kkkkkkkkkkkk..', '................', '................',
|
||||
],
|
||||
// Three white dots in a black frame: the frame reads on the silver desktop, the white on a dark one.
|
||||
dots: [
|
||||
'................', '................', '................', '................', '................', '.kkkk.kkkk.kkkk.', '.kwwk.kwwk.kwwk.', '.kwwk.kwwk.kwwk.',
|
||||
'.kkkk.kkkk.kkkk.', '................', '................', '................', '................', '................', '................', '................',
|
||||
],
|
||||
pencil: [
|
||||
'............kk..', '...........kmmk.', '..........kyymk.', '.........kyyyk..', '........kyyyk...', '.......kyyyk....', '......kyyyk.....', '.....kyyyk......',
|
||||
'....kyyyk.......', '...kdyyk........', '...kddk.........', '..kwwk..........', '..kkkk..........', '................', '................', '................',
|
||||
],
|
||||
balloon: [
|
||||
'................', '..kkkkkkkkkkkk..', '.kwwwwwwwwwwwwk.', '.kwwwwwwwwwwwwk.', '.kwwkkkkkkkkwwk.', '.kwwwwwwwwwwwwk.', '.kwwkkkkkkwwwwk.', '.kwwwwwwwwwwwwk.',
|
||||
'..kkkkwwkkkkkk..', '....kwwk........', '....kwk.........', '....kk..........', '................', '................', '................', '................',
|
||||
],
|
||||
// Off: white arrows like the other outlined actions (X draws repost muted until it is on); on: green.
|
||||
arrows: [
|
||||
'................', '.....k..........', '....kwk.........', '...kwwwkkkkkk...', '..kwwwwwwwwwwk..', '...kwwwkkkkkwk..', '....kwk.....kwk.', '.....k......kwk.',
|
||||
'.kwk......k.....', '.kwk.....kwk....', '.kwkkkkkkwwwk...', '..kwwwwwwwwwwk..', '...kkkkkwwwk....', '.........kwk....', '..........k.....', '................',
|
||||
],
|
||||
arrowsOn: [
|
||||
'................', '.....k..........', '....kek.........', '...keeekkkkkk...', '..keeeeeeeeeek..', '...keeekkkkkek..', '....kek.....kek.', '.....k......kek.',
|
||||
'.kek......k.....', '.kek.....kek....', '.kekkkkkkeeek...', '..keeeeeeeeeek..', '...kkkkkeeek....', '.........kek....', '..........k.....', '................',
|
||||
],
|
||||
heart: [
|
||||
'................', '..kkk.....kkk...', '.kpppk...kpppk..', 'kpwppkkkkpppppk.', 'kpwppppppppppk..', 'kppppppppppppk..', 'kppppppppppppk..', '.kppppppppppk...',
|
||||
'..kppppppppk....', '...kppppppk.....', '....kppppk......', '.....kppk.......', '......kk........', '................', '................', '................',
|
||||
],
|
||||
heartOn: [
|
||||
'................', '..kkk.....kkk...', '.krrrk...krrrk..', 'krwrrrkkkrrrrrk.', 'krwrrrrrrrrrrk..', 'krrrrrrrrrrrrk..', 'krrrrrrrrrrrrk..', '.krrrrrrrrrrk...',
|
||||
'..krrrrrrrrk....', '...krrrrrrk.....', '....krrrrk......', '.....krrk.......', '......kk........', '................', '................', '................',
|
||||
],
|
||||
bars: [
|
||||
'................', '................', '...........kkk..', '...........kbk..', '...........kbk..', '.......kkk.kbk..', '.......kbk.kbk..', '.......kbk.kbk..',
|
||||
'...kkk.kbk.kbk..', '...kbk.kbk.kbk..', '...kbk.kbk.kbk..', '...kbk.kbk.kbk..', '..kkkkkkkkkkkkk.', '................', '................', '................',
|
||||
],
|
||||
share: [
|
||||
'.......kk.......', '......kwwk......', '.....kwwwwk.....', '....kwwwwwwk....', '...kkkwwwwkkk...', '.....kwwwwk.....', '.....kwwwwk.....', '.....kwwwwk.....',
|
||||
'..kk.kkkkkk.kk..', '..ks........sk..', '..ks........sk..', '..kssssssssssk..', '..kkkkkkkkkkkk..', '................', '................', '................',
|
||||
],
|
||||
picture: [
|
||||
'................', '.kkkkkkkkkkkkkk.', '.kttttttttyyttk.', '.kttttttttyyttk.', '.kttttttttttttk.', '.ktttttteettttk.', '.kttttteeeetttk.', '.kttteeeeeeettk.',
|
||||
'.kteeeeeeeeeetk.', '.keeeeddeeeeeek.', '.keeeeeeeeeeeek.', '.kkkkkkkkkkkkkk.', '................', '................', '................', '................',
|
||||
],
|
||||
bookmark: [
|
||||
'................', '...kkkkkkkkkk...', '...kwwwwwwwwk...', '...kwwwwwwwwk...', '...kwwwwwwwwk...', '...kwwwwwwwwk...', '...kwwwwwwwwk...', '...kwwwwwwwwk...',
|
||||
'...kwwwwwwwwk...', '...kwwwwwwwwk...', '...kwwwkkwwwk...', '...kwwkk.kwwk...', '...kwkk...kwk...', '...kkk.....kk...', '................', '................',
|
||||
],
|
||||
bookmarkOn: [
|
||||
'................', '...kkkkkkkkkk...', '...kbbbbbbbbk...', '...kbwbbbbbbk...', '...kbwbbbbbbk...', '...kbbbbbbbbk...', '...kbbbbbbbbk...', '...kbbbbbbbbk...',
|
||||
'...kbbbbbbbbk...', '...kbbbbbbbbk...', '...kbbbkkbbbk...', '...kbbkk.kbbk...', '...kbkk...kbk...', '...kkk.....kk...', '................', '................',
|
||||
],
|
||||
gif: [
|
||||
'................', '................', 'kkkkkkkkkkkkkkkk', 'knnnnnnnnnnnnnnk', 'knnnnnnnnnnnnnnk', 'knnwwwnwwwnwwwnk', 'knnwnnnnwnnwnnnk', 'knnwnnnnwnnwwnnk',
|
||||
'knnwnwnnwnnwnnnk', 'knnwwwnwwwnwnnnk', 'knnnnnnnnnnnnnnk', 'knnnnnnnnnnnnnnk', 'kkkkkkkkkkkkkkkk', '................', '................', '................',
|
||||
],
|
||||
poll: [
|
||||
'................', '................', '.kkkkkkkkkkkkkk.', '.kwwwwwwwwwwwwk.', '.kwkkkkkkkwwwwk.', '.kwkbbbbbkwwwwk.', '.kwkkkkkkkwwwwk.', '.kwkkkkkkkkkkwk.',
|
||||
'.kwkeeeeeeeekwk.', '.kwkkkkkkkkkkwk.', '.kwwwwwwwwwwwwk.', '.kkkkkkkkkkkkkk.', '................', '................', '................', '................',
|
||||
],
|
||||
smile: [
|
||||
'................', '.....kkkkkk.....', '...kkyyyyyykk...', '..kyyyyyyyyyyk..', '..kyykkyykkyyk..', '.kyyykkyykkyyyk.', '.kyyyyyyyyyyyyk.', '.kykyyyyyyyykyk.',
|
||||
'.kyykyyyyyykyyk.', '..kyykkkkkkyyk..', '..kyyyyyyyyyyk..', '...kkyyyyyykk...', '.....kkkkkk.....', '................', '................', '................',
|
||||
],
|
||||
clock: [
|
||||
'................', '.....kkkkkk.....', '...kkwwwwwwkk...', '..kwwwwkwwwwwk..', '..kwwwwkwwwwwk..', '.kwwwwwkwwwwwwk.', '.kwwwwwkwwwwwwk.', '.kwwwwwkkkkwwwk.',
|
||||
'.kwwwwwwwwwwwwk.', '.kwwwwwwwwwwwwk.', '..kwwwwwwwwwwk..', '..kwwwwwwwwwwk..', '...kkwwwwwwkk...', '.....kkkkkk.....', '................', '................',
|
||||
],
|
||||
pin: [
|
||||
'................', '.....kkkkkk.....', '....krrrrrrk....', '...krrwrrrrrrk..', '...krwwrrrrrrk..', '...krrrrkkrrrk..', '...krrrrkkrrrk..', '....krrrrrrrk...',
|
||||
'.....krrrrrk....', '......krrrk.....', '.......krk......', '........k.......', '................', '................', '................', '................',
|
||||
],
|
||||
lock: [
|
||||
'................', '.....kkkkkk.....', '....kgwwwwgk....', '....kw....wk....', '....kw....wk....', '....kw....wk....', '..kkkkkkkkkkkk..', '..kyyyyyyyyyyk..',
|
||||
'..kywwwwwwwwdk..', '..kyyyykkyyyyk..', '..kyyyykkyyyyk..', '..kyyyyyyyyyyk..', '..kddddddddddk..', '..kkkkkkkkkkkk..', '................', '................',
|
||||
],
|
||||
check: [
|
||||
'................', '.....kkkkkk.....', '...kkbbbbbbkk...', '..kbbbbbbbbbbk..', '.kbbbbbbbbbwwbk.', '.kbbbbbbbbwwbbk.', '.kbwwbbbbwwbbbk.', '.kbbwwbbwwbbbbk.',
|
||||
'.kbbbwwwwbbbbbk.', '..kbbbbwwbbbbk..', '..kbbbbbbbbbbk..', '...kkbbbbbbkk...', '.....kkkkkk.....', '................', '................', '................',
|
||||
],
|
||||
back: [
|
||||
'................', '................', '.......k........', '......kk........', '.....kgk........', '....kgwwkkkkkkk.', '...kgwwwwwwwwwk.', '..kgwwwwwwwwwwk.',
|
||||
'...kgwwwwwwwwk..', '....kgwwkkkkkk..', '.....kgk........', '......kk........', '.......k........', '................', '................', '................',
|
||||
],
|
||||
// A bright red cross in a black frame (the dark red of the first draft vanished on dark grounds).
|
||||
close: [
|
||||
'................', '................', '..kk........kk..', '..krk......krk..', '...krk....krk...', '....krk..krk....', '.....krkkrk.....', '......krrk......',
|
||||
'.....krkkrk.....', '....krk..krk....', '...krk....krk...', '..krk......krk..', '..kk........kk..', '................', '................', '................',
|
||||
],
|
||||
gear: [
|
||||
'................', '......kkkk......', '...kk.kssk.kk...', '..ksskksskksk...', '...kssssssssk...', '..kksskkkksskk..', '.kssskkwwkksssk.', '.kssskwwwwksssk.',
|
||||
'.kssskwwwwksssk.', '..kksskkkksskk..', '...kssssssssk...', '..ksskksskksk...', '...kk.kssk.kk...', '......kkkk......', '................', '................',
|
||||
],
|
||||
};
|
||||
// Anything a hand-typed row got wrong is reported by rasterGlyph with the icon's name and the row.
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
// retro-xp: vector gel, 24 by 24
|
||||
|
||||
const n2 = (n: number) => +n.toFixed(2);
|
||||
const circ = (cx: number, cy: number, r: number) => `M${n2(cx - r)} ${n2(cy)}a${n2(r)} ${n2(r)} 0 1 0 ${n2(2 * r)} 0a${n2(r)} ${n2(r)} 0 1 0 ${n2(-2 * r)} 0z`;
|
||||
const ell = (cx: number, cy: number, rx: number, ry: number) => `M${n2(cx - rx)} ${n2(cy)}a${n2(rx)} ${n2(ry)} 0 1 0 ${n2(2 * rx)} 0a${n2(rx)} ${n2(ry)} 0 1 0 ${n2(-2 * rx)} 0z`;
|
||||
const rr = (x: number, y: number, w: number, h: number, r: number) =>
|
||||
`M${n2(x + r)} ${n2(y)}h${n2(w - 2 * r)}a${n2(r)} ${n2(r)} 0 0 1 ${n2(r)} ${n2(r)}v${n2(h - 2 * r)}a${n2(r)} ${n2(r)} 0 0 1 ${n2(-r)} ${n2(r)}h${n2(-(w - 2 * r))}a${n2(r)} ${n2(r)} 0 0 1 ${n2(-r)} ${n2(-r)}v${n2(-(h - 2 * r))}a${n2(r)} ${n2(r)} 0 0 1 ${n2(r)} ${n2(-r)}z`;
|
||||
const poly = (...pts: Array<[number, number]>) => `M${pts.map(([x, y]) => `${n2(x)} ${n2(y)}`).join('L')}z`;
|
||||
/** A straight bar of width `w` from one point to another. */
|
||||
const bar = (x1: number, y1: number, x2: number, y2: number, w: number) => {
|
||||
const dx = x2 - x1, dy = y2 - y1, len = Math.hypot(dx, dy) || 1;
|
||||
const px = (-dy / len) * (w / 2), py = (dx / len) * (w / 2);
|
||||
return poly([x1 + px, y1 + py], [x2 + px, y2 + py], [x2 - px, y2 - py], [x1 - px, y1 - py]);
|
||||
};
|
||||
const star = (cx: number, cy: number, R: number, r: number, points = 5) => poly(...Array.from({ length: points * 2 }, (_, i): [number, number] => {
|
||||
const angle = -Math.PI / 2 + (i * Math.PI) / points, radius = i % 2 ? r : R;
|
||||
return [cx + radius * Math.cos(angle), cy + radius * Math.sin(angle)];
|
||||
}));
|
||||
type Layer = { d: string; fill: string | { from: string; to: string }; opacity?: number };
|
||||
const flat = (d: string, fill: string): Layer => ({ d, fill });
|
||||
const gel = (d: string, from: string, to: string): Layer => ({ d, fill: { from, to } });
|
||||
const sheen = (d: string, opacity = 0.42): Layer => ({ d, fill: { from: '#ffffff', to: '#ffffff' }, opacity });
|
||||
const glyph = (...layers: Layer[]): IconGlyph => {
|
||||
if (layers.length > 6) throw new Error(`a glyph has 6 layers at most (${layers.length})`);
|
||||
return { layers };
|
||||
};
|
||||
|
||||
const EDGE = { blue: '#143c8c', red: '#7a1a10', green: '#17591f', gold: '#7a5410', gray: '#3b4256', brown: '#5a3410' };
|
||||
const BLUE: [string, string] = ['#8fc0ff', '#2563d6'];
|
||||
const RED: [string, string] = ['#ff9a80', '#d2301a'];
|
||||
const GREEN: [string, string] = ['#a6ec8a', '#2f9e2b'];
|
||||
const GOLD: [string, string] = ['#ffe9a0', '#eaa21a'];
|
||||
const PAPER: [string, string] = ['#ffffff', '#dfe8f6'];
|
||||
|
||||
const XP: Record<string, IconGlyph> = {
|
||||
home: glyph(
|
||||
flat(rr(3.4, 10.4, 17.2, 11.6, 1.2), '#6a5a2a'), gel(rr(4.4, 11.4, 15.2, 9.6, 0.6), '#fff9dc', '#e8d28c'),
|
||||
flat(poly([12, 1.6], [23.4, 12.4], [0.6, 12.4]), EDGE.red), gel(poly([12, 4.2], [20.6, 11.2], [3.4, 11.2]), ...RED),
|
||||
gel(rr(9.8, 14.4, 4.4, 6.6, 0.8), '#6fa8ff', '#1c4fb8'), sheen(poly([12, 4.6], [16.4, 8.2], [7.6, 8.2]), 0.3),
|
||||
),
|
||||
explore: glyph(
|
||||
flat(bar(15.2, 15.2, 21.4, 21.4, 4.6), EDGE.brown), gel(bar(15.2, 15.2, 21.2, 21.2, 3), '#f6bd5a', '#b8651a'),
|
||||
flat(circ(10, 10, 8), EDGE.blue), gel(circ(10, 10, 6.9), ...BLUE), gel(circ(10, 10, 4.9), '#f2f9ff', '#a8cfff'), sheen(ell(8.5, 7.4, 3.1, 1.8), 0.7),
|
||||
),
|
||||
bell: glyph(
|
||||
flat('M12 1.8a1.6 1.6 0 0 1 1.6 1.6v.5a6.4 6.4 0 0 1 4.4 6.1v4.7l2.2 3.6H3.8L6 14.7V10a6.4 6.4 0 0 1 4.4-6.1v-.5A1.6 1.6 0 0 1 12 1.8z', EDGE.gold),
|
||||
gel('M12 3.2a.6.6 0 0 1 .6.6v1.1a5.2 5.2 0 0 1 4.2 5.1v4.9l1.7 2.9H5.5l1.7-2.9V10a5.2 5.2 0 0 1 4.2-5.1V3.8a.6.6 0 0 1 .6-.6z', ...GOLD),
|
||||
flat(circ(12, 20.4, 2.2), EDGE.gold), gel(circ(12, 20.4, 1.3), '#ffe28a', '#d58b10'), sheen(ell(9.6, 9, 1.6, 3.2), 0.55),
|
||||
),
|
||||
messages: glyph(
|
||||
flat(rr(1.6, 4.6, 20.8, 14.8, 1.8), EDGE.blue), gel(rr(2.6, 5.6, 18.8, 12.8, 1), ...PAPER),
|
||||
flat(poly([3, 6.6], [12, 13.6], [21, 6.6], [21, 8.4], [12, 15.4], [3, 8.4]), '#2a62d4'), sheen(poly([3.2, 6], [12, 11.8], [20.8, 6]), 0.4),
|
||||
),
|
||||
grok: glyph(
|
||||
flat(circ(12, 12, 10.4), '#10162e'), gel(circ(12, 12, 9.4), '#6a78a8', '#141a3a'), flat(bar(6.4, 17.6, 17.6, 6.4, 2.2), '#ffffff'),
|
||||
flat(poly([11, 5.6], [18.4, 5.6], [18.4, 13]), '#ffffff'), sheen(ell(9.6, 6.6, 4.4, 2.4), 0.3),
|
||||
),
|
||||
folder: glyph(
|
||||
flat('M2.2 5.4A1.6 1.6 0 0 1 3.8 3.8h5.4l2 2.2h9A1.6 1.6 0 0 1 21.8 7.6v11.2a1.6 1.6 0 0 1-1.6 1.6H3.8a1.6 1.6 0 0 1-1.6-1.6z', EDGE.gold),
|
||||
gel('M3.2 5.6a.8.8 0 0 1 .8-.8h4.8l2 2.2h9a.8.8 0 0 1 .8.8v10.8a.8.8 0 0 1-.8.8H4a.8.8 0 0 1-.8-.8z', '#fff1b0', '#f0b72a'),
|
||||
gel(rr(3.2, 9.2, 17.6, 10, 0.8), '#ffe27a', '#e69a12'), sheen(rr(4, 9.8, 16, 3.2, 0.6), 0.45),
|
||||
),
|
||||
lists: glyph(
|
||||
flat(rr(4.2, 1.8, 15.6, 20.4, 1.4), EDGE.gray), gel(rr(5.2, 2.8, 13.6, 18.4, 0.7), ...PAPER),
|
||||
flat(rr(7.4, 6.2, 9.2, 1.6, 0.8), '#2a62d4'), flat(rr(7.4, 10.2, 9.2, 1.6, 0.8), '#2a62d4'), flat(rr(7.4, 14.2, 9.2, 1.6, 0.8), '#2a62d4'), flat(rr(7.4, 17.8, 5.4, 1.4, 0.7), '#2a62d4'),
|
||||
),
|
||||
people: glyph(
|
||||
flat(circ(8, 7.6, 4.2), EDGE.blue), gel(circ(8, 7.6, 3.2), '#ffe2c0', '#e8a86c'), flat('M1.2 21a6.8 6.8 0 0 1 13.6 0z', EDGE.blue), gel('M2.4 20.2a5.6 5.6 0 0 1 11.2 0z', ...BLUE),
|
||||
flat(circ(17, 8.4, 3.6), EDGE.red), gel('M12.2 21a4.8 4.8 0 0 1 9.6 0z', ...RED),
|
||||
),
|
||||
star: glyph(
|
||||
flat(star(12, 12.6, 11, 4.9), EDGE.gold), gel(star(12, 12.8, 9.6, 4.1), ...GOLD), sheen(poly([12, 4.2], [14, 9.4], [12, 10.4], [10, 9.4]), 0.55),
|
||||
),
|
||||
person: glyph(
|
||||
flat(circ(12, 7, 5.4), EDGE.blue), gel(circ(12, 7, 4.4), '#ffe2c0', '#e8a86c'), flat('M2.6 22a9.4 9.4 0 0 1 18.8 0z', EDGE.blue), gel('M3.8 21a8.2 8.2 0 0 1 16.4 0z', ...BLUE),
|
||||
sheen(ell(10.4, 5.4, 2.2, 1.4), 0.7),
|
||||
),
|
||||
more: glyph(
|
||||
flat(rr(1.4, 7.6, 21.2, 8.8, 4.4), EDGE.blue), gel(rr(2.4, 8.6, 19.2, 6.8, 3.4), ...BLUE), flat(circ(7, 12, 1.5), '#ffffff'), flat(circ(12, 12, 1.5), '#ffffff'), flat(circ(17, 12, 1.5), '#ffffff'),
|
||||
sheen(rr(3.4, 9, 17.2, 2.8, 1.4), 0.4),
|
||||
),
|
||||
compose: glyph(
|
||||
flat(rr(2.4, 3.6, 15.6, 18, 1.4), EDGE.gray), gel(rr(3.4, 4.6, 13.6, 16, 0.7), ...PAPER),
|
||||
flat(bar(11.4, 16.4, 20.6, 4.4, 4.2), EDGE.gold), gel(bar(11.6, 16, 20.2, 4.8, 2.6), '#ffe27a', '#e69a12'),
|
||||
flat(poly([9.8, 20.4], [10.6, 15.6], [14, 17.6]), '#3b4256'), flat(poly([19.2, 3.4], [21.6, 2.2], [22.2, 5.4]), '#e0472b'),
|
||||
),
|
||||
reply: glyph(
|
||||
flat('M3 3.4h18a1.6 1.6 0 0 1 1.6 1.6v10.2a1.6 1.6 0 0 1-1.6 1.6H12.4L7 21.6v-4.8H3A1.6 1.6 0 0 1 1.4 15.2V5A1.6 1.6 0 0 1 3 3.4z', EDGE.blue),
|
||||
gel('M3.2 4.6h17.6a.6.6 0 0 1 .6.6v9.8a.6.6 0 0 1-.6.6h-9L8.2 19v-3.4H3.2a.6.6 0 0 1-.6-.6V5.2a.6.6 0 0 1 .6-.6z', '#c4e0ff', '#4c8fe8'), sheen(rr(3.6, 5.2, 16.8, 4, 0.6), 0.5),
|
||||
),
|
||||
// Off: brushed-steel arrows (X shows repost muted until it is on); on: the green gel.
|
||||
repost: glyph(
|
||||
flat('M3 11V9a3 3 0 0 1 3-3h8V2.6l6.4 5.2-6.4 5.2V9.6H7v1.4z', EDGE.gray), gel('M4.2 10.2V9.2a2.2 2.2 0 0 1 2.2-2.2h8.8V4.8l4.2 3.4-4.2 3.4V9.4H7z', '#f2f5fa', '#9aa4b8'),
|
||||
flat('M21 13v2a3 3 0 0 1-3 3h-8v3.4L3.6 16.2 10 11v3.4h7v-1.4z', EDGE.gray), gel('M19.8 13.8v1a2.2 2.2 0 0 1-2.2 2.2H8.8v2.2l-4.2-3.4 4.2-3.4v2h8z', '#f2f5fa', '#9aa4b8'),
|
||||
),
|
||||
repostOn: glyph(
|
||||
flat('M3 11V9a3 3 0 0 1 3-3h8V2.6l6.4 5.2-6.4 5.2V9.6H7v1.4z', EDGE.green), gel('M4.2 10.2V9.2a2.2 2.2 0 0 1 2.2-2.2h8.8V4.8l4.2 3.4-4.2 3.4V9.4H7z', '#d6ffb8', '#38b52a'),
|
||||
flat('M21 13v2a3 3 0 0 1-3 3h-8v3.4L3.6 16.2 10 11v3.4h7v-1.4z', EDGE.green), gel('M19.8 13.8v1a2.2 2.2 0 0 1-2.2 2.2H8.8v2.2l-4.2-3.4 4.2-3.4v2h8z', '#d6ffb8', '#38b52a'),
|
||||
sheen(rr(6, 7.2, 8, 1.2, 0.6), 0.6),
|
||||
),
|
||||
heart: glyph(
|
||||
flat('M12 22.4L2.4 12.8A6 6 0 0 1 12 5.4a6 6 0 0 1 9.6 7.4z', '#8a5568'), gel('M12 20.8L3.8 12.6A4.6 4.6 0 0 1 12 6.9a4.6 4.6 0 0 1 8.2 5.7z', '#fff0f6', '#f0a6c4'), sheen(ell(8, 9.4, 2.6, 1.5), 0.7),
|
||||
),
|
||||
heartOn: glyph(
|
||||
flat('M12 22.4L2.4 12.8A6 6 0 0 1 12 5.4a6 6 0 0 1 9.6 7.4z', '#7a0f2c'), gel('M12 20.8L3.8 12.6A4.6 4.6 0 0 1 12 6.9a4.6 4.6 0 0 1 8.2 5.7z', '#ff8fb0', '#d4123f'), sheen(ell(8, 9.4, 2.6, 1.5), 0.6),
|
||||
),
|
||||
views: glyph(
|
||||
flat(rr(2.2, 13, 5.2, 8.8, 1), EDGE.blue), gel(rr(3, 13.8, 3.6, 7.2, 0.5), ...BLUE),
|
||||
flat(rr(9.4, 4.6, 5.2, 17.2, 1), EDGE.green), gel(rr(10.2, 5.4, 3.6, 15.6, 0.5), ...GREEN),
|
||||
flat(rr(16.6, 9, 5.2, 12.8, 1), EDGE.red), gel(rr(17.4, 9.8, 3.6, 11.2, 0.5), ...RED),
|
||||
),
|
||||
share: glyph(
|
||||
flat(poly([12, 1.6], [19, 8.8], [14.4, 8.8], [14.4, 15.4], [9.6, 15.4], [9.6, 8.8], [5, 8.8]), EDGE.green), gel(poly([12, 3.8], [16.4, 8], [13.2, 8], [13.2, 14.2], [10.8, 14.2], [10.8, 8], [7.6, 8]), ...GREEN),
|
||||
flat(rr(2.6, 13.4, 18.8, 8.2, 1.4), EDGE.gray), gel(rr(3.6, 14.4, 16.8, 6.2, 0.8), '#f4f7fc', '#b8c6e0'),
|
||||
),
|
||||
bookmark: glyph(
|
||||
flat('M6 2h12a1.4 1.4 0 0 1 1.4 1.4V22.2L12 16.8 4.6 22.2V3.4A1.4 1.4 0 0 1 6 2z', EDGE.blue), gel('M6.2 3.2h11.6v15.8L12 14.8 6.2 19z', '#e8f2ff', '#8ab6f4'), sheen(rr(6.6, 3.6, 10.8, 3.4, 0.5), 0.5),
|
||||
),
|
||||
bookmarkOn: glyph(
|
||||
flat('M6 2h12a1.4 1.4 0 0 1 1.4 1.4V22.2L12 16.8 4.6 22.2V3.4A1.4 1.4 0 0 1 6 2z', EDGE.blue), gel('M6.2 3.2h11.6v15.8L12 14.8 6.2 19z', '#8fc0ff', '#1f55c4'), sheen(rr(6.6, 3.6, 10.8, 3.4, 0.5), 0.45),
|
||||
),
|
||||
back: glyph(
|
||||
flat(circ(12, 12, 10.6), '#0f4a12'), gel(circ(12, 12, 9.6), '#a6ec8a', '#2b9a28'), flat(poly([5.6, 12], [11.6, 6.2], [11.6, 9.6], [18.4, 9.6], [18.4, 14.4], [11.6, 14.4], [11.6, 17.8]), '#ffffff'), sheen(ell(12, 6.6, 7, 3.4), 0.4),
|
||||
),
|
||||
close: glyph(
|
||||
flat(rr(2, 2, 20, 20, 3.4), '#ffffff'), gel(rr(3, 3, 18, 18, 2.6), '#f6a58f', '#d2301a'), flat(bar(7.6, 7.6, 16.4, 16.4, 2.6), '#ffffff'), flat(bar(16.4, 7.6, 7.6, 16.4, 2.6), '#ffffff'), sheen(rr(3.8, 3.8, 16.4, 6.4, 1.8), 0.35),
|
||||
),
|
||||
media: glyph(
|
||||
flat(rr(1.6, 3.6, 20.8, 16.8, 1.6), EDGE.gray), gel(rr(2.6, 4.6, 18.8, 14.8, 0.8), '#b8e0ff', '#5aa8f0'),
|
||||
flat('M2.6 19.4V15l5.6-5 5.2 4.4 3-2.4 4.8 4.4v3z', '#2f8a2a'), flat(circ(16.6, 8.6, 2), '#ffd84a'), sheen(rr(3.2, 5.2, 17.6, 4, 0.6), 0.3),
|
||||
),
|
||||
gif: glyph(
|
||||
flat(rr(1.6, 5, 20.8, 14, 2.4), EDGE.blue), gel(rr(2.6, 6, 18.8, 12, 1.6), '#8fc0ff', '#2563d6'),
|
||||
// "GIF" in block letters, legible at 16px (G: top, side, foot, the hook in; I; F: stem, top, bar).
|
||||
flat([rr(4.6, 8.4, 4.8, 1.6, 0.3), rr(4.6, 8.4, 1.6, 7.2, 0.3), rr(4.6, 14, 4.8, 1.6, 0.3), rr(7.8, 11.6, 1.6, 4, 0.3), rr(7, 11.6, 2.4, 1.4, 0.3),
|
||||
rr(11.2, 8.4, 1.6, 7.2, 0.3), rr(14.4, 8.4, 1.6, 7.2, 0.3), rr(14.4, 8.4, 5, 1.6, 0.3), rr(14.4, 11.4, 3.8, 1.4, 0.3)].join(''), '#ffffff'),
|
||||
sheen(rr(3, 6.4, 18, 4, 1.2), 0.3),
|
||||
),
|
||||
poll: glyph(
|
||||
flat(rr(2, 2.6, 20, 18.8, 1.6), EDGE.gray), gel(rr(3, 3.6, 18, 16.8, 0.8), ...PAPER),
|
||||
flat(rr(5, 6.2, 12, 2.4, 1.2), '#2563d6'), flat(rr(5, 10.8, 8, 2.4, 1.2), '#2f9e2b'), flat(rr(5, 15.4, 5, 2.4, 1.2), '#d2301a'),
|
||||
),
|
||||
smile: glyph(
|
||||
flat(circ(12, 12, 10.6), '#7a5410'), gel(circ(12, 12, 9.6), '#fff3a0', '#f2b81a'), flat(ell(8.6, 9.6, 1.2, 1.8), '#3a2a08'), flat(ell(15.4, 9.6, 1.2, 1.8), '#3a2a08'),
|
||||
flat('M6.4 14a6.4 6.4 0 0 0 11.2 0z', '#3a2a08'), sheen(ell(10.4, 6, 5, 2.6), 0.55),
|
||||
),
|
||||
clock: glyph(
|
||||
flat(circ(12, 12, 10.6), EDGE.blue), gel(circ(12, 12, 9.4), '#ffffff', '#cfdcf4'), flat(bar(12, 12, 12, 5.4, 1.8), '#143c8c'), flat(bar(12, 12, 16.6, 14.8, 1.8), '#143c8c'), flat(circ(12, 12, 1.4), '#d2301a'),
|
||||
sheen(ell(10.4, 6, 5, 2.2), 0.5),
|
||||
),
|
||||
pin: glyph(
|
||||
flat('M12 22.6C8 17.6 4.8 14 4.8 9.8a7.2 7.2 0 0 1 14.4 0c0 4.2-3.2 7.8-7.2 12.8z', EDGE.red), gel('M12 20.6C9 16.8 6.2 13.6 6.2 9.8a5.8 5.8 0 0 1 11.6 0c0 3.8-2.8 7-5.8 10.8z', ...RED),
|
||||
flat(circ(12, 9.8, 2.4), '#ffffff'), sheen(ell(9.6, 6.6, 2, 1.8), 0.6),
|
||||
),
|
||||
lock: glyph(
|
||||
flat('M7 10.4V7.6a5 5 0 0 1 10 0v2.8h-2.4V7.6a2.6 2.6 0 0 0-5.2 0v2.8z', '#4a4f5c'),
|
||||
flat(rr(3.6, 10, 16.8, 12, 2), EDGE.gold), gel(rr(4.6, 11, 14.8, 10, 1.2), ...GOLD), flat(circ(12, 15.2, 1.8), '#5a3a08'), flat(rr(11.2, 15.4, 1.6, 3.6, 0.8), '#5a3a08'), sheen(rr(5, 11.4, 14, 3.4, 1), 0.45),
|
||||
),
|
||||
verified: glyph(
|
||||
flat(star(12, 12, 11.4, 9.4, 9), '#10408f'), gel(circ(12, 12, 8.6), '#8fc4ff', '#1f6fe0'), flat('M7.4 12.2l3.2 3.2 6-6.6-1.6-1.5-4.4 4.9-1.6-1.6z', '#ffffff'), sheen(ell(10.4, 7.4, 4.4, 2.2), 0.45),
|
||||
),
|
||||
gear: glyph(
|
||||
flat(star(12, 12, 11.4, 9, 8), EDGE.gray), gel(circ(12, 12, 8.6), '#f4f7fc', '#a6b4cf'), flat(circ(12, 12, 3.6), EDGE.gray), gel(circ(12, 12, 2.6), '#ffffff', '#c8d4ea'),
|
||||
),
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
|
||||
type Names = Partial<Record<IconName, IconGlyph>>;
|
||||
const px = (key: keyof typeof ART98) => rasterGlyph(key, ART98[key]!);
|
||||
const G98: Names = {
|
||||
home: px('home'), 'home.active': px('home'), explore: px('search'), 'explore.active': px('search'), notifications: px('bell'), 'notifications.active': px('bell'),
|
||||
messages: px('mail'), 'messages.active': px('mail'), grok: px('monitor'), bookmarks: px('folder'), 'bookmarks.active': px('folder'), lists: px('notepad'), communities: px('people'),
|
||||
premium: px('badge'), profile: px('person'), 'profile.active': px('person'), more: px('dots'), compose: px('pencil'),
|
||||
reply: px('balloon'), repost: px('arrows'), 'repost.on': px('arrowsOn'), like: px('heart'), 'like.on': px('heartOn'), views: px('bars'),
|
||||
bookmark: px('bookmark'), 'bookmark.on': px('bookmarkOn'), share: px('share'), verified: px('check'), back: px('back'), close: px('close'), search: px('search'), settings: px('gear'),
|
||||
media: px('picture'), gif: px('gif'), poll: px('poll'), emoji: px('smile'), schedule: px('clock'), location: px('pin'), lock: px('lock'),
|
||||
};
|
||||
const GXP: Names = {
|
||||
home: XP.home!, 'home.active': XP.home!, explore: XP.explore!, 'explore.active': XP.explore!, notifications: XP.bell!, 'notifications.active': XP.bell!,
|
||||
messages: XP.messages!, 'messages.active': XP.messages!, grok: XP.grok!, bookmarks: XP.folder!, 'bookmarks.active': XP.folder!, lists: XP.lists!, communities: XP.people!,
|
||||
premium: XP.star!, profile: XP.person!, 'profile.active': XP.person!, more: XP.more!, compose: XP.compose!,
|
||||
reply: XP.reply!, repost: XP.repost!, 'repost.on': XP.repostOn!, like: XP.heart!, 'like.on': XP.heartOn!, views: XP.views!,
|
||||
bookmark: XP.bookmark!, 'bookmark.on': XP.bookmarkOn!, share: XP.share!, verified: XP.verified!, back: XP.back!, close: XP.close!, search: XP.explore!, settings: XP.gear!,
|
||||
media: XP.media!, gif: XP.gif!, poll: XP.poll!, emoji: XP.smile!, schedule: XP.clock!, location: XP.pin!, lock: XP.lock!,
|
||||
};
|
||||
|
||||
const OWN = { author: 'wayBetter for X', license: 'own', source: 'drawn for wayBetter for X; no asset is taken from Windows or from any icon archive', credits: 'wayBetter for X contributors' };
|
||||
const documents = [
|
||||
{
|
||||
id: 'retro-98', name: 'Retro 98', description: 'Sixteen-pixel desktop icons in the sixteen-color palette of 1998: black outlines, silver, navy and teal. Every icon of the left navigation and the action bar.',
|
||||
...OWN, style: { stroke: 1.75, cap: 'square', join: 'miter', scale: 1 }, glyphs: G98,
|
||||
},
|
||||
{
|
||||
id: 'retro-xp', name: 'Retro XP', description: 'Glossy gel icons in the manner of 2001: a dark edge, a lit top, bright blue, green and gold. Every icon of the left navigation and the action bar.',
|
||||
...OWN, style: { stroke: 1.75, cap: 'round', join: 'round', scale: 1 }, glyphs: GXP,
|
||||
},
|
||||
];
|
||||
|
||||
/** The retro packs, validated like any imported pack. */
|
||||
export const RETRO_PACKS: IconPack[] = documents.map(doc => {
|
||||
const pack = sanitizeIconPack(doc);
|
||||
if (!pack) throw new Error(`retro icon pack ${doc.id} is not valid`);
|
||||
const wanted = Object.keys(doc.glyphs).length;
|
||||
if (Object.keys(pack.glyphs).length !== wanted) throw new Error(`retro icon pack ${doc.id}: ${wanted - Object.keys(pack.glyphs).length} glyph(s) were refused by the sanitizer`);
|
||||
return pack;
|
||||
});
|
||||
|
||||
/** A retro pack as the JSON document it is published as (`<id>.icons.json`). */
|
||||
export const retroDocument = (id: string) => {
|
||||
const pack = RETRO_PACKS.find(item => item.id === id);
|
||||
return pack ? { $schema: 'https://unpkg.com/waybetter/icons.schema.json', ...pack } : null;
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue