From b9ecebffde53666acf836ee4831a898fe834d167 Mon Sep 17 00:00:00 2001 From: jay Date: Sat, 30 May 2026 22:50:11 +0000 Subject: [PATCH] Add Boundaries panel to the UI: precise personal avoid-terms first MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - New BoundariesPanel.svelte: gentle, device-local controls. Avoid words/phrases first (the trust-critical piece), then 'Paused for now' and 'Always hidden', each with easy remove. Reassures 'nothing leaves this device'; adding a term refreshes the brief/feed immediately. - Quiet 'Boundaries' toggle (active indicator) replaces the old calm bar, keeping the first viewport calm. - Wording stays gentle throughout: avoid / pause / hide / boundaries — never blocked/banned/blacklist. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../src/lib/components/BoundariesPanel.svelte | 133 ++++++++++++++++++ frontend/src/routes/+page.svelte | 37 ++--- 2 files changed, 153 insertions(+), 17 deletions(-) create mode 100644 frontend/src/lib/components/BoundariesPanel.svelte diff --git a/frontend/src/lib/components/BoundariesPanel.svelte b/frontend/src/lib/components/BoundariesPanel.svelte new file mode 100644 index 0000000..26cfc46 --- /dev/null +++ b/frontend/src/lib/components/BoundariesPanel.svelte @@ -0,0 +1,133 @@ + + +
+
+

Your boundaries

+ +
+

Kept on this device. Nothing leaves it, and there's no account.

+ +
+ +
+ e.key === 'Enter' && addTerm()} /> + +
+ {#if prefs.avoid_terms.length} +
+ {#each prefs.avoid_terms as t, i (t)} + {t} + {/each} +
+ {:else} +

Anything you'd rather not see — a person, a diagnosis, a subject — goes here and is hidden everywhere.

+ {/if} +
+ +
+ Paused for now + {#if prefs.pauses.length} +
+ {#each prefs.pauses as p, i (p.kind + p.value + p.until)} + {p.value} · until {when(p.until)} + {/each} +
+ {:else} +

Nothing paused.

+ {/if} +
+ +
+ Always hidden + {#if mutes.length} +
+ {#each mutes as [kind, v] (kind + v)} + {v} + {/each} +
+ {:else} +

Nothing hidden.

+ {/if} +
+ + {#if anything} + + {/if} +
+ + diff --git a/frontend/src/routes/+page.svelte b/frontend/src/routes/+page.svelte index 160bc6f..4d29348 100644 --- a/frontend/src/routes/+page.svelte +++ b/frontend/src/routes/+page.svelte @@ -5,6 +5,7 @@ import MoodNav from '$lib/components/MoodNav.svelte'; import Lane from '$lib/components/Lane.svelte'; import ArticleCard from '$lib/components/ArticleCard.svelte'; + import BoundariesPanel from '$lib/components/BoundariesPanel.svelte'; let moods = $state([]); let selected = $state('today'); @@ -12,6 +13,7 @@ let feed = $state([]); let lanes = $state([]); let userPrefs = $state(P.blank()); + let showBoundaries = $state(false); let loading = $state(true); let error = $state(''); @@ -52,16 +54,14 @@ if (typeof window !== 'undefined') window.scrollTo({ top: 0, behavior: 'smooth' }); } - function applyAction(kind, value) { - P[kind]?.(userPrefs, value); + function refreshPrefs() { userPrefs = { ...userPrefs }; P.save(userPrefs); select(selected); } - function resetFilters() { - userPrefs = P.blank(); - P.save(userPrefs); - select(selected); + function applyAction(kind, value) { + P[kind]?.(userPrefs, value); + refreshPrefs(); } onMount(async () => { @@ -80,11 +80,14 @@ {/if} -{#if filtersOn} -
- Calm filters on — your feed is personalized on this device. - -
+
+ +
+ +{#if showBoundaries} + (showBoundaries = false)} /> {/if} {#if loading} @@ -131,13 +134,13 @@ {/if}