diff --git a/build/class-api-removals.json b/build/class-api-removals.json index 60dcc94f48..df60b3f3e8 100644 --- a/build/class-api-removals.json +++ b/build/class-api-removals.json @@ -56,6 +56,7 @@ "dark\\:text-white": "The dark:/light: theme-variant utilities are gone. They were generated only for the colour utilities, never documented, and duplicated every value under a [data-coreui-theme] selector. Use the colour-mode-aware tokens instead - the palette already resolves per theme through light-dark(), so .bg-body follows the theme without a variant class.", "dark\\:text-white-50": "The dark:/light: theme-variant utilities are gone. They were generated only for the colour utilities, never documented, and duplicated every value under a [data-coreui-theme] selector. Use the colour-mode-aware tokens instead - the palette already resolves per theme through light-dark(), so .bg-body follows the theme without a variant class.", "date-picker-cleaner": "The v1 picker shells are gone: the pickers are now composed from the section-input field, Calendar and TimeSelection, so the field internals are styled by forms/_form-date-time.scss and the icons are inline SVG rendered by the component. See the v6 migration guide.", + "date-picker-dropdown": "Renamed to .date-picker-popup / .time-picker-popup. The panel is the shared `.popup` surface, and every other family had already dropped the `-dropdown` vocabulary when the options menu became .combobox-popup; the pickers were the last holdout. The class carries the panel's tokens now instead of inheriting them from the field's root, so it works the same teleported, portaled or in place.", "date-picker-indicator": "The frame of every field component is the shared .form-control-group primitive now. Use .form-control-action for an adornment button, .form-control-cleaner for the one that clears the value, .form-control-icon for decoration, and .form-control-sm / .form-control-lg on the group for sizing. See the v6 migration guide.", "date-picker-input": "The v1 picker shells are gone: the pickers are now composed from the section-input field, Calendar and TimeSelection, so the field internals are styled by forms/_form-date-time.scss and the icons are inline SVG rendered by the component. See the v6 migration guide.", "date-picker-input-group": "The frame of every field component is the shared .form-control-group primitive now, so the input group squares off that one class instead of a different wrapper per family. Nothing has emitted these since the primitive landed - the only thing keeping them in the stylesheet was the input-group rules that matched them, which matched no markup.", @@ -97,6 +98,7 @@ "text-medium-emphasis": "Removed in v6 \u2014 a CoreUI-only addition, deprecated since v5.0.0. Use .text-body-secondary.", "text-medium-emphasis-inverse": "Removed in v6 \u2014 a CoreUI-only addition, deprecated since v5.0.0. Use .text-white with an opacity utility.", "time-picker-cleaner": "The v1 picker shells are gone: the pickers are now composed from the section-input field, Calendar and TimeSelection, so the field internals are styled by forms/_form-date-time.scss and the icons are inline SVG rendered by the component. See the v6 migration guide.", + "time-picker-dropdown": "Renamed to .date-picker-popup / .time-picker-popup. The panel is the shared `.popup` surface, and every other family had already dropped the `-dropdown` vocabulary when the options menu became .combobox-popup; the pickers were the last holdout. The class carries the panel's tokens now instead of inheriting them from the field's root, so it works the same teleported, portaled or in place.", "time-picker-indicator": "The frame of every field component is the shared .form-control-group primitive now. Use .form-control-action for an adornment button, .form-control-cleaner for the one that clears the value, .form-control-icon for decoration, and .form-control-sm / .form-control-lg on the group for sizing. See the v6 migration guide.", "time-picker-inline-icon": "The v1 picker shells are gone: the pickers are now composed from the section-input field, Calendar and TimeSelection, so the field internals are styled by forms/_form-date-time.scss and the icons are inline SVG rendered by the component. See the v6 migration guide.", "time-picker-input": "The v1 picker shells are gone: the pickers are now composed from the section-input field, Calendar and TimeSelection, so the field internals are styled by forms/_form-date-time.scss and the icons are inline SVG rendered by the component. See the v6 migration guide.", diff --git a/docs/src/content/docs/migration/v6.mdx b/docs/src/content/docs/migration/v6.mdx index f40a5f8076..f96530ab67 100644 --- a/docs/src/content/docs/migration/v6.mdx +++ b/docs/src/content/docs/migration/v6.mdx @@ -281,10 +281,34 @@ shell's own elements no longer exist: `.date-picker-input`, `.date-picker-input-wrapper`, `.date-picker-input-preview`, `.date-picker-cleaner`, `.time-picker-input`, `.time-picker-cleaner` and `.time-picker-inline-icon`. Custom CSS targeting those needs rewriting against -the new structure; everything else (`.date-picker`, `.date-picker-dropdown`, +the new structure; everything else (`.date-picker`, `.date-picker-popup`, `.date-picker-body`, `.date-picker-footer`, the `-sm`/`-lg` size modifiers, the `.time-picker-roll*` bodies) keeps its name. +#### The picker panel is `.date-picker-popup` / `.time-picker-popup` + +Breaking + +`-dropdown` was the vocabulary of the per-family panels, and every other family +lost it when the options menu became `.combobox-popup`. The pickers were the +last holdout: + +| v5 | v6 | +| --- | --- | +| `.date-picker-dropdown` | `.date-picker-popup` | +| `.time-picker-dropdown` | `.time-picker-popup` | + +The rename comes with the reason for it. **The panel declares its own tokens +now** rather than inheriting them from the field's root through a +`*:not(.date-picker) > …` patch, so nothing inside it depends on having a +particular ancestor — it renders the same in place, teleported through the +`container` option, or rendered into `document.body` by a framework port's +portal. + +`width: min-content` went with it: an absolutely positioned panel already +shrinks to its content, and both pickers measure identically without the +declaration. + #### Input group: one frame class instead of five Breaking @@ -1134,7 +1158,7 @@ Prefer the `.d-sidebar-narrow*` names in new markup. v1 input-layer classes** (`.date-picker-input`, `.date-picker-input-wrapper`, `.date-picker-input-preview`, `.date-picker-cleaner`, `.date-picker-separator` icon masks) **will not apply to the v2 markup** — those layers no longer - exist. Overrides on the surviving classes (`.date-picker-dropdown`, + exist. Overrides on the surviving classes (`.date-picker-popup`, `.date-picker-footer`, `.date-picker-ranges`) keep working — but the frame and the indicator now come from the shared primitive below. - **The frame of every field component is diff --git a/js/src/date-picker.ts b/js/src/date-picker.ts index 5ff3235349..e122b10066 100644 --- a/js/src/date-picker.ts +++ b/js/src/date-picker.ts @@ -44,7 +44,7 @@ const CLASS_NAME_BODY = 'date-picker-body' const CLASS_NAME_CALENDAR = 'date-picker-calendar' const CLASS_NAME_CALENDARS = 'date-picker-calendars' const CLASS_NAME_DATE_PICKER = 'date-picker' -const CLASS_NAME_DROPDOWN = 'date-picker-dropdown' +const CLASS_NAME_DROPDOWN = 'date-picker-popup' const CLASS_NAME_FOOTER = 'date-picker-footer' const CLASS_NAME_CLEANER = 'form-control-cleaner' const CLASS_NAME_INDICATOR = 'form-control-action' diff --git a/js/src/date-range-picker.ts b/js/src/date-range-picker.ts index 34a2397f45..ff20f63de8 100644 --- a/js/src/date-range-picker.ts +++ b/js/src/date-range-picker.ts @@ -46,7 +46,7 @@ const CLASS_NAME_CALENDAR = 'date-picker-calendar' const CLASS_NAME_CALENDARS = 'date-picker-calendars' const CLASS_NAME_DATE_PICKER = 'date-picker' const CLASS_NAME_DATE_RANGE_PICKER = 'date-range-picker' -const CLASS_NAME_DROPDOWN = 'date-picker-dropdown' +const CLASS_NAME_DROPDOWN = 'date-picker-popup' const CLASS_NAME_FOOTER = 'date-picker-footer' const CLASS_NAME_CLEANER = 'form-control-cleaner' const CLASS_NAME_INDICATOR = 'form-control-action' diff --git a/js/src/date-time-picker.ts b/js/src/date-time-picker.ts index ce90a972c9..3f8ab0c6de 100644 --- a/js/src/date-time-picker.ts +++ b/js/src/date-time-picker.ts @@ -44,7 +44,7 @@ const CLASS_NAME_CALENDAR = 'date-picker-calendar' const CLASS_NAME_CALENDARS = 'date-picker-calendars' const CLASS_NAME_DATE_PICKER = 'date-picker' const CLASS_NAME_DATE_TIME_PICKER = 'date-time-picker' -const CLASS_NAME_DROPDOWN = 'date-picker-dropdown' +const CLASS_NAME_DROPDOWN = 'date-picker-popup' const CLASS_NAME_FOOTER = 'date-picker-footer' const CLASS_NAME_CLEANER = 'form-control-cleaner' const CLASS_NAME_INDICATOR = 'form-control-action' diff --git a/js/src/time-picker.ts b/js/src/time-picker.ts index b56886f3b3..4c1786d207 100644 --- a/js/src/time-picker.ts +++ b/js/src/time-picker.ts @@ -38,7 +38,7 @@ const EVENT_SHOWN = `shown${EVENT_KEY}` const EVENT_TIME_CHANGE = `timeChange${EVENT_KEY}` const CLASS_NAME_BODY = 'time-picker-body' -const CLASS_NAME_DROPDOWN = 'time-picker-dropdown' +const CLASS_NAME_DROPDOWN = 'time-picker-popup' const CLASS_NAME_FOOTER = 'time-picker-footer' const CLASS_NAME_CLEANER = 'form-control-cleaner' const CLASS_NAME_INDICATOR = 'form-control-action' diff --git a/js/tests/unit/date-picker.spec.js b/js/tests/unit/date-picker.spec.js index 2c6434b752..c416db76d0 100644 --- a/js/tests/unit/date-picker.spec.js +++ b/js/tests/unit/date-picker.spec.js @@ -33,7 +33,7 @@ describe('DatePicker', () => { expect(el.classList.contains('date-picker')).toBeTrue() expect(el.querySelector('.form-control-group')).not.toBeNull() expect(el.querySelector('.form-control-action')).not.toBeNull() - expect(el.querySelector('.date-picker-dropdown .date-picker-calendar')).not.toBeNull() + expect(el.querySelector('.date-picker-popup .date-picker-calendar')).not.toBeNull() }) it('should not build the calendar until the popup opens', () => { @@ -46,7 +46,7 @@ describe('DatePicker', () => { picker.show() expect(picker._calendar).not.toBeNull() - expect(el.querySelector('.date-picker-dropdown .calendar')).not.toBeNull() + expect(el.querySelector('.date-picker-popup .calendar')).not.toBeNull() }) it('should seed the lazily built calendar with the current value', () => { diff --git a/scss/_date-picker.scss b/scss/_date-picker.scss index cb258bae8c..38b5059cb4 100644 --- a/scss/_date-picker.scss +++ b/scss/_date-picker.scss @@ -34,11 +34,6 @@ $date-picker-tokens: defaults( // content is userland. Sass knobs reuse the existing $date-picker-* shell-layer // variables — no new configuration surface. - .date-picker, - *:not(.date-picker) > .date-picker-dropdown { - @include tokens($date-picker-tokens); - } - .date-picker { position: relative; } @@ -49,10 +44,14 @@ $date-picker-tokens: defaults( @include form-control-group-focus(); } - // The chrome comes from the `.popup` primitive the panel carries; what is - // left here is the panel's own shape and the parent-driven open state. - .date-picker-dropdown { - width: min-content; + // The panel declares its own tokens rather than inheriting them from the + // field's root: a panel can be teleported by the `container` option, and a + // framework port may render it through a portal, so nothing inside it may + // depend on having a particular ancestor. Chrome comes from `.popup`; its + // width needs no declaration, an absolutely positioned box already shrinks + // to its content. + .date-picker-popup { + @include tokens($date-picker-tokens); } .date-picker-body { diff --git a/scss/_time-picker.scss b/scss/_time-picker.scss index 2e35e449fc..f3c4834c96 100644 --- a/scss/_time-picker.scss +++ b/scss/_time-picker.scss @@ -35,30 +35,22 @@ $time-picker-tokens: defaults( ); // scss-docs-end time-picker-css-vars @layer components { - .time-picker, - *:not(.time-picker) > .time-picker-dropdown { - @include tokens($time-picker-tokens); - - } - - // The shell mirrors the date picker's frame while reading the - // --#{$prefix}time-picker-* properties defined on `.time-picker` above. .time-picker { position: relative; } + // See .date-picker-popup: the panel owns its tokens so it survives being + // teleported or portaled away from the field. + .time-picker-popup { + @include tokens($time-picker-tokens); + } + // The popup takes the focus away from the group, but the control is still // active — so the frame keeps its focus treatment while it is open. .time-picker.show .form-control-group { @include form-control-group-focus(); } - // See .date-picker-dropdown — chrome from `.popup`, shape and parent-driven - // open state here. - .time-picker-dropdown { - width: min-content; - } - .time-picker-body { display: flex; align-items: center;