From bc9d33b5cc4e818bc5cf8960d6a6e8248f82cc7b Mon Sep 17 00:00:00 2001 From: Nicolas Merget Date: Wed, 24 Jul 2024 15:37:15 +0200 Subject: [PATCH 01/23] test: write test for required inputs to read messages --- showcases/screen-reader/tests/input.spec.ts | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/showcases/screen-reader/tests/input.spec.ts b/showcases/screen-reader/tests/input.spec.ts index 67ac4e5779d..c6d70cfce01 100644 --- a/showcases/screen-reader/tests/input.spec.ts +++ b/showcases/screen-reader/tests/input.spec.ts @@ -21,7 +21,6 @@ test.describe('DBInput', () => { await voiceOver?.next(); } }); - // We don't test default "next" here because we will be locked inside the textarea testDefault({ test, title: 'should have message and label (tab)', @@ -38,4 +37,24 @@ test.describe('DBInput', () => { await nvda?.press('Tab'); } }); + testDefault({ + test, + title: 'should inform user for changes', + url: './#/03/input?page=requirement', + async testFn(voiceOver, nvda) { + if (voiceOver) { + await voiceOver?.next(); + await voiceOver?.type('Test'); + await voiceOver?.press('Command+A'); + await voiceOver?.press('Delete'); + await voiceOver?.type('Test'); + } else { + await nvda?.press('Tab'); + await nvda?.type('Test'); + await nvda?.press('Control+A'); + await nvda?.press('Delete'); + await nvda?.type('Test'); + } + } + }); }); From 6510a606c8cc0e6c43a0059007adc97ea45df938 Mon Sep 17 00:00:00 2001 From: Nicolas Merget Date: Thu, 25 Jul 2024 08:05:31 +0200 Subject: [PATCH 02/23] chore: add windows snapshot --- .../DBInput-should-inform-user-for-changes.txt | 1 + showcases/screen-reader/default.ts | 12 +----------- showcases/screen-reader/tests/input.spec.ts | 4 ++++ showcases/screen-reader/translations.ts | 16 ++++++++++++++++ 4 files changed, 22 insertions(+), 11 deletions(-) create mode 100644 showcases/screen-reader/__snapshots__/windows/chromium/DBInput-should-inform-user-for-changes.txt create mode 100644 showcases/screen-reader/translations.ts diff --git a/showcases/screen-reader/__snapshots__/windows/chromium/DBInput-should-inform-user-for-changes.txt b/showcases/screen-reader/__snapshots__/windows/chromium/DBInput-should-inform-user-for-changes.txt new file mode 100644 index 00000000000..72bb6bae613 --- /dev/null +++ b/showcases/screen-reader/__snapshots__/windows/chromium/DBInput-should-inform-user-for-changes.txt @@ -0,0 +1 @@ +["Label star, edit, required, Required, blank","T. e. s. t. TODO: Add a valid Message","Test selected","blank. Please fill out this field.. unselected","T. e. s. t. TODO: Add a valid Message"] \ No newline at end of file diff --git a/showcases/screen-reader/default.ts b/showcases/screen-reader/default.ts index 61e4188479a..7bd1e5cd501 100644 --- a/showcases/screen-reader/default.ts +++ b/showcases/screen-reader/default.ts @@ -13,17 +13,7 @@ import { type RunTestType, type ScreenReaderTestType } from './data'; - -const translations: Record = { - button: ['Schalter'], - edit: ['Eingabefeld'], - 'radio button': ['Auswahlschalter'], - blank: ['Leer'], - checked: ['aktiviert'], - ' of ': [' von '], - clickable: ['anklickbar'], - 'has auto complete': ['mit Auto Vervollständigung'] -}; +import { translations } from './translations'; const cleanSpeakInstructions = (phraseLog: string[]): string[] => phraseLog.map((phrase) => diff --git a/showcases/screen-reader/tests/input.spec.ts b/showcases/screen-reader/tests/input.spec.ts index c6d70cfce01..eb05684dfc6 100644 --- a/showcases/screen-reader/tests/input.spec.ts +++ b/showcases/screen-reader/tests/input.spec.ts @@ -43,7 +43,11 @@ test.describe('DBInput', () => { url: './#/03/input?page=requirement', async testFn(voiceOver, nvda) { if (voiceOver) { + /* Goto desired input */ await voiceOver?.next(); + await voiceOver?.next(); + await voiceOver?.next(); + await voiceOver?.type('Test'); await voiceOver?.press('Command+A'); await voiceOver?.press('Delete'); diff --git a/showcases/screen-reader/translations.ts b/showcases/screen-reader/translations.ts new file mode 100644 index 00000000000..f36e0dd3b8a --- /dev/null +++ b/showcases/screen-reader/translations.ts @@ -0,0 +1,16 @@ +export const translations: Record = { + star: ['Stern'], + button: ['Schalter'], + edit: ['Eingabefeld'], + 'radio button': ['Auswahlschalter'], + blank: ['Leer'], + checked: ['aktiviert'], + ' of ': [' von '], + clickable: ['anklickbar'], + 'has auto complete': ['mit Auto Vervollständigung'], + required: ['erforderlich'], + 'Please fill out this field..': ['Fülle dieses Feld aus..'], + unselected: ['nicht ausgewählt'], + selected: ['ausgewählt'], + '': ['. Nummernblock eingeschaltet'] +}; From 07904d470555a877f5b238bf954454abc4e49d15 Mon Sep 17 00:00:00 2001 From: Nicolas Merget Date: Thu, 25 Jul 2024 08:30:30 +0200 Subject: [PATCH 03/23] chore: update from main --- showcases/screen-reader/translations.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/showcases/screen-reader/translations.ts b/showcases/screen-reader/translations.ts index f36e0dd3b8a..4c3ab2b5c0e 100644 --- a/showcases/screen-reader/translations.ts +++ b/showcases/screen-reader/translations.ts @@ -12,5 +12,8 @@ export const translations: Record = { 'Please fill out this field..': ['Fülle dieses Feld aus..'], unselected: ['nicht ausgewählt'], selected: ['ausgewählt'], - '': ['. Nummernblock eingeschaltet'] + '': ['. Nummernblock eingeschaltet'], + unknown: ['Unbekannt'], + dialog: ['Dialogfeld'], + document: ['Dokument'] }; From 6ecbba203e5f01238f69198209d20927a9f24a4f Mon Sep 17 00:00:00 2001 From: Nicolas Merget Date: Thu, 25 Jul 2024 15:18:23 +0200 Subject: [PATCH 04/23] fix: add span only for voiceover to inform users about valid/invalid messages --- .../src/components/checkbox/checkbox.lite.tsx | 17 ++++++++++++++- .../src/components/input/input.lite.tsx | 17 ++++++++++++++- .../src/components/select/select.lite.tsx | 17 ++++++++++++++- .../src/components/textarea/textarea.lite.tsx | 17 ++++++++++++++- packages/components/src/shared/model.ts | 7 +++++++ .../src/styles/_form-components.scss | 2 ++ .../src/styles/visually-hidden.scss | 21 +++++++++++++++++++ packages/components/src/utils/index.ts | 8 ++++++- showcases/screen-reader/tests/input.spec.ts | 2 +- 9 files changed, 102 insertions(+), 6 deletions(-) create mode 100644 packages/components/src/styles/visually-hidden.scss diff --git a/packages/components/src/components/checkbox/checkbox.lite.tsx b/packages/components/src/components/checkbox/checkbox.lite.tsx index 2990ddb59db..87c2f6420b1 100644 --- a/packages/components/src/components/checkbox/checkbox.lite.tsx +++ b/packages/components/src/components/checkbox/checkbox.lite.tsx @@ -7,7 +7,7 @@ import { useStore } from '@builder.io/mitosis'; import { DBCheckboxProps, DBCheckboxState } from './model'; -import { cls, uuid } from '../../utils'; +import { cls, hasVoiceOver, uuid } from '../../utils'; import { DEFAULT_INVALID_MESSAGE, DEFAULT_INVALID_MESSAGE_ID_SUFFIX, @@ -33,6 +33,7 @@ export default function DBCheckbox(props: DBCheckboxProps) { _validMessageId: this._id + DEFAULT_VALID_MESSAGE_ID_SUFFIX, _invalidMessageId: this._id + DEFAULT_INVALID_MESSAGE_ID_SUFFIX, _descByIds: '', + _voiceOverFallback: '', handleChange: (event: ChangeEvent) => { if (props.onChange) { props.onChange(event); @@ -46,11 +47,21 @@ export default function DBCheckbox(props: DBCheckboxProps) { /* For a11y reasons we need to map the correct message with the checkbox */ if (!ref?.validity.valid || props.customValidity === 'invalid') { state._descByIds = state._invalidMessageId; + if (hasVoiceOver()) { + state._voiceOverFallback = + props.invalidMessage ?? + ref?.validationMessage ?? + DEFAULT_INVALID_MESSAGE; + } } else if ( props.customValidity === 'valid' || (ref?.validity.valid && props.required) ) { state._descByIds = state._validMessageId; + if (hasVoiceOver()) { + state._voiceOverFallback = + props.validMessage ?? DEFAULT_VALID_MESSAGE; + } } else if (props.message) { state._descByIds = state._messageId; } else { @@ -179,6 +190,10 @@ export default function DBCheckbox(props: DBCheckboxProps) { ref?.validationMessage ?? DEFAULT_INVALID_MESSAGE} + + + {state._voiceOverFallback} + ); } diff --git a/packages/components/src/components/input/input.lite.tsx b/packages/components/src/components/input/input.lite.tsx index 6f4918fdd29..08472b9fcb4 100644 --- a/packages/components/src/components/input/input.lite.tsx +++ b/packages/components/src/components/input/input.lite.tsx @@ -7,7 +7,7 @@ import { useRef, useStore } from '@builder.io/mitosis'; -import { cls, isArrayOfStrings, uuid } from '../../utils'; +import { cls, hasVoiceOver, isArrayOfStrings, uuid } from '../../utils'; import { DBInputProps, DBInputState } from './model'; import { DEFAULT_DATALIST_ID_SUFFIX, @@ -42,6 +42,7 @@ export default function DBInput(props: DBInputProps) { _dataListId: this._id + DEFAULT_DATALIST_ID_SUFFIX, _descByIds: '', _value: '', + _voiceOverFallback: '', defaultValues: { label: DEFAULT_LABEL, placeholder: ' ' @@ -69,6 +70,12 @@ export default function DBInput(props: DBInputProps) { /* For a11y reasons we need to map the correct message with the input */ if (!ref?.validity.valid || props.customValidity === 'invalid') { state._descByIds = state._invalidMessageId; + if (hasVoiceOver()) { + state._voiceOverFallback = + props.invalidMessage ?? + ref?.validationMessage ?? + DEFAULT_INVALID_MESSAGE; + } } else if ( props.customValidity === 'valid' || (ref?.validity.valid && @@ -78,6 +85,10 @@ export default function DBInput(props: DBInputProps) { props.pattern)) ) { state._descByIds = state._validMessageId; + if (hasVoiceOver()) { + state._voiceOverFallback = + props.validMessage ?? DEFAULT_VALID_MESSAGE; + } } else if (props.message) { state._descByIds = state._messageId; } else { @@ -230,6 +241,10 @@ export default function DBInput(props: DBInputProps) { ref?.validationMessage ?? DEFAULT_INVALID_MESSAGE} + + + {state._voiceOverFallback} + ); // jscpd:ignore-end diff --git a/packages/components/src/components/select/select.lite.tsx b/packages/components/src/components/select/select.lite.tsx index 6adb6394be2..0b228ec7829 100644 --- a/packages/components/src/components/select/select.lite.tsx +++ b/packages/components/src/components/select/select.lite.tsx @@ -8,7 +8,7 @@ import { useStore } from '@builder.io/mitosis'; import { DBSelectOptionType, DBSelectProps, DBSelectState } from './model'; -import { cls, uuid } from '../../utils'; +import { cls, hasVoiceOver, uuid } from '../../utils'; import { DEFAULT_INVALID_MESSAGE, DEFAULT_INVALID_MESSAGE_ID_SUFFIX, @@ -47,6 +47,7 @@ export default function DBSelect(props: DBSelectProps) { _descByIds: '', _value: '', initialized: false, + _voiceOverFallback: '', handleClick: (event: ClickEvent) => { if (props.onClick) { props.onClick(event); @@ -75,11 +76,21 @@ export default function DBSelect(props: DBSelectProps) { /* For a11y reasons we need to map the correct message with the select */ if (!ref?.validity.valid || props.customValidity === 'invalid') { state._descByIds = state._invalidMessageId; + if (hasVoiceOver()) { + state._voiceOverFallback = + props.invalidMessage ?? + ref?.validationMessage ?? + DEFAULT_INVALID_MESSAGE; + } } else if ( props.customValidity === 'valid' || (ref?.validity.valid && props.required) ) { state._descByIds = state._validMessageId; + if (hasVoiceOver()) { + state._voiceOverFallback = + props.validMessage ?? DEFAULT_VALID_MESSAGE; + } } else if (props.message) { state._descByIds = state._messageId; } else { @@ -243,6 +254,10 @@ export default function DBSelect(props: DBSelectProps) { ref?.validationMessage ?? DEFAULT_INVALID_MESSAGE} + + + {state._voiceOverFallback} + ); // jscpd:ignore-end diff --git a/packages/components/src/components/textarea/textarea.lite.tsx b/packages/components/src/components/textarea/textarea.lite.tsx index fd0dd74032d..eb39b2dde67 100644 --- a/packages/components/src/components/textarea/textarea.lite.tsx +++ b/packages/components/src/components/textarea/textarea.lite.tsx @@ -8,7 +8,7 @@ import { } from '@builder.io/mitosis'; import { DBTextareaProps, DBTextareaState } from './model'; import { DBInfotext } from '../infotext'; -import { cls, uuid } from '../../utils'; +import { cls, hasVoiceOver, uuid } from '../../utils'; import { DEFAULT_INVALID_MESSAGE, DEFAULT_INVALID_MESSAGE_ID_SUFFIX, @@ -40,6 +40,7 @@ export default function DBTextarea(props: DBTextareaProps) { placeholder: ' ', rows: '4' }, + _voiceOverFallback: '', handleInput: (event: InputEvent) => { if (props.onInput) { props.onInput(event); @@ -63,12 +64,22 @@ export default function DBTextarea(props: DBTextareaProps) { /* For a11y reasons we need to map the correct message with the textarea */ if (!ref?.validity.valid || props.customValidity === 'invalid') { state._descByIds = state._invalidMessageId; + if (hasVoiceOver()) { + state._voiceOverFallback = + props.invalidMessage ?? + ref?.validationMessage ?? + DEFAULT_INVALID_MESSAGE; + } } else if ( props.customValidity === 'valid' || (ref?.validity.valid && (props.required || props.minLength || props.maxLength)) ) { state._descByIds = state._validMessageId; + if (hasVoiceOver()) { + state._voiceOverFallback = + props.validMessage ?? DEFAULT_VALID_MESSAGE; + } } else if (props.message) { state._descByIds = state._messageId; } else { @@ -188,6 +199,10 @@ export default function DBTextarea(props: DBTextareaProps) { ref?.validationMessage ?? DEFAULT_INVALID_MESSAGE} + + + {state._voiceOverFallback} + ); // jscpd:ignore-end diff --git a/packages/components/src/shared/model.ts b/packages/components/src/shared/model.ts index 06d9dfaa316..c7f82958cab 100644 --- a/packages/components/src/shared/model.ts +++ b/packages/components/src/shared/model.ts @@ -355,6 +355,13 @@ export type FormState = { _invalidMessageId?: string; _descByIds?: string; _value?: string; + + /** + * https://www.davidmacd.com/blog/test-aria-describedby-errormessage-aria-live.html + * Currently VoiceOver isn't supporting changes from aria-describedby. + * This is an internal Fallback + */ + _voiceOverFallback?: string; }; export type InitializedState = { diff --git a/packages/components/src/styles/_form-components.scss b/packages/components/src/styles/_form-components.scss index 287382169b5..ffb909b3bba 100644 --- a/packages/components/src/styles/_form-components.scss +++ b/packages/components/src/styles/_form-components.scss @@ -7,6 +7,8 @@ @use "@db-ui/foundations/build/scss/helpers"; @use "component"; +@forward "visually-hidden"; + $dropdown-icon-transition: transform variables.$db-transition-straight-emotional; $dropdown-icon-transform: rotate(-180deg); diff --git a/packages/components/src/styles/visually-hidden.scss b/packages/components/src/styles/visually-hidden.scss new file mode 100644 index 00000000000..e919a1fc4f8 --- /dev/null +++ b/packages/components/src/styles/visually-hidden.scss @@ -0,0 +1,21 @@ +%visually-hidden { + clip: rect(0, 0, 0, 0) !important; + overflow: hidden !important; + white-space: nowrap !important; + font-size: 0 !important; + all: initial; + inset-block-start: 0 !important; + block-size: 1px !important; + position: absolute !important; + inline-size: 1px !important; + border-width: 0 !important; + border-style: initial !important; + border-color: initial !important; + border-image: initial !important; + padding: 0 !important; + pointer-events: none !important; +} + +.visually-hidden { + @extend %visually-hidden; +} diff --git a/packages/components/src/utils/index.ts b/packages/components/src/utils/index.ts index 20195b4387b..e1b22666291 100644 --- a/packages/components/src/utils/index.ts +++ b/packages/components/src/utils/index.ts @@ -194,6 +194,11 @@ export const handleDataOutside = (el: Element): DBDataOutsidePair => { export const isArrayOfStrings = (value: unknown): value is string[] => Array.isArray(value) && value.every((item) => typeof item === 'string'); +const appleOs = ['Mac', 'iPhone', 'iPad', 'iPod']; +export const hasVoiceOver = (): boolean => + typeof window !== 'undefined' && + appleOs.some((os) => window.navigator.userAgent.includes(os)); + export default { filterPassingProps, cls, @@ -203,5 +208,6 @@ export default { visibleInVY, isInView, handleDataOutside, - isArrayOfStrings + isArrayOfStrings, + hasVoiceOver }; diff --git a/showcases/screen-reader/tests/input.spec.ts b/showcases/screen-reader/tests/input.spec.ts index eb05684dfc6..da1114aae56 100644 --- a/showcases/screen-reader/tests/input.spec.ts +++ b/showcases/screen-reader/tests/input.spec.ts @@ -46,8 +46,8 @@ test.describe('DBInput', () => { /* Goto desired input */ await voiceOver?.next(); await voiceOver?.next(); + await nvda?.clearSpokenPhraseLog(); await voiceOver?.next(); - await voiceOver?.type('Test'); await voiceOver?.press('Command+A'); await voiceOver?.press('Delete'); From f3eec776b52a9df7e7735eb2d608e4b629db224a Mon Sep 17 00:00:00 2001 From: Nicolas Merget Date: Thu, 25 Jul 2024 16:04:10 +0200 Subject: [PATCH 05/23] chore: update snapshots --- .../macos/webkit/DBInput-should-inform-user-for-changes.txt | 1 + .../windows/chromium/DBDrawer-should-autofocus.txt | 2 +- showcases/screen-reader/tests/input.spec.ts | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 showcases/screen-reader/__snapshots__/macos/webkit/DBInput-should-inform-user-for-changes.txt diff --git a/showcases/screen-reader/__snapshots__/macos/webkit/DBInput-should-inform-user-for-changes.txt b/showcases/screen-reader/__snapshots__/macos/webkit/DBInput-should-inform-user-for-changes.txt new file mode 100644 index 00000000000..289dc4f2a00 --- /dev/null +++ b/showcases/screen-reader/__snapshots__/macos/webkit/DBInput-should-inform-user-for-changes.txt @@ -0,0 +1 @@ +["Label * Label* Required required edit text","TODO: Add a validMessage. Test","Test selected","Test. Fill out this field","TODO: Add a validMessage. Test"] diff --git a/showcases/screen-reader/__snapshots__/windows/chromium/DBDrawer-should-autofocus.txt b/showcases/screen-reader/__snapshots__/windows/chromium/DBDrawer-should-autofocus.txt index d8b26321ea1..67573116a9c 100644 --- a/showcases/screen-reader/__snapshots__/windows/chromium/DBDrawer-should-autofocus.txt +++ b/showcases/screen-reader/__snapshots__/windows/chromium/DBDrawer-should-autofocus.txt @@ -1 +1 @@ -["unknown. dialog. document. clickable, Close Button, button. dialog. button, Close Button","Functional"] \ No newline at end of file +["button. dialog. document. clickable, Close Button, button. dialog. button, Close Button","Functional"] diff --git a/showcases/screen-reader/tests/input.spec.ts b/showcases/screen-reader/tests/input.spec.ts index da1114aae56..7a1269d40db 100644 --- a/showcases/screen-reader/tests/input.spec.ts +++ b/showcases/screen-reader/tests/input.spec.ts @@ -46,7 +46,7 @@ test.describe('DBInput', () => { /* Goto desired input */ await voiceOver?.next(); await voiceOver?.next(); - await nvda?.clearSpokenPhraseLog(); + await voiceOver?.clearSpokenPhraseLog(); await voiceOver?.next(); await voiceOver?.type('Test'); await voiceOver?.press('Command+A'); From f611d1cc5f2addbf02837f09e901debb88693d3e Mon Sep 17 00:00:00 2001 From: Nicolas Merget Date: Thu, 25 Jul 2024 16:28:26 +0200 Subject: [PATCH 06/23] chore: update snapshots --- .../macos/webkit/DBInput-should-inform-user-for-changes.txt | 2 +- .../windows/chromium/DBDrawer-should-autofocus.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/showcases/screen-reader/__snapshots__/macos/webkit/DBInput-should-inform-user-for-changes.txt b/showcases/screen-reader/__snapshots__/macos/webkit/DBInput-should-inform-user-for-changes.txt index 289dc4f2a00..28a6a206d61 100644 --- a/showcases/screen-reader/__snapshots__/macos/webkit/DBInput-should-inform-user-for-changes.txt +++ b/showcases/screen-reader/__snapshots__/macos/webkit/DBInput-should-inform-user-for-changes.txt @@ -1 +1 @@ -["Label * Label* Required required edit text","TODO: Add a validMessage. Test","Test selected","Test. Fill out this field","TODO: Add a validMessage. Test"] +["Label * Label* Required required edit text","TODO: Add a validMessage. Test","Test selected","Test. Fill out this field","TODO: Add a validMessage. Test"] \ No newline at end of file diff --git a/showcases/screen-reader/__snapshots__/windows/chromium/DBDrawer-should-autofocus.txt b/showcases/screen-reader/__snapshots__/windows/chromium/DBDrawer-should-autofocus.txt index 67573116a9c..36f2b938c2e 100644 --- a/showcases/screen-reader/__snapshots__/windows/chromium/DBDrawer-should-autofocus.txt +++ b/showcases/screen-reader/__snapshots__/windows/chromium/DBDrawer-should-autofocus.txt @@ -1 +1 @@ -["button. dialog. document. clickable, Close Button, button. dialog. button, Close Button","Functional"] +["button. dialog. document. clickable, Close Button, button. dialog. button, Close Button","Functional"] \ No newline at end of file From 46a9978832a988a00d922bf8f6ca77987736a395 Mon Sep 17 00:00:00 2001 From: Maximilian Franzke Date: Fri, 26 Jul 2024 13:46:16 +0200 Subject: [PATCH 07/23] refactor: using an attribute instead of a class e.g. to mimic the standarized hidden attribute --- .../src/components/checkbox/checkbox.lite.tsx | 16 ++++------ .../src/components/select/select.lite.tsx | 32 +++++++------------ .../src/components/textarea/textarea.lite.tsx | 26 ++++++--------- .../src/styles/visually-hidden.scss | 2 +- 4 files changed, 28 insertions(+), 48 deletions(-) diff --git a/packages/components/src/components/checkbox/checkbox.lite.tsx b/packages/components/src/components/checkbox/checkbox.lite.tsx index 87c2f6420b1..f007b5e9ea1 100644 --- a/packages/components/src/components/checkbox/checkbox.lite.tsx +++ b/packages/components/src/components/checkbox/checkbox.lite.tsx @@ -34,7 +34,7 @@ export default function DBCheckbox(props: DBCheckboxProps) { _invalidMessageId: this._id + DEFAULT_INVALID_MESSAGE_ID_SUFFIX, _descByIds: '', _voiceOverFallback: '', - handleChange: (event: ChangeEvent) => { + handleChange: (event: ChangeEvent) => { if (props.onChange) { props.onChange(event); } @@ -68,7 +68,7 @@ export default function DBCheckbox(props: DBCheckboxProps) { state._descByIds = ''; } }, - handleBlur: (event: InteractionEvent) => { + handleBlur: (event: InteractionEvent) => { if (props.onBlur) { props.onBlur(event); } @@ -77,7 +77,7 @@ export default function DBCheckbox(props: DBCheckboxProps) { props.blur(event); } }, - handleFocus: (event: InteractionEvent) => { + handleFocus: (event: InteractionEvent) => { if (props.onFocus) { props.onFocus(event); } @@ -149,13 +149,11 @@ export default function DBCheckbox(props: DBCheckboxProps) { disabled={props.disabled} value={props.value} required={props.required} - onChange={(event: ChangeEvent) => - state.handleChange(event) - } - onBlur={(event: InteractionEvent) => + onChange={(event: ChangeEvent) => state.handleChange(event)} + onBlur={(event: InteractionEvent) => state.handleBlur(event) } - onFocus={(event: InteractionEvent) => + onFocus={(event: InteractionEvent) => state.handleFocus(event) } aria-describedby={state._descByIds} @@ -191,7 +189,7 @@ export default function DBCheckbox(props: DBCheckboxProps) { DEFAULT_INVALID_MESSAGE} - + {state._voiceOverFallback} diff --git a/packages/components/src/components/select/select.lite.tsx b/packages/components/src/components/select/select.lite.tsx index 0b228ec7829..0608892c4bd 100644 --- a/packages/components/src/components/select/select.lite.tsx +++ b/packages/components/src/components/select/select.lite.tsx @@ -48,12 +48,12 @@ export default function DBSelect(props: DBSelectProps) { _value: '', initialized: false, _voiceOverFallback: '', - handleClick: (event: ClickEvent) => { + handleClick: (event: ClickEvent) => { if (props.onClick) { props.onClick(event); } }, - handleInput: (event: InputEvent) => { + handleInput: (event: InputEvent) => { if (props.onInput) { props.onInput(event); } @@ -62,7 +62,7 @@ export default function DBSelect(props: DBSelectProps) { props.input(event); } }, - handleChange: (event: ChangeEvent) => { + handleChange: (event: ChangeEvent) => { if (props.onChange) { props.onChange(event); } @@ -97,7 +97,7 @@ export default function DBSelect(props: DBSelectProps) { state._descByIds = state._placeholderId; } }, - handleBlur: (event: InteractionEvent) => { + handleBlur: (event: InteractionEvent) => { if (props.onBlur) { props.onBlur(event); } @@ -106,7 +106,7 @@ export default function DBSelect(props: DBSelectProps) { props.blur(event); } }, - handleFocus: (event: InteractionEvent) => { + handleFocus: (event: InteractionEvent) => { if (props.onFocus) { props.onFocus(event); } @@ -167,21 +167,11 @@ export default function DBSelect(props: DBSelectProps) { name={props.name} value={props.value ?? state._value} autocomplete={props.autocomplete} - onInput={(event: ChangeEvent) => - state.handleInput(event) - } - onClick={(event: ClickEvent) => - state.handleClick(event) - } - onChange={(event: ChangeEvent) => - state.handleChange(event) - } - onBlur={(event: InteractionEvent) => - state.handleBlur(event) - } - onFocus={(event: InteractionEvent) => - state.handleFocus(event) - } + onInput={(event: ChangeEvent) => state.handleInput(event)} + onClick={(event: ClickEvent) => state.handleClick(event)} + onChange={(event: ChangeEvent) => state.handleChange(event)} + onBlur={(event: InteractionEvent) => state.handleBlur(event)} + onFocus={(event: InteractionEvent) => state.handleFocus(event)} aria-describedby={state._descByIds}> {/* Empty option for floating label */} @@ -255,7 +245,7 @@ export default function DBSelect(props: DBSelectProps) { DEFAULT_INVALID_MESSAGE} - + {state._voiceOverFallback} diff --git a/packages/components/src/components/textarea/textarea.lite.tsx b/packages/components/src/components/textarea/textarea.lite.tsx index eb39b2dde67..101f18a652e 100644 --- a/packages/components/src/components/textarea/textarea.lite.tsx +++ b/packages/components/src/components/textarea/textarea.lite.tsx @@ -41,7 +41,7 @@ export default function DBTextarea(props: DBTextareaProps) { rows: '4' }, _voiceOverFallback: '', - handleInput: (event: InputEvent) => { + handleInput: (event: InputEvent) => { if (props.onInput) { props.onInput(event); } @@ -50,7 +50,7 @@ export default function DBTextarea(props: DBTextareaProps) { props.input(event); } }, - handleChange: (event: ChangeEvent) => { + handleChange: (event: ChangeEvent) => { if (props.onChange) { props.onChange(event); } @@ -86,7 +86,7 @@ export default function DBTextarea(props: DBTextareaProps) { state._descByIds = ''; } }, - handleBlur: (event: InteractionEvent) => { + handleBlur: (event: InteractionEvent) => { if (props.onBlur) { props.onBlur(event); } @@ -95,7 +95,7 @@ export default function DBTextarea(props: DBTextareaProps) { props.blur(event); } }, - handleFocus: (event: InteractionEvent) => { + handleFocus: (event: InteractionEvent) => { if (props.onFocus) { props.onFocus(event); } @@ -154,18 +154,10 @@ export default function DBTextarea(props: DBTextareaProps) { wrap={props.wrap} spellcheck={props.spellCheck} autocomplete={props.autocomplete} - onInput={(event: ChangeEvent) => - state.handleInput(event) - } - onChange={(event: ChangeEvent) => - state.handleChange(event) - } - onBlur={(event: InteractionEvent) => - state.handleBlur(event) - } - onFocus={(event: InteractionEvent) => - state.handleFocus(event) - } + onInput={(event: ChangeEvent) => state.handleInput(event)} + onChange={(event: ChangeEvent) => state.handleChange(event)} + onBlur={(event: InteractionEvent) => state.handleBlur(event)} + onFocus={(event: InteractionEvent) => state.handleFocus(event)} value={props.value ?? state._value} aria-describedby={state._descByIds} placeholder={ @@ -200,7 +192,7 @@ export default function DBTextarea(props: DBTextareaProps) { DEFAULT_INVALID_MESSAGE} - + {state._voiceOverFallback} diff --git a/packages/components/src/styles/visually-hidden.scss b/packages/components/src/styles/visually-hidden.scss index e919a1fc4f8..807a22f4690 100644 --- a/packages/components/src/styles/visually-hidden.scss +++ b/packages/components/src/styles/visually-hidden.scss @@ -16,6 +16,6 @@ pointer-events: none !important; } -.visually-hidden { +[data-visually-hidden] { @extend %visually-hidden; } From 24977cc81df8cc22e257ccd17984ec891a22d423 Mon Sep 17 00:00:00 2001 From: Maximilian Franzke Date: Fri, 26 Jul 2024 13:47:39 +0200 Subject: [PATCH 08/23] Revert "refactor: using an attribute instead of a class" This reverts commit 46a9978832a988a00d922bf8f6ca77987736a395. --- .../src/components/checkbox/checkbox.lite.tsx | 16 ++++++---- .../src/components/select/select.lite.tsx | 32 ++++++++++++------- .../src/components/textarea/textarea.lite.tsx | 26 +++++++++------ .../src/styles/visually-hidden.scss | 2 +- 4 files changed, 48 insertions(+), 28 deletions(-) diff --git a/packages/components/src/components/checkbox/checkbox.lite.tsx b/packages/components/src/components/checkbox/checkbox.lite.tsx index f007b5e9ea1..87c2f6420b1 100644 --- a/packages/components/src/components/checkbox/checkbox.lite.tsx +++ b/packages/components/src/components/checkbox/checkbox.lite.tsx @@ -34,7 +34,7 @@ export default function DBCheckbox(props: DBCheckboxProps) { _invalidMessageId: this._id + DEFAULT_INVALID_MESSAGE_ID_SUFFIX, _descByIds: '', _voiceOverFallback: '', - handleChange: (event: ChangeEvent) => { + handleChange: (event: ChangeEvent) => { if (props.onChange) { props.onChange(event); } @@ -68,7 +68,7 @@ export default function DBCheckbox(props: DBCheckboxProps) { state._descByIds = ''; } }, - handleBlur: (event: InteractionEvent) => { + handleBlur: (event: InteractionEvent) => { if (props.onBlur) { props.onBlur(event); } @@ -77,7 +77,7 @@ export default function DBCheckbox(props: DBCheckboxProps) { props.blur(event); } }, - handleFocus: (event: InteractionEvent) => { + handleFocus: (event: InteractionEvent) => { if (props.onFocus) { props.onFocus(event); } @@ -149,11 +149,13 @@ export default function DBCheckbox(props: DBCheckboxProps) { disabled={props.disabled} value={props.value} required={props.required} - onChange={(event: ChangeEvent) => state.handleChange(event)} - onBlur={(event: InteractionEvent) => + onChange={(event: ChangeEvent) => + state.handleChange(event) + } + onBlur={(event: InteractionEvent) => state.handleBlur(event) } - onFocus={(event: InteractionEvent) => + onFocus={(event: InteractionEvent) => state.handleFocus(event) } aria-describedby={state._descByIds} @@ -189,7 +191,7 @@ export default function DBCheckbox(props: DBCheckboxProps) { DEFAULT_INVALID_MESSAGE} - + {state._voiceOverFallback} diff --git a/packages/components/src/components/select/select.lite.tsx b/packages/components/src/components/select/select.lite.tsx index 0608892c4bd..0b228ec7829 100644 --- a/packages/components/src/components/select/select.lite.tsx +++ b/packages/components/src/components/select/select.lite.tsx @@ -48,12 +48,12 @@ export default function DBSelect(props: DBSelectProps) { _value: '', initialized: false, _voiceOverFallback: '', - handleClick: (event: ClickEvent) => { + handleClick: (event: ClickEvent) => { if (props.onClick) { props.onClick(event); } }, - handleInput: (event: InputEvent) => { + handleInput: (event: InputEvent) => { if (props.onInput) { props.onInput(event); } @@ -62,7 +62,7 @@ export default function DBSelect(props: DBSelectProps) { props.input(event); } }, - handleChange: (event: ChangeEvent) => { + handleChange: (event: ChangeEvent) => { if (props.onChange) { props.onChange(event); } @@ -97,7 +97,7 @@ export default function DBSelect(props: DBSelectProps) { state._descByIds = state._placeholderId; } }, - handleBlur: (event: InteractionEvent) => { + handleBlur: (event: InteractionEvent) => { if (props.onBlur) { props.onBlur(event); } @@ -106,7 +106,7 @@ export default function DBSelect(props: DBSelectProps) { props.blur(event); } }, - handleFocus: (event: InteractionEvent) => { + handleFocus: (event: InteractionEvent) => { if (props.onFocus) { props.onFocus(event); } @@ -167,11 +167,21 @@ export default function DBSelect(props: DBSelectProps) { name={props.name} value={props.value ?? state._value} autocomplete={props.autocomplete} - onInput={(event: ChangeEvent) => state.handleInput(event)} - onClick={(event: ClickEvent) => state.handleClick(event)} - onChange={(event: ChangeEvent) => state.handleChange(event)} - onBlur={(event: InteractionEvent) => state.handleBlur(event)} - onFocus={(event: InteractionEvent) => state.handleFocus(event)} + onInput={(event: ChangeEvent) => + state.handleInput(event) + } + onClick={(event: ClickEvent) => + state.handleClick(event) + } + onChange={(event: ChangeEvent) => + state.handleChange(event) + } + onBlur={(event: InteractionEvent) => + state.handleBlur(event) + } + onFocus={(event: InteractionEvent) => + state.handleFocus(event) + } aria-describedby={state._descByIds}> {/* Empty option for floating label */} @@ -245,7 +255,7 @@ export default function DBSelect(props: DBSelectProps) { DEFAULT_INVALID_MESSAGE} - + {state._voiceOverFallback} diff --git a/packages/components/src/components/textarea/textarea.lite.tsx b/packages/components/src/components/textarea/textarea.lite.tsx index 101f18a652e..eb39b2dde67 100644 --- a/packages/components/src/components/textarea/textarea.lite.tsx +++ b/packages/components/src/components/textarea/textarea.lite.tsx @@ -41,7 +41,7 @@ export default function DBTextarea(props: DBTextareaProps) { rows: '4' }, _voiceOverFallback: '', - handleInput: (event: InputEvent) => { + handleInput: (event: InputEvent) => { if (props.onInput) { props.onInput(event); } @@ -50,7 +50,7 @@ export default function DBTextarea(props: DBTextareaProps) { props.input(event); } }, - handleChange: (event: ChangeEvent) => { + handleChange: (event: ChangeEvent) => { if (props.onChange) { props.onChange(event); } @@ -86,7 +86,7 @@ export default function DBTextarea(props: DBTextareaProps) { state._descByIds = ''; } }, - handleBlur: (event: InteractionEvent) => { + handleBlur: (event: InteractionEvent) => { if (props.onBlur) { props.onBlur(event); } @@ -95,7 +95,7 @@ export default function DBTextarea(props: DBTextareaProps) { props.blur(event); } }, - handleFocus: (event: InteractionEvent) => { + handleFocus: (event: InteractionEvent) => { if (props.onFocus) { props.onFocus(event); } @@ -154,10 +154,18 @@ export default function DBTextarea(props: DBTextareaProps) { wrap={props.wrap} spellcheck={props.spellCheck} autocomplete={props.autocomplete} - onInput={(event: ChangeEvent) => state.handleInput(event)} - onChange={(event: ChangeEvent) => state.handleChange(event)} - onBlur={(event: InteractionEvent) => state.handleBlur(event)} - onFocus={(event: InteractionEvent) => state.handleFocus(event)} + onInput={(event: ChangeEvent) => + state.handleInput(event) + } + onChange={(event: ChangeEvent) => + state.handleChange(event) + } + onBlur={(event: InteractionEvent) => + state.handleBlur(event) + } + onFocus={(event: InteractionEvent) => + state.handleFocus(event) + } value={props.value ?? state._value} aria-describedby={state._descByIds} placeholder={ @@ -192,7 +200,7 @@ export default function DBTextarea(props: DBTextareaProps) { DEFAULT_INVALID_MESSAGE} - + {state._voiceOverFallback} diff --git a/packages/components/src/styles/visually-hidden.scss b/packages/components/src/styles/visually-hidden.scss index 807a22f4690..e919a1fc4f8 100644 --- a/packages/components/src/styles/visually-hidden.scss +++ b/packages/components/src/styles/visually-hidden.scss @@ -16,6 +16,6 @@ pointer-events: none !important; } -[data-visually-hidden] { +.visually-hidden { @extend %visually-hidden; } From 2d934640b3a980943f7d7618ea6bc036783503a6 Mon Sep 17 00:00:00 2001 From: Maximilian Franzke <787658+mfranzke@users.noreply.github.com> Date: Fri, 26 Jul 2024 13:48:53 +0200 Subject: [PATCH 09/23] refactor: using an attribute instead of a class e.g. to mimic the standarized hidden attribute --- packages/components/src/styles/visually-hidden.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/components/src/styles/visually-hidden.scss b/packages/components/src/styles/visually-hidden.scss index e919a1fc4f8..807a22f4690 100644 --- a/packages/components/src/styles/visually-hidden.scss +++ b/packages/components/src/styles/visually-hidden.scss @@ -16,6 +16,6 @@ pointer-events: none !important; } -.visually-hidden { +[data-visually-hidden] { @extend %visually-hidden; } From cfe23eeb186a09dfb750f46d4e6099f4c1c44045 Mon Sep 17 00:00:00 2001 From: Maximilian Franzke <787658+mfranzke@users.noreply.github.com> Date: Fri, 26 Jul 2024 13:49:13 +0200 Subject: [PATCH 10/23] Update textarea.lite.tsx --- packages/components/src/components/textarea/textarea.lite.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/components/src/components/textarea/textarea.lite.tsx b/packages/components/src/components/textarea/textarea.lite.tsx index eb39b2dde67..245afb98529 100644 --- a/packages/components/src/components/textarea/textarea.lite.tsx +++ b/packages/components/src/components/textarea/textarea.lite.tsx @@ -200,7 +200,7 @@ export default function DBTextarea(props: DBTextareaProps) { DEFAULT_INVALID_MESSAGE} - + {state._voiceOverFallback} From c4f4e102e2430788d6580ade7223712f339ca315 Mon Sep 17 00:00:00 2001 From: Maximilian Franzke <787658+mfranzke@users.noreply.github.com> Date: Fri, 26 Jul 2024 13:49:22 +0200 Subject: [PATCH 11/23] Update select.lite.tsx --- packages/components/src/components/select/select.lite.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/components/src/components/select/select.lite.tsx b/packages/components/src/components/select/select.lite.tsx index 0b228ec7829..1e4599177cc 100644 --- a/packages/components/src/components/select/select.lite.tsx +++ b/packages/components/src/components/select/select.lite.tsx @@ -255,7 +255,7 @@ export default function DBSelect(props: DBSelectProps) { DEFAULT_INVALID_MESSAGE} - + {state._voiceOverFallback} From 78d36ffe499b3111c650c252445710f48ed5a264 Mon Sep 17 00:00:00 2001 From: Maximilian Franzke <787658+mfranzke@users.noreply.github.com> Date: Fri, 26 Jul 2024 13:49:30 +0200 Subject: [PATCH 12/23] Update checkbox.lite.tsx --- packages/components/src/components/checkbox/checkbox.lite.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/components/src/components/checkbox/checkbox.lite.tsx b/packages/components/src/components/checkbox/checkbox.lite.tsx index 87c2f6420b1..86e86d8af79 100644 --- a/packages/components/src/components/checkbox/checkbox.lite.tsx +++ b/packages/components/src/components/checkbox/checkbox.lite.tsx @@ -191,7 +191,7 @@ export default function DBCheckbox(props: DBCheckboxProps) { DEFAULT_INVALID_MESSAGE} - + {state._voiceOverFallback} From 13d8369b3901a915cc311d2f2cb772604fcab489 Mon Sep 17 00:00:00 2001 From: Maximilian Franzke <787658+mfranzke@users.noreply.github.com> Date: Fri, 26 Jul 2024 13:55:15 +0200 Subject: [PATCH 13/23] Update input.lite.tsx --- packages/components/src/components/input/input.lite.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/components/src/components/input/input.lite.tsx b/packages/components/src/components/input/input.lite.tsx index 08472b9fcb4..f85f6785b75 100644 --- a/packages/components/src/components/input/input.lite.tsx +++ b/packages/components/src/components/input/input.lite.tsx @@ -242,7 +242,7 @@ export default function DBInput(props: DBInputProps) { DEFAULT_INVALID_MESSAGE} - + {state._voiceOverFallback} From 58b18eb8e623a395b3906f0a638e169603f022d1 Mon Sep 17 00:00:00 2001 From: Maximilian Franzke <787658+mfranzke@users.noreply.github.com> Date: Fri, 26 Jul 2024 14:11:35 +0200 Subject: [PATCH 14/23] Update textarea.lite.tsx --- .../components/src/components/textarea/textarea.lite.tsx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/components/src/components/textarea/textarea.lite.tsx b/packages/components/src/components/textarea/textarea.lite.tsx index 245afb98529..dc65cb2da3f 100644 --- a/packages/components/src/components/textarea/textarea.lite.tsx +++ b/packages/components/src/components/textarea/textarea.lite.tsx @@ -200,6 +200,11 @@ export default function DBTextarea(props: DBTextareaProps) { DEFAULT_INVALID_MESSAGE} + {state._voiceOverFallback} From b669db973ea12057729493b30f6bfdf5bf9cf3b0 Mon Sep 17 00:00:00 2001 From: Maximilian Franzke <787658+mfranzke@users.noreply.github.com> Date: Fri, 26 Jul 2024 14:11:42 +0200 Subject: [PATCH 15/23] Update select.lite.tsx --- packages/components/src/components/select/select.lite.tsx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/components/src/components/select/select.lite.tsx b/packages/components/src/components/select/select.lite.tsx index 1e4599177cc..1c7e3cf5fb5 100644 --- a/packages/components/src/components/select/select.lite.tsx +++ b/packages/components/src/components/select/select.lite.tsx @@ -255,6 +255,11 @@ export default function DBSelect(props: DBSelectProps) { DEFAULT_INVALID_MESSAGE} + {state._voiceOverFallback} From a6f6b37e5eb102f92f5fae91c31916387f5969da Mon Sep 17 00:00:00 2001 From: Maximilian Franzke <787658+mfranzke@users.noreply.github.com> Date: Fri, 26 Jul 2024 14:11:46 +0200 Subject: [PATCH 16/23] Update input.lite.tsx --- packages/components/src/components/input/input.lite.tsx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/components/src/components/input/input.lite.tsx b/packages/components/src/components/input/input.lite.tsx index f85f6785b75..2323ec9cccf 100644 --- a/packages/components/src/components/input/input.lite.tsx +++ b/packages/components/src/components/input/input.lite.tsx @@ -242,6 +242,11 @@ export default function DBInput(props: DBInputProps) { DEFAULT_INVALID_MESSAGE} + {state._voiceOverFallback} From e024f31dedb5da32c09ed742fd6f104506b6af96 Mon Sep 17 00:00:00 2001 From: Maximilian Franzke <787658+mfranzke@users.noreply.github.com> Date: Fri, 26 Jul 2024 14:11:50 +0200 Subject: [PATCH 17/23] Update checkbox.lite.tsx --- .../components/src/components/checkbox/checkbox.lite.tsx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/components/src/components/checkbox/checkbox.lite.tsx b/packages/components/src/components/checkbox/checkbox.lite.tsx index 86e86d8af79..5fa367b14f9 100644 --- a/packages/components/src/components/checkbox/checkbox.lite.tsx +++ b/packages/components/src/components/checkbox/checkbox.lite.tsx @@ -191,6 +191,11 @@ export default function DBCheckbox(props: DBCheckboxProps) { DEFAULT_INVALID_MESSAGE} + {state._voiceOverFallback} From 6854aadef4cb6233e8846c81f23be8b034c54c23 Mon Sep 17 00:00:00 2001 From: Maximilian Franzke Date: Fri, 26 Jul 2024 14:55:09 +0200 Subject: [PATCH 18/23] refactor: cool dude comment --- .../src/components/checkbox/checkbox.lite.tsx | 22 +++++------ .../src/components/input/input.lite.tsx | 32 ++++++---------- .../src/components/select/select.lite.tsx | 38 +++++++------------ .../src/components/textarea/textarea.lite.tsx | 32 ++++++---------- 4 files changed, 44 insertions(+), 80 deletions(-) diff --git a/packages/components/src/components/checkbox/checkbox.lite.tsx b/packages/components/src/components/checkbox/checkbox.lite.tsx index 5fa367b14f9..41e1ee44ef5 100644 --- a/packages/components/src/components/checkbox/checkbox.lite.tsx +++ b/packages/components/src/components/checkbox/checkbox.lite.tsx @@ -34,7 +34,7 @@ export default function DBCheckbox(props: DBCheckboxProps) { _invalidMessageId: this._id + DEFAULT_INVALID_MESSAGE_ID_SUFFIX, _descByIds: '', _voiceOverFallback: '', - handleChange: (event: ChangeEvent) => { + handleChange: (event: ChangeEvent) => { if (props.onChange) { props.onChange(event); } @@ -68,7 +68,7 @@ export default function DBCheckbox(props: DBCheckboxProps) { state._descByIds = ''; } }, - handleBlur: (event: InteractionEvent) => { + handleBlur: (event: InteractionEvent) => { if (props.onBlur) { props.onBlur(event); } @@ -77,7 +77,7 @@ export default function DBCheckbox(props: DBCheckboxProps) { props.blur(event); } }, - handleFocus: (event: InteractionEvent) => { + handleFocus: (event: InteractionEvent) => { if (props.onFocus) { props.onFocus(event); } @@ -149,13 +149,11 @@ export default function DBCheckbox(props: DBCheckboxProps) { disabled={props.disabled} value={props.value} required={props.required} - onChange={(event: ChangeEvent) => - state.handleChange(event) - } - onBlur={(event: InteractionEvent) => + onChange={(event: ChangeEvent) => state.handleChange(event)} + onBlur={(event: InteractionEvent) => state.handleBlur(event) } - onFocus={(event: InteractionEvent) => + onFocus={(event: InteractionEvent) => state.handleFocus(event) } aria-describedby={state._descByIds} @@ -191,11 +189,9 @@ export default function DBCheckbox(props: DBCheckboxProps) { DEFAULT_INVALID_MESSAGE} - + {/* * https://www.davidmacd.com/blog/test-aria-describedby-errormessage-aria-live.html + * Currently VoiceOver isn't supporting changes from aria-describedby. + * This is an internal Fallback */} {state._voiceOverFallback} diff --git a/packages/components/src/components/input/input.lite.tsx b/packages/components/src/components/input/input.lite.tsx index 2323ec9cccf..9b4c524bf56 100644 --- a/packages/components/src/components/input/input.lite.tsx +++ b/packages/components/src/components/input/input.lite.tsx @@ -47,7 +47,7 @@ export default function DBInput(props: DBInputProps) { label: DEFAULT_LABEL, placeholder: ' ' }, - handleInput: (event: InputEvent) => { + handleInput: (event: InputEvent) => { if (props.onInput) { props.onInput(event); } @@ -56,7 +56,7 @@ export default function DBInput(props: DBInputProps) { props.input(event); } }, - handleChange: (event: ChangeEvent) => { + handleChange: (event: ChangeEvent) => { if (props.onChange) { props.onChange(event); } @@ -95,7 +95,7 @@ export default function DBInput(props: DBInputProps) { state._descByIds = ''; } }, - handleBlur: (event: InteractionEvent) => { + handleBlur: (event: InteractionEvent) => { if (props.onBlur) { props.onBlur(event); } @@ -104,7 +104,7 @@ export default function DBInput(props: DBInputProps) { props.blur(event); } }, - handleFocus: (event: InteractionEvent) => { + handleFocus: (event: InteractionEvent) => { if (props.onFocus) { props.onFocus(event); } @@ -184,18 +184,10 @@ export default function DBInput(props: DBInputProps) { form={props.form} pattern={props.pattern} autocomplete={props.autocomplete} - onInput={(event: ChangeEvent) => - state.handleInput(event) - } - onChange={(event: ChangeEvent) => - state.handleChange(event) - } - onBlur={(event: InteractionEvent) => - state.handleBlur(event) - } - onFocus={(event: InteractionEvent) => - state.handleFocus(event) - } + onInput={(event: ChangeEvent) => state.handleInput(event)} + onChange={(event: ChangeEvent) => state.handleChange(event)} + onBlur={(event: InteractionEvent) => state.handleBlur(event)} + onFocus={(event: InteractionEvent) => state.handleFocus(event)} list={props.dataList && state._dataListId} aria-describedby={state._descByIds} /> @@ -242,11 +234,9 @@ export default function DBInput(props: DBInputProps) { DEFAULT_INVALID_MESSAGE} - + {/* * https://www.davidmacd.com/blog/test-aria-describedby-errormessage-aria-live.html + * Currently VoiceOver isn't supporting changes from aria-describedby. + * This is an internal Fallback */} {state._voiceOverFallback} diff --git a/packages/components/src/components/select/select.lite.tsx b/packages/components/src/components/select/select.lite.tsx index 1c7e3cf5fb5..1a474677598 100644 --- a/packages/components/src/components/select/select.lite.tsx +++ b/packages/components/src/components/select/select.lite.tsx @@ -48,12 +48,12 @@ export default function DBSelect(props: DBSelectProps) { _value: '', initialized: false, _voiceOverFallback: '', - handleClick: (event: ClickEvent) => { + handleClick: (event: ClickEvent) => { if (props.onClick) { props.onClick(event); } }, - handleInput: (event: InputEvent) => { + handleInput: (event: InputEvent) => { if (props.onInput) { props.onInput(event); } @@ -62,7 +62,7 @@ export default function DBSelect(props: DBSelectProps) { props.input(event); } }, - handleChange: (event: ChangeEvent) => { + handleChange: (event: ChangeEvent) => { if (props.onChange) { props.onChange(event); } @@ -97,7 +97,7 @@ export default function DBSelect(props: DBSelectProps) { state._descByIds = state._placeholderId; } }, - handleBlur: (event: InteractionEvent) => { + handleBlur: (event: InteractionEvent) => { if (props.onBlur) { props.onBlur(event); } @@ -106,7 +106,7 @@ export default function DBSelect(props: DBSelectProps) { props.blur(event); } }, - handleFocus: (event: InteractionEvent) => { + handleFocus: (event: InteractionEvent) => { if (props.onFocus) { props.onFocus(event); } @@ -167,21 +167,11 @@ export default function DBSelect(props: DBSelectProps) { name={props.name} value={props.value ?? state._value} autocomplete={props.autocomplete} - onInput={(event: ChangeEvent) => - state.handleInput(event) - } - onClick={(event: ClickEvent) => - state.handleClick(event) - } - onChange={(event: ChangeEvent) => - state.handleChange(event) - } - onBlur={(event: InteractionEvent) => - state.handleBlur(event) - } - onFocus={(event: InteractionEvent) => - state.handleFocus(event) - } + onInput={(event: ChangeEvent) => state.handleInput(event)} + onClick={(event: ClickEvent) => state.handleClick(event)} + onChange={(event: ChangeEvent) => state.handleChange(event)} + onBlur={(event: InteractionEvent) => state.handleBlur(event)} + onFocus={(event: InteractionEvent) => state.handleFocus(event)} aria-describedby={state._descByIds}> {/* Empty option for floating label */} @@ -255,11 +245,9 @@ export default function DBSelect(props: DBSelectProps) { DEFAULT_INVALID_MESSAGE} - + {/* * https://www.davidmacd.com/blog/test-aria-describedby-errormessage-aria-live.html + * Currently VoiceOver isn't supporting changes from aria-describedby. + * This is an internal Fallback */} {state._voiceOverFallback} diff --git a/packages/components/src/components/textarea/textarea.lite.tsx b/packages/components/src/components/textarea/textarea.lite.tsx index dc65cb2da3f..bcad6011cb4 100644 --- a/packages/components/src/components/textarea/textarea.lite.tsx +++ b/packages/components/src/components/textarea/textarea.lite.tsx @@ -41,7 +41,7 @@ export default function DBTextarea(props: DBTextareaProps) { rows: '4' }, _voiceOverFallback: '', - handleInput: (event: InputEvent) => { + handleInput: (event: InputEvent) => { if (props.onInput) { props.onInput(event); } @@ -50,7 +50,7 @@ export default function DBTextarea(props: DBTextareaProps) { props.input(event); } }, - handleChange: (event: ChangeEvent) => { + handleChange: (event: ChangeEvent) => { if (props.onChange) { props.onChange(event); } @@ -86,7 +86,7 @@ export default function DBTextarea(props: DBTextareaProps) { state._descByIds = ''; } }, - handleBlur: (event: InteractionEvent) => { + handleBlur: (event: InteractionEvent) => { if (props.onBlur) { props.onBlur(event); } @@ -95,7 +95,7 @@ export default function DBTextarea(props: DBTextareaProps) { props.blur(event); } }, - handleFocus: (event: InteractionEvent) => { + handleFocus: (event: InteractionEvent) => { if (props.onFocus) { props.onFocus(event); } @@ -154,18 +154,10 @@ export default function DBTextarea(props: DBTextareaProps) { wrap={props.wrap} spellcheck={props.spellCheck} autocomplete={props.autocomplete} - onInput={(event: ChangeEvent) => - state.handleInput(event) - } - onChange={(event: ChangeEvent) => - state.handleChange(event) - } - onBlur={(event: InteractionEvent) => - state.handleBlur(event) - } - onFocus={(event: InteractionEvent) => - state.handleFocus(event) - } + onInput={(event: ChangeEvent) => state.handleInput(event)} + onChange={(event: ChangeEvent) => state.handleChange(event)} + onBlur={(event: InteractionEvent) => state.handleBlur(event)} + onFocus={(event: InteractionEvent) => state.handleFocus(event)} value={props.value ?? state._value} aria-describedby={state._descByIds} placeholder={ @@ -200,11 +192,9 @@ export default function DBTextarea(props: DBTextareaProps) { DEFAULT_INVALID_MESSAGE} - + {/* * https://www.davidmacd.com/blog/test-aria-describedby-errormessage-aria-live.html + * Currently VoiceOver isn't supporting changes from aria-describedby. + * This is an internal Fallback */} {state._voiceOverFallback} From 8f83ed75bca29dd6acada37f9fa08e7cd19f8ec1 Mon Sep 17 00:00:00 2001 From: Nicolas Merget Date: Fri, 26 Jul 2024 15:34:13 +0200 Subject: [PATCH 19/23] fix: issues with _voiceOverFallback not clearing fix: issue with duplicate a11y-hidden --- .../src/components/checkbox/checkbox.lite.tsx | 4 +++- .../src/components/input/input.lite.tsx | 4 +++- .../src/components/select/select.lite.tsx | 4 +++- .../src/components/textarea/textarea.lite.tsx | 4 +++- .../src/styles/visually-hidden.scss | 23 ++++--------------- packages/foundations/scss/helpers/_a11y.scss | 19 +++++++++++---- 6 files changed, 30 insertions(+), 28 deletions(-) diff --git a/packages/components/src/components/checkbox/checkbox.lite.tsx b/packages/components/src/components/checkbox/checkbox.lite.tsx index 41e1ee44ef5..2b754a3373d 100644 --- a/packages/components/src/components/checkbox/checkbox.lite.tsx +++ b/packages/components/src/components/checkbox/checkbox.lite.tsx @@ -76,6 +76,8 @@ export default function DBCheckbox(props: DBCheckboxProps) { if (props.blur) { props.blur(event); } + + state._voiceOverFallback = ''; }, handleFocus: (event: InteractionEvent) => { if (props.onFocus) { @@ -192,7 +194,7 @@ export default function DBCheckbox(props: DBCheckboxProps) { {/* * https://www.davidmacd.com/blog/test-aria-describedby-errormessage-aria-live.html * Currently VoiceOver isn't supporting changes from aria-describedby. * This is an internal Fallback */} - + {state._voiceOverFallback} diff --git a/packages/components/src/components/input/input.lite.tsx b/packages/components/src/components/input/input.lite.tsx index 9b4c524bf56..d91abe2a6f0 100644 --- a/packages/components/src/components/input/input.lite.tsx +++ b/packages/components/src/components/input/input.lite.tsx @@ -103,6 +103,8 @@ export default function DBInput(props: DBInputProps) { if (props.blur) { props.blur(event); } + + state._voiceOverFallback = ''; }, handleFocus: (event: InteractionEvent) => { if (props.onFocus) { @@ -237,7 +239,7 @@ export default function DBInput(props: DBInputProps) { {/* * https://www.davidmacd.com/blog/test-aria-describedby-errormessage-aria-live.html * Currently VoiceOver isn't supporting changes from aria-describedby. * This is an internal Fallback */} - + {state._voiceOverFallback} diff --git a/packages/components/src/components/select/select.lite.tsx b/packages/components/src/components/select/select.lite.tsx index 1a474677598..006b0c69979 100644 --- a/packages/components/src/components/select/select.lite.tsx +++ b/packages/components/src/components/select/select.lite.tsx @@ -105,6 +105,8 @@ export default function DBSelect(props: DBSelectProps) { if (props.blur) { props.blur(event); } + + state._voiceOverFallback = ''; }, handleFocus: (event: InteractionEvent) => { if (props.onFocus) { @@ -248,7 +250,7 @@ export default function DBSelect(props: DBSelectProps) { {/* * https://www.davidmacd.com/blog/test-aria-describedby-errormessage-aria-live.html * Currently VoiceOver isn't supporting changes from aria-describedby. * This is an internal Fallback */} - + {state._voiceOverFallback} diff --git a/packages/components/src/components/textarea/textarea.lite.tsx b/packages/components/src/components/textarea/textarea.lite.tsx index bcad6011cb4..a5deb6ff7cc 100644 --- a/packages/components/src/components/textarea/textarea.lite.tsx +++ b/packages/components/src/components/textarea/textarea.lite.tsx @@ -94,6 +94,8 @@ export default function DBTextarea(props: DBTextareaProps) { if (props.blur) { props.blur(event); } + + state._voiceOverFallback = ''; }, handleFocus: (event: InteractionEvent) => { if (props.onFocus) { @@ -195,7 +197,7 @@ export default function DBTextarea(props: DBTextareaProps) { {/* * https://www.davidmacd.com/blog/test-aria-describedby-errormessage-aria-live.html * Currently VoiceOver isn't supporting changes from aria-describedby. * This is an internal Fallback */} - + {state._voiceOverFallback} diff --git a/packages/components/src/styles/visually-hidden.scss b/packages/components/src/styles/visually-hidden.scss index 807a22f4690..6a175b4c45b 100644 --- a/packages/components/src/styles/visually-hidden.scss +++ b/packages/components/src/styles/visually-hidden.scss @@ -1,21 +1,6 @@ -%visually-hidden { - clip: rect(0, 0, 0, 0) !important; - overflow: hidden !important; - white-space: nowrap !important; - font-size: 0 !important; - all: initial; - inset-block-start: 0 !important; - block-size: 1px !important; - position: absolute !important; - inline-size: 1px !important; - border-width: 0 !important; - border-style: initial !important; - border-color: initial !important; - border-image: initial !important; - padding: 0 !important; - pointer-events: none !important; -} +@use "@db-ui/foundations/build/scss/helpers"; -[data-visually-hidden] { - @extend %visually-hidden; +.db-visually-hidden, +[data-visually-hidden="true"] { + @extend %a11y-visually-hidden; } diff --git a/packages/foundations/scss/helpers/_a11y.scss b/packages/foundations/scss/helpers/_a11y.scss index f382bbbf126..e7ff6b4d5ac 100644 --- a/packages/foundations/scss/helpers/_a11y.scss +++ b/packages/foundations/scss/helpers/_a11y.scss @@ -1,8 +1,17 @@ %a11y-visually-hidden { - clip: rect(0, 0, 0, 0); - block-size: 1px; - overflow: hidden; + clip: rect(0, 0, 0, 0) !important; + overflow: hidden !important; + white-space: nowrap !important; + font-size: 0 !important; + all: initial; + inset-block-start: 0 !important; + block-size: 1px !important; position: absolute !important; - white-space: nowrap; - inline-size: 1px; + inline-size: 1px !important; + border-width: 0 !important; + border-style: initial !important; + border-color: initial !important; + border-image: initial !important; + padding: 0 !important; + pointer-events: none !important; } From 2ab0e43212178d011d7b8079ec05f7000347cdb7 Mon Sep 17 00:00:00 2001 From: Nicolas Merget Date: Fri, 26 Jul 2024 15:40:22 +0200 Subject: [PATCH 20/23] fix: someone broke typescript --- .../src/components/checkbox/checkbox.lite.tsx | 14 ++++++----- .../src/components/input/input.lite.tsx | 24 ++++++++++++------- .../src/components/select/select.lite.tsx | 10 ++++---- .../src/components/textarea/textarea.lite.tsx | 24 ++++++++++++------- 4 files changed, 45 insertions(+), 27 deletions(-) diff --git a/packages/components/src/components/checkbox/checkbox.lite.tsx b/packages/components/src/components/checkbox/checkbox.lite.tsx index 2b754a3373d..8426697818d 100644 --- a/packages/components/src/components/checkbox/checkbox.lite.tsx +++ b/packages/components/src/components/checkbox/checkbox.lite.tsx @@ -34,7 +34,7 @@ export default function DBCheckbox(props: DBCheckboxProps) { _invalidMessageId: this._id + DEFAULT_INVALID_MESSAGE_ID_SUFFIX, _descByIds: '', _voiceOverFallback: '', - handleChange: (event: ChangeEvent) => { + handleChange: (event: ChangeEvent) => { if (props.onChange) { props.onChange(event); } @@ -68,7 +68,7 @@ export default function DBCheckbox(props: DBCheckboxProps) { state._descByIds = ''; } }, - handleBlur: (event: InteractionEvent) => { + handleBlur: (event: InteractionEvent) => { if (props.onBlur) { props.onBlur(event); } @@ -79,7 +79,7 @@ export default function DBCheckbox(props: DBCheckboxProps) { state._voiceOverFallback = ''; }, - handleFocus: (event: InteractionEvent) => { + handleFocus: (event: InteractionEvent) => { if (props.onFocus) { props.onFocus(event); } @@ -151,11 +151,13 @@ export default function DBCheckbox(props: DBCheckboxProps) { disabled={props.disabled} value={props.value} required={props.required} - onChange={(event: ChangeEvent) => state.handleChange(event)} - onBlur={(event: InteractionEvent) => + onChange={(event: ChangeEvent) => + state.handleChange(event) + } + onBlur={(event: InteractionEvent) => state.handleBlur(event) } - onFocus={(event: InteractionEvent) => + onFocus={(event: InteractionEvent) => state.handleFocus(event) } aria-describedby={state._descByIds} diff --git a/packages/components/src/components/input/input.lite.tsx b/packages/components/src/components/input/input.lite.tsx index d91abe2a6f0..d4e43fc25d4 100644 --- a/packages/components/src/components/input/input.lite.tsx +++ b/packages/components/src/components/input/input.lite.tsx @@ -47,7 +47,7 @@ export default function DBInput(props: DBInputProps) { label: DEFAULT_LABEL, placeholder: ' ' }, - handleInput: (event: InputEvent) => { + handleInput: (event: InputEvent) => { if (props.onInput) { props.onInput(event); } @@ -56,7 +56,7 @@ export default function DBInput(props: DBInputProps) { props.input(event); } }, - handleChange: (event: ChangeEvent) => { + handleChange: (event: ChangeEvent) => { if (props.onChange) { props.onChange(event); } @@ -95,7 +95,7 @@ export default function DBInput(props: DBInputProps) { state._descByIds = ''; } }, - handleBlur: (event: InteractionEvent) => { + handleBlur: (event: InteractionEvent) => { if (props.onBlur) { props.onBlur(event); } @@ -106,7 +106,7 @@ export default function DBInput(props: DBInputProps) { state._voiceOverFallback = ''; }, - handleFocus: (event: InteractionEvent) => { + handleFocus: (event: InteractionEvent) => { if (props.onFocus) { props.onFocus(event); } @@ -186,10 +186,18 @@ export default function DBInput(props: DBInputProps) { form={props.form} pattern={props.pattern} autocomplete={props.autocomplete} - onInput={(event: ChangeEvent) => state.handleInput(event)} - onChange={(event: ChangeEvent) => state.handleChange(event)} - onBlur={(event: InteractionEvent) => state.handleBlur(event)} - onFocus={(event: InteractionEvent) => state.handleFocus(event)} + onInput={(event: ChangeEvent) => + state.handleInput(event) + } + onChange={(event: ChangeEvent) => + state.handleChange(event) + } + onBlur={(event: InteractionEvent) => + state.handleBlur(event) + } + onFocus={(event: InteractionEvent) => + state.handleFocus(event) + } list={props.dataList && state._dataListId} aria-describedby={state._descByIds} /> diff --git a/packages/components/src/components/select/select.lite.tsx b/packages/components/src/components/select/select.lite.tsx index 006b0c69979..fbeaf50ce1d 100644 --- a/packages/components/src/components/select/select.lite.tsx +++ b/packages/components/src/components/select/select.lite.tsx @@ -48,12 +48,12 @@ export default function DBSelect(props: DBSelectProps) { _value: '', initialized: false, _voiceOverFallback: '', - handleClick: (event: ClickEvent) => { + handleClick: (event: ClickEvent) => { if (props.onClick) { props.onClick(event); } }, - handleInput: (event: InputEvent) => { + handleInput: (event: InputEvent) => { if (props.onInput) { props.onInput(event); } @@ -62,7 +62,7 @@ export default function DBSelect(props: DBSelectProps) { props.input(event); } }, - handleChange: (event: ChangeEvent) => { + handleChange: (event: ChangeEvent) => { if (props.onChange) { props.onChange(event); } @@ -97,7 +97,7 @@ export default function DBSelect(props: DBSelectProps) { state._descByIds = state._placeholderId; } }, - handleBlur: (event: InteractionEvent) => { + handleBlur: (event: InteractionEvent) => { if (props.onBlur) { props.onBlur(event); } @@ -108,7 +108,7 @@ export default function DBSelect(props: DBSelectProps) { state._voiceOverFallback = ''; }, - handleFocus: (event: InteractionEvent) => { + handleFocus: (event: InteractionEvent) => { if (props.onFocus) { props.onFocus(event); } diff --git a/packages/components/src/components/textarea/textarea.lite.tsx b/packages/components/src/components/textarea/textarea.lite.tsx index a5deb6ff7cc..d5fed4eefe8 100644 --- a/packages/components/src/components/textarea/textarea.lite.tsx +++ b/packages/components/src/components/textarea/textarea.lite.tsx @@ -41,7 +41,7 @@ export default function DBTextarea(props: DBTextareaProps) { rows: '4' }, _voiceOverFallback: '', - handleInput: (event: InputEvent) => { + handleInput: (event: InputEvent) => { if (props.onInput) { props.onInput(event); } @@ -50,7 +50,7 @@ export default function DBTextarea(props: DBTextareaProps) { props.input(event); } }, - handleChange: (event: ChangeEvent) => { + handleChange: (event: ChangeEvent) => { if (props.onChange) { props.onChange(event); } @@ -86,7 +86,7 @@ export default function DBTextarea(props: DBTextareaProps) { state._descByIds = ''; } }, - handleBlur: (event: InteractionEvent) => { + handleBlur: (event: InteractionEvent) => { if (props.onBlur) { props.onBlur(event); } @@ -97,7 +97,7 @@ export default function DBTextarea(props: DBTextareaProps) { state._voiceOverFallback = ''; }, - handleFocus: (event: InteractionEvent) => { + handleFocus: (event: InteractionEvent) => { if (props.onFocus) { props.onFocus(event); } @@ -156,10 +156,18 @@ export default function DBTextarea(props: DBTextareaProps) { wrap={props.wrap} spellcheck={props.spellCheck} autocomplete={props.autocomplete} - onInput={(event: ChangeEvent) => state.handleInput(event)} - onChange={(event: ChangeEvent) => state.handleChange(event)} - onBlur={(event: InteractionEvent) => state.handleBlur(event)} - onFocus={(event: InteractionEvent) => state.handleFocus(event)} + onInput={(event: ChangeEvent) => + state.handleInput(event) + } + onChange={(event: ChangeEvent) => + state.handleChange(event) + } + onBlur={(event: InteractionEvent) => + state.handleBlur(event) + } + onFocus={(event: InteractionEvent) => + state.handleFocus(event) + } value={props.value ?? state._value} aria-describedby={state._descByIds} placeholder={ From a5fbcc146c4116abf2a391ca99ca68ca1662506e Mon Sep 17 00:00:00 2001 From: Nicolas Merget Date: Mon, 29 Jul 2024 10:03:21 +0200 Subject: [PATCH 21/23] fix: issue with double valid message by adding delay fn --- .../src/components/checkbox/checkbox.lite.tsx | 6 ++--- .../src/components/drawer/drawer.lite.tsx | 4 +-- .../src/components/input/input.lite.tsx | 6 ++--- .../src/components/select/select.lite.tsx | 26 +++++++++++++------ .../src/components/textarea/textarea.lite.tsx | 6 ++--- packages/components/src/utils/index.ts | 6 ++++- 6 files changed, 34 insertions(+), 20 deletions(-) diff --git a/packages/components/src/components/checkbox/checkbox.lite.tsx b/packages/components/src/components/checkbox/checkbox.lite.tsx index 8426697818d..98b658e44b2 100644 --- a/packages/components/src/components/checkbox/checkbox.lite.tsx +++ b/packages/components/src/components/checkbox/checkbox.lite.tsx @@ -7,7 +7,7 @@ import { useStore } from '@builder.io/mitosis'; import { DBCheckboxProps, DBCheckboxState } from './model'; -import { cls, hasVoiceOver, uuid } from '../../utils'; +import { cls, delay, hasVoiceOver, uuid } from '../../utils'; import { DEFAULT_INVALID_MESSAGE, DEFAULT_INVALID_MESSAGE_ID_SUFFIX, @@ -52,6 +52,7 @@ export default function DBCheckbox(props: DBCheckboxProps) { props.invalidMessage ?? ref?.validationMessage ?? DEFAULT_INVALID_MESSAGE; + delay(() => (state._voiceOverFallback = ''), 1000); } } else if ( props.customValidity === 'valid' || @@ -61,6 +62,7 @@ export default function DBCheckbox(props: DBCheckboxProps) { if (hasVoiceOver()) { state._voiceOverFallback = props.validMessage ?? DEFAULT_VALID_MESSAGE; + delay(() => (state._voiceOverFallback = ''), 1000); } } else if (props.message) { state._descByIds = state._messageId; @@ -76,8 +78,6 @@ export default function DBCheckbox(props: DBCheckboxProps) { if (props.blur) { props.blur(event); } - - state._voiceOverFallback = ''; }, handleFocus: (event: InteractionEvent) => { if (props.onFocus) { diff --git a/packages/components/src/components/drawer/drawer.lite.tsx b/packages/components/src/components/drawer/drawer.lite.tsx index 0b3bab71b2d..ce6b302b0d1 100644 --- a/packages/components/src/components/drawer/drawer.lite.tsx +++ b/packages/components/src/components/drawer/drawer.lite.tsx @@ -10,7 +10,7 @@ import { import { DBDrawerProps, DBDrawerState } from './model'; import { DBButton } from '../button'; import { DEFAULT_CLOSE_BUTTON } from '../../shared/constants'; -import { cls } from '../../utils'; +import { cls, delay } from '../../utils'; useMetadata({ isAttachedToShadowDom: true @@ -54,7 +54,7 @@ export default function DBDrawer(props: DBDrawerProps) { if (dialogContainerRef) { dialogContainerRef.hidden = true; } - setTimeout(() => { + delay(() => { if (dialogContainerRef) { dialogContainerRef.hidden = false; } diff --git a/packages/components/src/components/input/input.lite.tsx b/packages/components/src/components/input/input.lite.tsx index d4e43fc25d4..494adde355c 100644 --- a/packages/components/src/components/input/input.lite.tsx +++ b/packages/components/src/components/input/input.lite.tsx @@ -7,7 +7,7 @@ import { useRef, useStore } from '@builder.io/mitosis'; -import { cls, hasVoiceOver, isArrayOfStrings, uuid } from '../../utils'; +import { cls, delay, hasVoiceOver, isArrayOfStrings, uuid } from '../../utils'; import { DBInputProps, DBInputState } from './model'; import { DEFAULT_DATALIST_ID_SUFFIX, @@ -75,6 +75,7 @@ export default function DBInput(props: DBInputProps) { props.invalidMessage ?? ref?.validationMessage ?? DEFAULT_INVALID_MESSAGE; + delay(() => (state._voiceOverFallback = ''), 1000); } } else if ( props.customValidity === 'valid' || @@ -88,6 +89,7 @@ export default function DBInput(props: DBInputProps) { if (hasVoiceOver()) { state._voiceOverFallback = props.validMessage ?? DEFAULT_VALID_MESSAGE; + delay(() => (state._voiceOverFallback = ''), 1000); } } else if (props.message) { state._descByIds = state._messageId; @@ -103,8 +105,6 @@ export default function DBInput(props: DBInputProps) { if (props.blur) { props.blur(event); } - - state._voiceOverFallback = ''; }, handleFocus: (event: InteractionEvent) => { if (props.onFocus) { diff --git a/packages/components/src/components/select/select.lite.tsx b/packages/components/src/components/select/select.lite.tsx index fbeaf50ce1d..78939a0ec37 100644 --- a/packages/components/src/components/select/select.lite.tsx +++ b/packages/components/src/components/select/select.lite.tsx @@ -8,7 +8,7 @@ import { useStore } from '@builder.io/mitosis'; import { DBSelectOptionType, DBSelectProps, DBSelectState } from './model'; -import { cls, hasVoiceOver, uuid } from '../../utils'; +import { cls, delay, hasVoiceOver, uuid } from '../../utils'; import { DEFAULT_INVALID_MESSAGE, DEFAULT_INVALID_MESSAGE_ID_SUFFIX, @@ -81,6 +81,7 @@ export default function DBSelect(props: DBSelectProps) { props.invalidMessage ?? ref?.validationMessage ?? DEFAULT_INVALID_MESSAGE; + delay(() => (state._voiceOverFallback = ''), 1000); } } else if ( props.customValidity === 'valid' || @@ -90,6 +91,7 @@ export default function DBSelect(props: DBSelectProps) { if (hasVoiceOver()) { state._voiceOverFallback = props.validMessage ?? DEFAULT_VALID_MESSAGE; + delay(() => (state._voiceOverFallback = ''), 1000); } } else if (props.message) { state._descByIds = state._messageId; @@ -105,8 +107,6 @@ export default function DBSelect(props: DBSelectProps) { if (props.blur) { props.blur(event); } - - state._voiceOverFallback = ''; }, handleFocus: (event: InteractionEvent) => { if (props.onFocus) { @@ -169,11 +169,21 @@ export default function DBSelect(props: DBSelectProps) { name={props.name} value={props.value ?? state._value} autocomplete={props.autocomplete} - onInput={(event: ChangeEvent) => state.handleInput(event)} - onClick={(event: ClickEvent) => state.handleClick(event)} - onChange={(event: ChangeEvent) => state.handleChange(event)} - onBlur={(event: InteractionEvent) => state.handleBlur(event)} - onFocus={(event: InteractionEvent) => state.handleFocus(event)} + onInput={(event: ChangeEvent) => + state.handleInput(event) + } + onClick={(event: ClickEvent) => + state.handleClick(event) + } + onChange={(event: ChangeEvent) => + state.handleChange(event) + } + onBlur={(event: InteractionEvent) => + state.handleBlur(event) + } + onFocus={(event: InteractionEvent) => + state.handleFocus(event) + } aria-describedby={state._descByIds}> {/* Empty option for floating label */} diff --git a/packages/components/src/components/textarea/textarea.lite.tsx b/packages/components/src/components/textarea/textarea.lite.tsx index d5fed4eefe8..fbf639c965a 100644 --- a/packages/components/src/components/textarea/textarea.lite.tsx +++ b/packages/components/src/components/textarea/textarea.lite.tsx @@ -8,7 +8,7 @@ import { } from '@builder.io/mitosis'; import { DBTextareaProps, DBTextareaState } from './model'; import { DBInfotext } from '../infotext'; -import { cls, hasVoiceOver, uuid } from '../../utils'; +import { cls, delay, hasVoiceOver, uuid } from '../../utils'; import { DEFAULT_INVALID_MESSAGE, DEFAULT_INVALID_MESSAGE_ID_SUFFIX, @@ -69,6 +69,7 @@ export default function DBTextarea(props: DBTextareaProps) { props.invalidMessage ?? ref?.validationMessage ?? DEFAULT_INVALID_MESSAGE; + delay(() => (state._voiceOverFallback = ''), 1000); } } else if ( props.customValidity === 'valid' || @@ -79,6 +80,7 @@ export default function DBTextarea(props: DBTextareaProps) { if (hasVoiceOver()) { state._voiceOverFallback = props.validMessage ?? DEFAULT_VALID_MESSAGE; + delay(() => (state._voiceOverFallback = ''), 1000); } } else if (props.message) { state._descByIds = state._messageId; @@ -94,8 +96,6 @@ export default function DBTextarea(props: DBTextareaProps) { if (props.blur) { props.blur(event); } - - state._voiceOverFallback = ''; }, handleFocus: (event: InteractionEvent) => { if (props.onFocus) { diff --git a/packages/components/src/utils/index.ts b/packages/components/src/utils/index.ts index e1b22666291..f18e961eb65 100644 --- a/packages/components/src/utils/index.ts +++ b/packages/components/src/utils/index.ts @@ -199,6 +199,9 @@ export const hasVoiceOver = (): boolean => typeof window !== 'undefined' && appleOs.some((os) => window.navigator.userAgent.includes(os)); +export const delay = (fn: () => void, ms: number) => + new Promise(() => setTimeout(fn, ms)); + export default { filterPassingProps, cls, @@ -209,5 +212,6 @@ export default { isInView, handleDataOutside, isArrayOfStrings, - hasVoiceOver + hasVoiceOver, + delay }; From 705f537fe36820830e1be8cc0c018ff187da1a08 Mon Sep 17 00:00:00 2001 From: Nicolas Merget Date: Wed, 14 Aug 2024 09:37:52 +0200 Subject: [PATCH 22/23] chore: update sr tests --- ...ould-inform-user-for-changes.txt => DBInput-required-1.txt} | 0 ...ould-inform-user-for-changes.txt => DBInput-required-1.txt} | 0 showcases/screen-reader/tests/input.spec.ts | 3 ++- 3 files changed, 2 insertions(+), 1 deletion(-) rename showcases/screen-reader/__snapshots__/macos/webkit/{DBInput-should-inform-user-for-changes.txt => DBInput-required-1.txt} (100%) rename showcases/screen-reader/__snapshots__/windows/chromium/{DBInput-should-inform-user-for-changes.txt => DBInput-required-1.txt} (100%) diff --git a/showcases/screen-reader/__snapshots__/macos/webkit/DBInput-should-inform-user-for-changes.txt b/showcases/screen-reader/__snapshots__/macos/webkit/DBInput-required-1.txt similarity index 100% rename from showcases/screen-reader/__snapshots__/macos/webkit/DBInput-should-inform-user-for-changes.txt rename to showcases/screen-reader/__snapshots__/macos/webkit/DBInput-required-1.txt diff --git a/showcases/screen-reader/__snapshots__/windows/chromium/DBInput-should-inform-user-for-changes.txt b/showcases/screen-reader/__snapshots__/windows/chromium/DBInput-required-1.txt similarity index 100% rename from showcases/screen-reader/__snapshots__/windows/chromium/DBInput-should-inform-user-for-changes.txt rename to showcases/screen-reader/__snapshots__/windows/chromium/DBInput-required-1.txt diff --git a/showcases/screen-reader/tests/input.spec.ts b/showcases/screen-reader/tests/input.spec.ts index 52f26439d3f..334807196f4 100644 --- a/showcases/screen-reader/tests/input.spec.ts +++ b/showcases/screen-reader/tests/input.spec.ts @@ -41,7 +41,8 @@ test.describe('DBInput', () => { }); testDefault({ test, - title: 'should inform user for changes', + title: 'required', + description: 'should inform user for changes', url: './#/03/input?page=requirement', async testFn(voiceOver, nvda) { if (voiceOver) { From 6e9196181f6c5d6f7a1f8d8a36b4022178362f5a Mon Sep 17 00:00:00 2001 From: Nicolas Merget Date: Wed, 14 Aug 2024 12:31:11 +0200 Subject: [PATCH 23/23] fix: issue with input typing sr test --- showcases/screen-reader/tests/input.spec.ts | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/showcases/screen-reader/tests/input.spec.ts b/showcases/screen-reader/tests/input.spec.ts index 334807196f4..0c29cbccfd7 100644 --- a/showcases/screen-reader/tests/input.spec.ts +++ b/showcases/screen-reader/tests/input.spec.ts @@ -1,5 +1,5 @@ import { NVDAKeyCodeCommands } from '@guidepup/guidepup'; -import { getTest, testDefault } from '../default'; +import { generateSnapshot, getTest, testDefault } from '../default'; const test = getTest(); test.describe('DBInput', () => { @@ -62,6 +62,18 @@ test.describe('DBInput', () => { await nvda?.press('Delete'); await nvda?.type('Test'); } + }, + async postTestFn(voiceOver, nvda, retry) { + if (nvda) { + await generateSnapshot(nvda, retry); + } else if (voiceOver) { + /* + * There is a timing issue for macOS for typing in input we clean the result + */ + await generateSnapshot(nvda, retry, (phraseLog) => + phraseLog.map((log) => log.replace('t. ', '')) + ); + } } }); });