diff --git a/core/src/components/select/select.scss b/core/src/components/select/select.scss
index f0f4e5a877..dd31ef52fa 100644
--- a/core/src/components/select/select.scss
+++ b/core/src/components/select/select.scss
@@ -50,8 +50,18 @@
opacity: var(--placeholder-opacity);
}
-button {
+label {
@include input-cover();
+
+ display: flex;
+
+ align-items: center;
+
+ opacity: 0;
+}
+
+button {
+ @include visually-hidden();
}
.select-icon {
diff --git a/core/src/components/select/select.tsx b/core/src/components/select/select.tsx
index 5bb8e2945b..1eb6dd4652 100644
--- a/core/src/components/select/select.tsx
+++ b/core/src/components/select/select.tsx
@@ -2,7 +2,7 @@ import { Component, ComponentInterface, Element, Event, EventEmitter, Host, Meth
import { getIonMode } from '../../global/ionic-global';
import { ActionSheetButton, ActionSheetOptions, AlertInput, AlertOptions, CssClassMap, OverlaySelect, PopoverOptions, SelectChangeEventDetail, SelectInterface, SelectPopoverOption, StyleEventDetail } from '../../interface';
-import { findItemLabel, renderHiddenInput } from '../../utils/helpers';
+import { findItemLabel, getAriaLabel, renderHiddenInput } from '../../utils/helpers';
import { actionSheetController, alertController, popoverController } from '../../utils/overlays';
import { hostContext } from '../../utils/theme';
import { watchForOptions } from '../../utils/watch-options';
@@ -29,7 +29,7 @@ export class Select implements ComponentInterface {
private inputId = `ion-sel-${selectIds++}`;
private overlay?: OverlaySelect;
private didInit = false;
- private buttonEl?: HTMLButtonElement;
+ private focusEl?: HTMLButtonElement;
private mutationO?: MutationObserver;
@Element() el!: HTMLIonSelectElement;
@@ -403,8 +403,8 @@ export class Select implements ComponentInterface {
}
private setFocus() {
- if (this.buttonEl) {
- this.buttonEl.focus();
+ if (this.focusEl) {
+ this.focusEl.focus();
}
}
@@ -420,6 +420,9 @@ export class Select implements ComponentInterface {
}
private onClick = (ev: UIEvent) => {
+ ev.preventDefault();
+ ev.stopPropagation();
+
this.setFocus();
this.open(ev);
}
@@ -432,23 +435,21 @@ export class Select implements ComponentInterface {
}
render() {
- const { placeholder, name, disabled, isExpanded, value, el } = this;
+ const { disabled, el, inputId, isExpanded, name, placeholder, value } = this;
const mode = getIonMode(this);
- const labelId = this.inputId + '-lbl';
- const label = findItemLabel(el);
- if (label) {
- label.id = labelId;
- }
+ const { labelText, labelId } = getAriaLabel(el, inputId);
+
+ renderHiddenInput(true, el, name, parseValue(value), disabled);
+
+ const displayValue = this.getText();
let addPlaceholderClass = false;
- let selectText = this.getText();
+ let selectText = displayValue;
if (selectText === '' && placeholder != null) {
selectText = placeholder;
addPlaceholderClass = true;
}
- renderHiddenInput(true, el, name, parseValue(value), disabled);
-
const selectTextClasses: CssClassMap = {
'select-text': true,
'select-placeholder': addPlaceholderClass
@@ -456,14 +457,20 @@ export class Select implements ComponentInterface {
const textPart = addPlaceholderClass ? 'placeholder' : 'text';
+ // If there is a label then we need to concatenate it with the
+ // current value and a comma so it separates nicely when the screen reader
+ // announces it, otherwise just announce the value
+ const displayLabel = labelText !== undefined
+ ? `${displayValue}, ${labelText}`
+ : displayValue;
+
return (