feat(DateTimePicker): new component with two-step popover and presets - #55
feat(DateTimePicker): new component with two-step popover and presets#55IgorShevchik wants to merge 6 commits into
Conversation
- Adds B24DateTimePicker built on B24Popover, B24Calendar and B24Input - Two-step UX: calendar → hour/minute grid with configurable minute step - Side preset list with localized defaults (Today, Tomorrow, End of week, In a week, End of month) and full override via the `presets` prop - `dateOnly` mode forces value to CalendarDate with 00:00:00 - Works with @internationalized/date types via v-model (CalendarDateTime, ZonedDateTime, CalendarDate) - Adds theme, locale messages for all 19 locales, demo+nuxt playground pages, docs page with five examples and skill references update
…er-component-NqwmO
…er-component-NqwmO
… i18n, docs) - tests: add DateTimePicker.spec.ts (snapshots + minuteStep clamp + axe a11y) — 42 tests across nuxt + vue projects, both green - security/correctness: guard `minuteStep` against `NaN` (Number.isFinite check) - correctness: memoize resolved preset values into `resolvedPresets` so factory presets evaluate once per render instead of twice (was called by both `:active` and `:data-active`) - a11y: add `role="group"` + `aria-labelledby` on hour/minute grids and `aria-pressed` on each cell - i18n: fix "endOfWeek" mistranslations in de/fr/it/br/tr — they meant "weekend" instead of "end of work week (Friday)" - docs: drop misleading `B24Button` from intro composition, fix "Pick a time" → "Pick a date and time", add "With min/max dates" section and matching example, show `open` slot prop in custom trigger, add `name`/`required` to form-field example - skills: mention `DateTimePickerPreset` type for custom presets - theme: correct `@memo` comment (uses `B24Input`, not `B24InputDate`)
…er-component-NqwmO
Addresses all 11 review issues from the second pass:
1. Time footer (clock + value) is now a clickable button that switches
to the time step. Styled with accent color to match the reference.
2. Weekend day cells (Sat/Sun) coloured red via #day slot.
3. Two-tone highlight on time grid: solid accent for selected,
`data-now` light fill for the real-world current hour/minute.
4. Time-step header now shows date only (was date + time).
6. Preset card titles use `--b24ui-typography-label-color` instead of
default inherited text → matches the rest of the design system.
7. Time-step header colour matches the calendar heading
(`--b24ui-typography-legend-color`).
8. Mobile (`screen.isMobile`) renders the picker in a `B24Drawer`
(bottom sheet) instead of `B24Popover`. Same content tree, different
wrapper picked via `<component :is>`.
9. `Minute step` doc example placeholder fixed (covered by trigger fix).
10. `Locale` doc example switched to Hindi (`hi`).
11. **Dead-zone fix on the trigger**: clicks on padding around the input
now open the picker. Trigger is a `role=button` div wrapping the
`B24Input` (`pointer-events-none`, `tabindex=-1`, `aria-hidden`).
`$attrs` move to the wrapper so consumer-passed `aria-label`/`id`/etc
land where ARIA expects them. Adds `dateTimePicker.openPicker`
locale string as fallback `aria-label` (filled across all 20 locales).
Test snapshots regenerated; 42 tests still green.
Two axe rules (`nested-interactive`, `label`) are disabled in the a11y
test for the trigger composition — the inner input is `tabindex=-1`,
`aria-hidden`, and `pointer-events-none`, so it is not user-reachable.
|
Housekeeping note, no action requested on this PR. The follow-up issues listed in the description have been closed as not planned: #56, #57, #58, #59 (#60 was already closed back in June). They all described work inside For the record, measured today rather than recalled:
Two findings that would otherwise have been lost with the issues:
This PR stays open and the branch is untouched. If Generated by Claude Code |
What this PR is about
A new
B24DateTimePickercomponent — a Bitrix24-style date + time picker with a two-step popover (calendar → hour/minute grid), a side preset column, and an optionaldate-onlymode (time forced to00:00:00). It fills the gap between the segmentedB24InputDate/B24InputTimeand the more "native" Bitrix24 UX.What was done
src/runtime/components/DateTimePicker.vuecomposed of built-inB24Popover,B24Calendarand a read-onlyB24Input(default trigger). Model —CalendarDateTime/ZonedDateTime(orCalendarDateindate-onlymode).src/theme/date-time-picker.ts— minimum styling, design-system classes only.dateTimePicker.*added to theMessagestype and filled in for all 19 locales.endOfWeekfor DE/FR/IT/BR/TR was fixed to actually mean "end of week" (the machine translation produced "weekend" instead).role="group"+aria-labelledbyon the hours/minutes grids,aria-pressedon each cell, unique id viauseId().Number.isFiniteguard onminute-stepto protect againstNaN.test/components/DateTimePicker.spec.ts+ 2 snapshot files: 21 cases × (nuxt + vue) = 42 green tests, including an axe a11y check.docs/content/docs/2.components/date-time-picker.md+ 6 examples (Basic,DateOnly,CustomPresets,CustomTrigger,FormField,MinMaxDates). Responsive: presets drop below the calendar on mobile (flex-col-reverse sm:flex-row).date-time-picker.vuematrix page + registration inuseNavigation.ts.b24-ui-nuxt— updatedcomponents.md,component-selection.mdand the "Date" section informs.md.theme/index.ts, key inThemeDefaults.API
Key props:
modelValue,defaultValue,dateOnly,minuteStep(5),locale,placeholder,presets,hidePresets,format,color,size,disabled,icon,timeIcon,popover,calendar,input.Slots:
default(trigger),presets,preset,time-header.Manual QA checklist
pnpm dev→/components/date-time-picker: popover opens, picking a date switches to the time step, clicking a minute closes the popoverDate only— time step disappears, model becomesCalendarDateminute-step={5|10|15|30}— correct cell count;NaN/0/9999don't break rendering (covered by tests)presets(factory function) —DateTimePickerCustomPresetsExample, factory runs once per render#default(DateTimePickerCustomTriggerExample) —openreacts; defaultB24Inputtriggerlocale="ru"/locale="en"— value format, weekday names, preset labels all changecolor,size,disabled— walk through the Matrix in the playgroundhide-presets— side column disappearsB24FormField(DateTimePickerFormFieldExample) —name/required/label/hintwork:calendar="{ minValue, maxValue }"(DateTimePickerMinMaxDatesExample) — bounds respectedaria-pressedstate on cellspnpm test— neighboring components' snapshots are not affectedWhat's next
Follow-up issues have been filed (from review):
as anyкасты вокруг @internationalized/date #56 — clean upas anycasts around@internationalized/date(also affects Calendar/InputDate)min/max/isDateDisabledpropsv-modeltodefineModel(batched across components)Nothing urgent after merge — the component is self-contained and introduces no breaking changes to the public API.
Ready for squash-merge. Green locally:
pnpm lint,pnpm typecheck,pnpm exec vitest test/components/DateTimePicker.spec.ts(42/42).🤖 Generated with Claude Code