Add dismiss-only Heads up tier for semantic nudges

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-05-31 18:10:03 -04:00
parent 97577c003f
commit 20a102b4a4
+27 -4
View File
@@ -34,6 +34,10 @@
.drift-actions button { margin: 0 8px 0 0; padding: 8px 14px; } .drift-actions button { margin: 0 8px 0 0; padding: 8px 14px; }
.drift-actions button.secondary { background: #2d3242; color: #cdd2e0; } .drift-actions button.secondary { background: #2d3242; color: #cdd2e0; }
.drift-hint { font-size: 12px; color: #7a8095; margin-bottom: 10px; } .drift-hint { font-size: 12px; color: #7a8095; margin-bottom: 10px; }
.nudge { background: #1d2630; border: 1px solid #2f4255; border-radius: 10px; padding: 12px 14px; margin-bottom: 16px; }
.nudge-title { font-weight: 600; color: #8fb6d9; }
.nudge-msg { color: #c2d2e0; margin: 4px 0 8px; }
.nudge-actions button { padding: 6px 12px; background: #2d3242; color: #cdd2e0; }
</style> </style>
</head> </head>
<body> <body>
@@ -45,6 +49,7 @@
const view = document.getElementById('view'); const view = document.getElementById('view');
let countdownTimer = null; let countdownTimer = null;
let renderedState = null; // which runtime_state the DOM currently shows let renderedState = null; // which runtime_state the DOM currently shows
let dismissedNudge = null; // text of the nudge the user has dismissed
function post(path, body) { function post(path, body) {
return fetch(path, { return fetch(path, {
@@ -93,11 +98,29 @@ function updateActiveDrift(drift) {
document.getElementById('refocus').onclick = () => post('/refocus'); document.getElementById('refocus').onclick = () => post('/refocus');
document.getElementById('ontask').onclick = () => post('/ontask'); document.getElementById('ontask').onclick = () => post('/ontask');
document.getElementById('enddrift').onclick = () => post('/complete'); document.getElementById('enddrift').onclick = () => post('/complete');
} else if (status === 'pending') { return;
el.innerHTML = `<div class="drift-hint">checking focus…</div>`;
} else {
el.innerHTML = '';
} }
const nudge = (drift && drift.nudge) || '';
if (!nudge) dismissedNudge = null; // trajectory recovered; allow future nudges
if (nudge && nudge !== dismissedNudge) {
el.innerHTML = `<div class="nudge">
<div class="nudge-title">Heads up</div>
<div class="nudge-msg">${nudge}</div>
<div class="nudge-actions">
<button id="dismissnudge" type="button">Dismiss</button>
</div></div>`;
document.getElementById('dismissnudge').onclick = () => {
dismissedNudge = nudge;
const e = document.getElementById('drift');
if (e) e.innerHTML = '';
};
return;
}
if (status === 'pending') {
el.innerHTML = `<div class="drift-hint">checking focus…</div>`;
return;
}
el.innerHTML = '';
} }
function updatePlanningCoach(coach) { function updatePlanningCoach(coach) {