korbit-ai[bot] commented on code in PR #33396:
URL: https://github.com/apache/superset/pull/33396#discussion_r2142968273


##########
superset-frontend/src/features/home/SubMenu.tsx:
##########
@@ -196,20 +198,22 @@ const SubMenuComponent: FunctionComponent<SubMenuProps> = 
props => {
     <StyledHeader>
       <Row className="menu" role="navigation">
         {props.name && <div className="header">{props.name}</div>}
-        <Menu mode={showMenu} disabledOverflow>
+        <Menu mode={showMenu} disabledOverflow role="tablist">
           {props.tabs?.map(tab => {
             if ((props.usesRouter || hasHistory) && !!tab.usesRouter) {
               return (
                 <Menu.Item key={tab.label}>
-                  <div
+                  <Link
+                    to={tab.url || ''}
                     role="tab"
+                    id={tab.id || tab.name}

Review Comment:
   ### Non-unique IDs in tab elements <sub>![category 
Functionality](https://img.shields.io/badge/Functionality-0284c7)</sub>
   
   <details>
     <summary>Tell me more</summary>
   
   ###### What is the issue?
   Using tab.name as a fallback for tab.id could lead to non-unique IDs if 
multiple tabs have the same name but different URLs.
   
   
   ###### Why this matters
   Non-unique IDs can cause screen readers to announce incorrect content and 
break ARIA relationships, compromising accessibility functionality.
   
   ###### Suggested change ∙ *Feature Preview*
   Generate unique IDs using a combination of tab name and index, or implement 
a dedicated unique ID generator:
   
   ```typescript
   id={tab.id || `tab-${tab.name}-${index}`}
   ```
   
   This requires modifying the map function to include the index:
   ```typescript
   {props.tabs?.map((tab, index) => {
   ```
   
   
   ###### Provide feedback to improve future suggestions
   [![Nice 
Catch](https://img.shields.io/badge/👍%20Nice%20Catch-71BC78)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/cd60c8bf-e347-42bb-886f-aec7588a9ca2/upvote)
 
[![Incorrect](https://img.shields.io/badge/👎%20Incorrect-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/cd60c8bf-e347-42bb-886f-aec7588a9ca2?what_not_true=true)
  [![Not in 
Scope](https://img.shields.io/badge/👎%20Out%20of%20PR%20scope-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/cd60c8bf-e347-42bb-886f-aec7588a9ca2?what_out_of_scope=true)
 [![Not in coding 
standard](https://img.shields.io/badge/👎%20Not%20in%20our%20standards-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/cd60c8bf-e347-42bb-886f-aec7588a9ca2?what_not_in_standard=true)
 
[![Other](https://img.shields.io/badge/👎%20Other-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/cd60c8bf-e347-42bb-886f-aec7588a9ca2)
   </details>
   
   <sub>
   
   💬 Looking for more details? Reply to this comment to chat with Korbit.
   </sub>
   
   <!--- korbi internal id:5ac260c0-ac2b-4a13-be20-57315d2c18d7 -->
   
   
   [](5ac260c0-ac2b-4a13-be20-57315d2c18d7)



##########
superset-frontend/packages/superset-ui-chart-controls/src/shared-controls/components/RadioButtonControl.tsx:
##########
@@ -69,24 +69,45 @@ export default function RadioButtonControl({
           boxShadow: 'none',
         },
       }}
+      role="tablist"
+      aria-label={typeof props.label === 'string' ? props.label : undefined}
     >
       <ControlHeader {...props} />
       <div className="btn-group btn-group-sm">
         {options.map(([val, label]) => (
           <button
+            aria-label={typeof label === 'string' ? label : undefined}
+            id={`tab-${val}`}
             key={JSON.stringify(val)}
             type="button"
+            aria-selected={val === currentValue}
+            role="tab"
             className={`btn btn-default ${
               val === currentValue ? 'active' : ''
             }`}
-            onClick={() => {
+            onClick={e => {
+              e.currentTarget?.focus();
               onChange(val);
             }}
           >
             {label}
           </button>
         ))}
       </div>
+      {/* accessibility begin */}
+      <div
+        aria-live="polite"
+        style={{
+          position: 'absolute',
+          left: '-9999px',
+          height: '1px',
+          width: '1px',
+          overflow: 'hidden',
+        }}
+      >
+        {options.find(([val]) => val === currentValue)?.[1]} tab selected
+      </div>
+      {/* accessibility end */}

Review Comment:
   ### Insufficient Context for Accessibility Implementation <sub>![category 
Documentation](https://img.shields.io/badge/Documentation-7c3aed)</sub>
   
   <details>
     <summary>Tell me more</summary>
   
   ###### What is the issue?
   The inline comment markers 'accessibility begin/end' don't provide 
meaningful context about why this accessibility div is necessary or how it 
functions.
   
   
   ###### Why this matters
   Without proper documentation, future developers might remove or modify this 
critical accessibility feature, not understanding it's providing screen reader 
announcements for tab selections.
   
   ###### Suggested change ∙ *Feature Preview*
   /* Screen reader announcement div - Provides audio feedback when tabs are 
selected.
      Uses off-screen positioning to be invisible but still accessible to 
screen readers. */
   
   
   ###### Provide feedback to improve future suggestions
   [![Nice 
Catch](https://img.shields.io/badge/👍%20Nice%20Catch-71BC78)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/5210310f-1295-40e7-8501-cca87fcfec8c/upvote)
 
[![Incorrect](https://img.shields.io/badge/👎%20Incorrect-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/5210310f-1295-40e7-8501-cca87fcfec8c?what_not_true=true)
  [![Not in 
Scope](https://img.shields.io/badge/👎%20Out%20of%20PR%20scope-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/5210310f-1295-40e7-8501-cca87fcfec8c?what_out_of_scope=true)
 [![Not in coding 
standard](https://img.shields.io/badge/👎%20Not%20in%20our%20standards-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/5210310f-1295-40e7-8501-cca87fcfec8c?what_not_in_standard=true)
 
[![Other](https://img.shields.io/badge/👎%20Other-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/5210310f-1295-40e7-8501-cca87fcfec8c)
   </details>
   
   <sub>
   
   💬 Looking for more details? Reply to this comment to chat with Korbit.
   </sub>
   
   <!--- korbi internal id:80580cd3-e30d-436a-b77b-d01ff312fc8b -->
   
   
   [](80580cd3-e30d-436a-b77b-d01ff312fc8b)



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to