feat(calc-01): move controls into a compact top bar

This commit is contained in:
2026-04-25 02:10:04 +02:00
parent 6a28aaaac6
commit 784c470b67
4 changed files with 130 additions and 50 deletions
+64 -20
View File
@@ -149,12 +149,32 @@ body {
pointer-events: none; pointer-events: none;
} }
.toolbar { .topbar {
display: flex;
justify-content: space-between;
align-items: flex-start;
gap: 14px;
margin-top: 14px; margin-top: 14px;
display: grid;
grid-template-columns: minmax(120px, 148px) minmax(132px, 160px) 1fr minmax(72px, 88px) minmax(108px, 128px) minmax(72px, 88px);
gap: 10px;
align-items: stretch;
}
.topbar-cell,
.topbar-status {
min-height: 70px;
background: rgba(6, 10, 16, 0.18);
border: 1px solid rgba(255, 255, 255, 0.06);
border-radius: 16px;
padding: 10px;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);
}
.topbar-label,
.mode-select > span {
display: block;
margin-bottom: 6px;
font-size: 11px;
color: #d9e1ec;
text-transform: uppercase;
letter-spacing: 0.12em;
} }
.status { .status {
@@ -163,6 +183,7 @@ body {
gap: 8px; gap: 8px;
color: #edf2fa; color: #edf2fa;
font-size: 12px; font-size: 12px;
align-content: center;
} }
.pill { .pill {
@@ -175,11 +196,33 @@ body {
.mode-select { .mode-select {
display: grid; display: grid;
gap: 6px; gap: 6px;
min-width: 148px; min-width: 0;
font-size: 12px; font-size: 12px;
color: #d9e1ec; }
text-transform: uppercase;
letter-spacing: 0.08em; .mode-cell select {
width: 100%;
}
.const-buttons {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 8px;
}
.action-cell {
display: flex;
align-items: stretch;
}
.action-cell > button,
.const-buttons > button {
width: 100%;
}
.topbar-status {
display: flex;
align-items: center;
} }
select, select,
@@ -225,17 +268,17 @@ select {
.functions-grid { .functions-grid {
grid-template-columns: repeat(4, minmax(0, 1fr)); grid-template-columns: repeat(4, minmax(0, 1fr));
grid-template-rows: repeat(5, 56px); grid-template-rows: repeat(4, 56px);
} }
.numbers-grid { .numbers-grid {
grid-template-columns: repeat(3, minmax(0, 1fr)); grid-template-columns: repeat(3, minmax(0, 1fr));
grid-template-rows: repeat(5, 56px); grid-template-rows: repeat(4, 56px);
} }
.operators-grid { .operators-grid {
grid-template-columns: repeat(2, minmax(0, 1fr)); grid-template-columns: repeat(2, minmax(0, 1fr));
grid-template-rows: repeat(5, 56px); grid-template-rows: repeat(4, 56px);
} }
.key-spacer { .key-spacer {
@@ -299,6 +342,12 @@ button:active {
line-height: 1.5; line-height: 1.5;
} }
@media (max-width: 980px) {
.topbar {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
}
@media (max-width: 860px) { @media (max-width: 860px) {
.keyboard-layout { .keyboard-layout {
grid-template-columns: 1fr; grid-template-columns: 1fr;
@@ -320,19 +369,14 @@ button:active {
align-items: flex-start; align-items: flex-start;
} }
.toolbar { .topbar {
flex-direction: column; grid-template-columns: 1fr;
}
.mode-select {
min-width: 0;
width: 100%;
} }
.functions-grid, .functions-grid,
.numbers-grid, .numbers-grid,
.operators-grid { .operators-grid {
grid-template-rows: repeat(5, 52px); grid-template-rows: repeat(4, 52px);
} }
} }
+17 -8
View File
@@ -25,20 +25,29 @@
<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="toolbar"> <div class="topbar">
<div class="status"> <label class="topbar-cell mode-select mode-cell">
<div class="pill">inputValue: <span id="inputValueLabel"></span></div> <span>mode</span>
<div class="pill">isEditing: <span id="editingLabel"></span></div>
</div>
<label class="mode-select">
<span>Angle</span>
<select id="angleMode"> <select id="angleMode">
<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> </label>
<div class="topbar-cell consts-cell">
<div class="topbar-label">consts</div>
<div class="const-buttons" id="constButtons"></div>
</div>
<div class="topbar-status status">
<div class="pill">inputValue: <span id="inputValueLabel"></span></div>
<div class="pill">isEditing: <span id="editingLabel"></span></div>
</div>
<div class="topbar-cell action-cell" id="deleteButton"></div>
<div class="topbar-cell action-cell" id="backspaceButton"></div>
<div class="topbar-cell action-cell" id="escapeButton"></div>
</div> </div>
<div class="keyboard-layout"> <div class="keyboard-layout">
+32 -13
View File
@@ -12,12 +12,6 @@ const angleMode = document.getElementById('angleMode');
const keyLayouts = { const keyLayouts = {
functions: [ functions: [
[
{ type: 'command', value: 'pi', label: 'π', className: 'key-function' },
{ type: 'command', value: 'e', label: 'e', className: 'key-function' },
null,
null,
],
[ [
{ type: 'command', value: 'sqrt', label: 'sqrt', className: 'key-function' }, { type: 'command', value: 'sqrt', label: 'sqrt', className: 'key-function' },
{ type: 'command', value: 'pow', label: 'y^x', className: 'key-function' }, { type: 'command', value: 'pow', label: 'y^x', className: 'key-function' },
@@ -44,7 +38,6 @@ const keyLayouts = {
], ],
], ],
numbers: [ numbers: [
[null, null, null],
[ [
{ type: 'input', value: '7', label: '7', className: 'key-number' }, { type: 'input', value: '7', label: '7', className: 'key-number' },
{ type: 'input', value: '8', label: '8', className: 'key-number' }, { type: 'input', value: '8', label: '8', className: 'key-number' },
@@ -67,13 +60,9 @@ const keyLayouts = {
], ],
], ],
operators: [ operators: [
[
{ type: 'command', value: 'clear', label: 'del', className: 'key-danger' },
{ type: 'action', value: 'escape', label: 'esc', className: 'key-danger' },
],
[ [
{ type: 'command', value: 'div', label: '/', className: 'key-operator' }, { type: 'command', value: 'div', label: '/', className: 'key-operator' },
{ type: 'command', value: 'drop', label: 'back', className: 'key-operator' }, null,
], ],
[ [
{ type: 'command', value: 'mul', label: '*', className: 'key-operator' }, { type: 'command', value: 'mul', label: '*', className: 'key-operator' },
@@ -90,6 +79,16 @@ const keyLayouts = {
], ],
}; };
const topButtons = {
consts: [
{ type: 'command', value: 'pi', label: 'π', className: 'key-function' },
{ type: 'command', value: 'e', label: 'e', className: 'key-function' },
],
del: { type: 'command', value: 'clear', label: 'del', className: 'key-danger' },
backspace: { type: 'action', value: 'backspace', label: 'backspace', className: 'key-operator' },
escape: { type: 'action', value: 'escape', label: 'esc', className: 'key-danger' },
};
let stackCursor = null; let stackCursor = null;
let isMovingStackItem = false; let isMovingStackItem = false;
let stackSnapshotBeforeMove = null; let stackSnapshotBeforeMove = null;
@@ -128,6 +127,16 @@ function pressKey(key) {
render(); render();
} }
function handleBackspaceAction() {
if (calc.isEditing) {
editXWithKey('Backspace');
render();
return;
}
execute('drop');
}
function createButton(cell) { function createButton(cell) {
if (!cell) { if (!cell) {
const spacer = document.createElement('div'); const spacer = document.createElement('div');
@@ -146,10 +155,16 @@ function createButton(cell) {
pressKey(cell.value); pressKey(cell.value);
return; return;
} }
if (cell.type === 'action' && cell.value === 'escape') { if (cell.type === 'action') {
if (cell.value === 'escape') {
handleEscapeAction(); handleEscapeAction();
return; return;
} }
if (cell.value === 'backspace') {
handleBackspaceAction();
return;
}
}
execute(cell.value); execute(cell.value);
}); });
return button; return button;
@@ -589,6 +604,10 @@ angleMode.addEventListener('change', (event) => {
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]);
document.getElementById('deleteButton').appendChild(createButton(topButtons.del));
document.getElementById('backspaceButton').appendChild(createButton(topButtons.backspace));
document.getElementById('escapeButton').appendChild(createButton(topButtons.escape));
render(); render();
focusScreen(); focusScreen();
+12 -4
View File
@@ -1,7 +1,15 @@
┌───────────── Functions ──────────────── Numbers ─────── Operators ───┐ ┌──────────────────────────────────────────────────────────────────────────────┐
| consts | | | | | | | del | esc | | T: |
| sqrt | y^x | x² | 1/x | 7 | 8 | 9 | / | backspace | | Z: |
| Y: |
| X: |
└──────────────────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────────────────┐
| mode | consts | | del | backspace | esc |
└──────────────────────────────────────────────────────────────────────────────┘
┌───────────── Functions ───────────────────┬───── Numbers ─────┬─ Operators ─┐
| sqrt | y^x | x² | 1/x | 7 | 8 | 9 | / | |
| log | ln | | % | 4 | 5 | 6 | * | | | log | ln | | % | 4 | 5 | 6 | * | |
| sin | cos | tan | | 1 | 2 | 3 | - | Enter | | sin | cos | tan | | 1 | 2 | 3 | - | Enter |
| asin | acos | atan | | 0 | . | +/- | + | Enter | | asin | acos | atan | | 0 | . | +/- | + | Enter |
└─────────────────────────────────────────────────────┴───────────────── └───────────────────────────────────────────┴───────────────────┴──────────────┘