Skip to content

Commit f527660

Browse files
authored
Update accessibility
Update colors page, add instructions for texture implementation, add cusy font-faces
2 parents b674412 + 63ef4b8 commit f527660

File tree

89 files changed

+133944
-77
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

89 files changed

+133944
-77
lines changed

docs/_static/colorTooltips.js

Lines changed: 337 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,337 @@
1+
function rgbToHSV(r, g, b) {
2+
const r_ = r / 255;
3+
const g_ = g / 255;
4+
const b_ = b / 255;
5+
6+
const cMax = Math.max(r_, g_, b_);
7+
const cMin = Math.min(r_, g_, b_);
8+
const delta = cMax - cMin;
9+
10+
let hue = 0;
11+
if (delta !== 0) {
12+
if (cMax === r_) {
13+
hue = 60 * (((g_ - b_) / delta) + (g_ < b_ ? 6 : 0))
14+
} else if (cMax === g_) {
15+
hue = 60 * ((b_ - r_) / delta + 2)
16+
} else {
17+
hue = 60 * ((r_ - g_) / delta + 4)
18+
}
19+
}
20+
21+
const saturation = cMax === 0 ? 0 : (delta / cMax) * 100;
22+
23+
const value = cMax * 100;
24+
25+
return [Math.round(hue), Math.round(saturation), Math.round(value)];
26+
}
27+
28+
function calculateVividness(r, g, b) {
29+
const hsv = rgbToHSV(r, g, b);
30+
return (hsv[1] * hsv[2] / 100).toFixed(1);
31+
}
32+
33+
function rgbToLuminance(r, g, b) {
34+
r /= 255;
35+
g /= 255;
36+
b /= 255;
37+
r <= 0.04045 ? r = r / 12.92 : r = Math.pow((r + 0.055) / 1.055, 2.4);
38+
g <= 0.04045 ? g = g / 12.92 : g = Math.pow((g + 0.055) / 1.055, 2.4);
39+
b <= 0.04045 ? b = b / 12.92 : b = Math.pow((b + 0.055) / 1.055, 2.4);
40+
return 0.2126 * r + 0.7152 * g + 0.0722 * b;
41+
}
42+
function luminanceToContrast(l1, l2) {
43+
return (Math.max(l1, l2) + 0.05) / (Math.min(l1, l2) + 0.05);
44+
}
45+
function rgbToWhiteContrast(r, g, b) {
46+
return luminanceToContrast(rgbToLuminance(r, g, b), 1).toPrecision(2);
47+
}
48+
function rgbToBlackContrast(r, g, b) {
49+
return luminanceToContrast(rgbToLuminance(r, g, b), 0).toPrecision(2);
50+
}
51+
52+
function rgbToHexCode(r, g, b) {
53+
r = Number(r).toString(16)
54+
r.length == 1 ? r = "0" + r : r
55+
g = Number(g).toString(16)
56+
g.length == 1 ? g = "0" + g : g
57+
b = Number(b).toString(16)
58+
b.length == 1 ? b = "0" + b : b
59+
return "#" + r + g + b;
60+
}
61+
62+
function rgbToCMYK(r,g,b){
63+
r /= 255;
64+
g /= 255;
65+
b /= 255;
66+
67+
const k = 1-Math.max(r,g,b);
68+
const c = Math.round(((1-r-k)/(1-k))*100);
69+
const m = Math.round(((1-g-k)/(1-k))*100);
70+
const y = Math.round(((1-b-k)/(1-k))*100);
71+
72+
return [c,m,y,Math.round(k*100)];
73+
}
74+
75+
const CSS_UNIT = "px";
76+
const HEIGHT_OFFSET = 160;
77+
const svg = document.querySelector('svg');
78+
const svgRect = svg.getBoundingClientRect();
79+
80+
const copySVG = `
81+
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-copy" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="#000000" fill="none" stroke-linecap="round" stroke-linejoin="round">
82+
<title>Copy to clipboard</title>
83+
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
84+
<rect x="8" y="8" width="12" height="12" rx="2"></rect>
85+
<path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path>
86+
</svg>
87+
`
88+
const copyAllSVG = `
89+
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-copy all" width="70" height="16" viewBox="0 0 70 16" fill="none" stroke-linecap="round" stroke-linejoin="round">
90+
<title>Copy all to clipboard</title>
91+
<text x="2" y="12" stroke-width="0.3" font-size="10" style="font-weight='100'; font-family='SegoeUI', 'Segoe UI'">Copy all</text>
92+
<g transform="scale(0.75 0.75) translate(26 6)" stroke-width="1.5">
93+
<rect x="40" y="2" width="12" height="12" rx="2"></rect>
94+
<path d="M48 2v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path>
95+
</g>
96+
</svg>`;
97+
98+
const checkSVG = `
99+
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-check" width="24" height="24" viewBox="0 0 24 24" stroke-width="1.5" stroke="#28a745" fill="none" stroke-linecap="round" stroke-linejoin="round">
100+
<title>Copied!</title>
101+
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
102+
<path d="M5 12l5 5l10 -10"></path>
103+
</svg>`;
104+
105+
const checkAllSVG = `
106+
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-check all" width="70" height="16" viewBox="0 0 70 16" fill="none" stroke-linecap="round" stroke-linejoin="round">
107+
<title>Copied!</title>
108+
<text y="12" font-size="10" style="font-weight='200'; font-family='SegoeUI', 'Segoe UI'">All copied</text>
109+
<g transform="scale(0.75 0.75) translate(58 0)" stroke-width="1.5" stroke="#28a745">
110+
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
111+
<path d="M5 12l5 5l10 -10" stroke-width="1.5"></path>
112+
</g>
113+
</svg>`;
114+
115+
function copyToClipboard(text, button) {
116+
navigator.clipboard.writeText(text).then(() => {
117+
button.innerHTML = checkSVG;
118+
119+
setTimeout(() => {
120+
button.innerHTML = copySVG;
121+
}, 2000);
122+
}).catch((err) => {
123+
console.error('Failed to copy text: ', err);
124+
});
125+
}
126+
function copyAllToClipboard(text, button) {
127+
navigator.clipboard.writeText(text).then(() => {
128+
button.innerHTML = checkAllSVG;
129+
130+
setTimeout(() => {
131+
button.innerHTML = copyAllSVG;
132+
}, 2000);
133+
}).catch((err) => {
134+
console.error('Failed to copy text: ', err);
135+
});
136+
}
137+
138+
139+
function addCircleHints() {
140+
const circles = document.querySelectorAll("circle");
141+
const nameDiv = document.getElementById("name");
142+
let activeCircle = null;
143+
let tooltip = null;
144+
145+
function hideTooltip() {
146+
nameDiv.style.opacity = 0;
147+
nameDiv.innerHTML = null;
148+
activeCircle = null;
149+
}
150+
151+
function showTooltip(circle, r, g, b) {
152+
153+
const colorInfo = [
154+
`Hex: ${rgbToHexCode(r, g, b)}`,
155+
`RGB: ${r}, ${g}, ${b}`,
156+
`HSV: ${rgbToHSV(r, g, b).join(', ')}`,
157+
`CMYK: ${rgbToCMYK(r, g, b).join(', ')}`,
158+
`Vividness: ${calculateVividness(r, g, b)}`,
159+
`Kontrast weiß: ${rgbToWhiteContrast(r, g, b)}`,
160+
`Kontrast schwarz: ${rgbToBlackContrast(r, g, b)}`
161+
];
162+
163+
let pantoneSet = false;
164+
if (circle.parentElement.hasAttribute('serif:id')) {
165+
let serifs = circle.parentElement.getAttribute('serif:id');
166+
if(serifs.includes("Pantone")) {
167+
colorInfo.push(serifs.split("|")[1]);
168+
pantoneSet = true;
169+
}
170+
colorInfo.unshift(serifs.split("|")[0]);
171+
}
172+
173+
const circleBBox = circle.getBoundingClientRect();
174+
const circleX = circleBBox.left + svgRect.left + (circleBBox.width / 2);
175+
const circleY = circleBBox.top + svgRect.top + window.scrollY;
176+
177+
nameDiv.style.left = (circleX - 85) + 'px';
178+
nameDiv.style.top = pantoneSet ? (circleY - HEIGHT_OFFSET - 35) + 'px' : (circleY - HEIGHT_OFFSET - 15) + 'px';
179+
180+
const tooltipContent = colorInfo.map((info, index) => {
181+
if (index === 0) {
182+
return `<div>${info} <button class="all copy-all-button">${copyAllSVG}</button></div>`;
183+
}
184+
return `<div>${info} <button class="copy-button">${copySVG}</button></div>`;
185+
}).join("");
186+
187+
nameDiv.innerHTML = tooltipContent;
188+
document.querySelector(".copy-all-button").addEventListener("click", function () {
189+
copyAllToClipboard(colorInfo.join("\n"), this);
190+
});
191+
192+
document.querySelectorAll(".copy-button").forEach((button, index) => {
193+
button.addEventListener("click", function () {
194+
copyToClipboard(colorInfo[index], this);
195+
});
196+
});
197+
198+
nameDiv.style.opacity = 1;
199+
nameDiv.style.borderColor = `rgb(${r},${g},${b})`;
200+
201+
activeCircle = circle;
202+
tooltip = document.getElementById("name");
203+
}
204+
205+
document.addEventListener('click', (event) => {
206+
if (activeCircle && !activeCircle.contains(event.target) && !tooltip.contains(event.target)) {
207+
hideTooltip();
208+
}
209+
});
210+
211+
for (let i = 0; i < circles.length; i++) {
212+
const circle = circles[i];
213+
const style = circle.getAttribute('style');
214+
215+
if (style) {
216+
const colorMatch = style.match(/fill:rgb\((\d+),(\d+),(\d+)\)/);
217+
if (colorMatch) {
218+
219+
const [_, r, g, b] = colorMatch;
220+
221+
circle.addEventListener("click", (event) => {
222+
event.stopPropagation();
223+
224+
if (activeCircle === circle && !tooltip.contains(event.target)) {
225+
hideTooltip();
226+
} else {
227+
showTooltip(circle, r, g, b);
228+
}
229+
});
230+
}
231+
} else {
232+
if(!circle.hasAttribute('id'))
233+
circle.setAttribute('id', `circle_${i}`);
234+
}
235+
}
236+
}
237+
addCircleHints();
238+
239+
function addSquareHints() {
240+
const squares = document.querySelectorAll("rect");
241+
const nameDiv = document.getElementById("name");
242+
let activeSquare = null;
243+
let tooltip = null;
244+
245+
function hideTooltip() {
246+
nameDiv.style.opacity = 0;
247+
nameDiv.innerHTML = null;
248+
activeSquare = null;
249+
}
250+
251+
function showTooltip(square, r, g, b) {
252+
253+
const colorInfo = [
254+
`Hex: ${rgbToHexCode(r, g, b)}`,
255+
`RGB: ${r}, ${g}, ${b}`,
256+
`HSV: ${rgbToHSV(r, g, b).join(', ')}`,
257+
`CMYK: ${rgbToCMYK(r, g, b).join(', ')}`,
258+
`Vividness: ${calculateVividness(r, g, b)}`,
259+
`Kontrast weiß: ${rgbToWhiteContrast(r, g, b)}`,
260+
`Kontrast schwarz: ${rgbToBlackContrast(r, g, b)}`
261+
];
262+
263+
let pantoneSet = false;
264+
if (square.parentElement.hasAttribute('serif:id')) {
265+
let serifs = square.parentElement.getAttribute('serif:id');
266+
if(serifs.includes("Pantone")) {
267+
colorInfo.push(serifs.split("|")[1]);
268+
pantoneSet = true;
269+
}
270+
colorInfo.unshift(serifs.split("|")[0]);
271+
}
272+
273+
const squareBBox = square.getBoundingClientRect();
274+
const squareX = squareBBox.left + svgRect.left + (squareBBox.width / 2);
275+
const squareY = squareBBox.top + svgRect.top + window.scrollY;
276+
277+
nameDiv.style.left = (squareX - 85) + 'px';
278+
nameDiv.style.top = pantoneSet ? (squareY - HEIGHT_OFFSET - 20) + 'px' : (squareY - HEIGHT_OFFSET) + 'px';
279+
280+
const tooltipContent = colorInfo.map((info, index) => {
281+
if (index === 0) {
282+
return `<div>${info} <button class="all copy-all-button">${copyAllSVG}</button></div>`;
283+
}
284+
return `<div>${info} <button class="copy-button">${copySVG}</button></div>`;
285+
}).join("");
286+
287+
nameDiv.innerHTML = tooltipContent;
288+
document.querySelector(".copy-all-button").addEventListener("click", function () {
289+
copyAllToClipboard(colorInfo.join("\n"), this);
290+
});
291+
292+
document.querySelectorAll(".copy-button").forEach((button, index) => {
293+
button.addEventListener("click", function () {
294+
copyToClipboard(colorInfo[index], this);
295+
});
296+
});
297+
298+
nameDiv.style.opacity = 1;
299+
nameDiv.style.borderColor = `rgb(${r},${g},${b})`;
300+
301+
activeSquare = square;
302+
tooltip = document.getElementById("name");
303+
}
304+
305+
document.addEventListener('click', (event) => {
306+
if (activeSquare && !activeSquare.contains(event.target) && !tooltip.contains(event.target)) {
307+
hideTooltip();
308+
}
309+
});
310+
311+
for (let i = 0; i < squares.length; i++) {
312+
const square = squares[i];
313+
const style = square.getAttribute('style');
314+
315+
if (style) {
316+
const colorMatch = style.match(/fill:rgb\((\d+),(\d+),(\d+)\)/);
317+
if (colorMatch) {
318+
319+
const [_, r, g, b] = colorMatch;
320+
321+
square.addEventListener("click", (event) => {
322+
event.stopPropagation();
323+
324+
if (activeSquare === square && !tooltip.contains(event.target)) {
325+
hideTooltip();
326+
} else {
327+
showTooltip(square, r, g, b);
328+
}
329+
});
330+
}
331+
} else {
332+
if(!square.hasAttribute('id'))
333+
square.setAttribute('id', `square_${i}`);
334+
}
335+
}
336+
}
337+
addSquareHints();

0 commit comments

Comments
 (0)