Skip to content

fix(TaskItem): use div instead of label element as task item wrapper#8568

Merged
mejo- merged 2 commits into
mainfrom
fix/task_item_click
May 12, 2026
Merged

fix(TaskItem): use div instead of label element as task item wrapper#8568
mejo- merged 2 commits into
mainfrom
fix/task_item_click

Conversation

@mejo-
Copy link
Copy Markdown
Member

@mejo- mejo- commented May 11, 2026

📝 Summary

Fixes problems with more than one block node in task items. label elements have special click behaviour: clicking on them fires a second click on the their first "labelable" descendant.

This resulted in weird bugs when having e.g. a code block or image as second block node in a task item.

🏁 Checklist

  • Code is properly formatted (npm run lint / npm run stylelint / composer run cs:check)
  • Sign-off message is added to all commits

@mejo- mejo- self-assigned this May 11, 2026
@mejo- mejo- added bug Something isn't working feature: formatting - lists labels May 11, 2026
@github-project-automation github-project-automation Bot moved this to 🧭 Planning evaluation (don't pick) in 📝 Productivity team May 11, 2026
@mejo-
Copy link
Copy Markdown
Member Author

mejo- commented May 11, 2026

/backport to stable33

@mejo- mejo- moved this from 🧭 Planning evaluation (don't pick) to 🏗️ In progress in 📝 Productivity team May 11, 2026
@mejo- mejo- moved this from 🏗️ In progress to 👀 In review in 📝 Productivity team May 11, 2026
@mejo- mejo- force-pushed the fix/task_item_click branch from 6a91b76 to 666b36d Compare May 11, 2026 11:13
Comment thread src/nodes/TaskItem.ts Outdated
Comment on lines 52 to 63
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.

I think if you have an object that never changes you can get a very precise type annotation with Object.freeze for free:

Suggested change
const checkboxAttributes: Object.freeze({
type: 'checkbox',
class: '',
contenteditable: false,
...( node.attrs.checked ? { checked: true } : {} ),
})

In this case checkboxAttributes.type will not just be a string but the string checkbox and it will be readonly.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Interesting, I discussed this a bit with Claude and here's it's thoughts:

The argument is partially valid — Object.freeze does cause TypeScript to infer literal types and readonly modifiers. But it's the wrong tool for achieving that goal in TypeScript code.

The idiomatic solution: as const

const checkboxAttributes = {
    type: 'checkbox',
    class: '',
    contenteditable: false,
    ...(node.attrs.checked ? { checked: true } : {}),
} as const

Why as const is better than Object.freeze here:

_ Object.freeze as const
Literal type inference ('checkbox' not string) Yes Yes
readonly properties Yes Yes
Runtime overhead Yes (actual freeze operation) None (compile-time only)
Idiomatic TypeScript No Yes
Enforces immutability at runtime Yes (throws/silently fails) No

The key distinction: as const is a compile-time type assertion that achieves exactly the same typing benefits the author was after, with zero runtime cost. Object.freeze is a runtime operation that happens to also affect TypeScript's type inference as a side effect — that's backwards reasoning for a TypeScript codebase.

The fact that the object is never mutated after creation is a TypeScript-design concern, not a runtime concern. as const is the correct way to communicate and enforce that intent in the type system.

One nuance to be aware of: with a conditional spread and as const, TypeScript infers a union-ish type for the resulting object, so checked becomes true (literal) when present — which is actually more precise than the original checked?: true annotation. This is a genuine improvement.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I refactored it to use as const now and also fixed the tiptap.spec.js test.

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.

A nice... Did not know about as const. That's inded better.

@max-nextcloud
Copy link
Copy Markdown
Collaborator

I'm wondering if this has downsides in terms of accessibility. I checked but right now that extra click is not used, right? At least clicking the text of a task item does not (un-)check it.

mejo- added 2 commits May 12, 2026 10:04
Signed-off-by: Jonas <jonas@freesources.org>
Fixes problems with more than one block node in task items. `label`
elements have special click behaviour: clicking on them fires a second
click on the their first "labelable" descendant.

This resulted in weird bugs when having e.g. a code block or image as
second block node in a task item.

Fixes: #5225

Signed-off-by: Jonas <jonas@freesources.org>
@mejo- mejo- force-pushed the fix/task_item_click branch from 666b36d to 6a2a606 Compare May 12, 2026 08:05
@mejo-
Copy link
Copy Markdown
Member Author

mejo- commented May 12, 2026

I'm wondering if this has downsides in terms of accessibility. I checked but right now that extra click is not used, right? At least clicking the text of a task item does not (un-)check it.

Actually I think it's the other way round: accessibility improved as we no longer have label elements that lack a sibling element that they're the label for. The double click was actually a bug in my understanding.

@mejo- mejo- requested a review from max-nextcloud May 12, 2026 08:07
@codecov
Copy link
Copy Markdown

codecov Bot commented May 12, 2026

Codecov Report

❌ Patch coverage is 72.22222% with 5 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/nodes/TaskItem.ts 72.22% 3 Missing and 2 partials ⚠️

📢 Thoughts on this report? Let us know!

@mejo- mejo- merged commit d910c3f into main May 12, 2026
71 of 76 checks passed
@mejo- mejo- deleted the fix/task_item_click branch May 12, 2026 09:53
@github-project-automation github-project-automation Bot moved this from 👀 In review to ☑️ Done in 📝 Productivity team May 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working feature: formatting - lists

Projects

Status: ☑️ Done

Development

Successfully merging this pull request may close these issues.

Not possible to click into list item which also includes an image

2 participants