Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Päivämääräkentän saavutettavuus #6117

Merged
merged 3 commits into from
Dec 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions frontend/src/lib-components/i18n.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ export interface Translations {
dateTooEarly: string
dateTooLate: string
}
open: string
close: string
}
documentTemplates: {
templateQuestions: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ const translations: Translations = {
validDate: 'Invalid date',
dateTooEarly: 'Date too early',
dateTooLate: 'Date too late'
}
},
open: 'Open date picker',
close: 'Close date picker'
}
}

Expand All @@ -38,7 +40,7 @@ describe('DatePicker', () => {
</TestContextProvider>
)
const get = () =>
screen.getByRole('textbox', { description: 'Date picker description' })
screen.getByRole('textbox', { name: 'Date picker description' })

it('attributes', () => {
render(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export default React.memo(function DatePickerDay({
return (
<DayPicker
mode="single"
autoFocus
onDayClick={handleDayClick}
locale={localeData}
selected={date?.toSystemTzDate()}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import React, { useCallback, useMemo } from 'react'
import styled from 'styled-components'

import LocalDate from 'lib-common/local-date'
import { useUniqueId } from 'lib-common/utils/useUniqueId'

import InputField, { InputInfo } from '../../atoms/form/InputField'
import { useTranslations } from '../../i18n'
Expand Down Expand Up @@ -37,27 +36,20 @@ const DateInputField = styled(InputField)`
`

export default React.memo(function DatePickerInput(props: Props) {
const i18n = useTranslations()
const { locale, useBrowserPicker, ...rest } = props
const ariaId = useUniqueId('date-picker-input')

return (
<>
{useBrowserPicker ? (
<DateInputNative {...rest} locale={locale} ariaId={ariaId} />
<DateInputNative locale={locale} {...rest} />
) : (
<DateInputText {...rest} locale={locale} ariaId={ariaId} />
<DateInputText locale={locale} {...rest} />
)}
<HelpTextForScreenReader lang={locale} id={ariaId}>
{i18n.datePicker.description}
</HelpTextForScreenReader>
</>
)
})

interface InternalProps extends Omit<Props, 'useBrowserPicker'> {
ariaId: string
}
type InternalProps = Omit<Props, 'useBrowserPicker'>

const DateInputText = React.memo(function DateInputText({
value,
Expand All @@ -69,8 +61,7 @@ const DateInputText = React.memo(function DateInputText({
disabled,
'data-qa': dataQa,
id,
required,
ariaId
required
}: InternalProps) {
const i18n = useTranslations()

Expand All @@ -88,7 +79,7 @@ const DateInputText = React.memo(function DateInputText({
onChange={handleChange}
onFocus={onFocus}
onBlur={onBlur}
aria-describedby={ariaId}
aria-label={i18n.datePicker.description}
info={info}
hideErrorsBeforeTouched={hideErrorsBeforeTouched}
readonly={disabled}
Expand All @@ -112,8 +103,7 @@ const DateInputNative = React.memo(function DateInputNative({
id,
required,
minDate,
maxDate,
ariaId
maxDate
}: InternalProps) {
const i18n = useTranslations()

Expand All @@ -140,7 +130,7 @@ const DateInputNative = React.memo(function DateInputNative({
onChangeTarget={handleChange}
onFocus={onFocus}
onBlur={onBlur}
aria-describedby={ariaId}
aria-label={i18n.datePicker.description}
info={info}
hideErrorsBeforeTouched={hideErrorsBeforeTouched}
readonly={disabled}
Expand All @@ -154,14 +144,3 @@ const DateInputNative = React.memo(function DateInputNative({
/>
)
})

const HelpTextForScreenReader = styled.p`
border: 0;
clip: rect(0 0 0 0);
height: 1px;
width: 1px;
margin: -1px;
padding: 0;
overflow: hidden;
position: absolute;
`
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import styled from 'styled-components'

import { useBoolean } from 'lib-common/form/hooks'
import LocalDate from 'lib-common/local-date'
import { IconOnlyButton } from 'lib-components/atoms/buttons/IconOnlyButton'
import { useTranslations } from 'lib-components/i18n'
import { faCalendarAlt } from 'lib-icons'

import { InputInfo } from '../../atoms/form/InputField'
import { fontWeights } from '../../typography'
Expand All @@ -18,11 +21,12 @@ import DatePickerInput from './DatePickerInput'
import { nativeDatePickerEnabled } from './helpers'

const inputWidth = 120
const iconWidth = 36

const DatePickerWrapper = styled.div`
position: relative;
display: inline-block;
width: ${inputWidth}px;
display: flex;
width: ${inputWidth + iconWidth}px;
`
const minMargin = 16
const overflow = 100
Expand Down Expand Up @@ -123,6 +127,7 @@ export interface DatePickerLowLevelProps {
minDate?: LocalDate
maxDate?: LocalDate
useBrowserPicker?: boolean
openOnFocus?: boolean
}

export default React.memo(function DatePickerLowLevel({
Expand All @@ -141,7 +146,8 @@ export default React.memo(function DatePickerLowLevel({
minDate,
maxDate,
useBrowserPicker = nativeDatePickerEnabled,
'data-qa': dataQa
'data-qa': dataQa,
openOnFocus = false
}: DatePickerLowLevelProps) {
const [showDatePicker, useShowDatePicker] = useBoolean(false)
const wrapperRef = useRef<HTMLDivElement>(null)
Expand All @@ -150,6 +156,8 @@ export default React.memo(function DatePickerLowLevel({
const showDatePickerOn = useShowDatePicker.on
const showDatePickerOff = useShowDatePicker.off

const i18n = useTranslations()

const handleUserKeyPress = useCallback(
(e: React.KeyboardEvent) => {
if (e.key === 'Esc' || e.key === 'Escape' || e.key === 'Enter') {
Expand All @@ -159,8 +167,11 @@ export default React.memo(function DatePickerLowLevel({
}
showDatePickerOff()
}
if (!showDatePicker && e.key === 'ArrowDown') {
showDatePickerOn()
}
},
[showDatePickerOff]
[showDatePicker, showDatePickerOff, showDatePickerOn]
)

const handleDayClick = useCallback(
Expand All @@ -176,10 +187,12 @@ export default React.memo(function DatePickerLowLevel({

const handleFocus = useCallback(
(e: React.FocusEvent<HTMLInputElement>) => {
showDatePickerOn()
if (openOnFocus) {
showDatePickerOn()
}
onFocus?.(e)
},
[onFocus, showDatePickerOn]
[onFocus, openOnFocus, showDatePickerOn]
)

const handleBlur = useCallback(
Expand Down Expand Up @@ -251,6 +264,14 @@ export default React.memo(function DatePickerLowLevel({
return () => undefined
}, [showDatePickerOff, showDatePicker])

const toggleDatePicker = useCallback(() => {
if (showDatePicker) {
showDatePickerOff()
} else {
showDatePickerOn()
}
}, [showDatePicker, showDatePickerOff, showDatePickerOn])

return (
<DatePickerWrapper ref={wrapperRef} onKeyDown={handleUserKeyPress}>
<DatePickerInput
Expand All @@ -269,6 +290,16 @@ export default React.memo(function DatePickerLowLevel({
minDate={minDate}
maxDate={maxDate}
/>
<StyledIconButton
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would take a quick look at the employee side too to check if the increased with of this component broke some layouts e.g. in modals where the space is limited

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point - is there a specific modal where it is an issue that should be checked?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure 🤔 Creating a new document template (lomakepohjat ylävalikosta) could be one. Maybe just use 10min to randomly poke around. Not that big of a deal anyway.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like there's "enoughish"(?) space on the citizen modal and e.g. the employee new doc template ->

Screenshot 2024-12-12 at 15 12 56 Screenshot 2024-12-12 at 15 14 31

icon={faCalendarAlt}
onClick={toggleDatePicker}
aria-controls="dialog"
aria-haspopup="dialog"
aria-expanded={showDatePicker}
aria-label={
showDatePicker ? i18n.datePicker.close : i18n.datePicker.open
}
/>
{!nativeDatePickerEnabled && showDatePicker ? (
<DayPickerPositioner ref={pickerRef} openAbove={openAbove}>
<DayPickerDiv>
Expand All @@ -286,3 +317,8 @@ export default React.memo(function DatePickerLowLevel({
</DatePickerWrapper>
)
})

const StyledIconButton = styled(IconOnlyButton)`
width: 100%;
margin: 0 0 0 4px;
`
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ const translations: Translations = {
validDate: 'Invalid date',
dateTooEarly: 'Date too early',
dateTooLate: 'Date too late'
}
},
open: 'Open date picker',
close: 'Close date picker'
}
}

Expand All @@ -44,7 +46,7 @@ describe('DateRangePicker', () => {
)

const [start, end] = screen.getAllByRole('textbox', {
description: 'Date picker description'
name: 'Date picker description'
})
expect(start).toHaveAttribute('placeholder', 'Placeholder')
expect(end).toHaveAttribute('placeholder', 'Placeholder')
Expand Down
4 changes: 3 additions & 1 deletion frontend/src/lib-components/utils/TestContextProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ export const testTranslations: Translations = {
validDate: '',
dateTooEarly: '',
dateTooLate: ''
}
},
open: '',
close: ''
},
documentTemplates: {
templateQuestions: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,14 @@ const components: Translations = {
datePicker: {
placeholder: 'dd.mm.yyyy',
description:
'Type the date in dd.mm.yyyy format. You can get to month picker with the tab key.',
'Type the date in dd.mm.yyyy format. You can get to month picker with the Down Arrow key.',
validationErrors: {
validDate: 'Valid date format is dd.mm.yyyy',
dateTooEarly: 'Pick a later date',
dateTooLate: 'Pick an earlier date'
}
},
open: 'Open date picker',
close: 'Close date picker'
},
documentTemplates: {
// only on employee frontend
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,14 @@ const components: Translations = {
datePicker: {
placeholder: 'pp.kk.vvvv',
description:
'Kirjoita päivämäärä kenttään muodossa pp.kk.vvvv. Tab-näppäimellä pääset kuukausivalitsimeen.',
'Kirjoita päivämäärä kenttään muodossa pp.kk.vvvv. Nuoli alas -näppäimellä pääset kuukausivalitsimeen.',
validationErrors: {
validDate: 'Anna muodossa pp.kk.vvvv',
dateTooEarly: 'Valitse myöhäisempi päivä',
dateTooLate: 'Valitse aikaisempi päivä'
}
},
open: 'Avaa päivämäärävalitsin',
close: 'Sulje päivämäärävalitsin'
},
documentTemplates: {
templateQuestions: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,14 @@ const components: Translations = {
datePicker: {
placeholder: 'dd.mm.åååå',
description:
'Skriv in datumet i formatet dd.mm.åååå. Du kan komma till månadsväljaren med tabbtangenten.',
'Skriv in datumet i formatet dd.mm.åååå. Du kan komma till månadsväljaren med pil ned-tangenten.',
validationErrors: {
validDate: 'Ange i format dd.mm.åååå',
dateTooEarly: 'Välj ett senare datum',
dateTooLate: 'Välj ett tidigare datum'
}
},
open: 'Öppna datumväljaren',
close: 'Stäng datumväljaren'
},
documentTemplates: {
// only on employee frontend
Expand Down
Loading