From f3608fa92bc1bf5682aff87ec8409698c9f28d5c Mon Sep 17 00:00:00 2001 From: Halvor Haugan <halvor.haugan@nav.no> Date: Wed, 20 Nov 2024 17:05:48 +0100 Subject: [PATCH 1/2] DatePicker/MonthPicker: add support for translations provider --- .changeset/moody-gorillas-try.md | 5 + .../react/src/date/datepicker/DatePicker.tsx | 9 +- .../date/datepicker/DatePickerStandalone.tsx | 9 +- .../src/date/datepicker/parts/Caption.tsx | 11 +- .../date/datepicker/parts/DropdownCaption.tsx | 19 +- .../src/date/datepicker/parts/WeekNumber.tsx | 47 +--- .../src/date/datepicker/parts/WeekRow.tsx | 13 +- .../react/src/date/hooks/useDatepicker.tsx | 6 +- .../react/src/date/hooks/useMonthPicker.tsx | 6 +- .../src/date/hooks/useRangeDatepicker.tsx | 6 +- .../src/date/monthpicker/MonthCaption.tsx | 19 +- .../src/date/monthpicker/MonthPicker.tsx | 8 +- .../core/react/src/date/parts/DateInput.tsx | 17 +- .../core/react/src/date/parts/DateWrapper.tsx | 18 +- @navikt/core/react/src/date/utils/index.ts | 9 +- @navikt/core/react/src/date/utils/labels.ts | 219 ------------------ @navikt/core/react/src/date/utils/locale.ts | 18 ++ .../core/react/src/util/i18n/locales/en.ts | 20 ++ .../core/react/src/util/i18n/locales/nb.ts | 20 ++ .../core/react/src/util/i18n/locales/nn.ts | 20 ++ 20 files changed, 172 insertions(+), 327 deletions(-) create mode 100644 .changeset/moody-gorillas-try.md delete mode 100644 @navikt/core/react/src/date/utils/labels.ts diff --git a/.changeset/moody-gorillas-try.md b/.changeset/moody-gorillas-try.md new file mode 100644 index 0000000000..1964d243f6 --- /dev/null +++ b/.changeset/moody-gorillas-try.md @@ -0,0 +1,5 @@ +--- +"@navikt/ds-react": patch +--- + +DatePicker/MonthPicker: Remove pointerEvents=none on CalendarIcon so that the title shows up as tooltip on hover diff --git a/@navikt/core/react/src/date/datepicker/DatePicker.tsx b/@navikt/core/react/src/date/datepicker/DatePicker.tsx index 64b9f65d33..7c150d62a4 100644 --- a/@navikt/core/react/src/date/datepicker/DatePicker.tsx +++ b/@navikt/core/react/src/date/datepicker/DatePicker.tsx @@ -5,10 +5,11 @@ import { DateRange, DayPicker, isMatch } from "react-day-picker"; import { omit } from "../../util"; import { useId } from "../../util/hooks"; import { useMergeRefs } from "../../util/hooks/useMergeRefs"; +import { useDateLocale } from "../../util/i18n/i18n.context"; import { DateContext } from "../context"; import { DatePickerInput } from "../parts/DateInput"; import { DateWrapper } from "../parts/DateWrapper"; -import { getLocaleFromString, labels } from "../utils"; +import { getLocaleFromString } from "../utils"; import DatePickerStandalone from "./DatePickerStandalone"; import Caption from "./parts/Caption"; import DropdownCaption from "./parts/DropdownCaption"; @@ -66,7 +67,7 @@ export const DatePicker = forwardRef<HTMLDivElement, DatePickerProps>( ( { children, - locale = "nb", + locale, dropdownCaption, disabled = [], disableWeekends = false, @@ -85,6 +86,7 @@ export const DatePicker = forwardRef<HTMLDivElement, DatePickerProps>( }, ref, ) => { + const langProviderLocale = useDateLocale(); const ariaId = useId(id); const [open, setOpen] = useState(_open ?? false); @@ -114,7 +116,7 @@ export const DatePicker = forwardRef<HTMLDivElement, DatePickerProps>( const DatePickerComponent = ( <DayPicker - locale={getLocaleFromString(locale)} + locale={locale ? getLocaleFromString(locale) : langProviderLocale} mode={mode} onSelect={handleSelect} selected={selected ?? selectedDates} @@ -134,7 +136,6 @@ export const DatePicker = forwardRef<HTMLDivElement, DatePickerProps>( }} weekStartsOn={1} initialFocus={false} - labels={labels as any} modifiers={{ weekend: (day) => disableWeekends && isWeekend(day), }} diff --git a/@navikt/core/react/src/date/datepicker/DatePickerStandalone.tsx b/@navikt/core/react/src/date/datepicker/DatePickerStandalone.tsx index f4ed9d74e2..dcf132e60c 100644 --- a/@navikt/core/react/src/date/datepicker/DatePickerStandalone.tsx +++ b/@navikt/core/react/src/date/datepicker/DatePickerStandalone.tsx @@ -3,7 +3,8 @@ import { isWeekend } from "date-fns"; import React, { forwardRef } from "react"; import { DateRange, DayPicker, isMatch } from "react-day-picker"; import { omit } from "../../util"; -import { getLocaleFromString, labels } from "../utils"; +import { useDateLocale } from "../../util/i18n/i18n.context"; +import { getLocaleFromString } from "../utils"; import Caption from "./parts/Caption"; import DropdownCaption from "./parts/DropdownCaption"; import { HeadRow } from "./parts/HeadRow"; @@ -49,7 +50,7 @@ export const DatePickerStandalone: DatePickerStandaloneType = forwardRef< ( { className, - locale = "nb", + locale, dropdownCaption, disabled = [], disableWeekends = false, @@ -63,6 +64,7 @@ export const DatePickerStandalone: DatePickerStandaloneType = forwardRef< }, ref, ) => { + const langProviderLocale = useDateLocale(); const [selectedDates, setSelectedDates] = React.useState< Date | Date[] | DateRange | undefined >(defaultSelected); @@ -83,7 +85,7 @@ export const DatePickerStandalone: DatePickerStandaloneType = forwardRef< className={cl("navds-date__standalone-wrapper", className)} > <DayPicker - locale={getLocaleFromString(locale)} + locale={locale ? getLocaleFromString(locale) : langProviderLocale} mode={mode} onSelect={handleSelect} selected={selected ?? selectedDates} @@ -103,7 +105,6 @@ export const DatePickerStandalone: DatePickerStandaloneType = forwardRef< }} weekStartsOn={1} initialFocus={false} - labels={labels as any} modifiers={{ weekend: (day) => disableWeekends && isWeekend(day), }} diff --git a/@navikt/core/react/src/date/datepicker/parts/Caption.tsx b/@navikt/core/react/src/date/datepicker/parts/Caption.tsx index 8df9eb357d..7e5bb32af7 100644 --- a/@navikt/core/react/src/date/datepicker/parts/Caption.tsx +++ b/@navikt/core/react/src/date/datepicker/parts/Caption.tsx @@ -3,6 +3,8 @@ import { CaptionProps, useDayPicker, useNavigation } from "react-day-picker"; import { ArrowLeftIcon, ArrowRightIcon } from "@navikt/aksel-icons"; import { Button } from "../../../button"; import { Label } from "../../../typography"; +import { useI18n } from "../../../util/i18n/i18n.context"; +import { getTranslations } from "../../utils"; import WeekRow from "./WeekRow"; /** @@ -11,13 +13,10 @@ import WeekRow from "./WeekRow"; export const DatePickerCaption = ({ displayMonth, id }: CaptionProps) => { const { goToMonth, nextMonth, previousMonth } = useNavigation(); const { - labels: { labelPrevious, labelNext }, formatters: { formatCaption }, locale, } = useDayPicker(); - - const previousLabel = labelPrevious(previousMonth, { locale }); - const nextLabel = labelNext(nextMonth, { locale }); + const translate = useI18n("DatePicker", getTranslations(locale.code)); return ( <> @@ -26,7 +25,7 @@ export const DatePickerCaption = ({ displayMonth, id }: CaptionProps) => { variant="tertiary" disabled={!previousMonth} onClick={() => previousMonth && goToMonth(previousMonth)} - icon={<ArrowLeftIcon title={previousLabel} />} + icon={<ArrowLeftIcon title={translate("previousMonth")} />} className="navds-date__caption-button" type="button" /> @@ -40,7 +39,7 @@ export const DatePickerCaption = ({ displayMonth, id }: CaptionProps) => { {formatCaption(displayMonth, { locale })} </Label> <Button - icon={<ArrowRightIcon title={nextLabel} />} + icon={<ArrowRightIcon title={translate("nextMonth")} />} onClick={() => nextMonth && goToMonth(nextMonth)} disabled={!nextMonth} variant="tertiary" diff --git a/@navikt/core/react/src/date/datepicker/parts/DropdownCaption.tsx b/@navikt/core/react/src/date/datepicker/parts/DropdownCaption.tsx index 8dc242046c..baefc329af 100644 --- a/@navikt/core/react/src/date/datepicker/parts/DropdownCaption.tsx +++ b/@navikt/core/react/src/date/datepicker/parts/DropdownCaption.tsx @@ -4,8 +4,8 @@ import { CaptionProps, useDayPicker, useNavigation } from "react-day-picker"; import { ArrowLeftIcon, ArrowRightIcon } from "@navikt/aksel-icons"; import { Button } from "../../../button"; import { Select } from "../../../form/select"; -import { getMonths, getYears } from "../../utils/get-dates"; -import { labelMonthDropdown, labelYearDropdown } from "../../utils/labels"; +import { useI18n } from "../../../util/i18n/i18n.context"; +import { getMonths, getTranslations, getYears } from "../../utils"; import WeekRow from "./WeekRow"; /** @@ -17,9 +17,9 @@ export const DropdownCaption = ({ displayMonth, id }: CaptionProps) => { fromDate, toDate, formatters: { formatYearCaption, formatMonthCaption, formatCaption }, - labels: { labelPrevious, labelNext }, locale, } = useDayPicker(); + const translate = useI18n("DatePicker", getTranslations(locale.code)); if (!fromDate || !toDate) { console.warn("Using dropdownCaption required fromDate and toDate"); @@ -44,11 +44,6 @@ export const DropdownCaption = ({ displayMonth, id }: CaptionProps) => { ).reverse(); const months = getMonths(fromDate, toDate, displayMonth); - const previousLabel = labelPrevious(previousMonth, { locale }); - const nextLabel = labelNext(nextMonth, { locale }); - const yearDropdownLabel = labelYearDropdown(locale); - const MonthDropdownLabel = labelMonthDropdown(locale); - return ( <> <div className="navds-date__caption"> @@ -64,14 +59,14 @@ export const DropdownCaption = ({ displayMonth, id }: CaptionProps) => { variant="tertiary" disabled={!previousMonth} onClick={() => previousMonth && goToMonth(previousMonth)} - icon={<ArrowLeftIcon title={previousLabel} />} + icon={<ArrowLeftIcon title={translate("previousMonth")} />} className="navds-date__caption-button" type="button" /> <div className="navds-date__caption"> <Select - label={MonthDropdownLabel} + label={translate("month")} hideLabel className="navds-date__caption__month" value={displayMonth.getMonth()} @@ -84,7 +79,7 @@ export const DropdownCaption = ({ displayMonth, id }: CaptionProps) => { ))} </Select> <Select - label={yearDropdownLabel} + label={translate("year")} hideLabel value={displayMonth.getFullYear()} onChange={handleYearChange} @@ -99,7 +94,7 @@ export const DropdownCaption = ({ displayMonth, id }: CaptionProps) => { </div> <Button - icon={<ArrowRightIcon title={nextLabel} />} + icon={<ArrowRightIcon title={translate("nextMonth")} />} onClick={() => nextMonth && goToMonth(nextMonth)} disabled={!nextMonth} variant="tertiary" diff --git a/@navikt/core/react/src/date/datepicker/parts/WeekNumber.tsx b/@navikt/core/react/src/date/datepicker/parts/WeekNumber.tsx index 7b69e29d8c..2d368fee62 100644 --- a/@navikt/core/react/src/date/datepicker/parts/WeekNumber.tsx +++ b/@navikt/core/react/src/date/datepicker/parts/WeekNumber.tsx @@ -1,75 +1,52 @@ /* https://github.com/gpbl/react-day-picker/blob/7f78cd5/src/components/WeekNumber/WeekNumber.tsx#L21 */ import React from "react"; import { Button, useDayPicker } from "react-day-picker"; -import { labelWeekNumber, labelWeekNumberButton } from "../../utils/labels"; +import { useI18n } from "../../../util/i18n/i18n.context"; +import { getTranslations } from "../../utils"; export interface WeekNumberProps { /** The number of the week. */ number: number; /** The dates in the week. */ dates: Date[]; - headerVersion?: boolean; } /** * https://github.com/gpbl/react-day-picker/tree/main/src/components/WeekNumber */ -function WeekNumber(props: WeekNumberProps): JSX.Element { - const { number: weekNumber, dates } = props; +function WeekNumber({ + number: weekNumber, + dates, +}: WeekNumberProps): JSX.Element { const { onWeekNumberClick, styles, classNames, locale: { code }, } = useDayPicker(); - - const weekLabel = labelWeekNumber({ - week: Number(weekNumber), - localeCode: code, - }); + const translate = useI18n("DatePicker", getTranslations(code)); if (!onWeekNumberClick) { return ( <span className={classNames.weeknumber} style={styles.weeknumber} - aria-label={weekLabel} + aria-label={translate("weekNumber", { week: weekNumber })} > {weekNumber} </span> ); } - const label = labelWeekNumberButton({ - week: Number(weekNumber), - localeCode: code, - }); - - const handleClick: React.MouseEventHandler = function (e) { - onWeekNumberClick(weekNumber, dates, e); - }; - - if (props?.headerVersion) { - return ( - <Button - name="week-number" - aria-label={label} - className={classNames.weeknumber} - style={styles.weeknumber} - onClick={handleClick} - > - {weekNumber} - </Button> - ); - } - return ( <Button name="week-number" - aria-label={label} + aria-label={translate("selectWeekNumber", { week: weekNumber })} className={classNames.weeknumber} style={styles.weeknumber} - onClick={handleClick} + onClick={(event) => { + onWeekNumberClick(weekNumber, dates, event); + }} > {weekNumber} </Button> diff --git a/@navikt/core/react/src/date/datepicker/parts/WeekRow.tsx b/@navikt/core/react/src/date/datepicker/parts/WeekRow.tsx index e82cd6f06c..f830f77061 100644 --- a/@navikt/core/react/src/date/datepicker/parts/WeekRow.tsx +++ b/@navikt/core/react/src/date/datepicker/parts/WeekRow.tsx @@ -3,13 +3,14 @@ import { useDayPicker } from "react-day-picker"; import { Show } from "../../../layout/responsive"; import { Detail } from "../../../typography"; import { useId } from "../../../util/hooks"; +import { useI18n } from "../../../util/i18n/i18n.context"; +import { getTranslations } from "../../utils"; import { getMonthWeeks } from "../../utils/get-month-weeks"; -import { labelWeek } from "../../utils/labels"; import WeekNumber from "./WeekNumber"; const WeekRow = ({ displayMonth }: { displayMonth: Date }) => { const { locale, fixedWeeks, onWeekNumberClick } = useDayPicker(); - + const translate = useI18n("DatePicker", getTranslations(locale.code)); const labelId = useId(); if (!onWeekNumberClick) { @@ -32,7 +33,7 @@ const WeekRow = ({ displayMonth }: { displayMonth: Date }) => { className="rdp-cell navds-date__week-cell" > <span className="navds-date__week-wrapper" id={labelId}> - {labelWeek(locale?.code)} + {`${translate("week")}:`} </span> </Detail> @@ -42,11 +43,7 @@ const WeekRow = ({ displayMonth }: { displayMonth: Date }) => { className="rdp-cell navds-date__week-cell" > <span className="navds-date__week-wrapper"> - <WeekNumber - number={week.weekNumber} - dates={week.dates} - headerVersion - /> + <WeekNumber number={week.weekNumber} dates={week.dates} /> </span> </td> ))} diff --git a/@navikt/core/react/src/date/hooks/useDatepicker.tsx b/@navikt/core/react/src/date/hooks/useDatepicker.tsx index 13b545273e..f0f9d6e477 100644 --- a/@navikt/core/react/src/date/hooks/useDatepicker.tsx +++ b/@navikt/core/react/src/date/hooks/useDatepicker.tsx @@ -1,6 +1,7 @@ import { differenceInCalendarDays, isWeekend } from "date-fns"; import React, { useCallback, useState } from "react"; import { DayClickEventHandler, isMatch } from "react-day-picker"; +import { useDateLocale } from "../../util/i18n/i18n.context"; import { DatePickerProps } from "../datepicker/DatePicker"; import { DateInputProps } from "../parts/DateInput"; import { @@ -130,7 +131,7 @@ export const useDatepicker = ( opt: UseDatepickerOptions = {}, ): UseDatepickerValue => { const { - locale: _locale = "nb", + locale: _locale, required, defaultSelected: _defaultSelected, today = new Date(), @@ -146,7 +147,8 @@ export const useDatepicker = ( } = opt; const [anchorRef, setAnchorRef] = useState<HTMLButtonElement | null>(null); - const locale = getLocaleFromString(_locale); + const localeFromProvider = useDateLocale(); + const locale = _locale ? getLocaleFromString(_locale) : localeFromProvider; const [defaultSelected, setDefaultSelected] = useState(_defaultSelected); diff --git a/@navikt/core/react/src/date/hooks/useMonthPicker.tsx b/@navikt/core/react/src/date/hooks/useMonthPicker.tsx index b04958dd8d..02e3be24ee 100644 --- a/@navikt/core/react/src/date/hooks/useMonthPicker.tsx +++ b/@navikt/core/react/src/date/hooks/useMonthPicker.tsx @@ -1,4 +1,5 @@ import React, { useCallback, useMemo, useState } from "react"; +import { useDateLocale } from "../../util/i18n/i18n.context"; import { MonthPickerProps } from "../monthpicker/types"; import { DateInputProps } from "../parts/DateInput"; import { @@ -126,7 +127,7 @@ export const useMonthpicker = ( opt: UseMonthPickerOptions = {}, ): UseMonthPickerValue => { const { - locale: _locale = "nb", + locale: _locale, defaultSelected: _defaultSelected, fromDate, toDate, @@ -143,7 +144,8 @@ export const useMonthpicker = ( const [defaultSelected, setDefaultSelected] = useState(_defaultSelected); const today = useMemo(() => new Date(), []); - const locale = getLocaleFromString(_locale); + const localeFromProvider = useDateLocale(); + const locale = _locale ? getLocaleFromString(_locale) : localeFromProvider; // Initialize states const [year, setYear] = useState(defaultSelected ?? defaultYear ?? today); diff --git a/@navikt/core/react/src/date/hooks/useRangeDatepicker.tsx b/@navikt/core/react/src/date/hooks/useRangeDatepicker.tsx index 819e729739..59cec139ae 100644 --- a/@navikt/core/react/src/date/hooks/useRangeDatepicker.tsx +++ b/@navikt/core/react/src/date/hooks/useRangeDatepicker.tsx @@ -5,6 +5,7 @@ import { } from "date-fns"; import React, { useState } from "react"; import { DateRange, isMatch } from "react-day-picker"; +import { useDateLocale } from "../../util/i18n/i18n.context"; import { DatePickerProps } from "../datepicker/DatePicker"; import { DateInputProps } from "../parts/DateInput"; import { @@ -220,7 +221,7 @@ export const useRangeDatepicker = ( opt: UseRangeDatepickerOptions = {}, ): UseRangeDatepickerValue => { const { - locale: _locale = "nb", + locale: _locale, defaultSelected: _defaultSelected, today = new Date(), fromDate, @@ -236,7 +237,8 @@ export const useRangeDatepicker = ( const [anchorRef, setAnchorRef] = useState<HTMLButtonElement | null>(null); - const locale = getLocaleFromString(_locale); + const localeFromProvider = useDateLocale(); + const locale = _locale ? getLocaleFromString(_locale) : localeFromProvider; const [defaultSelected, setDefaultSelected] = useState(_defaultSelected); diff --git a/@navikt/core/react/src/date/monthpicker/MonthCaption.tsx b/@navikt/core/react/src/date/monthpicker/MonthCaption.tsx index f0a72e9a0b..4a34b73d30 100644 --- a/@navikt/core/react/src/date/monthpicker/MonthCaption.tsx +++ b/@navikt/core/react/src/date/monthpicker/MonthCaption.tsx @@ -10,8 +10,9 @@ import { useDayPicker } from "react-day-picker"; import { ArrowLeftIcon, ArrowRightIcon } from "@navikt/aksel-icons"; import { Button } from "../../button"; import { Select } from "../../form/select"; +import { useI18n } from "../../util/i18n/i18n.context"; import { useSharedMonthContext } from "../context"; -import { labelNextYear, labelPrevYear } from "../utils"; +import { getTranslations } from "../utils"; export const MonthCaption = () => { const { @@ -20,8 +21,8 @@ export const MonthCaption = () => { formatters: { formatYearCaption }, locale, } = useDayPicker(); - const { hasDropdown, year, toYear } = useSharedMonthContext(); + const translate = useI18n("DatePicker", getTranslations(locale.code)); const years: Date[] = []; @@ -38,8 +39,8 @@ export const MonthCaption = () => { years.sort((a, b) => b.getFullYear() - a.getFullYear()); } - const handleYearChange = (e) => - toYear(setYear(startOfMonth(new Date()), Number(e.target.value))); + const handleYearChange = (event: React.ChangeEvent<HTMLSelectElement>) => + toYear(setYear(startOfMonth(new Date()), Number(event.target.value))); const handleButtonClick = (val: number) => { const newYear = Number(year.getFullYear() + val); @@ -64,17 +65,16 @@ export const MonthCaption = () => { className="navds-date__caption-button" disabled={disablePreviousYear()} onClick={() => handleButtonClick(-1)} - aria-label={labelPrevYear(locale?.code)} - icon={<ArrowLeftIcon aria-hidden />} + icon={<ArrowLeftIcon title={translate("previousYear")} />} variant="tertiary" type="button" /> {hasDropdown ? ( <Select - label="velg år" + label={translate("year")} hideLabel - value={year?.getFullYear()} + value={year.getFullYear()} onChange={handleYearChange} className="navds-date__caption__year" > @@ -93,8 +93,7 @@ export const MonthCaption = () => { className="navds-date__caption-button" disabled={disableNextYear()} onClick={() => handleButtonClick(1)} - aria-label={labelNextYear(locale?.code)} - icon={<ArrowRightIcon aria-hidden />} + icon={<ArrowRightIcon title={translate("nextYear")} />} variant="tertiary" type="button" /> diff --git a/@navikt/core/react/src/date/monthpicker/MonthPicker.tsx b/@navikt/core/react/src/date/monthpicker/MonthPicker.tsx index 3a3f91d0d5..0be0763ad7 100644 --- a/@navikt/core/react/src/date/monthpicker/MonthPicker.tsx +++ b/@navikt/core/react/src/date/monthpicker/MonthPicker.tsx @@ -3,6 +3,7 @@ import React, { forwardRef, useState } from "react"; import { DayPickerProvider } from "react-day-picker"; import { useId } from "../../util/hooks"; import { useMergeRefs } from "../../util/hooks/useMergeRefs"; +import { useDateLocale } from "../../util/i18n/i18n.context"; import { DateContext, SharedMonthProvider } from "../context"; import { MonthPickerInput } from "../parts/DateInput"; import { DateWrapper } from "../parts/DateWrapper"; @@ -67,7 +68,7 @@ export const MonthPicker = forwardRef<HTMLDivElement, MonthPickerProps>( id, onClose, onOpenToggle, - locale = "nb", + locale, onMonthSelect, className, wrapperClassName, @@ -78,6 +79,7 @@ export const MonthPicker = forwardRef<HTMLDivElement, MonthPickerProps>( }, ref, ) => { + const langProviderLocale = useDateLocale(); const ariaId = useId(id); const [open, setOpen] = useState(_open ?? false); @@ -130,7 +132,9 @@ export const MonthPicker = forwardRef<HTMLDivElement, MonthPickerProps>( > <DayPickerProvider initialProps={{ - locale: getLocaleFromString(locale), + locale: locale + ? getLocaleFromString(locale) + : langProviderLocale, selected: selected ?? selectedMonth, toDate, fromDate, diff --git a/@navikt/core/react/src/date/parts/DateInput.tsx b/@navikt/core/react/src/date/parts/DateInput.tsx index de27e8c6ff..d92021adc0 100644 --- a/@navikt/core/react/src/date/parts/DateInput.tsx +++ b/@navikt/core/react/src/date/parts/DateInput.tsx @@ -5,6 +5,7 @@ import { ReadOnlyIcon } from "../../form/ReadOnlyIcon"; import { FormFieldProps, useFormField } from "../../form/useFormField"; import { BodyShort, ErrorMessage, Label } from "../../typography"; import { omit } from "../../util"; +import { useI18n } from "../../util/i18n/i18n.context"; import { useDateInputContext } from "../context"; export interface DateInputProps @@ -46,16 +47,17 @@ const DateInput = forwardRef<HTMLInputElement, DateInputProps>((props, ref) => { } = props; const buttonRef = useRef<HTMLButtonElement>(null); + const translate = useI18n("DatePicker"); const isDatepickerVariant = variant === "datepicker"; const conditionalVariables = { prefix: isDatepickerVariant ? "datepicker-input" : "monthpicker-input", iconTitle: { - open: isDatepickerVariant ? "Åpne datovelger" : "Åpne månedsvelger", - close: isDatepickerVariant ? "Lukk datovelger" : "Lukk månedsvelger", + open: isDatepickerVariant ? "openDatePicker" : "openMonthPicker", + close: isDatepickerVariant ? "closeDatePicker" : "closeMonthPicker", }, - }; + } as const; const context = useDateInputContext(); @@ -137,12 +139,9 @@ const DateInput = forwardRef<HTMLInputElement, DateInputProps>((props, ref) => { ref={buttonRef} > <CalendarIcon - pointerEvents="none" - title={ - context?.open - ? conditionalVariables.iconTitle.close - : conditionalVariables.iconTitle.open - } + title={translate( + conditionalVariables.iconTitle[context?.open ? "close" : "open"], + )} /> </button> </div> diff --git a/@navikt/core/react/src/date/parts/DateWrapper.tsx b/@navikt/core/react/src/date/parts/DateWrapper.tsx index 965ed0c2e5..b20f9ad325 100644 --- a/@navikt/core/react/src/date/parts/DateWrapper.tsx +++ b/@navikt/core/react/src/date/parts/DateWrapper.tsx @@ -5,14 +5,23 @@ import { Modal } from "../../modal"; import { useModalContext } from "../../modal/Modal.context"; import { Popover } from "../../popover"; import { useMedia } from "../../util/hooks"; -import { modalCloseButtonLabel, modalLabel } from "../utils/labels"; +import { useI18n } from "../../util/i18n/i18n.context"; +import { getTranslations } from "../utils"; + +const variantToLabel = { + single: "chooseDate", + multiple: "chooseDates", + range: "chooseDateRange", + month: "chooseMonth", +} as const; type DateWrapperProps = { open: boolean; children: React.ReactNode; onClose: () => void; anchor: HTMLDivElement | null; - locale: "nb" | "nn" | "en"; + /** @deprecated Temporary to support locale prop */ + locale: "nb" | "nn" | "en" | undefined; variant: "single" | "multiple" | "range" | "month"; popoverProps: { id?: string; @@ -29,6 +38,7 @@ export const DateWrapper = ({ variant, popoverProps, }: DateWrapperProps) => { + const translate = useI18n("DatePicker", getTranslations(locale)); const modalRef = useRef<HTMLDialogElement>(null); const isInModal = useModalContext(false) !== undefined; const hideModal = @@ -61,7 +71,7 @@ export const DateWrapper = ({ event.stopPropagation(); onClose(); }} - aria-label={modalLabel(locale, variant)} + aria-label={translate(variantToLabel[variant])} className={cl("navds-date__modal", { "navds-date__nested-modal": isInModal, "navds-date": variant === "month", @@ -76,7 +86,7 @@ export const DateWrapper = ({ size="small" type="button" > - {modalCloseButtonLabel(locale)} + {translate("close")} </Button> </div> </Modal> diff --git a/@navikt/core/react/src/date/utils/index.ts b/@navikt/core/react/src/date/utils/index.ts index dd415b2d3f..4e6db10410 100644 --- a/@navikt/core/react/src/date/utils/index.ts +++ b/@navikt/core/react/src/date/utils/index.ts @@ -1,18 +1,11 @@ export { formatDateForInput } from "./format-date"; export { getMonths, getYears } from "./get-dates"; -export { - labelMonthDropdown, - labelYearDropdown, - labels, - labelNextYear, - labelPrevYear, -} from "./labels"; export { INPUT_DATE_STRING_FORMAT_DATE, INPUT_DATE_STRING_FORMAT_MONTH, parseDate, } from "./parse-date"; -export { getLocaleFromString } from "./locale"; +export { getLocaleFromString, getTranslations } from "./locale"; export { disableDate } from "./dates-disabled"; export { dateIsInCurrentMonth, isValidDate } from "./check-dates"; diff --git a/@navikt/core/react/src/date/utils/labels.ts b/@navikt/core/react/src/date/utils/labels.ts deleted file mode 100644 index 0e6ec16491..0000000000 --- a/@navikt/core/react/src/date/utils/labels.ts +++ /dev/null @@ -1,219 +0,0 @@ -import { Locale } from "date-fns"; -import { Labels, NavButtonLabel } from "react-day-picker"; - -const labelNext: NavButtonLabel = (date, options) => { - switch (options?.locale?.code) { - case "nb": - return "Gå til neste måned"; - case "nn": - return "Gå til neste månad"; - case "en": - return "Go to next month"; - default: - return "Gå til neste måned"; - } -}; - -const labelPrevious: NavButtonLabel = (date, options) => { - switch (options?.locale?.code) { - case "nb": - return "Gå til forrige måned"; - case "nn": - return "Gå til førre månad"; - case "en": - return "Go to previous month"; - default: - return "Gå til forrige måned"; - } -}; - -export const labelYearDropdown = (locale: Locale) => { - switch (locale?.code) { - case "nb": - return "År"; - case "nn": - return "År"; - case "en": - return "Year"; - default: - return "År"; - } -}; - -export const labelMonthDropdown = (locale: Locale) => { - switch (locale?.code) { - case "nb": - return "Måned"; - case "nn": - return "Månad"; - case "en": - return "Month"; - default: - return "Måned"; - } -}; - -export const labelNextYear = (localeCode: string | undefined) => { - switch (localeCode) { - case "nb": - return "Gå til neste år"; - case "nn": - return "Gå til neste år"; - case "en-GB": - return "Go to next year"; - default: - return "Gå til neste måned"; - } -}; - -export const labelPrevYear = (localeCode: string | undefined): string => { - switch (localeCode) { - case "nb": - return "Gå til forrige år"; - case "nn": - return "Gå til førre år"; - case "en-GB": - return "Go to next year"; - default: - return "Gå til neste år"; - } -}; - -export const labels: Partial<Labels> = { - labelNext, - labelPrevious, -}; - -export const labelWeekNumber = ({ - localeCode, - week, -}: { - localeCode?: string; - week: number; -}): string => { - switch (localeCode) { - case "nb": - return `Uke ${week}`; - case "nn": - return `Veke ${week}`; - case "en-GB": - return `Week ${week}`; - default: - return `Uke ${week}`; - } -}; - -export const labelWeekNumberButton = ({ - localeCode, - week, -}: { - localeCode?: string; - week: number; -}): string => { - switch (localeCode) { - case "nb": - return `Velg uke ${week}`; - case "nn": - return `Vel veke ${week}`; - case "en-GB": - return `Pick week ${week}`; - default: - return `Velg uke ${week}`; - } -}; - -export const labelWeek = (localeCode?: string): string => { - switch (localeCode) { - case "nb": - return `Uke:`; - case "nn": - return `Veke:`; - case "en-GB": - return `Week:`; - default: - return `Uke:`; - } -}; - -const modalLabelSingle = (localeCode?: string): string => { - switch (localeCode) { - case "nb": - return `Velg dato`; - case "nn": - return `Vel dato`; - case "en-GB": - return `Pick a date`; - default: - return `Velg dato`; - } -}; - -const modalLabelMultiple = (localeCode?: string): string => { - switch (localeCode) { - case "nb": - return `Velg datoer`; - case "nn": - return `Vel datoar`; - case "en-GB": - return `Pick dates`; - default: - return `Velg datoer`; - } -}; - -const modalLabelRanged = (localeCode?: string): string => { - switch (localeCode) { - case "nb": - return `Velg start- og sluttdato`; - case "nn": - return `Vel start- og sluttdato`; - case "en-GB": - return `Pick a start and end date`; - default: - return `Velg start- og sluttdato`; - } -}; - -const modalLabelMonth = (localeCode?: string): string => { - switch (localeCode) { - case "nb": - return `Velg måned`; - case "nn": - return `Vel månad`; - case "en-GB": - return `Pick a month`; - default: - return `Velg måned`; - } -}; - -export const modalLabel = ( - localeCode: string, - variant: "single" | "multiple" | "range" | "month", -) => { - switch (variant) { - case "single": - return modalLabelSingle(localeCode); - case "multiple": - return modalLabelMultiple(localeCode); - case "range": - return modalLabelRanged(localeCode); - case "month": - return modalLabelMonth(localeCode); - default: - return modalLabelSingle(localeCode); - } -}; - -export const modalCloseButtonLabel = (localeCode?: string): string => { - switch (localeCode) { - case "nb": - return `Lukk`; - case "nn": - return `Lukk`; - case "en-GB": - return `Close`; - default: - return `Lukk`; - } -}; diff --git a/@navikt/core/react/src/date/utils/locale.ts b/@navikt/core/react/src/date/utils/locale.ts index 5392bf159f..e9431b386a 100644 --- a/@navikt/core/react/src/date/utils/locale.ts +++ b/@navikt/core/react/src/date/utils/locale.ts @@ -1,4 +1,6 @@ import { enGB, nb, nn } from "date-fns/locale"; +import en_translations from "../../util/i18n/locales/en"; +import nn_translations from "../../util/i18n/locales/nn"; /** @private */ export const getLocaleFromString = (locale: "nb" | "nn" | "en" = "nb") => { @@ -11,3 +13,19 @@ export const getLocaleFromString = (locale: "nb" | "nn" | "en" = "nb") => { return nb; } }; + +/** + * @private + * Temporary for backwards compatibility with locale prop + */ +export const getTranslations = (locale: string | undefined) => { + switch (locale) { + case "nn": + return nn_translations.DatePicker; + case "en": + case "en-GB": + return en_translations.DatePicker; + default: + return undefined; + } +}; diff --git a/@navikt/core/react/src/util/i18n/locales/en.ts b/@navikt/core/react/src/util/i18n/locales/en.ts index 9a4aaa6f8f..ececcb02c6 100644 --- a/@navikt/core/react/src/util/i18n/locales/en.ts +++ b/@navikt/core/react/src/util/i18n/locales/en.ts @@ -97,4 +97,24 @@ export default { reset: "Reset zoom", }, }, + DatePicker: { + close: "Close", + chooseDate: "Choose date", + chooseDates: "Choose dates", + chooseDateRange: "Choose start and end date", + chooseMonth: "Choose month", + week: "Week", + weekNumber: "Week {week}", + selectWeekNumber: "Select week {week}", + month: "Month", + nextMonth: "Go to next month", + previousMonth: "Go to previous month", + year: "Year", + nextYear: "Go to next year", + previousYear: "Go to previous year", + openDatePicker: "Open date picker", + openMonthPicker: "Open month picker", + closeDatePicker: "Close date picker", + closeMonthPicker: "Close month picker", + }, } satisfies Translations; diff --git a/@navikt/core/react/src/util/i18n/locales/nb.ts b/@navikt/core/react/src/util/i18n/locales/nb.ts index 1ec694f440..e3631e6008 100644 --- a/@navikt/core/react/src/util/i18n/locales/nb.ts +++ b/@navikt/core/react/src/util/i18n/locales/nb.ts @@ -102,4 +102,24 @@ export default { reset: "Tilbakestill tidsperspektiv", }, }, + DatePicker: { + close: "Lukk", // TODO: Consider making global + chooseDate: "Velg dato", + chooseDates: "Velg datoer", + chooseDateRange: "Velg start- og sluttdato", + chooseMonth: "Velg måned", + week: "Uke", + weekNumber: "Uke {week}", + selectWeekNumber: "Velg uke {week}", + month: "Måned", + nextMonth: "Gå til neste måned", + previousMonth: "Gå til forrige måned", + year: "År", + nextYear: "Gå til neste år", + previousYear: "Gå til forrige år", + openDatePicker: "Åpne datovelger", + openMonthPicker: "Åpne månedsvelger", + closeDatePicker: "Lukk datovelger", + closeMonthPicker: "Lukk månedsvelger", + }, } satisfies TranslationMap; diff --git a/@navikt/core/react/src/util/i18n/locales/nn.ts b/@navikt/core/react/src/util/i18n/locales/nn.ts index 6c0bae318c..7fd975d416 100644 --- a/@navikt/core/react/src/util/i18n/locales/nn.ts +++ b/@navikt/core/react/src/util/i18n/locales/nn.ts @@ -97,4 +97,24 @@ export default { reset: "Tilbakestill tidsperspektiv", }, }, + DatePicker: { + close: "Lukk", + chooseDate: "Vel dato", + chooseDates: "Vel datoar", + chooseDateRange: "Vel start- og sluttdato", + chooseMonth: "Vel månad", + week: "Veke", + weekNumber: "Veke {week}", + selectWeekNumber: "Vel veke {week}", + month: "Månad", + nextMonth: "Gå til neste månad", + previousMonth: "Gå til førre månad", + year: "År", + nextYear: "Gå til neste år", + previousYear: "Gå til førre år", + openDatePicker: "Opne datoveljar", + openMonthPicker: "Opne månadsveljar", + closeDatePicker: "Lukk datoveljar", + closeMonthPicker: "Lukk månadsveljar", + }, } satisfies Translations; From 1d869fe570fd702d559bd7e2838a26ad287c12b2 Mon Sep 17 00:00:00 2001 From: Halvor Haugan <halvor.haugan@nav.no> Date: Thu, 21 Nov 2024 14:19:03 +0100 Subject: [PATCH 2/2] add "goTo" --- @navikt/core/react/src/date/datepicker/parts/Caption.tsx | 4 ++-- .../react/src/date/datepicker/parts/DropdownCaption.tsx | 4 ++-- @navikt/core/react/src/date/monthpicker/MonthCaption.tsx | 4 ++-- @navikt/core/react/src/util/i18n/locales/en.ts | 8 ++++---- @navikt/core/react/src/util/i18n/locales/nb.ts | 8 ++++---- @navikt/core/react/src/util/i18n/locales/nn.ts | 8 ++++---- 6 files changed, 18 insertions(+), 18 deletions(-) diff --git a/@navikt/core/react/src/date/datepicker/parts/Caption.tsx b/@navikt/core/react/src/date/datepicker/parts/Caption.tsx index 7e5bb32af7..9d39a447ce 100644 --- a/@navikt/core/react/src/date/datepicker/parts/Caption.tsx +++ b/@navikt/core/react/src/date/datepicker/parts/Caption.tsx @@ -25,7 +25,7 @@ export const DatePickerCaption = ({ displayMonth, id }: CaptionProps) => { variant="tertiary" disabled={!previousMonth} onClick={() => previousMonth && goToMonth(previousMonth)} - icon={<ArrowLeftIcon title={translate("previousMonth")} />} + icon={<ArrowLeftIcon title={translate("goToPreviousMonth")} />} className="navds-date__caption-button" type="button" /> @@ -39,7 +39,7 @@ export const DatePickerCaption = ({ displayMonth, id }: CaptionProps) => { {formatCaption(displayMonth, { locale })} </Label> <Button - icon={<ArrowRightIcon title={translate("nextMonth")} />} + icon={<ArrowRightIcon title={translate("goToNextMonth")} />} onClick={() => nextMonth && goToMonth(nextMonth)} disabled={!nextMonth} variant="tertiary" diff --git a/@navikt/core/react/src/date/datepicker/parts/DropdownCaption.tsx b/@navikt/core/react/src/date/datepicker/parts/DropdownCaption.tsx index baefc329af..27185fd5df 100644 --- a/@navikt/core/react/src/date/datepicker/parts/DropdownCaption.tsx +++ b/@navikt/core/react/src/date/datepicker/parts/DropdownCaption.tsx @@ -59,7 +59,7 @@ export const DropdownCaption = ({ displayMonth, id }: CaptionProps) => { variant="tertiary" disabled={!previousMonth} onClick={() => previousMonth && goToMonth(previousMonth)} - icon={<ArrowLeftIcon title={translate("previousMonth")} />} + icon={<ArrowLeftIcon title={translate("goToPreviousMonth")} />} className="navds-date__caption-button" type="button" /> @@ -94,7 +94,7 @@ export const DropdownCaption = ({ displayMonth, id }: CaptionProps) => { </div> <Button - icon={<ArrowRightIcon title={translate("nextMonth")} />} + icon={<ArrowRightIcon title={translate("goToNextMonth")} />} onClick={() => nextMonth && goToMonth(nextMonth)} disabled={!nextMonth} variant="tertiary" diff --git a/@navikt/core/react/src/date/monthpicker/MonthCaption.tsx b/@navikt/core/react/src/date/monthpicker/MonthCaption.tsx index 4a34b73d30..87c92ebaab 100644 --- a/@navikt/core/react/src/date/monthpicker/MonthCaption.tsx +++ b/@navikt/core/react/src/date/monthpicker/MonthCaption.tsx @@ -65,7 +65,7 @@ export const MonthCaption = () => { className="navds-date__caption-button" disabled={disablePreviousYear()} onClick={() => handleButtonClick(-1)} - icon={<ArrowLeftIcon title={translate("previousYear")} />} + icon={<ArrowLeftIcon title={translate("goToPreviousYear")} />} variant="tertiary" type="button" /> @@ -93,7 +93,7 @@ export const MonthCaption = () => { className="navds-date__caption-button" disabled={disableNextYear()} onClick={() => handleButtonClick(1)} - icon={<ArrowRightIcon title={translate("nextYear")} />} + icon={<ArrowRightIcon title={translate("goToNextYear")} />} variant="tertiary" type="button" /> diff --git a/@navikt/core/react/src/util/i18n/locales/en.ts b/@navikt/core/react/src/util/i18n/locales/en.ts index ececcb02c6..02d44ef73a 100644 --- a/@navikt/core/react/src/util/i18n/locales/en.ts +++ b/@navikt/core/react/src/util/i18n/locales/en.ts @@ -107,11 +107,11 @@ export default { weekNumber: "Week {week}", selectWeekNumber: "Select week {week}", month: "Month", - nextMonth: "Go to next month", - previousMonth: "Go to previous month", + goToNextMonth: "Go to next month", + goToPreviousMonth: "Go to previous month", year: "Year", - nextYear: "Go to next year", - previousYear: "Go to previous year", + goToNextYear: "Go to next year", + goToPreviousYear: "Go to previous year", openDatePicker: "Open date picker", openMonthPicker: "Open month picker", closeDatePicker: "Close date picker", diff --git a/@navikt/core/react/src/util/i18n/locales/nb.ts b/@navikt/core/react/src/util/i18n/locales/nb.ts index e3631e6008..38b2073d90 100644 --- a/@navikt/core/react/src/util/i18n/locales/nb.ts +++ b/@navikt/core/react/src/util/i18n/locales/nb.ts @@ -112,11 +112,11 @@ export default { weekNumber: "Uke {week}", selectWeekNumber: "Velg uke {week}", month: "Måned", - nextMonth: "Gå til neste måned", - previousMonth: "Gå til forrige måned", + goToNextMonth: "Gå til neste måned", + goToPreviousMonth: "Gå til forrige måned", year: "År", - nextYear: "Gå til neste år", - previousYear: "Gå til forrige år", + goToNextYear: "Gå til neste år", + goToPreviousYear: "Gå til forrige år", openDatePicker: "Åpne datovelger", openMonthPicker: "Åpne månedsvelger", closeDatePicker: "Lukk datovelger", diff --git a/@navikt/core/react/src/util/i18n/locales/nn.ts b/@navikt/core/react/src/util/i18n/locales/nn.ts index 7fd975d416..6f2f1dfbee 100644 --- a/@navikt/core/react/src/util/i18n/locales/nn.ts +++ b/@navikt/core/react/src/util/i18n/locales/nn.ts @@ -107,11 +107,11 @@ export default { weekNumber: "Veke {week}", selectWeekNumber: "Vel veke {week}", month: "Månad", - nextMonth: "Gå til neste månad", - previousMonth: "Gå til førre månad", + goToNextMonth: "Gå til neste månad", + goToPreviousMonth: "Gå til førre månad", year: "År", - nextYear: "Gå til neste år", - previousYear: "Gå til førre år", + goToNextYear: "Gå til neste år", + goToPreviousYear: "Gå til førre år", openDatePicker: "Opne datoveljar", openMonthPicker: "Opne månadsveljar", closeDatePicker: "Lukk datoveljar",