Apply sleek black theme and table format for chord panels

This commit is contained in:
Michael Winter 2026-03-31 19:17:37 +02:00
parent 00cfac2e5c
commit e0bacce10a

View file

@ -135,8 +135,8 @@
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
margin: 0; margin: 0;
padding: 20px; padding: 20px;
background: #1a1a2e; background: #000000;
color: #eee; color: #cccccc;
} }
.container { .container {
@ -147,6 +147,9 @@
h1 { h1 {
text-align: center; text-align: center;
margin-bottom: 10px; margin-bottom: 10px;
font-weight: 300;
letter-spacing: 2px;
color: #ffffff;
} }
.controls { .controls {
@ -158,35 +161,39 @@
} }
.controls button { .controls button {
padding: 10px 20px; padding: 8px 16px;
font-size: 16px; font-size: 14px;
cursor: pointer; cursor: pointer;
background: #16213e; background: #0a0a0a;
color: #eee; color: #888888;
border: 1px solid #0f3460; border: 1px solid #222222;
border-radius: 5px; border-radius: 4px;
transition: all 0.2s ease;
} }
.controls button:hover { .controls button:hover {
background: #0f3460; background: #151515;
color: #ffffff;
border-color: #444444;
} }
.controls button:disabled { .controls button:disabled {
opacity: 0.5; opacity: 0.3;
cursor: not-allowed; cursor: not-allowed;
} }
.index-display { .index-display {
font-size: 18px; font-size: 14px;
font-weight: bold; color: #666666;
letter-spacing: 1px;
} }
#graph-container { #graph-container {
width: 100%; width: 100%;
height: 450px; height: 450px;
border: 1px solid #0f3460; border: 1px solid #1a1a1a;
border-radius: 8px; border-radius: 4px;
background: #16213e; background: #050505;
position: relative; position: relative;
} }
@ -197,33 +204,44 @@
} }
.chord-panel { .chord-panel {
background: #16213e; background: #0a0a0a;
padding: 15px; padding: 15px;
border-radius: 8px; border-radius: 4px;
min-width: 250px; min-width: 200px;
border: 1px solid #1a1a1a;
} }
.chord-panel h3 { .chord-panel h3 {
margin-top: 0; margin-top: 0;
color: #e94560; color: #666666;
font-size: 12px;
text-transform: uppercase;
letter-spacing: 1px;
font-weight: 500;
} }
.chord-panel.current { .chord-panel.current {
border: 2px solid #e94560; border: 1px solid #333333;
}
.chord-panel.current h3 {
color: #00d4ff;
} }
.chord-panel.prev, .chord-panel.next { .chord-panel.prev, .chord-panel.next {
opacity: 0.7; opacity: 0.6;
} }
.pitch-list { .pitch-list {
list-style: none; list-style: none;
padding: 0; padding: 0;
font-size: 12px;
} }
.pitch-list li { .pitch-list li {
padding: 5px 0; padding: 4px 0;
font-family: monospace; color: #888888;
font-family: 'SF Mono', 'Monaco', 'Inconsolata', 'Fira Code', monospace;
} }
.file-input { .file-input {
@ -232,44 +250,20 @@
} }
.file-input input { .file-input input {
padding: 10px; padding: 8px;
background: #16213e; background: #0a0a0a;
color: #eee; color: #888888;
border: 1px solid #0f3460; border: 1px solid #222222;
border-radius: 5px; border-radius: 4px;
} }
svg { .file-select {
width: 100%; padding: 8px;
height: 100%; background: #0a0a0a;
} color: #888888;
border: 1px solid #222222;
.node circle { border-radius: 4px;
stroke: #fff; margin-left: 10px;
stroke-width: 2px;
}
.node.current circle {
stroke: #e94560;
stroke-width: 3px;
}
.link {
stroke: #4a5568;
stroke-width: 2px;
}
.link-label {
fill: #a0aec0;
font-size: 12px;
font-family: monospace;
}
.node-label {
fill: #eee;
font-size: 11px;
font-family: monospace;
text-anchor: middle;
} }
</style> </style>
</head> </head>
@ -326,7 +320,7 @@
const graphHeight = 450; const graphHeight = 450;
// Voice colors - sleek pastel scheme // Voice colors - sleek pastel scheme
const voiceColors = ['#5EAFD6', '#CE8E94', '#8FCEA4', '#E5C686']; const voiceColors = ['#7eb5a6', '#c5a3ff', '#ffb3b3', '#ffd700'];
// Create Cytoscape instance // Create Cytoscape instance
function initCytoscape() { function initCytoscape() {
@ -337,40 +331,41 @@
selector: 'node', selector: 'node',
style: { style: {
'background-color': 'data(color)', 'background-color': 'data(color)',
'width': 36, 'width': 32,
'height': 36, 'height': 32,
'label': 'data(cents)', 'label': 'data(cents)',
'text-valign': 'center', 'text-valign': 'center',
'text-halign': 'center', 'text-halign': 'center',
'color': '#eee', 'color': '#000000',
'font-size': '9px', 'font-size': '10px',
'text-outline-width': 2, 'font-family': 'monospace',
'text-outline-color': 'data(color)', 'font-weight': 'bold',
'text-outline-width': 0,
'border-width': 0, 'border-width': 0,
} }
}, },
{ {
selector: 'edge', selector: 'edge',
style: { style: {
'width': 2, 'width': 1.5,
'line-color': '#556', 'line-color': '#555555',
'curve-style': 'straight', 'curve-style': 'straight',
'target-arrow-shape': 'none', 'target-arrow-shape': 'none',
'label': 'data(ratio)', 'label': 'data(ratio)',
'font-size': '10px', 'font-size': '12px',
'color': '#aaa', 'color': '#ffffff',
'text-rotation': 'autorotate', 'text-rotation': 'autorotate',
'text-margin-y': -12, 'text-margin-y': -10,
'text-background-color': '#16213e', 'text-background-color': '#000000',
'text-background-opacity': 0.8, 'text-background-opacity': 0.8,
'text-background-padding': '3px', 'text-background-padding': '2px',
} }
}, },
{ {
selector: ':selected', selector: ':selected',
style: { style: {
'border-width': 3, 'border-width': 2,
'border-color': '#fff', 'border-color': '#00d4ff',
} }
} }
], ],
@ -598,24 +593,70 @@
} }
function updateChordPanel(elementId, data) { function updateChordPanel(elementId, data) {
const ul = document.getElementById(elementId); const container = document.getElementById(elementId);
ul.innerHTML = ""; container.innerHTML = "";
if (!data || (Array.isArray(data) && data.length === 0)) { if (!data || (Array.isArray(data) && data.length === 0)) {
ul.innerHTML = "<li>(none)</li>"; container.innerHTML = "<div>(none)</div>";
return; return;
} }
// Handle both formats: raw chord array or nodes array from graph API
const items = Array.isArray(data) ? data : (data.nodes || []); const items = Array.isArray(data) ? data : (data.nodes || []);
items.forEach(item => { if (items.length === 0) return;
const li = document.createElement("li");
const fraction = item.fraction || item.fraction; // Determine number of columns from first node's hs_array
const hs_array = item.hs_array || []; const cols = items[0].hs_array ? items[0].hs_array.length : 0;
li.textContent = `${fraction} (${hs_array.join(", ")})`; if (cols === 0) return;
ul.appendChild(li);
// Create table - let it size based on content
const table = document.createElement("table");
table.style.fontFamily = "monospace";
table.style.fontSize = "10px";
table.style.borderCollapse = "collapse";
table.style.tableLayout = "auto";
table.style.lineHeight = "1.2";
table.style.margin = "0 auto";
// Header row - split into separate cells to match row structure
const headerRow = document.createElement("tr");
const headerParts = ["2", "3", "5", "7"];
headerParts.forEach((part, idx) => {
const th = document.createElement("th");
th.textContent = part;
th.style.padding = "0px 4px";
th.style.textAlign = idx === 0 ? "left" : "right";
th.style.borderBottom = "1px solid #444";
th.style.paddingBottom = "1px";
th.style.fontWeight = "normal";
th.style.color = "#666";
th.style.whiteSpace = "nowrap";
headerRow.appendChild(th);
}); });
table.appendChild(headerRow);
// Data rows (all nodes)
items.forEach((item) => {
const row = document.createElement("tr");
const hs = item.hs_array || [];
hs.forEach((val, j) => {
const td = document.createElement("td");
td.textContent = val;
td.style.padding = "0px 4px";
td.style.textAlign = "right";
td.style.color = "#888";
td.style.whiteSpace = "nowrap";
if (j === 0) {
td.style.textAlign = "left";
}
row.appendChild(td);
});
table.appendChild(row);
});
container.appendChild(table);
} }
// Update display - now handled by loadFromAPI // Update display - now handled by loadFromAPI