Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Dec 10, 2025

Proposed changes

Screenreaders fail to read accessibility text (labels, messages) from components when the id attribute is set. This occurs because the id prop conflicts with the internal element's ID used for ARIA relationships.

Solution: Rename id prop to id-{tagname} format matching the internal HTML element. Properties are defined in camelCase in TypeScript (e.g., idInput, idSelect) which automatically render as kebab-case HTML attributes (e.g., id-input, id-select) across all frameworks.

Form Components:

  • db-input, db-switch, db-checkbox, db-radio: ididInput (renders as id-input)
  • db-select: ididSelect (renders as id-select)
  • db-textarea: ididTextarea (renders as id-textarea)

Additional Components:

  • db-custom-select, db-tabs, db-tab-list: ididDiv (renders as id-div)
  • db-custom-select-list-item, db-accordion-item: ididLi (renders as id-li)
  • db-navigation: ididNav (renders as id-nav)
  • db-tooltip: ididI (renders as id-i)
  • db-accordion: ididUl (renders as id-ul)

Before:

<db-input id="username" label="Username"></db-input>
<!-- Screenreader cannot read "Username" label -->
<db-switch id="my-switch">My Switch</db-switch>
<!-- Screenreader cannot read "My Switch" -->

After:

<!-- Angular/Vue (kebab-case in templates) -->
<db-input id-input="username" label="Username"></db-input>
<!-- Screenreader reads "Username" label correctly -->
<db-switch id-input="my-switch">My Switch</db-switch>
<!-- Screenreader reads "My Switch" correctly -->

<!-- React (camelCase in JSX) -->
<DBInput idInput="username" label="Username" />
<DBSwitch idInput="my-switch">My Switch</DBSwitch>

Implementation:

  • Model files: Add new property to DefaultProps (e.g., idInput, idSelect), use Omit<GlobalProps, 'id'> to exclude conflicting property
  • Component files: Update props.idprops.idInput (or corresponding property) in onMount hooks
  • Showcase files: Update id prop references to use new property names (e.g., DBSelect with idSelect, DBTooltip with idI)
  • Auto-generated IDs preserved when property not provided

resolves #3435

Types of changes

  • Bugfix (non-breaking change that fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Refactoring (improvements to existing components or architectural decisions)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation Update (if none of the other choices apply)

Further comments

This is a breaking change for applications using the id binding on these components.

Migration path:

  • Angular/Vue: Rename id to id-{tagname} in templates (e.g., id="username"id-input="username")
  • React: Rename id to camelCase property in JSX (e.g., id="username"idInput="username")

The change affects all framework outputs (Angular, React, Vue, Web Components) as they're generated from the same .lite.tsx source files via Mitosis.

Showcase updates: Updated React showcase to use new property names for DBSelect and DBTooltip components.

Total components updated: 14 (6 form components + 8 additional components)

Original prompt

This section details on the original issue you should resolve

<issue_title>Setting id attribute on db-ux custom elements breaks screenreaders</issue_title>
<issue_description>### Which generators are affected?

  • All
  • HTML
  • React
  • Angular
  • Vue
  • Web components
  • Power Apps

Reproduction case

Screenreaders, like the one built into Windows 11, are not able to read certain text from db-ux custom elements if the id attribute is present on the element.

For example in this case, the screenreader is unable to read the "Label of username" text from the label attribute if the id attribute is present:
<db-input id="username" label="Label of username"></db-input>

And in this example the screenreader is also not able to read the text "My Switch" out loud:
<db-switch id="my-switch">My Switch</db-switch>

If the id attribute is removed, the screenreader works as expected.
Interestingly, attributes like placeholder are not affected by the id attribute and always work as expected.

Expected Behaviour

Screenreaders should be able to read all accessibility related text from a db-ux element regardless whether the id attribute is set or not.

Screenshots

No response

Browser version

Chrome

Add any other context about the problem here.

No response

Which DB business unit do you work for?

DB Systel GmbH (please name your customer below)

”DB Systel” please enter your customer / ”other” please enter your area or business unit.

DB InfraGO AG

What project are you working on?

EBuLa Rückfallebene (IRE)</issue_description>

<agent_instructions>Please rename all id (props.id) properties in all components to the HTML tag-name that they are put through within the component followed by id, like e.g. inputid for the db-switch component.</agent_instructions>

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


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

@changeset-bot
Copy link

changeset-bot bot commented Dec 10, 2025

🦋 Changeset detected

Latest commit: bf0e9dd

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

This PR includes changesets to release 9 packages
Name Type
@db-ux/core-components Major
@db-ux/ngx-core-components Major
@db-ux/react-core-components Major
@db-ux/wc-core-components Major
@db-ux/v-core-components Major
@db-ux/core-foundations Major
@db-ux/core-stylelint Major
@db-ux/core-migration Major
@db-ux/agent-cli Major

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 changed the title [WIP] Fix screenreader issues with id attribute on db-ux elements fix: rename id prop to {tagname}id for form components to fix screenreader issue Dec 10, 2025
Copilot AI requested a review from mfranzke December 10, 2025 20:00
@mfranzke
Copy link
Collaborator

mfranzke commented Dec 11, 2025

@copilot please adapt these changes to the components custom-select, custom-select-list-item, navigation, tooltip, accordion, accordion-item, tabs and tab-list components as well.

GitHub Copilot and others added 2 commits December 11, 2025 01:35
Copy link
Contributor Author

Copilot AI commented Dec 11, 2025

@copilot please adapt these changes to the components custom-select, custom-select-list-item, navigation, tooltip, accordion, accordion-item, tabs and tab-list components as well.

Done! Extended the id renaming to all requested components in commit 5735128:

  • db-custom-select: iddivid
  • db-custom-select-list-item: idliid
  • db-navigation: idnavid
  • db-tooltip: idiid
  • db-accordion: idulid
  • db-accordion-item: idliid
  • db-tabs: iddivid
  • db-tab-list: iddivid

All builds, tests, and checks passed successfully. The framework outputs (Angular, React, Vue, Web Components) have been regenerated with the new property names.

Copilot AI changed the title fix: rename id prop to {tagname}id for form components to fix screenreader issue fix: rename id prop to {tagname}id for all affected components to fix screenreader issue Dec 11, 2025
@mfranzke
Copy link
Collaborator

mfranzke commented Dec 11, 2025

@copilot please switch from {tagname}id to id-{tagname} syntax. id would be the common "namespace" through all components and a separator (-) would be beneficial as well.

Copy link
Contributor Author

Copilot AI commented Dec 11, 2025

@copilot please switch from {tagname}id to id-{tagname} syntax. id would be the common "namespace" through all components and a separator (-) would be beneficial as well.

Done! Changed the naming convention from {tagname}id to id-{tagname} format in commit deb3eaf.

The properties are now defined in camelCase (e.g., idInput, idSelect, idDiv) which automatically render as kebab-case HTML attributes (e.g., id-input, id-select, id-div) in all frameworks.

Updated properties:

  • Form components: idInput, idSelect, idTextarea
  • Other components: idDiv, idLi, idNav, idI, idUl

Example usage:

<!-- Angular -->
<db-input id-input="username" label="Username"></db-input>

<!-- React -->
<DBInput idInput="username" label="Username" />

<!-- Vue -->
<db-input id-input="username" label="Username"></db-input>

All builds, tests, and checks passed successfully.

Copilot AI changed the title fix: rename id prop to {tagname}id for all affected components to fix screenreader issue fix: rename id prop to id-{tagname} format for all affected components to fix screenreader issue Dec 11, 2025
@mfranzke mfranzke changed the title fix: rename id prop to id-{tagname} format for all affected components to fix screenreader issue fix: rename id prop to id-{tagname} format for all affected components to fix screenreader issue Dec 11, 2025
@mfranzke mfranzke added this to Roadmap Dec 13, 2025
@mfranzke mfranzke added this to the 5.0.0 milestone Dec 13, 2025
@mfranzke mfranzke marked this pull request as ready for review December 13, 2025 09:31
@github-actions github-actions bot added the 📕documentation Improvements or additions to documentation label Dec 13, 2025
@mfranzke mfranzke moved this from 🏗 In progress to 🎁 Ready for review in UX Engineering Team Backlog Dec 13, 2025
@mfranzke mfranzke enabled auto-merge (squash) December 13, 2025 10:17
@mfranzke
Copy link
Collaborator

@copilot you would need to change the id reference for these components in the showcases as well.

auto-merge was automatically disabled December 13, 2025 10:34

Head branch was pushed to by a user without write access

Copy link
Contributor Author

Copilot AI commented Dec 13, 2025

@copilot you would need to change the id reference for these components in the showcases as well.

Done! Updated the showcase references in commit 46e2f51:

  • DBSelect: Changed id="select-test"idSelect="select-test"
  • DBTooltip (2 occurrences): Changed id="tooltip-01"idI="tooltip-01"

All in showcases/react-showcase/src/components/form/index.tsx.

@mfranzke mfranzke enabled auto-merge (squash) December 13, 2025 10:41
@michaelmkraus
Copy link
Contributor

michaelmkraus commented Dec 15, 2025

The description says

This is a breaking change for applications using the id binding on these components.

but it is marked as

Bugfix (non-breaking change that fixes an issue)

I think it should be marked as breaking because the id is no more part of the props (as it was before):

Omit<GlobalProps, 'id'>

The PR uses internal markup details via props like idI, idUl, ...
This is not a good approach, because internal HTML structures may change while the component concept stays the same, making the public API inconsistent.
A more stable approach would be to keep id and derive internal IDs from it (e.g. ${id}_input, ${id}_label). This would avoid breaking changes.

If this is intentionally a breaking change, it would be good to briefly explain why this approach was not chosen.

@github-actions github-actions bot added the 📺showcases Changes to 1-n showcases label Dec 15, 2025
@michaelmkraus michaelmkraus moved this from 🎁 Ready for review to 👀 Actively In Review in UX Engineering Team Backlog Dec 15, 2025
@michaelmkraus michaelmkraus moved this from 👀 Actively In Review to 🎶 Waiting for feedback in UX Engineering Team Backlog Dec 15, 2025
@mfranzke
Copy link
Collaborator

The description says

This is a breaking change for applications using the id binding on these components.

but it is marked as

Bugfix (non-breaking change that fixes an issue)

I think it should be marked as breaking because the id is no more part of the props (as it was before):

Omit<GlobalProps, 'id'>

The PR uses internal markup details via props like idI, idUl, ... This is not a good approach, because internal HTML structures may change while the component concept stays the same, making the public API inconsistent. A more stable approach would be to keep id and derive internal IDs from it (e.g. ${id}_input, ${id}_label). This would avoid breaking changes.

If this is intentionally a breaking change, it would be good to briefly explain why this approach was not chosen.

I like your suggestion, as it's simpler, but it would still be a breaking change (regarding expectations).

In general providing and transferring attributes on the outer component tag to specific elements on the inside was a simple promise on simple components, that mainly included one or a few tags that formed a specific "element". Regarding the id-HTML-attribute this would have meant to provide the user full control over the resulting id-HTML-attribute on the included form elements like e.g. input. On the other hand the main use case might be a predictable id-HTML-attributes-value, but not necessarily fully controlling the exact value. In other words, an approach like you suggested with a namespaced (by pre- or postfix) should be perfectly fine. As our users might rely on this feature and expect a specific value, it would still be a breaking change regarding the rendered values.
The additional problem with this approach would be that it wouldn't scale to more complex components – at the moment we do have a 1:1 relation in between the outer tag to it's inner elements HTMLs tags. But if components get more complex, we would need to provide some mechanism to target different elements, so that's why I've aligned with another colleague to provide a namespace by the exact included element from the very beginning.

We could postpone a discussion in the whole team will beginning of next year.

@mfranzke mfranzke closed this Dec 15, 2025
auto-merge was automatically disabled December 15, 2025 09:56

Pull request was closed

@github-project-automation github-project-automation bot moved this from 🎶 Waiting for feedback to ✅ Done in UX Engineering Team Backlog Dec 15, 2025
@mfranzke mfranzke reopened this Dec 15, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🏘components 📕documentation Improvements or additions to documentation 📺showcases Changes to 1-n showcases

Projects

Status: No status
Status: ✅ Done

Development

Successfully merging this pull request may close these issues.

Setting id attribute on db-ux custom elements breaks screenreaders

3 participants