Repository: Sage/carbon (ts)

Issue:
Select: aria-describedby does not get added to the combobox input element
### Description

When using the `aria-describedby` prop provided for the Select component, it does not get applied to the combobox input component, it instead gets applied to the subsequent span element that has the "Please select" placeholder text.

This is a incorrect behaviour as the expectation is for the prop to be applied to the intended component. This is required for a accessibility issue fix.

### Reproduction

https://stackblitz.com/edit/parsium-carbon-starter-uduhy9?file=src%2FApp.tsx

### Steps to reproduce

Inspect the Select component in the StackBlitz environment shared, you will see the aria-label is applied to the combobox input element as expected but the aria-describedby is not.

### JIRA ticket numbers (Sage only)

_No response_

### Suggested solution

_No response_

### Carbon version

142.9.1

### Design tokens version

4.34.0

### Relevant browsers

Microsoft Edge

### Relevant OSs

MacOS

### Additional context

_No response_

### Confidentiality

- [X] I confirm there is no confidential or commercially sensitive information included.

Pull request:
fix(select): ensure that aria-describedby is applied to the select-textbox element - FE-6889
Currently, the aria-describedby attribute is applied to the placeholder span of select-textbox. This fix ensures that the attribute is correctly applied to the select-textbox.

fixes #7057

### Proposed behaviour

`aria-describedby` attribute should be applied to the combo box (select-textbox).

### Current behaviour

`aria-describedby` attribute is being applied to the `span` element of the placeholder inside the select-textbox. This is because the `aria-describedby` attribute is being inadvertently passed via `...rest`

### Checklist

<!-- Each PR should include the following -->

- [x] Commits follow our style guide
- [x] Related issues linked in commit messages if required
- [ ] Screenshots are included in the PR if useful
- [ ] All themes are supported if required
- [ ] Unit tests added or updated if required
- [ ] Playwright automation tests added or updated if required
- [ ] Storybook added or updated if required
- [ ] Translations added or updated (including creating or amending translation keys table in storybook) if required
- [ ] Typescript `d.ts` file added or updated if required
- [x] Related docs have been updated if required

#### QA

- [ ] Tested in provided StackBlitz sandbox/Storybook
- [ ] Add new Playwright test coverage if required
- [ ] Carbon implementation matches Design System/designs
- [ ] UI Tests GitHub check reviewed if required

### Additional context

N/A

### Testing instructions

For Simple-Select, MultiSelect and Filterable.
- Using the `SimpleSelectWithAriaDescribedby` for Simple-Select  and `AriaDescribedbyExample` for Multi and Filterable, ensure that the `aria-describedby` is read aloud by the screen reader when the select-textbox is focused. 
- Ensure no other regressions with regards to screen reader behaviour with any of the Selects.


Patch:
diff --git a/src/components/select/__internal__/select-textbox/select-textbox.component.tsx b/src/components/select/__internal__/select-textbox/select-textbox.component.tsx
index e7500b690..e20014d61 100644
--- a/src/components/select/__internal__/select-textbox/select-textbox.component.tsx
+++ b/src/components/select/__internal__/select-textbox/select-textbox.component.tsx
@@ -152,6 +152,9 @@ const SelectTextbox = React.forwardRef(
       ...restProps,
     };
 
+    const { "aria-describedby": ariaDescribedBy, ...filteredRestProps } =
+      restProps;
+
     const inputAriaAttributes = {
       "aria-expanded": readOnly ? undefined : isOpen,
       "aria-labelledby": accessibilityLabelId
@@ -170,6 +173,7 @@ const SelectTextbox = React.forwardRef(
     return (
       <SelectTextboxContext.Provider value={{ isInputInSelect: true }}>
         <Textbox
+          ariaDescribedBy={ariaDescribedBy}
           aria-label={ariaLabel}
           data-element="select-input"
           data-role="select-textbox"
@@ -198,7 +202,7 @@ const SelectTextbox = React.forwardRef(
               readOnly={readOnly}
               transparent={transparent}
               size={size}
-              {...restProps}
+              {...filteredRestProps}
             >
               <StyledSelectTextChildrenWrapper>
                 {showPlaceholder ? placeholder : formattedValue}
diff --git a/src/components/select/simple-select/simple-select.component.tsx b/src/components/select/simple-select/simple-select.component.tsx
index 905c67cb2..903bed858 100644
--- a/src/components/select/simple-select/simple-select.component.tsx
+++ b/src/components/select/simple-select/simple-select.component.tsx
@@ -40,6 +40,8 @@ export interface CustomSelectChangeEvent
 
 export interface SimpleSelectProps
   extends Omit<FormInputPropTypes, "defaultValue" | "value"> {
+  /** Prop to specify the aria-describedby property of the component input */
+  "aria-describedby"?: string;
   /** Prop to specify the aria-label attribute of the component input */
   "aria-label"?: string;
   /** Prop to specify the aria-labelledby property of the component input */
@@ -107,6 +109,7 @@ export const SimpleSelect = React.forwardRef<
 >(
   (
     {
+      "aria-describedby": ariaDescribedBy,
       "aria-label": ariaLabel,
       "aria-labelledby": ariaLabelledby,
       value,
@@ -555,6 +558,7 @@ export const SimpleSelect = React.forwardRef<
             aria-controls={selectListId.current}
             activeDescendantId={activeDescendantId}
             ariaLabelledby={ariaLabelledby}
+            ariaDescribedBy={ariaDescribedBy}
             isOpen={isOpen}
             {...getTextboxProps()}
           />


Test patch:
diff --git a/src/components/select/filterable-select/filterable-select-test.stories.tsx b/src/components/select/filterable-select/filterable-select-test.stories.tsx
index 135247989..35998912d 100644
--- a/src/components/select/filterable-select/filterable-select-test.stories.tsx
+++ b/src/components/select/filterable-select/filterable-select-test.stories.tsx
@@ -4,6 +4,7 @@ import { FilterableSelect, Option, FilterableSelectProps } from "..";
 import OptionRow from "../option-row/option-row.component";
 import Dialog from "../../dialog";
 import Button from "../../button";
+import Typography from "../../typography";
 
 export default {
   component: FilterableSelect,
@@ -708,3 +709,37 @@ export const FilterableSelectWithTruncatedText = () => {
     </FilterableSelect>
   );
 };
+
+export const AriaDescribedByExample = () => (
+  <>
+    <FilterableSelect
+      name="simple"
+      id="simple"
+      label="color"
+      aria-describedby="combo-box-description"
+      labelInline
+      onOpen={partialAction("onOpen")}
+      onChange={partialAction("onChange")}
+      onClick={partialAction("onClick")}
+      onFilterChange={partialAction("onFilterChange")}
+      onFocus={partialAction("onFocus")}
+      onBlur={partialAction("onBlur")}
+      onKeyDown={partialAction("onKeyDown")}
+    >
+      <Option text="Amber" value="1" />
+      <Option text="Black" value="2" />
+      <Option text="Blue" value="3" />
+      <Option text="Brown" value="4" />
+      <Option text="Green" value="5" />
+      <Option text="Orange" value="6" />
+      <Option text="Pink" value="7" />
+      <Option text="Purple" value="8" />
+      <Option text="Red" value="9" />
+      <Option text="White" value="10" />
+      <Option text="Yellow" value="11" />
+    </FilterableSelect>
+    <Typography my={5} id="combo-box-description">
+      This is a description of the select textbox
+    </Typography>
+  </>
+);
diff --git a/src/components/select/multi-select/multi-select-test.stories.tsx b/src/components/select/multi-select/multi-select-test.stories.tsx
index 528ca2cdb..10e04a2ed 100644
--- a/src/components/select/multi-select/multi-select-test.stories.tsx
+++ b/src/components/select/multi-select/multi-select-test.stories.tsx
@@ -6,6 +6,7 @@ import Button from "../../button/button.component";
 import Dialog from "../../dialog";
 import Box from "../../box";
 import CarbonProvider from "../../carbon-provider/carbon-provider.component";
+import Typography from "../../typography";
 
 export default {
   component: MultiSelect,
@@ -646,3 +647,47 @@ export const OptionsWithSameName = () => {
   );
 };
 OptionsWithSameName.storyName = "Options with same name";
+
+export const AriaDescribedByExample = () => {
+  const MAX_SELECTIONS_ALLOWED = 2;
+  const [selectedPills, setSelectedPills] = useState([] as string[]);
+  const handleActivityChange = (event: React.ChangeEvent<HTMLInputElement>) => {
+    if (event.target.value.length <= MAX_SELECTIONS_ALLOWED) {
+      setSelectedPills(event.target.value as unknown as string[]);
+      partialAction("onChange")();
+    }
+  };
+  return (
+    <>
+      <MultiSelect
+        aria-describedby="combo-box-description"
+        name="testing"
+        value={selectedPills}
+        onChange={handleActivityChange}
+        onOpen={partialAction("onOpen")}
+        onClick={partialAction("onClick")}
+        onFilterChange={partialAction("onFilterChange")}
+        onFocus={partialAction("onFocus")}
+        onBlur={partialAction("onBlur")}
+        onKeyDown={partialAction("onKeyDown")}
+        openOnFocus
+        label="Test"
+        placeholder=" "
+      >
+        <Option value="1" text="One" />
+        <Option value="2" text="Two" />
+        <Option value="3" text="Three" />
+        <Option value="4" text="Four" />
+        <Option value="5" text="Five" />
+        <Option value="6" text="Six" />
+        <Option value="7" text="Seven" />
+        <Option value="8" text="Eight" />
+        <Option value="9" text="Nine" />
+        <Option value="10" text="Ten" />
+      </MultiSelect>
+      <Typography my={5} id="combo-box-description">
+        This is a description of the select textbox
+      </Typography>
+    </>
+  );
+};
diff --git a/src/components/select/simple-select/simple-select-test.stories.tsx b/src/components/select/simple-select/simple-select-test.stories.tsx
index 92db2359f..ff77935f9 100644
--- a/src/components/select/simple-select/simple-select-test.stories.tsx
+++ b/src/components/select/simple-select/simple-select-test.stories.tsx
@@ -701,3 +701,35 @@ export const ComplexCustomChildren = () => {
     </Box>
   );
 };
+
+export const SimpleSelectWithAriaDescribedby = () => {
+  return (
+    <Box m={3} width={300}>
+      <Select
+        name="simple"
+        id="simple"
+        label="color"
+        aria-label="color"
+        aria-describedby="combo-box-description"
+      >
+        <Option text="Amber" value="1" />
+        <Option text="Black" value="2" />
+        <Option text="Blue" value="3" />
+        <Option text="Brown" value="4" />
+        <Option text="Green" value="5" />
+        <Option text="Orange" value="6" />
+        <Option text="Pink" value="7" />
+        <Option text="Purple" value="8" />
+        <Option text="Red" value="9" />
+        <Option text="White" value="10" />
+        <Option text="Yellow" value="11" />
+      </Select>
+      <Typography my={5} id="combo-box-description">
+        This is a description of the select textbox
+      </Typography>
+    </Box>
+  );
+};
+
+SimpleSelectWithAriaDescribedby.storyName =
+  "SimpleSelect with aria-describedby";