From 05c055e010c0e3383b3fe435da6b137423b0893e Mon Sep 17 00:00:00 2001 From: Rafetikus Date: Wed, 15 Apr 2026 10:54:55 +0400 Subject: [PATCH 1/6] style(stickies): apply placeholder text color to checked checklist items --- ui/src/components/stickies/StickyNoteCard.tsx | 2 +- ui/src/index.css | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/ui/src/components/stickies/StickyNoteCard.tsx b/ui/src/components/stickies/StickyNoteCard.tsx index 7b9de0ed..d600f84a 100644 --- a/ui/src/components/stickies/StickyNoteCard.tsx +++ b/ui/src/components/stickies/StickyNoteCard.tsx @@ -326,7 +326,7 @@ export function StickyNoteCard({
{contentSaveError ? ( diff --git a/ui/src/index.css b/ui/src/index.css index 049853ec..c2faae78 100644 --- a/ui/src/index.css +++ b/ui/src/index.css @@ -82,3 +82,22 @@ .border-r-column-subtle { border-right: 1px solid color-mix(in srgb, var(--border-subtle) 45%, transparent); } + +/* Sticky checklist: checked items get placeholder-colored text (matches Plane) */ +.sticky-note-editor-content ul[data-type='taskList'] li[data-checked='true'] > div > p { + color: var(--txt-placeholder); + transition: color 0.2s ease; +} + +.sticky-note-editor-content ul[data-type='taskList'] li[data-checked='true'] > div { + color: var(--txt-placeholder); + transition: color 0.2s ease; +} + +.sticky-note-editor-content ul[data-type='taskList'] li > div > p { + transition: color 0.2s ease; +} + +.sticky-note-editor-content ul[data-type='taskList'] li > div { + transition: color 0.2s ease; +} From acb57e05d06b01c2e4713660eb77af6c401806db Mon Sep 17 00:00:00 2001 From: Rafetikus Date: Wed, 15 Apr 2026 11:17:00 +0400 Subject: [PATCH 2/6] feat(stickies): add tooltip to editor buttons showing action, platform-specific keyboard shortcuts --- ui/src/components/stickies/StickyNoteCard.tsx | 117 ++++++++++++------ 1 file changed, 77 insertions(+), 40 deletions(-) diff --git a/ui/src/components/stickies/StickyNoteCard.tsx b/ui/src/components/stickies/StickyNoteCard.tsx index d600f84a..32cfef37 100644 --- a/ui/src/components/stickies/StickyNoteCard.tsx +++ b/ui/src/components/stickies/StickyNoteCard.tsx @@ -5,6 +5,7 @@ import { TaskItem } from '@tiptap/extension-task-item'; import { TaskList } from '@tiptap/extension-task-list'; import StarterKit from '@tiptap/starter-kit'; import type { StickyApiResponse } from '../../api/types'; +import { Tooltip } from '../ui/Tooltip'; import { stickiesService } from '../../services/stickiesService'; import { STICKY_BACKGROUND_COLORS_DARK, @@ -314,6 +315,11 @@ export function StickyNoteCard({ const tb = 'rounded p-1 text-(--txt-icon-tertiary) hover:bg-(--bg-layer-transparent-hover) disabled:opacity-40'; + const isMac = typeof navigator !== 'undefined' && /mac|iphone|ipad|ipod/i.test(navigator.platform); + const modKey = isMac ? 'Cmd' : 'Ctrl'; + const boldShortcut = `${modKey} + B`; + const italicShortcut = `${modKey} + I`; + const todoShortcut = `${modKey} + Shift + 9`; if (!editor) return null; if (!safeSlug) return null; @@ -337,17 +343,19 @@ export function StickyNoteCard({
- + + + {colorOpen && (
)}
- -
+ } > - - - + + +

Italic

+

{italicShortcut}

+
+ } > - - - + + +

To-do list

+

{todoShortcut}

+ + } > - - + +
+ + + ); From 24b05814967334e21e1dc616684f8a2dc3f10d0d Mon Sep 17 00:00:00 2001 From: Rafetikus Date: Wed, 15 Apr 2026 11:23:22 +0400 Subject: [PATCH 3/6] style(formatting): reformat isMac constant declaration for readability --- ui/src/components/stickies/StickyNoteCard.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ui/src/components/stickies/StickyNoteCard.tsx b/ui/src/components/stickies/StickyNoteCard.tsx index 32cfef37..9c7736a0 100644 --- a/ui/src/components/stickies/StickyNoteCard.tsx +++ b/ui/src/components/stickies/StickyNoteCard.tsx @@ -315,7 +315,8 @@ export function StickyNoteCard({ const tb = 'rounded p-1 text-(--txt-icon-tertiary) hover:bg-(--bg-layer-transparent-hover) disabled:opacity-40'; - const isMac = typeof navigator !== 'undefined' && /mac|iphone|ipad|ipod/i.test(navigator.platform); + const isMac = + typeof navigator !== 'undefined' && /mac|iphone|ipad|ipod/i.test(navigator.platform); const modKey = isMac ? 'Cmd' : 'Ctrl'; const boldShortcut = `${modKey} + B`; const italicShortcut = `${modKey} + I`; From 545de4886fc15d71581f97615bc7e055d017ee17 Mon Sep 17 00:00:00 2001 From: Rafetikus Date: Wed, 15 Apr 2026 11:49:55 +0400 Subject: [PATCH 4/6] refactor(css): consolidate sticky note editor task list color transitions --- ui/src/index.css | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/ui/src/index.css b/ui/src/index.css index c2faae78..0af9ff46 100644 --- a/ui/src/index.css +++ b/ui/src/index.css @@ -84,20 +84,11 @@ } /* Sticky checklist: checked items get placeholder-colored text (matches Plane) */ -.sticky-note-editor-content ul[data-type='taskList'] li[data-checked='true'] > div > p { - color: var(--txt-placeholder); - transition: color 0.2s ease; -} - .sticky-note-editor-content ul[data-type='taskList'] li[data-checked='true'] > div { color: var(--txt-placeholder); - transition: color 0.2s ease; } +.sticky-note-editor-content ul[data-type='taskList'] li > div, .sticky-note-editor-content ul[data-type='taskList'] li > div > p { transition: color 0.2s ease; } - -.sticky-note-editor-content ul[data-type='taskList'] li > div { - transition: color 0.2s ease; -} From 0e696621fdab8becc1aa592acc14e4ce832b6741 Mon Sep 17 00:00:00 2001 From: Rafetikus Date: Wed, 15 Apr 2026 12:04:01 +0400 Subject: [PATCH 5/6] refactor(stickies): wrap delete button in div for proper margin alignment --- ui/src/components/stickies/StickyNoteCard.tsx | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/ui/src/components/stickies/StickyNoteCard.tsx b/ui/src/components/stickies/StickyNoteCard.tsx index 9c7736a0..12367cdf 100644 --- a/ui/src/components/stickies/StickyNoteCard.tsx +++ b/ui/src/components/stickies/StickyNoteCard.tsx @@ -437,16 +437,18 @@ export function StickyNoteCard({ - - - +
+ + + +
); From cccd78048ca268c86fc705e0e7af781130c56fd9 Mon Sep 17 00:00:00 2001 From: Rafetikus Date: Wed, 15 Apr 2026 12:23:56 +0400 Subject: [PATCH 6/6] feat(a11y): dynamically add aria-describedby to focusable tooltip triggers --- ui/src/components/ui/Tooltip.tsx | 41 +++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/ui/src/components/ui/Tooltip.tsx b/ui/src/components/ui/Tooltip.tsx index 4a99ff80..70bcdeb6 100644 --- a/ui/src/components/ui/Tooltip.tsx +++ b/ui/src/components/ui/Tooltip.tsx @@ -43,6 +43,23 @@ function computeStyle(el: HTMLElement, placement: TooltipPlacement): CSSProperti }; } +function mergeDescribedBy(existing: string | null, token: string): string { + const parts = (existing || '') + .split(/\s+/) + .map((s) => s.trim()) + .filter(Boolean); + if (!parts.includes(token)) parts.push(token); + return parts.join(' '); +} + +function removeDescribedBy(existing: string | null, token: string): string | null { + const next = (existing || '') + .split(/\s+/) + .map((s) => s.trim()) + .filter((s) => s && s !== token); + return next.length ? next.join(' ') : null; +} + export function Tooltip({ content, children, @@ -90,7 +107,7 @@ export function Tooltip({ }, [clearDelay]); const hideIfLeavingTrigger = useCallback( - (e: FocusEvent) => { + (e: FocusEvent) => { const next = e.relatedTarget as Node | null; if (next && e.currentTarget.contains(next)) return; hide(); @@ -112,6 +129,28 @@ export function Tooltip({ }; }, [open, updatePosition]); + useEffect(() => { + const root = triggerRef.current; + if (!root) return; + const focusable = root.querySelector( + 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])', + ); + if (!focusable) return; + + if (open) { + const next = mergeDescribedBy(focusable.getAttribute('aria-describedby'), id); + focusable.setAttribute('aria-describedby', next); + return; + } + + const next = removeDescribedBy(focusable.getAttribute('aria-describedby'), id); + if (next) { + focusable.setAttribute('aria-describedby', next); + } else { + focusable.removeAttribute('aria-describedby'); + } + }, [open, id]); + return ( <>