Hacktoberfest 2026:维护者为十月标记出来的 issue,仍然开放、适合新手。 浏览 Hacktoberfest issue

[ui5-dynamic-side-content]: accessibilityAttributes role "none"/"presentation" cannot remove the landmark because aria-label is always applied

未关闭 适合新手
#14,244 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

维护者通常 3 天内回复

还没有人认领这个 Issue。

评估

难度
2/5
预计耗时
1-3 小时
新手友好度
80/100
Issue 类型
缺陷
描述清晰度
描述清楚
活跃度
活跃
技术栈
html, typescript

调研方向

从 packages/fiori/src/DynamicSideContent.ts 开始,在 accInfo getter 中,sideContent 和主容器会构建 ariaLabel 和 role;注意 i18n 回退项 DSC_SIDE_ARIA_LABEL 和 DSC_MAIN_ARIA_LABEL。先解析 role,然后当该 role 为 none、presentation 或 undefined 时,对两个容器都移除 ariaLabel(以及 i18n 回退项)。完成意味着渲染出的 <aside> 不携带 aria-label(当设置了 role: "none" 时),并且无障碍树不再显示嵌套的 complementary landmark,需使用现有的 DynamicSideContent 测试进行验证。

由索引模型根据 Issue 内容生成。

描述

Bug Description

Follow-up to #13013 / PR #13476.

#13013 requested customizable ARIA roles for ui5-dynamic-side-content so it can be nested inside a page that already has a main landmark. PR #13476 added a role field to accessibilityAttributes and #13013 was closed as resolved.

However, the new role option cannot actually remove the landmark on the side (or main) container, so the original APG violation still occurs. Setting sideContent.role to "none"/"presentation" has no effect on the exposed landmark, because the component unconditionally applies a non-empty aria-label to the same element. Per the WAI-ARIA Presentational Roles Conflict Resolution, a role="none"/"presentation" element that also carries a global ARIA property such as aria-label has its presentational role ignored and its implicit role restored — so <aside> reverts to complementary.

Affected Component

ui5-dynamic-side-content

Expected Behaviour

When the resolved role of the main/side container is "none", "presentation", or undefined, the container should not be exposed as a landmark. Concretely, in that case the component should omit the container's aria-label (and skip the DSC_MAIN_ARIA_LABEL / DSC_SIDE_ARIA_LABEL i18n fallback), so that role="none" actually takes effect.

Isolated Example

No StackBlitz; the issue reproduces with plain markup (the web component renders exactly this into its shadow DOM). Minimal repro:

<main>
  <aside role="none" aria-label="Side Content">
    <div role="region" aria-label="Filter Panel">Filters</div>
  </aside>
</main>
Steps to Reproduce
  1. Render a ui5-dynamic-side-content inside a page that already exposes a main landmark.
  2. Set accessibilityAttributes = { sideContent: { role: "none" } } (or { role: undefined }).
  3. Inspect the computed accessibility tree (Chrome DevTools → Elements → Accessibility, or a screen reader's landmark list).
  4. Observe the side container is still exposed as a complementary landmark nested inside main.
Log Output, Stack Trace or Screenshots

Rendered side container (shadow DOM):

<aside role="none" aria-label="Side Content" class="ui5-dsc-side">…</aside>

Computed accessibility tree — landmark is still present, nested in main:

main
  complementary "Side Content"
    region "Filter Panel"

The only state that actually drops the landmark is role="none" with no aria-label:

main
  region "Filter Panel"      ← complementary gone, child region preserved

role: undefined does not help either: it only removes the role attribute, and a bare <aside> with an accessible name is still an implicit complementary landmark.

Priority

High

Environment Info

UI5 Web Components Version

@ui5/webcomponents-fiori 2.25.x (reproduced; accInfo unchanged on main as of filing)

Browser

Chrome

Operating System

macOS

Additional Info

Additional Context

Root cause — in accInfo (packages/fiori/src/DynamicSideContent.ts):

sideContent: {
  ariaLabel: sideContentAttr.ariaLabel || DynamicSideContent.i18nBundle.getText(DSC_SIDE_ARIA_LABEL),
  role: hasSideRole ? sideContentAttr.role : "complementary",
},

The role line is correct — passing role: "none" yields role="none" on the <aside>. The problem is the ariaLabel line above it: it is always truthy (falls back to the i18n default), and no prop value can blank it, so the presentational role is always nullified by conflict resolution.

Suggested fix (side shown; same for main):

const sideRole = hasSideRole ? sideContentAttr.role : "complementary";
const sidePresentational = sideRole === "none" || sideRole === "presentation" || sideRole === undefined;

sideContent: {
  ariaLabel: sidePresentational
    ? undefined
    : (sideContentAttr.ariaLabel || DynamicSideContent.i18nBundle.getText(DSC_SIDE_ARIA_LABEL)),
  role: sideRole,
},

Business impact — the SuccessFactors shell renders role="main" on the page content area, so any embedded DynamicSideContent produces a complementary (and previously a second main) landmark nested inside main — a WAI-ARIA APG violation flagged in accessibility audits. The role property from #13476 is the intended mitigation but cannot take effect while the aria-label is forced.

cc @DMihaylova — follow-up to #13013, since PR #13476 does not fully resolve it.

Organization

SAP-SF

Declaration
  • I’m not disclosing any internal or sensitive information.
主要语言
TypeScript
星标
1.8k
派生
290
平均合并
3 天 12 小时
30 天内合并 PR
54

环境准备

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

UI5/webcomponents 的其他 Issue

查看 UI5/webcomponents 的全部 Issue

相似的 Issue

更多 TypeScript Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。