mirror of
https://github.com/callumalpass/tasknotes.git
synced 2026-07-22 12:50:26 +00:00
refactor: consolidate CodeMirror widget cursor styles into reusable utility
Extracted duplicated cursor-hiding CSS from widget files into a single .cm-widget-cursor-fix utility class. Uses minimal approach that only hides widget buffer artifacts and prevents editing inside widgets, without hiding the editor cursor. Changes: - Created .cm-widget-cursor-fix utility class in utilities.css - Applied utility class to task-card-note-widget and project-note-subtasks - Removed 150+ lines of duplicated CSS across widget files - Simplified widget-specific CSS to only styling concerns Benefits: - DRY principle: Single source of truth for widget behavior - Maintainability: Update widget fixes in one place - Consistency: All widgets use same approach - Smaller bundle: Removed redundant CSS rules - Better UX: Preserves cursor visibility and normal navigation This approach only hides the widget buffer image artifact (the actual visual bug) and prevents text selection inside widgets, without interfering with normal editor cursor behavior or navigation.
This commit is contained in:
parent
2136e3d973
commit
3d54ddd393
5 changed files with 51 additions and 159 deletions
|
|
@ -141,7 +141,7 @@ export class ProjectSubtasksWidget extends WidgetType {
|
|||
this.editorView = view;
|
||||
|
||||
const container = document.createElement("div");
|
||||
container.className = "tasknotes-plugin project-note-subtasks project-subtasks-widget";
|
||||
container.className = "tasknotes-plugin project-note-subtasks project-subtasks-widget cm-widget-cursor-fix";
|
||||
|
||||
container.setAttribute("contenteditable", "false");
|
||||
container.setAttribute("spellcheck", "false");
|
||||
|
|
@ -1008,7 +1008,7 @@ class ProjectNoteDecorationsPlugin implements PluginValue {
|
|||
notePath,
|
||||
this.version
|
||||
),
|
||||
side: 1, // Place widget after the position so cursor can't go past it
|
||||
side: 1,
|
||||
});
|
||||
|
||||
builder.add(insertPos, insertPos, widget);
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ export class TaskCardWidget extends WidgetType {
|
|||
|
||||
toDOM(view: EditorView): HTMLElement {
|
||||
const container = document.createElement("div");
|
||||
container.className = "tasknotes-plugin task-card-note-widget";
|
||||
container.className = "tasknotes-plugin task-card-note-widget cm-widget-cursor-fix";
|
||||
|
||||
container.setAttribute("contenteditable", "false");
|
||||
container.setAttribute("spellcheck", "false");
|
||||
|
|
@ -312,7 +312,7 @@ class TaskCardNoteDecorationsPlugin implements PluginValue {
|
|||
|
||||
const widget = Decoration.widget({
|
||||
widget: new TaskCardWidget(this.plugin, this.cachedTask, this.version),
|
||||
side: 1, // Place widget after the position so cursor can't go past it
|
||||
side: 1,
|
||||
});
|
||||
|
||||
builder.add(insertPos, insertPos, widget);
|
||||
|
|
|
|||
|
|
@ -13,86 +13,10 @@
|
|||
border: 1px dashed var(--background-modifier-border-hover);
|
||||
border-radius: var(--radius-s);
|
||||
clear: both;
|
||||
position: relative;
|
||||
z-index: 10; /* Higher z-index to allow dropdowns to appear above other content */
|
||||
|
||||
|
||||
/* Allow filter dropdowns to extend beyond widget boundaries */
|
||||
overflow: visible !important;
|
||||
|
||||
/* Prevent cursor and editing issues */
|
||||
pointer-events: auto;
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
cursor: default;
|
||||
|
||||
/* Prevent contenteditable behavior */
|
||||
-webkit-user-modify: read-only;
|
||||
-moz-user-modify: read-only;
|
||||
|
||||
/* Ensure no text cursor appears */
|
||||
caret-color: transparent;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/* Hide CodeMirror widgetBuffer img when it's adjacent to our widget and our widget is on top of note (not last-child) */
|
||||
.cm-content > .cm-line:not(:last-child):has(.project-note-subtasks) img.cm-widgetBuffer {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Hide CodeMirror cursor when it's adjacent to our widget */
|
||||
.cm-line:has(.project-note-subtasks) .cm-cursor,
|
||||
.cm-line:has(.project-note-subtasks) + .cm-line .cm-cursor {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Alternative approach - hide cursor specifically around widget */
|
||||
.project-note-subtasks + .cm-cursor,
|
||||
.project-note-subtasks ~ .cm-cursor {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Hide cursor when widget is in focus context */
|
||||
.cm-focused .cm-line:has(.project-note-subtasks) .cm-cursor {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* More specific cursor hiding using new class and data attribute */
|
||||
.cm-line:has(.project-subtasks-widget) .cm-cursor,
|
||||
.cm-line:has([data-widget-type="project-subtasks"]) .cm-cursor {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Hide any cursor that appears after our widget */
|
||||
.project-subtasks-widget ~ .cm-cursor,
|
||||
[data-widget-type="project-subtasks"] ~ .cm-cursor {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Ensure widget creates proper isolation from editor cursor */
|
||||
.project-subtasks-widget {
|
||||
isolation: isolate;
|
||||
z-index: 10;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Hide cursor in the entire editor when widget is present and focused */
|
||||
.cm-editor:has(.project-subtasks-widget) .cm-cursor {
|
||||
opacity: 0 !important;
|
||||
visibility: hidden !important;
|
||||
}
|
||||
|
||||
/* Comprehensive cursor hiding - use as fallback */
|
||||
.cm-content:has(.project-subtasks-widget) .cm-cursor,
|
||||
.cm-scroller:has(.project-subtasks-widget) .cm-cursor {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Target cursor by position relative to widget */
|
||||
.project-subtasks-widget + * .cm-cursor,
|
||||
.project-subtasks-widget ~ * .cm-cursor {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.tasknotes-plugin .project-note-subtasks__header {
|
||||
|
|
|
|||
|
|
@ -1,89 +1,14 @@
|
|||
/* Task Card Note Widget Styles */
|
||||
/* Task Card Note Widget - minimal widget for inline task cards in notes */
|
||||
|
||||
.task-card-note-widget {
|
||||
/* Simple border container with a little padding - let task card handle its own styling */
|
||||
display: block;
|
||||
border-radius: var(--radius-s);
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
margin: var(--cs-spacing-md) 0;
|
||||
padding: var(--cs-spacing-sm);
|
||||
|
||||
/* Prevent cursor and editing issues */
|
||||
pointer-events: auto;
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
cursor: default;
|
||||
|
||||
/* Prevent contenteditable behavior */
|
||||
-webkit-user-modify: read-only;
|
||||
-moz-user-modify: read-only;
|
||||
|
||||
/* Ensure no text cursor appears */
|
||||
caret-color: transparent;
|
||||
outline: none;
|
||||
|
||||
}
|
||||
|
||||
.task-card-note-widget__card {
|
||||
/* Reset margins for the inner task card */
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
/* Hide CodeMirror widgetBuffer img when it's adjacent to our widget */
|
||||
.cm-content > .cm-line:has(.task-card-note-widget) img.cm-widgetBuffer {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Hide CodeMirror cursor when it's adjacent to our widget */
|
||||
.cm-line:has(.task-card-note-widget) .cm-cursor,
|
||||
.cm-line:has(.task-card-note-widget) + .cm-line .cm-cursor {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Alternative approach - hide cursor specifically around widget */
|
||||
.task-card-note-widget + .cm-cursor,
|
||||
.task-card-note-widget ~ .cm-cursor {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Hide cursor when widget is in focus context */
|
||||
.cm-focused .cm-line:has(.task-card-note-widget) .cm-cursor {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* More specific cursor hiding using new class and data attribute */
|
||||
.cm-line:has(.task-card-note-widget) .cm-cursor,
|
||||
.cm-line:has([data-widget-type="task-card"]) .cm-cursor {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Hide any cursor that appears after our widget */
|
||||
.task-card-note-widget ~ .cm-cursor,
|
||||
[data-widget-type="task-card"] ~ .cm-cursor {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Ensure widget creates proper isolation from editor cursor */
|
||||
.task-card-note-widget {
|
||||
isolation: isolate;
|
||||
z-index: 10;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Hide cursor in the entire editor when widget is present and focused */
|
||||
.cm-editor:has(.task-card-note-widget) .cm-cursor {
|
||||
opacity: 0 !important;
|
||||
visibility: hidden !important;
|
||||
}
|
||||
|
||||
/* Comprehensive cursor hiding - use as fallback */
|
||||
.cm-content:has(.task-card-note-widget) .cm-cursor,
|
||||
.cm-scroller:has(.task-card-note-widget) .cm-cursor {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Target cursor by position relative to widget */
|
||||
.task-card-note-widget + * .cm-cursor,
|
||||
.task-card-note-widget ~ * .cm-cursor {
|
||||
display: none !important;
|
||||
}
|
||||
|
|
@ -2299,3 +2299,46 @@
|
|||
border-radius: 50%;
|
||||
animation: tn-spin 0.8s linear infinite;
|
||||
}
|
||||
|
||||
|
||||
/* ================================================
|
||||
CODEMIRROR WIDGET UTILITIES
|
||||
================================================ */
|
||||
|
||||
/**
|
||||
* Widget Cursor Fix
|
||||
*
|
||||
* Minimal fix for CodeMirror widget artifacts.
|
||||
* Only prevents editing inside widgets and hides visual artifacts.
|
||||
* Does NOT hide the editor cursor to preserve normal editing experience.
|
||||
*
|
||||
* Fixes:
|
||||
* - Prevents text selection inside widgets
|
||||
* - Prevents contenteditable behavior
|
||||
* - Hides widget buffer image artifacts
|
||||
*
|
||||
* Trade-offs:
|
||||
* - Cursor may appear next to widgets (acceptable for normal editing UX)
|
||||
* - Widget buffer artifacts are hidden
|
||||
*
|
||||
* Usage: Add .cm-widget-cursor-fix to your widget container element
|
||||
*/
|
||||
.cm-widget-cursor-fix {
|
||||
/* Prevent text selection and editing inside widget */
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
|
||||
/* Prevent contenteditable behavior */
|
||||
-webkit-user-modify: read-only;
|
||||
-moz-user-modify: read-only;
|
||||
|
||||
/* Ensure no text cursor appears inside widget elements */
|
||||
caret-color: transparent;
|
||||
}
|
||||
|
||||
/* Hide CodeMirror widgetBuffer image artifacts only */
|
||||
.cm-content > .cm-line:has(.cm-widget-cursor-fix) img.cm-widgetBuffer {
|
||||
display: none !important;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue