Compare commits

...

3 Commits

Author SHA1 Message Date
ab93e2548c Make status/priority badges clickable; unify hover via .clickable class
- Add .clickable CSS class (cursor + brightness hover) shared by all
  chip-style interactive elements; remove ad-hoc cursor declarations
- Status and priority badges in list view filter in place on click
- Status and priority badges in detail view navigate to type list
  with that filter applied
- Type chip uses .clickable class consistently

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 16:24:45 +00:00
b0af84607f Always show type badge; make it clickable to navigate to that type
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 16:23:45 +00:00
7d8dcf85ce Fix tree filter and URL canonicality for filter state
- Root entries in tree view filtered strictly by entry_matches_filter;
  a parent no longer appears just because a descendant matches
- Expanded children always shown unfiltered (tree navigation intent)
- build_url always writes ?status=<val> so URL is fully canonical;
  apply_search falls back to open for absent/empty param (old URLs)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 16:21:46 +00:00
2 changed files with 22 additions and 19 deletions

View File

@@ -258,21 +258,25 @@ function make_entry_row(entry, children_map) {
set_text(row, '.task-id', `#${entry.id}`);
// Type chip — only shown in "All" view
// Type chip — always shown, clickable to navigate to that type
const type_chip = row.querySelector('.entry-type-chip');
if (!state.active_type) {
const et = state.entry_types.find(t => t.id === entry.type);
type_chip.textContent = et ? et.title : entry.type;
show(type_chip);
}
const et = state.entry_types.find(t => t.id === entry.type);
type_chip.textContent = et ? et.title : entry.type;
type_chip.classList.add('clickable');
type_chip.addEventListener('click', (e) => { e.stopPropagation(); navigate('type/' + entry.type); });
show(type_chip);
const status_el = row.querySelector('.task-status');
status_el.textContent = entry.status;
status_el.dataset.val = entry.status;
status_el.classList.add('clickable');
status_el.addEventListener('click', (e) => { e.stopPropagation(); set_filter('filter_status', entry.status); });
const priority_el = row.querySelector('.task-priority');
priority_el.textContent = entry.priority;
priority_el.dataset.val = entry.priority;
priority_el.classList.add('clickable');
priority_el.addEventListener('click', (e) => { e.stopPropagation(); set_filter('filter_priority', entry.priority); });
const main_el = row.querySelector('.task-main');
main_el.classList.add('clickable');
@@ -307,8 +311,6 @@ function make_entry_row(entry, children_map) {
}
function render_tree_node(entry, children_map) {
if (!entry_matches_filter(entry)) { return null; }
const children = children_map.get(entry.id) ?? [];
const node = document.createElement('div');
node.className = 'task-node';
@@ -318,8 +320,7 @@ function render_tree_node(entry, children_map) {
const children_el = document.createElement('div');
children_el.className = 'task-children';
for (const child of children) {
const child_node = render_tree_node(child, children_map);
if (child_node) { children_el.appendChild(child_node); }
children_el.appendChild(render_tree_node(child, children_map));
}
node.appendChild(children_el);
}
@@ -649,11 +650,10 @@ function navigate_new(type, parent_id) {
function build_url(hash) {
const params = new URLSearchParams();
if (state.filter_status !== 'open') { params.set('status', state.filter_status || 'all'); }
if (state.filter_priority) { params.set('priority', state.filter_priority); }
if (state.search) { params.set('search', state.search); }
const qs = params.toString();
return (qs ? '?' + qs : '') + '#' + hash;
params.set('status', state.filter_status || 'all');
if (state.filter_priority) { params.set('priority', state.filter_priority); }
if (state.search) { params.set('search', state.search); }
return '?' + params.toString() + '#' + hash;
}
function apply_search() {
@@ -761,19 +761,22 @@ function render_entry_detail(container) {
const type_chip = document.createElement('span');
type_chip.className = 'entry-type-chip';
type_chip.textContent = et.title;
type_chip.addEventListener('click', () => navigate('type/' + entry.type));
meta.appendChild(type_chip);
}
const status_el = document.createElement('span');
status_el.className = 'task-status';
status_el.className = 'task-status clickable';
status_el.textContent = entry.status;
status_el.dataset.val = entry.status;
status_el.addEventListener('click', () => { state.filter_status = entry.status; navigate('type/' + entry.type); });
meta.appendChild(status_el);
const priority_el = document.createElement('span');
priority_el.className = 'task-priority';
priority_el.className = 'task-priority clickable';
priority_el.textContent = entry.priority;
priority_el.dataset.val = entry.priority;
priority_el.addEventListener('click', () => { state.filter_priority = entry.priority; navigate('type/' + entry.type); });
meta.appendChild(priority_el);
for (const tag of entry.tags) {

View File

@@ -192,8 +192,8 @@ main { padding: 1.25rem; }
color: #8899cc;
}
.clickable-tag { cursor: pointer; }
.clickable-tag:hover { background: #363650; color: #aabbee; }
.clickable-tag, .clickable { cursor: pointer; }
.clickable-tag:hover, .clickable:hover { filter: brightness(1.3); }
.btn-expand {
width: 1.25rem;