Cannot change font color for sticky notes from floating toolbar #161

Open
opened 2026-05-06 11:49:07 +00:00 by AhmedHanafy725 · 2 comments
Member

Sticky notes have a background color picker (sticky color) but no text color picker in the floating toolbar. Other text-bearing objects (text, shape) have a Text color trigger. Add the same trigger to _renderSticky so users can change the sticky note text color independently from the background.

Sticky notes have a background color picker (sticky color) but no text color picker in the floating toolbar. Other text-bearing objects (text, shape) have a Text color trigger. Add the same trigger to `_renderSticky` so users can change the sticky note text color independently from the background.
Author
Member

Spec

Root cause

Three coordinated gaps in sticky rendering — wiring the toolbar trigger alone is not enough:

  1. _renderSticky has no Text color trigger.
  2. renderStickyContent (objects.js:288) hardcodes color: '#1a1a1a' and ignores group._mdFill.
  3. The inline-edit textarea path (editMarkdownText, objects.js:536) hardcodes '#1a1a1a' for sticky.
  4. Plus: sync.js doesn't serialize/consume sticky text color at all (the field never crosses the wire).

The field name _mdFill matches text/shape/document. The sync wire-key fill matches the text branch.

Files to Modify

  • crates/hero_whiteboard_ui/static/web/js/whiteboard/selection_toolbar.js
  • crates/hero_whiteboard_ui/static/web/js/whiteboard/objects.js
  • crates/hero_whiteboard_ui/static/web/js/whiteboard/sync.js

Implementation Plan

Step 1 — _renderSticky (selection_toolbar.js)

At the top of the function, alongside other locals, read the text color:

var textColor = node._mdFill || '#1a1a1a';

Insert between the existing _buildSizePicker and _buildAlignTrigger blocks (between font-size and align):

propsEl.appendChild(_colorTriggerWithTitle(textColor, function(c) {
    node._mdFill = c;
    WhiteboardObjects.rerenderSticky(node);
    WhiteboardSync.onUpdate(node);
}, DEFAULT_COLOR_PALETTE, 'Text color', false, 'text'));

Final sticky toolbar order: bg color, font-size, text color (NEW), align, edit pencil.

Step 2 — renderStickyContent (objects.js ~L288)

Replace color: '#1a1a1a' with color: group._mdFill || '#1a1a1a'. This is the load-bearing render-path change.

Step 3 — editMarkdownText (objects.js ~L536)

Replace:

textarea.style.color = type === 'sticky' ? '#1a1a1a' : (group._mdFill || '#dee2e6');

with:

textarea.style.color = type === 'sticky' ? (group._mdFill || '#1a1a1a') : (group._mdFill || '#dee2e6');

So the inline-edit textarea matches the rendered color.

Step 4 — sync.js sticky outbound (~L284–288)

After the existing data.fontSize = …; line, add:

data.fill = node._mdFill || '#1a1a1a';

Reuses the fill wire key (same as text branch) so the format stays uniform across text-bearing types.

Step 5 — sync.js sticky inbound (~L590–605)

After the existing data.fontSize line, add:

if (data && data.fill) { node._mdFill = data.fill; styleChanged = true; }

The existing styleChanged bookkeeping (~L775) already triggers rerenderSticky — no extra wiring.

Acceptance Criteria

  • Sticky toolbar order: bg color, font-size, text color, align, edit pencil.
  • Clicking text-color trigger opens DEFAULT_COLOR_PALETTE seeded with current _mdFill (or #1a1a1a).
  • Picking a color recolors the rendered markdown immediately.
  • Persists across reloads.
  • Replicates to other clients via data.fill.
  • Inline-edit textarea uses the chosen color.
  • Existing stickies (no _mdFill) still render with #1a1a1a — visually unchanged.
  • Tooltip reads "Text color".
  • Color-icon kind on the new trigger is 'text' (per 34156d5) — visually distinct from the bg trigger ('fill').

What NOT to break

  • Recently-committed font-size picker (c071747) and alignment trigger — new trigger is inserted between them.
  • Existing sticky background picker (objData.color, getStickyColors(), kind: 'fill') — unchanged.
  • Sync round-trip of _mdFill for text/shape/document — those wire keys are not renamed.
  • Default fallback is #1a1a1a for sticky everywhere (NOT #dee2e6). The text/shape default would be invisible on pastel sticky backgrounds.
  • Old peers that don't emit data.fill on stickies — the if (data && data.fill) guard preserves local _mdFill.
## Spec ### Root cause Three coordinated gaps in sticky rendering — wiring the toolbar trigger alone is not enough: 1. `_renderSticky` has no Text color trigger. 2. `renderStickyContent` (`objects.js:288`) hardcodes `color: '#1a1a1a'` and ignores `group._mdFill`. 3. The inline-edit textarea path (`editMarkdownText`, `objects.js:536`) hardcodes `'#1a1a1a'` for sticky. 4. Plus: sync.js doesn't serialize/consume sticky text color at all (the field never crosses the wire). The field name `_mdFill` matches text/shape/document. The sync wire-key `fill` matches the text branch. ### Files to Modify - `crates/hero_whiteboard_ui/static/web/js/whiteboard/selection_toolbar.js` - `crates/hero_whiteboard_ui/static/web/js/whiteboard/objects.js` - `crates/hero_whiteboard_ui/static/web/js/whiteboard/sync.js` ### Implementation Plan #### Step 1 — `_renderSticky` (selection_toolbar.js) At the top of the function, alongside other locals, read the text color: ```js var textColor = node._mdFill || '#1a1a1a'; ``` Insert between the existing `_buildSizePicker` and `_buildAlignTrigger` blocks (between font-size and align): ```js propsEl.appendChild(_colorTriggerWithTitle(textColor, function(c) { node._mdFill = c; WhiteboardObjects.rerenderSticky(node); WhiteboardSync.onUpdate(node); }, DEFAULT_COLOR_PALETTE, 'Text color', false, 'text')); ``` Final sticky toolbar order: bg color, font-size, **text color (NEW)**, align, edit pencil. #### Step 2 — `renderStickyContent` (objects.js ~L288) Replace `color: '#1a1a1a'` with `color: group._mdFill || '#1a1a1a'`. This is the load-bearing render-path change. #### Step 3 — `editMarkdownText` (objects.js ~L536) Replace: ```js textarea.style.color = type === 'sticky' ? '#1a1a1a' : (group._mdFill || '#dee2e6'); ``` with: ```js textarea.style.color = type === 'sticky' ? (group._mdFill || '#1a1a1a') : (group._mdFill || '#dee2e6'); ``` So the inline-edit textarea matches the rendered color. #### Step 4 — sync.js sticky outbound (~L284–288) After the existing `data.fontSize = …;` line, add: ```js data.fill = node._mdFill || '#1a1a1a'; ``` Reuses the `fill` wire key (same as text branch) so the format stays uniform across text-bearing types. #### Step 5 — sync.js sticky inbound (~L590–605) After the existing `data.fontSize` line, add: ```js if (data && data.fill) { node._mdFill = data.fill; styleChanged = true; } ``` The existing `styleChanged` bookkeeping (~L775) already triggers `rerenderSticky` — no extra wiring. ### Acceptance Criteria - [ ] Sticky toolbar order: bg color, font-size, text color, align, edit pencil. - [ ] Clicking text-color trigger opens DEFAULT_COLOR_PALETTE seeded with current `_mdFill` (or `#1a1a1a`). - [ ] Picking a color recolors the rendered markdown immediately. - [ ] Persists across reloads. - [ ] Replicates to other clients via `data.fill`. - [ ] Inline-edit textarea uses the chosen color. - [ ] Existing stickies (no `_mdFill`) still render with `#1a1a1a` — visually unchanged. - [ ] Tooltip reads "Text color". - [ ] Color-icon kind on the new trigger is `'text'` (per `34156d5`) — visually distinct from the bg trigger (`'fill'`). ### What NOT to break - Recently-committed font-size picker (`c071747`) and alignment trigger — new trigger is inserted between them. - Existing sticky background picker (`objData.color`, `getStickyColors()`, `kind: 'fill'`) — unchanged. - Sync round-trip of `_mdFill` for text/shape/document — those wire keys are not renamed. - Default fallback is `#1a1a1a` for sticky everywhere (NOT `#dee2e6`). The text/shape default would be invisible on pastel sticky backgrounds. - Old peers that don't emit `data.fill` on stickies — the `if (data && data.fill)` guard preserves local `_mdFill`.
Author
Member

Done

Commit 57cc6ea on development. 3 files changed (selection_toolbar.js + objects.js + sync.js, +11/-2). Toolbar trigger added between font-size and align; render path + inline-edit textarea now read _mdFill; sync wire format adds data.fill on the sticky branch.

  • cargo check --workspace: pass
## Done Commit `57cc6ea` on `development`. 3 files changed (selection_toolbar.js + objects.js + sync.js, +11/-2). Toolbar trigger added between font-size and align; render path + inline-edit textarea now read `_mdFill`; sync wire format adds `data.fill` on the sticky branch. - `cargo check --workspace`: pass
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
lhumina_code/hero_whiteboard#161
No description provided.