design: additional design improvements

chore: remove stale comment
This commit is contained in:
Per Stark
2025-09-17 18:55:44 +02:00
parent 3f774302c7
commit fe5143cd7f
8 changed files with 110 additions and 24 deletions

View File

@@ -8,7 +8,6 @@ use std::{
};
use tempfile::NamedTempFile;
use thiserror::Error;
// futures imports no longer needed here after abstraction
use tracing::info;
use uuid::Uuid;

View File

@@ -440,14 +440,63 @@
}
.kg-overlay {
@apply absolute top-4 left-4 z-10 flex items-center gap-2;
@apply absolute top-4 left-4 right-4 z-10 flex flex-col items-stretch gap-2;
max-width: min(420px, calc(100% - 2rem));
}
.kg-control-row {
@apply flex flex-wrap items-center gap-2;
}
.kg-control-row-primary {
@apply justify-start;
}
.kg-control-row-secondary {
@apply justify-center;
}
.kg-search-input {
@apply pl-2;
height: 2rem;
min-width: 220px;
width: 100%;
max-width: 320px;
min-width: 0;
}
.kg-control-row-primary .kg-search-input {
flex: 1 1 auto;
}
.kg-search-btn {
flex: 0 0 auto;
}
.kg-toggle {
@apply transition-colors;
}
.kg-toggle-active {
--btn-color: var(--color-accent);
--btn-fg: var(--color-accent-content);
--btn-noise: none;
background-image: none;
background-color: var(--color-accent);
color: var(--color-accent-content);
}
.kg-toggle-active:hover {
background-color: var(--color-accent);
color: var(--color-accent-content);
filter: saturate(1.1) brightness(1.05);
}
@media (min-width: 768px) {
.kg-overlay {
right: auto;
max-width: none;
width: auto;
}
}
.kg-legend {

View File

@@ -71,10 +71,16 @@
return { idToNode, neighbors };
}
function attachOverlay(container, { onSearch, onToggleLabels, onCenter }) {
function attachOverlay(container, { onSearch, onToggleNames, onToggleEdgeLabels, onCenter }) {
const overlay = document.createElement('div');
overlay.className = 'kg-overlay';
const primaryRow = document.createElement('div');
primaryRow.className = 'kg-control-row kg-control-row-primary';
const secondaryRow = document.createElement('div');
secondaryRow.className = 'kg-control-row kg-control-row-secondary';
// search box
const input = document.createElement('input');
input.type = 'text';
@@ -85,29 +91,41 @@
});
const searchBtn = document.createElement('button');
searchBtn.className = 'nb-btn btn-xs nb-cta';
searchBtn.className = 'nb-btn btn-xs nb-cta kg-search-btn';
searchBtn.textContent = 'Go';
searchBtn.addEventListener('click', () => onSearch && onSearch(input.value.trim()));
const namesToggle = document.createElement('button');
namesToggle.className = 'nb-btn btn-xs kg-toggle';
namesToggle.type = 'button';
namesToggle.textContent = 'Names';
namesToggle.addEventListener('click', () => onToggleNames && onToggleNames());
const labelToggle = document.createElement('button');
labelToggle.className = 'nb-btn btn-xs';
labelToggle.className = 'nb-btn btn-xs kg-toggle';
labelToggle.type = 'button';
labelToggle.textContent = 'Labels';
labelToggle.addEventListener('click', () => onToggleLabels && onToggleLabels());
labelToggle.addEventListener('click', () => onToggleEdgeLabels && onToggleEdgeLabels());
const centerBtn = document.createElement('button');
centerBtn.className = 'nb-btn btn-xs';
centerBtn.textContent = 'Center';
centerBtn.addEventListener('click', () => onCenter && onCenter());
overlay.appendChild(input);
overlay.appendChild(searchBtn);
overlay.appendChild(labelToggle);
overlay.appendChild(centerBtn);
primaryRow.appendChild(input);
primaryRow.appendChild(searchBtn);
secondaryRow.appendChild(namesToggle);
secondaryRow.appendChild(labelToggle);
secondaryRow.appendChild(centerBtn);
overlay.appendChild(primaryRow);
overlay.appendChild(secondaryRow);
container.style.position = 'relative';
container.appendChild(overlay);
return { input, overlay };
return { input, overlay, namesToggle, labelToggle };
}
function attachLegends(container, typeColor, relColor) {
@@ -180,13 +198,33 @@
const { neighbors } = buildAdjacency(data.nodes, data.links);
// Build overlay controls
let labelsVisible = true;
const { input } = attachOverlay(container, {
let namesVisible = true;
let edgeLabelsVisible = true;
const togglePressedState = (button, state) => {
if (!button) return;
button.setAttribute('aria-pressed', state ? 'true' : 'false');
button.classList.toggle('kg-toggle-active', !!state);
};
const { input, namesToggle, labelToggle } = attachOverlay(container, {
onSearch: (q) => focusSearch(q),
onToggleLabels: () => { labelsVisible = !labelsVisible; label.style('display', labelsVisible ? null : 'none'); },
onToggleNames: () => {
namesVisible = !namesVisible;
label.style('display', namesVisible ? null : 'none');
togglePressedState(namesToggle, namesVisible);
},
onToggleEdgeLabels: () => {
edgeLabelsVisible = !edgeLabelsVisible;
linkLabel.style('display', edgeLabelsVisible ? null : 'none');
togglePressedState(labelToggle, edgeLabelsVisible);
},
onCenter: () => zoomTo(1, [width / 2, height / 2])
});
togglePressedState(namesToggle, namesVisible);
togglePressedState(labelToggle, edgeLabelsVisible);
// SVG + zoom
const svg = d3.select(container)
.append('svg')

File diff suppressed because one or more lines are too long

View File

@@ -17,7 +17,7 @@ hx-swap="outerHTML"
{% endblock %}
{% block primary_actions %}
<button type="button" class="nb-btn mr-2" id="reset_prompt_button">
<button type="button" class="nb-btn w-full sm:w-auto sm:mr-2" id="reset_prompt_button">
Reset to Default
</button>
@@ -29,7 +29,7 @@ hx-swap="outerHTML"
});
</script>
<button type="submit" class="nb-btn nb-cta">
<button type="submit" class="nb-btn nb-cta w-full sm:w-auto">
<span class="htmx-indicator hidden">
<span class="loading loading-spinner loading-xs mr-2"></span>
</span>

View File

@@ -17,7 +17,7 @@ hx-swap="outerHTML"
{% endblock %}
{% block primary_actions %}
<button type="button" class="nb-btn mr-2" id="reset_prompt_button">
<button type="button" class="nb-btn w-full sm:w-auto sm:mr-2" id="reset_prompt_button">
Reset to Default
</button>
@@ -29,7 +29,7 @@ hx-swap="outerHTML"
});
</script>
<button type="submit" class="nb-btn nb-cta">
<button type="submit" class="nb-btn nb-cta w-full sm:w-auto">
<span class="htmx-indicator hidden">
<span class="loading loading-spinner loading-xs mr-2"></span>
</span>

View File

@@ -17,7 +17,7 @@ hx-swap="outerHTML"
{% endblock %}
{% block primary_actions %}
<button type="button" class="nb-btn mr-2" id="reset_prompt_button">
<button type="button" class="nb-btn w-full sm:w-auto sm:mr-2" id="reset_prompt_button">
Reset to Default
</button>
@@ -29,7 +29,7 @@ hx-swap="outerHTML"
});
</script>
<button type="submit" class="nb-btn nb-cta">
<button type="submit" class="nb-btn nb-cta w-full sm:w-auto">
<span class="htmx-indicator hidden">
<span class="loading loading-spinner loading-xs mr-2"></span>
</span>

View File

@@ -5,9 +5,9 @@
{% block modal_content %}{% endblock %}
</div>
<div class="u-hairline mt-4 pt-3 flex justify-end gap-2">
<div class="u-hairline mt-4 pt-3 flex flex-col gap-2 sm:flex-row sm:justify-end sm:items-center">
<!-- Close button (always visible) -->
<button type="button" class="nb-btn" onclick="document.getElementById('body_modal').close()">
<button type="button" class="nb-btn w-full sm:w-auto" onclick="document.getElementById('body_modal').close()">
Close
</button>