mirror of
https://github.com/felixfoertsch/EurKEY-macOS.git
synced 2026-04-17 23:18:28 +02:00
replace dead key panel with inline keyboard compositions
clicking a dead key or pressing its key combo (e.g. Option+M) now shows compositions directly on the keyboard. keys with compositions are highlighted, others dimmed. spacebar shows catchy group name. click the active dead key again or press Escape to exit. add helper text beneath keyboard explaining viewer interaction. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -41,11 +41,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<figure class="keyboard" id="keyboard"></figure>
|
<figure class="keyboard" id="keyboard"></figure>
|
||||||
<div class="dead-key-panel" id="dead-key-panel" hidden>
|
<p class="keyboard-hint">Hold <kbd>Shift</kbd> or <kbd>Option</kbd> to preview modifier layers. Click a yellow dead key to see its compositions. Press <kbd>Esc</kbd> to go back.</p>
|
||||||
<button class="dead-key-close" id="dead-key-close" aria-label="Close">×</button>
|
|
||||||
<h4 id="dead-key-title"></h4>
|
|
||||||
<div class="dead-key-grid" id="dead-key-grid"></div>
|
|
||||||
</div>
|
|
||||||
<div class="layout-pdf-links">
|
<div class="layout-pdf-links">
|
||||||
<a href="pdf/eurkey-v2.0-layout.pdf" id="pdf-download" class="btn btn--secondary">Download v2.0 PDF</a>
|
<a href="pdf/eurkey-v2.0-layout.pdf" id="pdf-download" class="btn btn--secondary">Download v2.0 PDF</a>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -5,29 +5,29 @@ const KEYBOARD_ROWS = [
|
|||||||
[10, 1.0, "§"], [18, 1.0, "1"], [19, 1.0, "2"], [20, 1.0, "3"],
|
[10, 1.0, "§"], [18, 1.0, "1"], [19, 1.0, "2"], [20, 1.0, "3"],
|
||||||
[21, 1.0, "4"], [23, 1.0, "5"], [22, 1.0, "6"], [26, 1.0, "7"],
|
[21, 1.0, "4"], [23, 1.0, "5"], [22, 1.0, "6"], [26, 1.0, "7"],
|
||||||
[28, 1.0, "8"], [25, 1.0, "9"], [29, 1.0, "0"], [27, 1.0, "-"],
|
[28, 1.0, "8"], [25, 1.0, "9"], [29, 1.0, "0"], [27, 1.0, "-"],
|
||||||
[24, 1.0, "="], [null, 1.5, "⌫"],
|
[24, 1.0, "="], [null, 1.5, "\u232b"],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
[null, 1.5, "⇥"], [12, 1.0, "Q"], [13, 1.0, "W"], [14, 1.0, "E"],
|
[null, 1.5, "\u21e5"], [12, 1.0, "Q"], [13, 1.0, "W"], [14, 1.0, "E"],
|
||||||
[15, 1.0, "R"], [17, 1.0, "T"], [16, 1.0, "Y"], [32, 1.0, "U"],
|
[15, 1.0, "R"], [17, 1.0, "T"], [16, 1.0, "Y"], [32, 1.0, "U"],
|
||||||
[34, 1.0, "I"], [31, 1.0, "O"], [35, 1.0, "P"], [33, 1.0, "["],
|
[34, 1.0, "I"], [31, 1.0, "O"], [35, 1.0, "P"], [33, 1.0, "["],
|
||||||
[30, 1.0, "]"], ["spacer", 1.0, ""],
|
[30, 1.0, "]"], ["spacer", 1.0, ""],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
[null, 1.75, "⇪"], [0, 1.0, "A"], [1, 1.0, "S"], [2, 1.0, "D"],
|
[null, 1.75, "\u21ea"], [0, 1.0, "A"], [1, 1.0, "S"], [2, 1.0, "D"],
|
||||||
[3, 1.0, "F"], [5, 1.0, "G"], [4, 1.0, "H"], [38, 1.0, "J"],
|
[3, 1.0, "F"], [5, 1.0, "G"], [4, 1.0, "H"], [38, 1.0, "J"],
|
||||||
[40, 1.0, "K"], [37, 1.0, "L"], [41, 1.0, ";"], [39, 1.0, "'"],
|
[40, 1.0, "K"], [37, 1.0, "L"], [41, 1.0, ";"], [39, 1.0, "'"],
|
||||||
[42, 1.0, "\\"], ["enter", 0.75, "⏎"],
|
[42, 1.0, "\\"], ["enter", 0.75, "\u23ce"],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
[null, 1.25, "⇧"], [50, 1.0, "`"], [6, 1.0, "Z"], [7, 1.0, "X"],
|
[null, 1.25, "\u21e7"], [50, 1.0, "`"], [6, 1.0, "Z"], [7, 1.0, "X"],
|
||||||
[8, 1.0, "C"], [9, 1.0, "V"], [11, 1.0, "B"], [45, 1.0, "N"],
|
[8, 1.0, "C"], [9, 1.0, "V"], [11, 1.0, "B"], [45, 1.0, "N"],
|
||||||
[46, 1.0, "M"], [43, 1.0, ","], [47, 1.0, "."], [44, 1.0, "/"],
|
[46, 1.0, "M"], [43, 1.0, ","], [47, 1.0, "."], [44, 1.0, "/"],
|
||||||
[null, 2.25, "⇧"],
|
[null, 2.25, "\u21e7"],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
[null, 1.0, "fn"], [null, 1.0, "⌃"], [null, 1.0, "⌥"], [null, 1.25, "⌘"],
|
[null, 1.0, "fn"], [null, 1.0, "\u2303"], [null, 1.0, "\u2325"], [null, 1.25, "\u2318"],
|
||||||
[null, 5.0, ""], [null, 1.25, "⌘"], [null, 1.0, "⌥"],
|
["spacebar", 5.0, ""], [null, 1.25, "\u2318"], [null, 1.0, "\u2325"],
|
||||||
["arrow-cluster", 3.0, ""],
|
["arrow-cluster", 3.0, ""],
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
@@ -46,9 +46,31 @@ const LAYERS = [
|
|||||||
|
|
||||||
const MOD_LABELS = { "\u21e7": "shift", "\u2325": "option" };
|
const MOD_LABELS = { "\u21e7": "shift", "\u2325": "option" };
|
||||||
|
|
||||||
|
/* Browser keyCode → macOS key code mapping (US/ISO QWERTY) */
|
||||||
|
const BROWSER_TO_MAC = {
|
||||||
|
65: 0, 83: 1, 68: 2, 70: 3, 72: 4, 71: 5, 90: 6, 88: 7,
|
||||||
|
67: 8, 86: 9, 192: 50, 66: 11, 81: 12, 87: 13, 69: 14, 82: 15,
|
||||||
|
89: 16, 84: 17, 49: 18, 50: 19, 51: 20, 52: 21, 54: 22, 53: 23,
|
||||||
|
187: 24, 57: 25, 55: 26, 189: 27, 56: 28, 48: 29, 221: 30,
|
||||||
|
79: 31, 85: 32, 219: 33, 73: 34, 80: 35, 76: 37, 74: 38,
|
||||||
|
222: 39, 75: 40, 186: 41, 220: 42, 188: 43, 191: 44, 78: 45,
|
||||||
|
77: 46, 190: 47, 191: 44, 171: 24, 173: 27, 61: 24, 59: 41,
|
||||||
|
};
|
||||||
|
|
||||||
|
const DEAD_KEY_NAMES = {
|
||||||
|
"\u00b4": "The Acutes", "`": "The Graves", "^": "The Circumflexes",
|
||||||
|
"~": "The Tildes", "\u00a8": "The Umlauts", "\u02c7": "The H\u00e1\u010deks",
|
||||||
|
"\u00af": "The Macrons", "\u02da": "The Rings & Dots",
|
||||||
|
"\u03b1": "The Greeks", "\u221a": "The Mathematicians",
|
||||||
|
"\u00ac": "The Navigators", "\u00a9": "The Navigators",
|
||||||
|
" ": "The Mathematicians",
|
||||||
|
};
|
||||||
|
|
||||||
const cache = new Map();
|
const cache = new Map();
|
||||||
let currentVersion = "v2.0";
|
let currentVersion = "v2.0";
|
||||||
let currentData = null;
|
let currentData = null;
|
||||||
|
let currentDeadKey = null;
|
||||||
|
let keyElements = new Map();
|
||||||
|
|
||||||
async function loadVersion(version) {
|
async function loadVersion(version) {
|
||||||
if (cache.has(version)) return cache.get(version);
|
if (cache.has(version)) return cache.get(version);
|
||||||
@@ -81,9 +103,27 @@ function clearElement(el) {
|
|||||||
while (el.firstChild) el.removeChild(el.firstChild);
|
while (el.firstChild) el.removeChild(el.firstChild);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* --- Build composition lookup for a dead key --- */
|
||||||
|
|
||||||
|
function buildCompositionMap(data, deadState) {
|
||||||
|
const dk = data.deadKeys[deadState];
|
||||||
|
if (!dk || !dk.compositions) return null;
|
||||||
|
|
||||||
|
const charMap = {};
|
||||||
|
for (const [actionId, composed] of Object.entries(dk.compositions)) {
|
||||||
|
const action = data.actions[actionId];
|
||||||
|
const base = action?.none || actionId;
|
||||||
|
if (base) charMap[base] = composed;
|
||||||
|
}
|
||||||
|
return charMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- Render keyboard --- */
|
||||||
|
|
||||||
function renderKeyboard(data) {
|
function renderKeyboard(data) {
|
||||||
const kb = document.getElementById("keyboard");
|
const kb = document.getElementById("keyboard");
|
||||||
clearElement(kb);
|
clearElement(kb);
|
||||||
|
keyElements.clear();
|
||||||
|
|
||||||
for (const row of KEYBOARD_ROWS) {
|
for (const row of KEYBOARD_ROWS) {
|
||||||
const rowEl = document.createElement("div");
|
const rowEl = document.createElement("div");
|
||||||
@@ -113,15 +153,21 @@ function renderKeyboard(data) {
|
|||||||
spacerL.className = "arrow-key arrow-key--spacer";
|
spacerL.className = "arrow-key arrow-key--spacer";
|
||||||
const spacerR = document.createElement("div");
|
const spacerR = document.createElement("div");
|
||||||
spacerR.className = "arrow-key arrow-key--spacer";
|
spacerR.className = "arrow-key arrow-key--spacer";
|
||||||
topRow.append(spacerL, makeArrowKey("▲"), spacerR);
|
topRow.append(spacerL, makeArrowKey("\u25b2"), spacerR);
|
||||||
|
|
||||||
const bottomRow = document.createElement("div");
|
const bottomRow = document.createElement("div");
|
||||||
bottomRow.className = "arrow-row";
|
bottomRow.className = "arrow-row";
|
||||||
for (const sym of ["◀", "▼", "▶"]) {
|
for (const sym of ["\u25c0", "\u25bc", "\u25b6"]) {
|
||||||
bottomRow.appendChild(makeArrowKey(sym));
|
bottomRow.appendChild(makeArrowKey(sym));
|
||||||
}
|
}
|
||||||
|
|
||||||
keyEl.append(topRow, bottomRow);
|
keyEl.append(topRow, bottomRow);
|
||||||
|
} else if (keyCode === "spacebar") {
|
||||||
|
keyEl.classList.add("key--mod", "key--spacebar");
|
||||||
|
const span = document.createElement("span");
|
||||||
|
span.className = "key-mod-label";
|
||||||
|
span.textContent = label;
|
||||||
|
keyEl.appendChild(span);
|
||||||
} else if (keyCode === "spacer") {
|
} else if (keyCode === "spacer") {
|
||||||
keyEl.classList.add("key--spacer");
|
keyEl.classList.add("key--spacer");
|
||||||
} else if (keyCode === "enter") {
|
} else if (keyCode === "enter") {
|
||||||
@@ -138,6 +184,8 @@ function renderKeyboard(data) {
|
|||||||
span.textContent = label;
|
span.textContent = label;
|
||||||
keyEl.appendChild(span);
|
keyEl.appendChild(span);
|
||||||
} else {
|
} else {
|
||||||
|
keyElements.set(keyCode, keyEl);
|
||||||
|
|
||||||
let hasDead = false;
|
let hasDead = false;
|
||||||
let deadState = null;
|
let deadState = null;
|
||||||
|
|
||||||
@@ -159,7 +207,7 @@ function renderKeyboard(data) {
|
|||||||
if (hasDead) {
|
if (hasDead) {
|
||||||
keyEl.classList.add("key--dead");
|
keyEl.classList.add("key--dead");
|
||||||
keyEl.dataset.deadKey = deadState;
|
keyEl.dataset.deadKey = deadState;
|
||||||
keyEl.addEventListener("click", () => showDeadKeyPanel(data, deadState));
|
keyEl.addEventListener("click", () => toggleDeadKeyMode(deadState));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,48 +218,92 @@ function renderKeyboard(data) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function showDeadKeyPanel(data, state) {
|
/* --- Dead key mode --- */
|
||||||
const panel = document.getElementById("dead-key-panel");
|
|
||||||
const title = document.getElementById("dead-key-title");
|
|
||||||
const grid = document.getElementById("dead-key-grid");
|
|
||||||
|
|
||||||
const dk = data.deadKeys[state];
|
function toggleDeadKeyMode(deadState) {
|
||||||
if (!dk) return;
|
if (currentDeadKey === deadState) {
|
||||||
|
exitDeadKeyMode();
|
||||||
|
} else {
|
||||||
|
enterDeadKeyMode(deadState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const terminator = dk.terminator || data.terminators[state] || "";
|
function enterDeadKeyMode(deadState) {
|
||||||
title.textContent = state + " \u2192 " + displayChar(terminator);
|
if (!currentData) return;
|
||||||
|
const charMap = buildCompositionMap(currentData, deadState);
|
||||||
|
if (!charMap) return;
|
||||||
|
|
||||||
clearElement(grid);
|
// clean up previous dead key mode if active
|
||||||
const compositions = dk.compositions;
|
if (currentDeadKey) exitDeadKeyMode();
|
||||||
if (!compositions) return;
|
|
||||||
|
|
||||||
for (const [actionId, composed] of Object.entries(compositions)) {
|
currentDeadKey = deadState;
|
||||||
const action = data.actions[actionId];
|
const kb = document.getElementById("keyboard");
|
||||||
const base = action?.none || actionId;
|
kb.classList.add("keyboard--dead-mode");
|
||||||
|
|
||||||
const pair = document.createElement("div");
|
// show catchy name on spacebar
|
||||||
pair.className = "dead-key-pair";
|
const dk = currentData.deadKeys[deadState];
|
||||||
|
const terminator = dk?.terminator || "";
|
||||||
const baseSpan = document.createElement("span");
|
const catchy = DEAD_KEY_NAMES[terminator] || "";
|
||||||
baseSpan.className = "dead-key-base";
|
const spaceBar = kb.querySelector(".key--spacebar");
|
||||||
baseSpan.textContent = displayChar(base);
|
if (spaceBar) {
|
||||||
|
spaceBar.querySelector(".key-mod-label").textContent = catchy;
|
||||||
const arrow = document.createElement("span");
|
spaceBar.classList.add("key--spacebar-label");
|
||||||
arrow.className = "dead-key-arrow";
|
|
||||||
arrow.textContent = "\u2192";
|
|
||||||
|
|
||||||
const composedSpan = document.createElement("span");
|
|
||||||
composedSpan.className = "dead-key-composed";
|
|
||||||
composedSpan.textContent = displayChar(composed);
|
|
||||||
|
|
||||||
pair.appendChild(baseSpan);
|
|
||||||
pair.appendChild(arrow);
|
|
||||||
pair.appendChild(composedSpan);
|
|
||||||
grid.appendChild(pair);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
panel.hidden = false;
|
for (const [keyCode, keyEl] of keyElements) {
|
||||||
panel.scrollIntoView({ behavior: "smooth", block: "nearest" });
|
const codeStr = String(keyCode);
|
||||||
|
const baseKey = currentData.keyMaps[MOD_BASE]?.keys[codeStr];
|
||||||
|
const shiftKey = currentData.keyMaps[MOD_SHIFT]?.keys[codeStr];
|
||||||
|
const baseChar = baseKey?.output || "";
|
||||||
|
const shiftChar = shiftKey?.output || "";
|
||||||
|
|
||||||
|
const baseComposed = charMap[baseChar] || "";
|
||||||
|
const shiftComposed = charMap[shiftChar] || "";
|
||||||
|
|
||||||
|
const spans = keyEl.querySelectorAll(".key-char");
|
||||||
|
// order: shift, shift-option, base, option
|
||||||
|
if (spans[0]) spans[0].textContent = displayChar(shiftComposed);
|
||||||
|
if (spans[1]) spans[1].textContent = "";
|
||||||
|
if (spans[2]) spans[2].textContent = displayChar(baseComposed);
|
||||||
|
if (spans[3]) spans[3].textContent = "";
|
||||||
|
|
||||||
|
if (keyEl.dataset.deadKey === deadState) {
|
||||||
|
keyEl.classList.add("key--dead-active");
|
||||||
|
} else if (baseComposed || shiftComposed) {
|
||||||
|
keyEl.classList.add("key--has-composition");
|
||||||
|
keyEl.classList.remove("key--no-composition");
|
||||||
|
} else {
|
||||||
|
keyEl.classList.add("key--no-composition");
|
||||||
|
keyEl.classList.remove("key--has-composition");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function exitDeadKeyMode() {
|
||||||
|
if (!currentDeadKey || !currentData) return;
|
||||||
|
currentDeadKey = null;
|
||||||
|
|
||||||
|
const kb = document.getElementById("keyboard");
|
||||||
|
kb.classList.remove("keyboard--dead-mode");
|
||||||
|
|
||||||
|
// restore spacebar
|
||||||
|
const spaceBar = kb.querySelector(".key--spacebar");
|
||||||
|
if (spaceBar) {
|
||||||
|
spaceBar.querySelector(".key-mod-label").textContent = "";
|
||||||
|
spaceBar.classList.remove("key--spacebar-label");
|
||||||
|
}
|
||||||
|
|
||||||
|
// restore original characters
|
||||||
|
for (const [keyCode, keyEl] of keyElements) {
|
||||||
|
keyEl.classList.remove("key--has-composition", "key--no-composition", "key--dead-active");
|
||||||
|
|
||||||
|
const spans = keyEl.querySelectorAll(".key-char");
|
||||||
|
const layerOrder = [MOD_SHIFT, MOD_SHIFT_OPTION, MOD_BASE, MOD_OPTION];
|
||||||
|
for (let i = 0; i < spans.length; i++) {
|
||||||
|
const info = charForKey(currentData, layerOrder[i], keyCode);
|
||||||
|
spans[i].textContent = info ? displayChar(info.char) : "";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function showError(msg) {
|
function showError(msg) {
|
||||||
@@ -243,10 +335,39 @@ function updateActiveLayer() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getActiveModIndex() {
|
||||||
|
const shift = activeModifiers.has("shift");
|
||||||
|
const option = activeModifiers.has("option");
|
||||||
|
if (shift && option) return MOD_SHIFT_OPTION;
|
||||||
|
if (shift) return MOD_SHIFT;
|
||||||
|
if (option) return MOD_OPTION;
|
||||||
|
return MOD_BASE;
|
||||||
|
}
|
||||||
|
|
||||||
document.addEventListener("keydown", (e) => {
|
document.addEventListener("keydown", (e) => {
|
||||||
if (e.key === "Shift") activeModifiers.add("shift");
|
if (e.key === "Shift") activeModifiers.add("shift");
|
||||||
if (e.key === "Alt") activeModifiers.add("option");
|
if (e.key === "Alt") activeModifiers.add("option");
|
||||||
updateActiveLayer();
|
updateActiveLayer();
|
||||||
|
|
||||||
|
// detect dead key trigger from physical keyboard
|
||||||
|
if (currentData && !e.metaKey && !e.ctrlKey) {
|
||||||
|
const macCode = BROWSER_TO_MAC[e.keyCode];
|
||||||
|
if (macCode !== undefined) {
|
||||||
|
const modIdx = getActiveModIndex();
|
||||||
|
const keyMap = currentData.keyMaps[modIdx];
|
||||||
|
const keyData = keyMap?.keys[String(macCode)];
|
||||||
|
if (keyData?.deadKey) {
|
||||||
|
e.preventDefault();
|
||||||
|
toggleDeadKeyMode(keyData.deadKey);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Escape exits dead key mode
|
||||||
|
if (e.key === "Escape" && currentDeadKey) {
|
||||||
|
exitDeadKeyMode();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
document.addEventListener("keyup", (e) => {
|
document.addEventListener("keyup", (e) => {
|
||||||
@@ -279,8 +400,8 @@ function initTabs() {
|
|||||||
tabs.forEach(t => t.classList.remove("active"));
|
tabs.forEach(t => t.classList.remove("active"));
|
||||||
tab.classList.add("active");
|
tab.classList.add("active");
|
||||||
currentVersion = version;
|
currentVersion = version;
|
||||||
|
currentDeadKey = null;
|
||||||
|
|
||||||
document.getElementById("dead-key-panel").hidden = true;
|
|
||||||
updatePdfLink();
|
updatePdfLink();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -296,10 +417,6 @@ function initTabs() {
|
|||||||
|
|
||||||
/* --- Init --- */
|
/* --- Init --- */
|
||||||
|
|
||||||
document.getElementById("dead-key-close").addEventListener("click", () => {
|
|
||||||
document.getElementById("dead-key-panel").hidden = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
initTabs();
|
initTabs();
|
||||||
loadVersion(currentVersion).then(data => {
|
loadVersion(currentVersion).then(data => {
|
||||||
currentData = data;
|
currentData = data;
|
||||||
|
|||||||
@@ -445,74 +445,60 @@ img {
|
|||||||
0 0.5px 0 2px #464646;
|
0 0.5px 0 2px #464646;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Dead key panel */
|
/* Dead key mode — compositions shown on keyboard */
|
||||||
.dead-key-panel {
|
.keyboard--dead-mode .key--no-composition {
|
||||||
max-width: fit-content;
|
opacity: 0.25;
|
||||||
margin: 1.5rem auto 0;
|
|
||||||
background: #fff;
|
|
||||||
border: 1px solid rgba(0, 0, 0, 0.1);
|
|
||||||
border-radius: 8px;
|
|
||||||
padding: 1.25rem;
|
|
||||||
position: relative;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.dead-key-panel h4 {
|
.keyboard--dead-mode .key--has-composition {
|
||||||
font-size: 1rem;
|
background: linear-gradient(to bottom, #fef9e7, #fef3cd 95%, #f5e6a8);
|
||||||
font-weight: 600;
|
}
|
||||||
margin-bottom: 1rem;
|
|
||||||
|
.keyboard--dead-mode .key--has-composition .key-char--shift-option,
|
||||||
|
.keyboard--dead-mode .key--has-composition .key-char--option {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.keyboard--dead-mode .key--has-composition .key-char--base {
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.keyboard--dead-mode .key--has-composition .key-char--shift {
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.keyboard--dead-mode .key--spacebar-label .key-mod-label {
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 700;
|
||||||
color: #1a1a2e;
|
color: #1a1a2e;
|
||||||
|
letter-spacing: 0.02em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dead-key-close {
|
.keyboard--dead-mode .key--dead-active {
|
||||||
position: absolute;
|
background: linear-gradient(to bottom, #d4e8ff, #b8d4f0 95%, #a0c0e0);
|
||||||
top: 0.75rem;
|
|
||||||
right: 0.75rem;
|
|
||||||
border: none;
|
|
||||||
background: none;
|
|
||||||
font-size: 1.25rem;
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Keyboard hint */
|
||||||
|
.keyboard-hint {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 0.8rem;
|
||||||
color: #5a6178;
|
color: #5a6178;
|
||||||
padding: 0.25rem 0.5rem;
|
margin-top: 0.75rem;
|
||||||
border-radius: 4px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.dead-key-close:hover {
|
.keyboard-hint kbd {
|
||||||
background: #f0f0f0;
|
background: #e0e4ed;
|
||||||
color: #1a1a2e;
|
border-radius: 3px;
|
||||||
}
|
padding: 0.1rem 0.35rem;
|
||||||
|
|
||||||
.dead-key-grid {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));
|
|
||||||
gap: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dead-key-pair {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
gap: 0.25rem;
|
|
||||||
background: #f5f7fa;
|
|
||||||
border-radius: 4px;
|
|
||||||
padding: 0.375rem 0.5rem;
|
|
||||||
font-family: "SF Mono", "Menlo", "Consolas", monospace;
|
font-family: "SF Mono", "Menlo", "Consolas", monospace;
|
||||||
font-size: 0.875rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dead-key-base {
|
|
||||||
color: #5a6178;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dead-key-arrow {
|
|
||||||
color: #aaa;
|
|
||||||
font-size: 0.75rem;
|
font-size: 0.75rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dead-key-composed {
|
|
||||||
color: #1a1a2e;
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* PDF links */
|
/* PDF links */
|
||||||
.layout-pdf-links {
|
.layout-pdf-links {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
Reference in New Issue
Block a user