feat: add DateInput, TimeInput, and DateTimeInput components - #617
Closed
mrholek wants to merge 13 commits into
Closed
feat: add DateInput, TimeInput, and DateTimeInput components#617mrholek wants to merge 13 commits into
mrholek wants to merge 13 commits into
Conversation
…events Namespaced listeners for these events (e.g. `paste.coreui.date-input`) were registered as literal custom event types and never fired; components had to fall back to un-namespaced names, which dispose() could not clean up.
Date.parse treats "2026-07-14" as UTC midnight, shifting the date one day back in negative-offset timezones (e.g. `minDate: '2026-07-01'` resolving to June 30 in New York). Append a time part so date-only ISO strings parse in the local timezone, consistently with every other supported date format.
Section-based masked fields for dates and times, covering the native date, time, and datetime-local inputs with full control over the format — modeled on the MUI X field components. - Shared SectionInput base (spinbutton per section, roving tabindex, letter and digit entry, arrow stepping, select all/copy/cut, paste, validation, hidden input for forms) and a pure section engine in util/date-sections.js - Format tokens compatible with dayjs, moment, date-fns, and luxon (dd/DD, MM/MMM/MMMM, yy/yyyy, H/HH, h/hh, mm, ss, A/a), locale-derived layouts via Intl (section order, separators, hour cycle, month and day period names), and inputDateParse for external date libraries - Day section bounds follow the selected month and year; text month sections match names typed by prefix; two-digit years expand with smart centuries - Renders as .form-control, so sizing, validation states, and input groups work; floating labels supported via a :focus-within/filled re-binding - Docs pages with live examples, sidebar entries, and full test coverage
In-place widgets auto-init from a bare attribute (data-coreui-date-input, data-coreui-time-input, data-coreui-date-time-input) instead of data-coreui-toggle — there is no trigger and nothing to toggle. Matches the chip-input/chip-set convention and the Bootstrap v6 direction ([data-bs-otp], [data-bs-chips]), which keeps data-bs-toggle for trigger/overlay components only.
Coverage Report for CI Build 29708635725Coverage decreased (-0.3%) to 94.331%Details
Uncovered Changes
Coverage RegressionsNo coverage regressions found. Coverage Stats💛 - Coveralls |
Arrow keys on an empty section started at the bounds, which is useless for the year (ArrowUp gave 0001, ArrowDown 9999). Start every empty section from the current date and time instead, MUI DateField-style; further arrows step from there.
Formats without every section work like the native month input — MM.yyyy or MMMM yyyy reports the first day of the month (missing sections default to 1970-01-01 midnight). The initial date is normalized through the mask too, so a config date carrying parts the mask doesn't show (day, time) no longer leaks into getDate() and change events.
Review feedback: boundary starts (ArrowUp -> min, ArrowDown -> max) are predictable for day, month, and time sections; only the year benefits from starting at the current year instead of 0001/9999.
Empty sections showed the muted placeholder color, but the separators between them kept the regular text color, so the DD.MM.YYYY mask rendered with dark dots. Separators inherit the placeholder color until the field has a value, matching the native date input.
The docs examples used bare divs, so until the load-event init added the form-control and form-date-time classes the element rendered unstyled and then jumped into shape. The examples now carry both classes in the markup, and .form-date-time holds min-height (with sm/lg overrides), so an uninitialized container keeps the final size and look.
MUI DateField onError parity: consumers previously only saw date: null with no way to tell why. The components now emit errorChange whenever the validation state transitions, with error being 'incomplete', 'minDate', 'maxDate', 'disabledDate', or null when the value is valid or the field is empty. 'incomplete' does not toggle .is-invalid, matching the existing behavior.
Focuses the first section right after initialization, like the native autofocus attribute on an input.
Member
Author
|
Shipping in v6 rather than 5.x. All 13 commits are already on Closing this in favour of the v6 line. The |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Three new form components with section-based input masks for dates and times, covering the native
date,time, anddatetime-localinputs with full control over the format — modeled on the MUI X field components (DateField/TimeField/DateTimeField):data-coreui-date-input)data-coreui-time-input)data-coreui-date-time-input)Each field is split into sections (day/month/year/hour/minute/second/AM-PM) rendered as
role="spinbutton"elements — the accessible DOM structure MUI adopted in v8, mirroring the native date input internals.Architecture
SectionInput— shared, unregistered base class with all interaction logic; the three components are thin subclasses providing defaults and locale-derived layouts. Designed for reuse as the input field of the pickers in a follow-up iteration.util/date-sections.js— pure, DOM-free section engine (format resolution, digit/letter entry state machines, increments, composition to/fromDate).Features
2→ done;1+3→ restart at03); arrows increment with wrapping; Backspace/Delete clear; Home/End/arrows navigate; Ctrl+A selects all (then Ctrl+C copies the formatted value, Ctrl+X cuts, typing restarts from the first section); paste fills all sections, including month names and day periodsdd/DD,MM/MMM/MMMM,yy/yyyy,H/HH,h/hh,mm,ss,A/a); text month sections match names typed by prefix (m→ March,may→ May);inputDateParseplugs in an external date library for pasted textIntl: section order, separators, hour cycle (h12/h23), month names in the grammatical form of a date context (overridable viamonthNames), localized day periods.form-control(sizing, validation states, and input groups work out of the box), hidden input for submission,valid/invalidoptions, and.was-validatedsubmit integration (the hidden input is excluded from native constraint validation):focus-within/filled-class re-binding (a div never matches:placeholder-shown)Fixes (separate commits)
beforeinput,copy,cut, andpasteadded to native events — namespaced listeners for them never fired before2026-07-14) parsed as local midnight instead of UTC, fixing an off-by-one-day shift in negative-offset timezones (also affectedminDate/maxDateof the pickers)Testing
libbuild, bundlewatch (budgets adjusted for the new components: ~2.9 kB min gzip for all three), anddocs-buildpassDocs
Three new pages under Forms (aligned structure, live examples incl. dayjs integration, keyboard tables, a11y notes) + sidebar entries.
Update: the data API uses bare attributes (
data-coreui-date-inputetc.) instead ofdata-coreui-toggle— the chip-input/chip-set convention and the Bootstrap v6 direction for in-place widgets.