add pills

This commit is contained in:
2026-06-16 20:49:46 -07:00
parent 6f5220125f
commit 8d960c615d
2 changed files with 70 additions and 4 deletions
+33 -2
View File
@@ -96,16 +96,30 @@ class OrgTodoListView extends ItemView {
root.createEl("h4", { text: "TODO list" }); root.createEl("h4", { text: "TODO list" });
const input = root.createEl("input", { const filterWrap = root.createDiv({ cls: "org-todo-filterwrap" });
this.pillsEl = filterWrap.createDiv({ cls: "org-todo-pills" });
const input = filterWrap.createEl("input", {
type: "text", type: "text",
placeholder: "Filter… (text or #tag)", placeholder: "Filter… (text or #tag)",
}); });
input.addClass("org-todo-filter"); input.addClass("org-todo-filter");
this.inputEl = input;
input.addEventListener("input", () => { input.addEventListener("input", () => {
this.filterText = input.value.toLowerCase(); this.filterText = input.value.toLowerCase();
this.renderList(); this.renderList();
this.renderTagBar(); this.renderTagBar();
}); });
// Backspace on an empty box removes the last pill — standard token-input feel.
input.addEventListener("keydown", (e) => {
if (e.key === "Backspace" && input.value === "" && this.activeTags.size > 0) {
const last = [...this.activeTags].pop();
this.activeTags.delete(last);
this.renderPills();
this.renderList();
this.renderTagBar();
}
});
const toggleWrap = root.createDiv({ cls: "org-todo-toggle" }); const toggleWrap = root.createDiv({ cls: "org-todo-toggle" });
const cb = toggleWrap.createEl("input", { type: "checkbox" }); const cb = toggleWrap.createEl("input", { type: "checkbox" });
@@ -123,6 +137,7 @@ class OrgTodoListView extends ItemView {
this.tasks = await this.scanVault(); this.tasks = await this.scanVault();
this.renderList(); this.renderList();
this.renderTagBar(); this.renderTagBar();
this.renderPills();
} }
async scanFile(file) { async scanFile(file) {
@@ -177,6 +192,7 @@ class OrgTodoListView extends ItemView {
this.tasks = this.tasks.filter((t) => t.file.path !== path); this.tasks = this.tasks.filter((t) => t.file.path !== path);
this.renderList(); this.renderList();
this.renderTagBar(); this.renderTagBar();
this.renderPills();
} }
// Rescan one file and splice its tasks in, replacing its previous entries. // Rescan one file and splice its tasks in, replacing its previous entries.
@@ -187,8 +203,22 @@ class OrgTodoListView extends ItemView {
for (const t of fresh) this.tasks.push(t); for (const t of fresh) this.tasks.push(t);
this.renderList(); this.renderList();
this.renderTagBar(); this.renderTagBar();
this.renderPills();
}
renderPills() {
this.pillsEl.empty();
for (const tag of [...this.activeTags].sort()) {
const pill = this.pillsEl.createSpan({ cls: "org-todo-pill" });
pill.createSpan({ text: "#" + tag });
const x = pill.createSpan({ text: "×", cls: "org-todo-pill-x" });
x.addEventListener("click", () => {
this.activeTags.delete(tag);
this.renderPills();
this.renderList();
this.renderTagBar();
});
}
} }
renderTagBar() { renderTagBar() {
this.tagBarEl.empty(); this.tagBarEl.empty();
@@ -215,6 +245,7 @@ class OrgTodoListView extends ItemView {
chip.addEventListener("click", () => { chip.addEventListener("click", () => {
if (this.activeTags.has(tag)) this.activeTags.delete(tag); if (this.activeTags.has(tag)) this.activeTags.delete(tag);
else this.activeTags.add(tag); else this.activeTags.add(tag);
this.renderPills();
this.renderList(); this.renderList();
this.renderTagBar(); this.renderTagBar();
}); });
+37 -2
View File
@@ -1,10 +1,45 @@
.org-todo-root { .org-todo-root {
padding: 0 8px; padding: 0 8px;
} }
.org-todo-filter { .org-todo-filterwrap {
width: 100%; display: flex;
flex-wrap: wrap;
align-items: center;
gap: 4px;
border: 1px solid var(--background-modifier-border);
border-radius: 6px;
padding: 4px 6px;
margin-bottom: 8px; margin-bottom: 8px;
} }
.org-todo-pills {
display: contents; /* pills participate directly in the wrap's flex layout */
}
.org-todo-pill {
display: inline-flex;
align-items: center;
gap: 4px;
font-size: 0.78em;
padding: 2px 6px;
border-radius: 10px;
background: var(--interactive-accent);
color: var(--text-on-accent);
white-space: nowrap;
}
.org-todo-pill-x {
cursor: pointer;
font-weight: bold;
opacity: 0.8;
}
.org-todo-pill-x:hover {
opacity: 1;
}
.org-todo-filter {
flex: 1;
min-width: 80px;
border: none;
outline: none;
background: transparent;
}
.org-todo-toggle { .org-todo-toggle {
display: flex; display: flex;
align-items: center; align-items: center;