Skip to content

feat: add accessible label wrapping for GFM task list checkboxes#792

Draft
Copilot wants to merge 4 commits intomainfrom
copilot/fix-gfm-checkboxes-semantics
Draft

feat: add accessible label wrapping for GFM task list checkboxes#792
Copilot wants to merge 4 commits intomainfrom
copilot/fix-gfm-checkboxes-semantics

Conversation

Copy link
Contributor

Copilot AI commented Jan 12, 2026

GFM task list checkboxes lack proper label association, causing accessibility issues flagged by Lighthouse and screen readers.

Changes

  • React: Added GfmTaskListItem component using React.useId (18+) with counter fallback for unique IDs
  • HTML: Added counter-based ID generation with <label for="..."> wrapping
  • SolidJS/Vue: Same pattern with global counters
  • Tests: Updated snapshots and added accessibility verification tests

Output

Before:

<li><input type="checkbox"/> Task text</li>

After:

<li><input id="task-1" type="checkbox"/><label for="task-1"> Task text</label></li>

Notes

  • HTML adapter uses disabled per GFM spec; React/Solid/Vue use readOnly for better form handling
  • Global counters ensure unique IDs within a JS context; _resetGfmTaskIdCounter() exposed for testing
Original prompt

This section details on the original issue you should resolve

<issue_title>GFM checkboxes need a small adjustment to make them semantically correct</issue_title>
<issue_description>### Description of the bug
When using markdown for making a tasks list, the checkboxes labels aren't parsed as labels but text nodes.

This is semantically incorrect, the text for each checkbox should be a <label> with the appropriate for and id. Not only it allows screen readers to announce what the checkbox actually means, but it also allows you to click on the label to select the checkbox (even if in this case it's not an option we want to give the user given the markdown conversion).

This bug is reported by Google Lighthouse (dev tools) when running accessibility assessment. It's also reported in other reputed accessibility tools.

Markdown used

Here are checkboxes

- [x] Checkbox on
- [ ] Checkbox off

Current HTML output

<ul>
    <li>
        <input type="checkbox" readonly="" checked="">
            Checkbox on
    </li>
    <li>
        <input type="checkbox" readonly="">
            Checkbox off
    </li>
</ul>

As you can see, it's rendering the checkbox text as a DOM Text Node instead of a <label>.

HTML ouput expected

<ul>
    <li>
        <input type="checkbox" readonly="" checked="" id="random-id-1">
        <label for="random-id-1">Checkbox on</label>
    </li>
    <li>
        <input type="checkbox" readonly="" id="random-id-2">
        <label for="random-id-2">Checkbox off</label>
    </li>
</ul>

Possible improvement

Given the <label> is directly linked to the checkbox, the default rendering for this <label> should probably done in the checkbox rendering function.

Not only does it makes it easier to link the id and the for attributes together, but it would also allow an easier time for users when they use component overrides.

Simply passing the text as a prop to the checkbox override would be sufficient. Semantically speaking, there shouldn't be any HTML element within the <label> from the markdown conversion, making it a simple string.</issue_description>

Comments on the Issue (you are @copilot in this section)

@quantizor Good idea

✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI self-assigned this Jan 12, 2026
@changeset-bot
Copy link

changeset-bot bot commented Jan 12, 2026

🦋 Changeset detected

Latest commit: 13f0a88

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
markdown-to-jsx Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Copilot AI and others added 3 commits January 12, 2026 03:35
- Added unique IDs to checkboxes using React.useId (React 18+) with fallback counter
- Wrapped checkbox labels in <label> elements with proper for/htmlFor attributes
- Updated React, HTML, SolidJS, and Vue adapters for accessibility
- Updated CommonMark spec expectations to reflect new accessible output

Co-authored-by: quantizor <570070+quantizor@users.noreply.github.com>
…lity

- Added comment explaining disabled vs readOnly attribute difference between HTML/React
- Added comments explaining global counter behavior for ID generation
- Added new tests for accessibility (id/for matching, formatted content in labels)

Co-authored-by: quantizor <570070+quantizor@users.noreply.github.com>
Co-authored-by: quantizor <570070+quantizor@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix GFM checkboxes for semantic correctness feat: add accessible label wrapping for GFM task list checkboxes Jan 12, 2026
Copilot AI requested a review from quantizor January 12, 2026 03:42
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.

GFM checkboxes need a small adjustment to make them semantically correct

2 participants