Skip to content

feat(apollo-react): add formatting toolbar to sticky notes (2/3) [MST-7636]#429

Open
david-rios-uipath wants to merge 2 commits intofeat/sticky-note-markdown-formattingfrom
feat/sticky-note-formatting-toolbar-v2
Open

feat(apollo-react): add formatting toolbar to sticky notes (2/3) [MST-7636]#429
david-rios-uipath wants to merge 2 commits intofeat/sticky-note-markdown-formattingfrom
feat/sticky-note-formatting-toolbar-v2

Conversation

@david-rios-uipath
Copy link
Copy Markdown
Contributor

@david-rios-uipath david-rios-uipath commented Mar 31, 2026

Summary

NOTE: this PR is focused on the UI that consumes the logic added in the bottom PR.

Adds an opinionated markdown editor UI for sticky notes.

It supports bold, italic, strikethrough, bullet lists, and numbered lists.

Interaction modes:

  • Toolbar
  • Keyboard
image
2026-03-30.17.37.18.mp4

Changes

  • FormattingToolbar component — toolbar with icon buttons for bold, italic, strikethrough, bullet list, and numbered list
  • Keyboard shortcuts — Cmd+B (bold), Cmd+I (italic), Cmd+Shift+X (strikethrough)
  • Smart toggle — clicking a format button when cursor is inside a formatted region removes the markers instead of inserting redundant ones
  • Bold+italic detection — correctly detects and toggles ***combined*** markers in toolbar state
  • List-aware formatting — applies inline formatting per-line in lists, protecting - and N. prefixes from being wrapped
  • Enter key list continuation — auto-inserts next bullet/number on Enter; exits list on empty item
  • Line-scoped detection — format detection respects line boundaries to prevent cross-line false positives
  • Double-click guard — prevents toolbar double-clicks from selecting all textarea content
  • Toolbar styling — adjusted spacing and padding for editing mode

Flow

flowchart TD
    A[User action: click toolbar / keyboard shortcut] --> B{Has selection?}
    B -->|No| C{Cursor inside formatted region?}
    C -->|Yes| D[Remove surrounding markers]
    C -->|No| E{On list line?}
    E -->|Yes| F[Wrap line content after prefix]
    E -->|No| G[Insert empty markers at cursor]
    B -->|Yes| H{Multi-line with list items?}
    H -->|Yes| I[Apply formatting per-line, protect prefixes]
    H -->|No| J[Wrap/unwrap selection]
    D --> K[Update activeFormats + set cursor via rAF]
    F --> K
    G --> K
    I --> K
    J --> K
Loading

Testing

  • pnpm run test passes (67 suites, 1344 tests)
  • pnpm run typecheck passes
  • pnpm run lint passes
  • Manual testing performed
  • Unit tests added (61 tests for markdownFormatting, 10 for FormattingToolbar component)

@david-rios-uipath
Copy link
Copy Markdown
Contributor Author

david-rios-uipath commented Mar 31, 2026

@github-actions
Copy link
Copy Markdown

Dependency License Review

  • 1924 package(s) scanned
  • ✅ No license issues found
  • ⚠️ 3 package(s) excluded (see details below)
License distribution
License Packages
MIT 1689
ISC 89
Apache-2.0 56
BSD-3-Clause 28
BSD-2-Clause 23
BlueOak-1.0.0 8
MPL-2.0 5
MIT OR Apache-2.0 3
MIT-0 3
CC0-1.0 3
LGPL-3.0-or-later 2
(MIT OR Apache-2.0) 2
Unlicense 2
Python-2.0 1
CC-BY-4.0 1
(MPL-2.0 OR Apache-2.0) 1
Unknown 1
Artistic-2.0 1
(WTFPL OR MIT) 1
(BSD-2-Clause OR MIT OR Apache-2.0) 1
CC-BY-3.0 1
0BSD 1
(MIT OR CC0-1.0) 1
MIT AND ISC 1
Excluded packages
Package Version License Reason
@img/sharp-libvips-linux-x64 1.2.4 LGPL-3.0-or-later LGPL pre-built binary, not linked
@img/sharp-libvips-linuxmusl-x64 1.2.4 LGPL-3.0-or-later LGPL pre-built binary, not linked
khroma 2.1.0 Unknown MIT per GitHub repo, missing license field in package.json

@david-rios-uipath david-rios-uipath changed the title feat(apollo-react): add formatting toolbar to sticky notes feat(apollo-react): add formatting toolbar to sticky notes (2/2) Mar 31, 2026
@david-rios-uipath david-rios-uipath force-pushed the feat/sticky-note-formatting-toolbar-v2 branch from 7b1fbea to 9b603ca Compare March 31, 2026 14:15
@david-rios-uipath david-rios-uipath force-pushed the feat/sticky-note-markdown-formatting branch 2 times, most recently from ca92f6e to 15037a1 Compare March 31, 2026 14:19
Add FormattingToolbar component and integrate markdown formatting
into the StickyNoteNode editor.

- FormattingToolbar with bold, italic, strikethrough, bullet list,
  and numbered list buttons with ApTooltip
- Keyboard shortcuts (Cmd+B, Cmd+I, Cmd+Shift+X) via useMarkdownShortcuts
- Active format detection updates on cursor movement and selection
- Enter key continues bullet and numbered lists with auto-increment
- Updated StickyNoteNode layout to flex column for toolbar + textarea

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@david-rios-uipath david-rios-uipath force-pushed the feat/sticky-note-formatting-toolbar-v2 branch from 9b603ca to 293d428 Compare March 31, 2026 14:20
@david-rios-uipath david-rios-uipath marked this pull request as ready for review March 31, 2026 14:25
@david-rios-uipath david-rios-uipath changed the title feat(apollo-react): add formatting toolbar to sticky notes (2/2) feat(apollo-react): add formatting toolbar to sticky notes (2/3) Mar 31, 2026
@david-rios-uipath david-rios-uipath changed the title feat(apollo-react): add formatting toolbar to sticky notes (2/3) feat(apollo-react): add formatting toolbar to sticky notes (2/3) [MST-7636] Mar 31, 2026
onMouseDown={(e) => e.preventDefault()}
className="nodrag nowheel"
>
<ApTooltip content="Bold (⌘B)" placement="top" delay>
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need plan for localization..
also the icons need to be platform specific, not all on

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some util..

/**
 * Returns true if the current platform is macOS
 */
export const isMac = (): boolean => {
  return typeof navigator !== 'undefined' && navigator.platform.includes('Mac');
};

/**
 * Returns the platform-specific modifier key symbol
 * - Mac: ⌘ (Command)
 * - Windows/Linux: Ctrl
 */
export const getModifierKey = (): string => {
  return isMac() ? '⌘' : 'Ctrl';
};

Copy link
Copy Markdown
Contributor Author

@david-rios-uipath david-rios-uipath Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the guidance here (added platform-specific logic).

I created an exploratory PR (link here) adding localization scaffolding to apollo-react canvas components in general as a potential follow-up task, since we don't have any atm.

A Lingui config change was needed to ensure compatibility w/ Storybook (changing compilation from cjs -> esm so it's more readily compatible w/ Vite).

These changes are quite invasive; while this doesn't break/affect the ApChat component (only Lingui consumer atm), I want to understand why we had Lingui configured to compile to cjs to make sure I'm not introducing any regressions (can probably sync w/ Cristi on this next week, since it's not urgent imo).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants