mirror of
https://github.com/stablyai/orca
synced 2026-04-21 14:17:16 +00:00
style(rich-md): show pointer cursor on links only while modifier held (#814)
Rich markdown links open on Cmd/Ctrl-click (plain click must place the caret inside contenteditable). Toggle a root class on keydown/keyup of the platform modifier so the pointer cursor appears only while the modifier is held, matching VS Code's link affordance.
This commit is contained in:
parent
58b43e0d17
commit
159081c2e6
3 changed files with 55 additions and 0 deletions
|
|
@ -490,6 +490,15 @@
|
|||
text-decoration: underline;
|
||||
text-decoration-color: color-mix(in srgb, currentColor 40%, transparent);
|
||||
text-underline-offset: 2px;
|
||||
}
|
||||
|
||||
/* Why: plain click places the caret inside the contenteditable region, so the
|
||||
link only activates on Cmd/Ctrl-click. Surface the pointer affordance only
|
||||
while that modifier is held so users can discover it without being misled
|
||||
into expecting a plain click to open. Class is toggled by RichMarkdownEditor
|
||||
in response to keydown/keyup of the platform modifier. */
|
||||
.rich-markdown-mod-held .rich-markdown-editor a,
|
||||
.rich-markdown-mod-held .rich-markdown-editor .ProseMirror a {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import {
|
|||
} from './RichMarkdownLinkBubble'
|
||||
import { useLinkBubble } from './useLinkBubble'
|
||||
import { useEditorScrollRestore } from './useEditorScrollRestore'
|
||||
import { useModifierHeldClass } from './useModifierHeldClass'
|
||||
import { registerPendingEditorFlush } from './editor-pending-flush'
|
||||
import { createRichMarkdownKeyHandler } from './rich-markdown-key-handler'
|
||||
import { normalizeSoftBreaks } from './rich-markdown-normalize'
|
||||
|
|
@ -314,6 +315,8 @@ export default function RichMarkdownEditor({
|
|||
|
||||
useEditorScrollRestore(scrollContainerRef, scrollCacheKey, editor)
|
||||
|
||||
useModifierHeldClass(rootRef, isMac)
|
||||
|
||||
// Why: the custom Image extension reads filePath from editor.storage to resolve
|
||||
// relative image src values to file:// URLs for display. After updating the
|
||||
// stored path we dispatch a no-op transaction so ProseMirror re-renders image
|
||||
|
|
|
|||
43
src/renderer/src/components/editor/useModifierHeldClass.ts
Normal file
43
src/renderer/src/components/editor/useModifierHeldClass.ts
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
import { useEffect, type RefObject } from 'react'
|
||||
|
||||
// Why: plain click inside a contenteditable places the caret, so markdown links
|
||||
// only open on Cmd/Ctrl-click. Toggling this class while the platform modifier
|
||||
// is held lets CSS surface a pointer cursor only at that moment — matching
|
||||
// VS Code's link affordance without misleading the user into expecting a plain
|
||||
// click to open.
|
||||
export function useModifierHeldClass(
|
||||
targetRef: RefObject<HTMLElement | null>,
|
||||
isMac: boolean,
|
||||
className = 'rich-markdown-mod-held'
|
||||
): void {
|
||||
useEffect(() => {
|
||||
const target = targetRef.current
|
||||
if (!target) {
|
||||
return
|
||||
}
|
||||
const modKey = isMac ? 'Meta' : 'Control'
|
||||
const update = (pressed: boolean): void => {
|
||||
target.classList.toggle(className, pressed)
|
||||
}
|
||||
const onKeyDown = (e: KeyboardEvent): void => {
|
||||
if (e.key === modKey) {
|
||||
update(true)
|
||||
}
|
||||
}
|
||||
const onKeyUp = (e: KeyboardEvent): void => {
|
||||
if (e.key === modKey) {
|
||||
update(false)
|
||||
}
|
||||
}
|
||||
const onBlur = (): void => update(false)
|
||||
window.addEventListener('keydown', onKeyDown)
|
||||
window.addEventListener('keyup', onKeyUp)
|
||||
window.addEventListener('blur', onBlur)
|
||||
return () => {
|
||||
window.removeEventListener('keydown', onKeyDown)
|
||||
window.removeEventListener('keyup', onKeyUp)
|
||||
window.removeEventListener('blur', onBlur)
|
||||
update(false)
|
||||
}
|
||||
}, [targetRef, isMac, className])
|
||||
}
|
||||
Loading…
Reference in a new issue