feat: replace calc topbar controls with popup menus
This commit is contained in:
+36
-14
@@ -167,8 +167,11 @@ body {
|
|||||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);
|
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);
|
||||||
}
|
}
|
||||||
|
|
||||||
.topbar-label,
|
.menu-cell {
|
||||||
.mode-select > span {
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.topbar-label {
|
||||||
display: block;
|
display: block;
|
||||||
margin-bottom: 6px;
|
margin-bottom: 6px;
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
@@ -193,21 +196,41 @@ body {
|
|||||||
background: rgba(255, 255, 255, 0.06);
|
background: rgba(255, 255, 255, 0.06);
|
||||||
}
|
}
|
||||||
|
|
||||||
.mode-select {
|
.menu-trigger {
|
||||||
display: grid;
|
|
||||||
gap: 6px;
|
|
||||||
min-width: 0;
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mode-cell select {
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
min-height: 38px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.const-buttons {
|
.popup-menu {
|
||||||
|
position: absolute;
|
||||||
|
top: calc(100% + 8px);
|
||||||
|
left: 10px;
|
||||||
|
right: 10px;
|
||||||
|
z-index: 20;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 14px;
|
||||||
|
background: rgba(18, 24, 34, 0.96);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||||
|
box-shadow: 0 16px 30px rgba(0, 0, 0, 0.35);
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-menu[hidden] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-menu-compact {
|
||||||
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.hidden-select {
|
||||||
|
position: absolute;
|
||||||
|
left: -9999px;
|
||||||
|
width: 1px;
|
||||||
|
height: 1px;
|
||||||
|
opacity: 0;
|
||||||
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.action-cell {
|
.action-cell {
|
||||||
@@ -215,8 +238,7 @@ body {
|
|||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
}
|
}
|
||||||
|
|
||||||
.action-cell > button,
|
.action-cell > button {
|
||||||
.const-buttons > button {
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,18 +26,21 @@
|
|||||||
<input id="input" class="hidden-input" type="text" autocomplete="off" aria-hidden="true" tabindex="-1">
|
<input id="input" class="hidden-input" type="text" autocomplete="off" aria-hidden="true" tabindex="-1">
|
||||||
|
|
||||||
<div class="topbar">
|
<div class="topbar">
|
||||||
<label class="topbar-cell mode-select mode-cell">
|
<div class="topbar-cell menu-cell" id="modeMenuWrap">
|
||||||
<span>mode</span>
|
<div class="topbar-label">mode</div>
|
||||||
<select id="angleMode">
|
<button type="button" class="menu-trigger key-function" id="modeMenuButton" aria-haspopup="true" aria-expanded="false">deg</button>
|
||||||
|
<div class="popup-menu" id="modeMenu" hidden></div>
|
||||||
|
<select id="angleMode" class="hidden-select" aria-hidden="true" tabindex="-1">
|
||||||
<option value="deg">Degrees</option>
|
<option value="deg">Degrees</option>
|
||||||
<option value="rad">Radians</option>
|
<option value="rad">Radians</option>
|
||||||
<option value="grad">Grads</option>
|
<option value="grad">Grads</option>
|
||||||
</select>
|
</select>
|
||||||
</label>
|
</div>
|
||||||
|
|
||||||
<div class="topbar-cell consts-cell">
|
<div class="topbar-cell menu-cell consts-cell" id="constsMenuWrap">
|
||||||
<div class="topbar-label">consts</div>
|
<div class="topbar-label">consts</div>
|
||||||
<div class="const-buttons" id="constButtons"></div>
|
<button type="button" class="menu-trigger key-function" id="constsMenuButton" aria-haspopup="true" aria-expanded="false">consts</button>
|
||||||
|
<div class="popup-menu popup-menu-compact" id="constsMenu" hidden></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="topbar-status status">
|
<div class="topbar-status status">
|
||||||
|
|||||||
@@ -9,6 +9,10 @@ const inputValueLabel = document.getElementById('inputValueLabel');
|
|||||||
const editingLabel = document.getElementById('editingLabel');
|
const editingLabel = document.getElementById('editingLabel');
|
||||||
const modeLabel = document.getElementById('modeLabel');
|
const modeLabel = document.getElementById('modeLabel');
|
||||||
const angleMode = document.getElementById('angleMode');
|
const angleMode = document.getElementById('angleMode');
|
||||||
|
const modeMenuButton = document.getElementById('modeMenuButton');
|
||||||
|
const modeMenu = document.getElementById('modeMenu');
|
||||||
|
const constsMenuButton = document.getElementById('constsMenuButton');
|
||||||
|
const constsMenu = document.getElementById('constsMenu');
|
||||||
|
|
||||||
const keyLayouts = {
|
const keyLayouts = {
|
||||||
functions: [
|
functions: [
|
||||||
@@ -137,6 +141,28 @@ function handleBackspaceAction() {
|
|||||||
execute('drop');
|
execute('drop');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function closePopupMenus() {
|
||||||
|
modeMenu.hidden = true;
|
||||||
|
constsMenu.hidden = true;
|
||||||
|
modeMenuButton.setAttribute('aria-expanded', 'false');
|
||||||
|
constsMenuButton.setAttribute('aria-expanded', 'false');
|
||||||
|
}
|
||||||
|
|
||||||
|
function togglePopupMenu(menuName) {
|
||||||
|
const isModeMenu = menuName === 'mode';
|
||||||
|
const targetMenu = isModeMenu ? modeMenu : constsMenu;
|
||||||
|
const targetButton = isModeMenu ? modeMenuButton : constsMenuButton;
|
||||||
|
const otherMenu = isModeMenu ? constsMenu : modeMenu;
|
||||||
|
const otherButton = isModeMenu ? constsMenuButton : modeMenuButton;
|
||||||
|
const willOpen = targetMenu.hidden;
|
||||||
|
|
||||||
|
otherMenu.hidden = true;
|
||||||
|
otherButton.setAttribute('aria-expanded', 'false');
|
||||||
|
|
||||||
|
targetMenu.hidden = !willOpen;
|
||||||
|
targetButton.setAttribute('aria-expanded', String(willOpen));
|
||||||
|
}
|
||||||
|
|
||||||
function createButton(cell) {
|
function createButton(cell) {
|
||||||
if (!cell) {
|
if (!cell) {
|
||||||
const spacer = document.createElement('div');
|
const spacer = document.createElement('div');
|
||||||
@@ -151,6 +177,7 @@ function createButton(cell) {
|
|||||||
button.className = cell.className;
|
button.className = cell.className;
|
||||||
button.addEventListener('click', () => {
|
button.addEventListener('click', () => {
|
||||||
focusScreen();
|
focusScreen();
|
||||||
|
closePopupMenus();
|
||||||
if (cell.type === 'input') {
|
if (cell.type === 'input') {
|
||||||
pressKey(cell.value);
|
pressKey(cell.value);
|
||||||
return;
|
return;
|
||||||
@@ -164,6 +191,11 @@ function createButton(cell) {
|
|||||||
handleBackspaceAction();
|
handleBackspaceAction();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (cell.value === 'setModeDeg' || cell.value === 'setModeRad' || cell.value === 'setModeGrad') {
|
||||||
|
angleMode.value = cell.value === 'setModeDeg' ? 'deg' : (cell.value === 'setModeRad' ? 'rad' : 'grad');
|
||||||
|
angleMode.dispatchEvent(new Event('change'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
execute(cell.value);
|
execute(cell.value);
|
||||||
});
|
});
|
||||||
@@ -348,6 +380,7 @@ function render() {
|
|||||||
inputValueLabel.textContent = calc.inputValue || '∅';
|
inputValueLabel.textContent = calc.inputValue || '∅';
|
||||||
editingLabel.textContent = String(calc.isEditing);
|
editingLabel.textContent = String(calc.isEditing);
|
||||||
modeLabel.textContent = calc.angleMode;
|
modeLabel.textContent = calc.angleMode;
|
||||||
|
modeMenuButton.textContent = calc.angleMode;
|
||||||
angleMode.value = calc.angleMode;
|
angleMode.value = calc.angleMode;
|
||||||
errorEl.textContent = '';
|
errorEl.textContent = '';
|
||||||
}
|
}
|
||||||
@@ -593,18 +626,43 @@ function handleKeydown(event) {
|
|||||||
|
|
||||||
window.addEventListener('keydown', handleKeydown);
|
window.addEventListener('keydown', handleKeydown);
|
||||||
|
|
||||||
screen.addEventListener('click', focusScreen);
|
screen.addEventListener('click', () => {
|
||||||
|
closePopupMenus();
|
||||||
|
focusScreen();
|
||||||
|
});
|
||||||
window.addEventListener('load', focusScreen);
|
window.addEventListener('load', focusScreen);
|
||||||
|
|
||||||
|
document.addEventListener('click', (event) => {
|
||||||
|
if (!event.target.closest('#modeMenuWrap') && !event.target.closest('#constsMenuWrap')) {
|
||||||
|
closePopupMenus();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
modeMenuButton.addEventListener('click', (event) => {
|
||||||
|
event.stopPropagation();
|
||||||
|
togglePopupMenu('mode');
|
||||||
|
});
|
||||||
|
|
||||||
|
constsMenuButton.addEventListener('click', (event) => {
|
||||||
|
event.stopPropagation();
|
||||||
|
togglePopupMenu('consts');
|
||||||
|
});
|
||||||
|
|
||||||
angleMode.addEventListener('change', (event) => {
|
angleMode.addEventListener('change', (event) => {
|
||||||
calc.angleMode = event.target.value;
|
calc.angleMode = event.target.value;
|
||||||
|
closePopupMenus();
|
||||||
render();
|
render();
|
||||||
});
|
});
|
||||||
|
|
||||||
renderKeyLayout(document.getElementById('functionsButtons'), keyLayouts.functions);
|
renderKeyLayout(document.getElementById('functionsButtons'), keyLayouts.functions);
|
||||||
renderKeyLayout(document.getElementById('numbersButtons'), keyLayouts.numbers);
|
renderKeyLayout(document.getElementById('numbersButtons'), keyLayouts.numbers);
|
||||||
renderKeyLayout(document.getElementById('operatorsButtons'), keyLayouts.operators);
|
renderKeyLayout(document.getElementById('operatorsButtons'), keyLayouts.operators);
|
||||||
renderKeyLayout(document.getElementById('constButtons'), [topButtons.consts]);
|
renderKeyLayout(modeMenu, [[
|
||||||
|
{ type: 'action', value: 'setModeDeg', label: 'Degrees', className: 'key-function' },
|
||||||
|
{ type: 'action', value: 'setModeRad', label: 'Radians', className: 'key-function' },
|
||||||
|
{ type: 'action', value: 'setModeGrad', label: 'Grads', className: 'key-function' },
|
||||||
|
]]);
|
||||||
|
renderKeyLayout(constsMenu, [topButtons.consts]);
|
||||||
document.getElementById('deleteButton').appendChild(createButton(topButtons.del));
|
document.getElementById('deleteButton').appendChild(createButton(topButtons.del));
|
||||||
document.getElementById('backspaceButton').appendChild(createButton(topButtons.backspace));
|
document.getElementById('backspaceButton').appendChild(createButton(topButtons.backspace));
|
||||||
document.getElementById('escapeButton').appendChild(createButton(topButtons.escape));
|
document.getElementById('escapeButton').appendChild(createButton(topButtons.escape));
|
||||||
|
|||||||
Reference in New Issue
Block a user