diff --git a/packages/gamut/src/DatePicker/DatePicker.tsx b/packages/gamut/src/DatePicker/DatePicker.tsx index b334e4992d..d9f7755b3b 100644 --- a/packages/gamut/src/DatePicker/DatePicker.tsx +++ b/packages/gamut/src/DatePicker/DatePicker.tsx @@ -156,7 +156,8 @@ export const DatePicker: React.FC = (props) => { {mode === 'range' ? ( <> @@ -164,13 +165,14 @@ export const DatePicker: React.FC = (props) => { {isRtl ? : } ) : ( - + )} = ({ {weekdayLabels.map((label, i) => ( - + {label} ))} diff --git a/packages/gamut/src/DatePicker/DatePickerCalendar/Calendar/__tests__/CalendarBody.test.tsx b/packages/gamut/src/DatePicker/DatePickerCalendar/Calendar/__tests__/CalendarBody.test.tsx index 27dea15dbb..5e2ccd2ecc 100644 --- a/packages/gamut/src/DatePicker/DatePickerCalendar/Calendar/__tests__/CalendarBody.test.tsx +++ b/packages/gamut/src/DatePicker/DatePickerCalendar/Calendar/__tests__/CalendarBody.test.tsx @@ -6,7 +6,7 @@ import { createRef } from 'react'; import { getIsoFirstDayFromLocale } from '../../../utils/locale'; import { CalendarBody } from '../CalendarBody'; import { getMonthGrid } from '../utils/dateGrid'; -import { formatDateForAriaLabel } from '../utils/format'; +import { formatDateForAriaLabel, getWeekdayNames } from '../utils/format'; const displayDate = new Date(2024, 2, 1); const focusedDate = new Date(2024, 2, 15); @@ -203,14 +203,21 @@ describe('CalendarBody', () => { await waitFor(() => expect(march15).toHaveFocus()); }); - it('renders seven weekday column headers with scope and abbreviations', () => { + it('renders seven weekday column headers with full accessible names', () => { const { view } = renderView(); + const locale = new Intl.Locale('en-US'); + const firstWeekday = getIsoFirstDayFromLocale(locale); + const fullNames = getWeekdayNames({ + format: 'long', + locale, + firstWeekday, + }); const headers = view.getAllByRole('columnheader'); expect(headers).toHaveLength(7); - headers.forEach((th) => { + headers.forEach((th, i) => { expect(th).toHaveAttribute('scope', 'col'); - expect(th).toHaveAttribute('abbr'); + expect(th).toHaveAccessibleName(fullNames[i]); }); }); diff --git a/packages/gamut/src/DatePicker/DatePickerInput/index.tsx b/packages/gamut/src/DatePicker/DatePickerInput/index.tsx index ebce7088a2..67bf076567 100644 --- a/packages/gamut/src/DatePicker/DatePickerInput/index.tsx +++ b/packages/gamut/src/DatePicker/DatePickerInput/index.tsx @@ -11,6 +11,7 @@ import { } from 'react'; import { FlexBox } from '../../Box'; +import { IconButton } from '../../Button'; import { FormGroup } from '../../Form/elements/FormGroup'; import type { InputWrapperProps } from '../../Form/inputs/Input'; import { isSameDay } from '../DatePickerCalendar/Calendar/utils/dateGrid'; @@ -38,11 +39,23 @@ export type DatePickerInputProps = Omit< > & { /** In range mode: which part of the range this input edits. Omit for single-date or combined display. */ rangePart?: 'start' | 'end'; + /** Description to display between the label and the input. */ + description?: string; }; export const DatePickerInput = forwardRef( ( - { disabled, error, form, label, name, rangePart, size = 'base', ...rest }, + { + disabled, + error, + form, + label, + name, + rangePart, + size = 'base', + description, + ...rest + }, ref ) => { const context = useDatePicker(); @@ -227,7 +240,8 @@ export const DatePickerInput = forwardRef( return ( ( width="fit-content" > ( type="hidden" value={hiddenValue} /> - - - + ); diff --git a/packages/gamut/src/DatePicker/types.ts b/packages/gamut/src/DatePicker/types.ts index c35cf19d35..88a2743620 100644 --- a/packages/gamut/src/DatePicker/types.ts +++ b/packages/gamut/src/DatePicker/types.ts @@ -96,6 +96,8 @@ export interface DatePickerSingleProps extends DatePickerBaseProps<'single'> { * ``` */ onSelected: (date: Date | null) => void; + /** Description to display between the label and the input. */ + description?: string; } export interface DatePickerRangeProps extends DatePickerBaseProps<'range'> { @@ -164,6 +166,10 @@ export interface DatePickerRangeProps extends DatePickerBaseProps<'range'> { * ``` */ onEndSelected: (date: Date | null) => void; + /** Description to display between the label and the start date input. */ + startDateDescription?: string; + /** Description to display between the label and the end date input. */ + endDateDescription?: string; } export type DatePickerProps = DatePickerSingleProps | DatePickerRangeProps; diff --git a/packages/styleguide/src/lib/Organisms/DatePicker/DatePicker.stories.tsx b/packages/styleguide/src/lib/Organisms/DatePicker/DatePicker.stories.tsx index 79019732d9..e11a1e06c6 100644 --- a/packages/styleguide/src/lib/Organisms/DatePicker/DatePicker.stories.tsx +++ b/packages/styleguide/src/lib/Organisms/DatePicker/DatePicker.stories.tsx @@ -84,6 +84,15 @@ const meta: Meta = { if: { arg: 'mode', eq: 'range' }, control: false, }, + description: { + if: { arg: 'mode', eq: 'single' }, + }, + startDateDescription: { + if: { arg: 'mode', eq: 'range' }, + }, + endDateDescription: { + if: { arg: 'mode', eq: 'range' }, + }, }, }; @@ -100,6 +109,8 @@ export const Default: Story = { ), ], render: function DatePickerStory(args) { + const description = + 'Select a date from the calendar. Insert any rules or instructions here.'; const [selectedDate, setSelectedDate] = useState(null); const [startDate, setStartDate] = useState(null); const [endDate, setEndDate] = useState(null); @@ -111,6 +122,7 @@ export const Default: Story = { endDate={endDate} mode="range" startDate={startDate} + startDateDescription={description} onEndSelected={setEndDate} onStartSelected={setStartDate} /> @@ -120,6 +132,7 @@ export const Default: Story = { return (