fix(canvas): mobile toolbar to right, persistent lock badge, reminder auth

- Move mobile toolbar to right side to avoid zoom bar overlap
- Toolbar panel opens leftward, bottom toolbar offsets flipped
- Add [locked] attribute reflection on folk-shape for external CSS
- Persistent 🔒 badge on locked shapes visible when unselected
- Add Authorization header to calendar reminder POST request

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Jeff Emmett 2026-03-22 20:13:15 -07:00
parent e2c6275308
commit 34a7a4e37e
2 changed files with 39 additions and 10 deletions

View File

@ -332,6 +332,9 @@ export class FolkShape extends FolkElement {
locked locked
? this.#internals.states.add("locked") ? this.#internals.states.add("locked")
: this.#internals.states.delete("locked"); : this.#internals.states.delete("locked");
// Reflect as attribute for external CSS styling
if (locked) this.setAttribute("locked", "");
else this.removeAttribute("locked");
} }
#editing = false; #editing = false;

View File

@ -1701,13 +1701,13 @@
display: none; display: none;
} }
/* Mobile toolbar: compact column on left, icons only, same as desktop */ /* Mobile toolbar: compact column on RIGHT to avoid zoom-bar overlap */
#toolbar { #toolbar {
position: fixed; position: fixed;
top: auto; top: auto;
bottom: 60px; /* above bottom-toolbar row */ bottom: 60px; /* above bottom-toolbar row */
left: 6px; left: auto;
right: auto; right: 6px;
flex-direction: column; flex-direction: column;
flex-wrap: nowrap; flex-wrap: nowrap;
align-items: center; align-items: center;
@ -1792,12 +1792,12 @@
max-width: calc(100vw - 32px); max-width: calc(100vw - 32px);
} }
/* Mobile: panel opens to the right of the toolbar */ /* Mobile: panel opens to the LEFT of the toolbar (toolbar is on right) */
#toolbar-panel { #toolbar-panel {
top: auto; top: auto;
bottom: 60px; bottom: 60px;
left: 56px; left: auto !important;
right: auto; right: 56px;
min-width: 180px; min-width: 180px;
border-radius: 12px; border-radius: 12px;
max-height: 50vh; max-height: 50vh;
@ -1809,13 +1809,13 @@
min-height: 44px; min-height: 44px;
} }
/* Bottom toolbar: raised above corner tools row */ /* Bottom toolbar: offset right of side toolbar (now on right side) */
#bottom-toolbar { #bottom-toolbar {
bottom: 8px; bottom: 8px;
padding: 4px 6px; padding: 4px 6px;
gap: 1px; gap: 1px;
left: 56px; /* offset right of side toolbar */ left: 8px;
right: 8px; right: 56px; /* offset left of side toolbar on right */
transform: none; transform: none;
overflow-x: auto; overflow-x: auto;
overflow-y: hidden; overflow-y: hidden;
@ -2433,6 +2433,27 @@
.shape-lock-icon.locked { .shape-lock-icon.locked {
border-color: #f59e0b; color: #f59e0b; border-color: #f59e0b; color: #f59e0b;
} }
/* Persistent lock badge on locked shapes (visible even when not selected) */
[locked]::after {
content: "🔒";
position: absolute;
top: -8px;
right: -8px;
font-size: 11px;
line-height: 1;
background: var(--rs-bg-surface, #1e1e2e);
border: 1px solid #f59e0b;
border-radius: 50%;
width: 22px;
height: 22px;
display: flex;
align-items: center;
justify-content: center;
pointer-events: none;
z-index: 1;
opacity: 0.8;
}
</style> </style>
<div id="reminder-widget"> <div id="reminder-widget">
<div class="rw-header"><span class="rw-header-icon">🔔</span> Remind me of this on:</div> <div class="rw-header"><span class="rw-header-icon">🔔</span> Remind me of this on:</div>
@ -7396,9 +7417,14 @@
sourceColor: info.color, sourceColor: info.color,
}; };
if (cachedUserEmail) body.notifyEmail = cachedUserEmail; if (cachedUserEmail) body.notifyEmail = cachedUserEmail;
const reminderHeaders = { "Content-Type": "application/json" };
try {
const s = JSON.parse(localStorage.getItem("encryptid_session") || "{}");
if (s?.accessToken) reminderHeaders["Authorization"] = "Bearer " + s.accessToken;
} catch {}
const res = await fetch(`${schedBase}/api/reminders`, { const res = await fetch(`${schedBase}/api/reminders`, {
method: "POST", method: "POST",
headers: { "Content-Type": "application/json" }, headers: reminderHeaders,
body: JSON.stringify(body), body: JSON.stringify(body),
}); });