Important
A few behavior changes worth checking before you upgrade:
- QEditor no longer emits a
placeholderattribute (it was not valid on a div). Custom CSS targeting.q-editor__content[placeholder]must switch to[aria-placeholder]. - QSelect renders its fall-through attributes only on the focus target, no longer also on the
.q-field__nativewrapper. Selectors or tests that matched the wrapper copy (or relied on the attribute matching two elements) need updating. - The touch/hover behavior of QTooltip, context menus, the touch directives and the slider family is now decided per interaction instead of by the mobile UA. Hybrid devices change the most: touchscreen laptops and tablets with a mouse gain hover tooltips and right-click context menus, mobile UAs gain keyboard support on QSlider/QRange/QKnob, and QRange stops emitting UA-dependent SSR markup.
- QDialog dismisses its backdrop on mousedown instead of click, so a press on the backdrop with a menu open closes only the menu on desktop too, matching what touch already did.
- QSlider/QRange/QKnob de-duplicate their emissions:
changefires only when an interaction actually moved the value, and a parent that does not sync the model prop back hears each value once per interaction rather than once per press/release/click. - Firefox now matches QField's autofill styling: the stylesheet moved from
:-webkit-autofillto the standard:autofill, so theq-autofillkeyframe and$input-autofill-colorapply there for the first time.
New
- feat(QMenu): open on hover -> new
hover,hover-delayandhover-hide-delayprops, also forwarded by QBtnDropdown (in split mode hovering either button opens it). A hover-open never steals focus from where you are typing, ESC still dismisses, submenus keep the chain open while the pointer travels between them, and touch devices keep tap-toggling. No effect whencontext-menuis set (#6776) - feat(QRange): new
min-rangeandmax-rangeprops -> constrain the width of the selection. Out-of-limits model values are coerced likeinner-min/inner-maxalready do, dragging and the keyboard clamp each thumb to what the other thumb allows, and a minimum width blocks thumb crossover (#18182, #2100). Based on PR #18182 by Teodor Atroshenko (thexeos) - feat(QTable): new
footerslot -> renders a real<tfoot>element, so a totals/summary row can be made sticky through CSS. Works in default and virtual-scroll modes (not in grid mode) (#7570) - feat(date): support the ISO week year -> new
getISOWeekYear()util and the Moment/Day.js-compatibleGGGG/GGformat tokens, so masks likeYYYY-[W]wwno longer render the wrong pairing at year boundaries (Jan 1st 2022 was formatted as 2022-W52 instead of 2021-W52) (#17088, credit: psevertson) - feat(Ripple): cancel an "early" ripple once the gesture can no longer end in a tap -> a touch that turns into a scroll/pan, or a pressed pointer dragged off the element, now fades the ripple out instead of leaving a full one behind with no click ever happening. On touch, painting waits 100ms (was 50ms) so flick-scrolls are cancelled before anything becomes visible
- feat(ui): correct the CSS vendor prefixes across the stylesheet -> printing keeps the QCheckbox/QRadio/QToggle backgrounds in Firefox and Safari (
print-color-adjust), Firefox gains the QField autofill styling (:autofill), the QFile/QUploader file button styling (::file-selector-button) and the QPagination input styling (appearance), while prefixes no engine reads any more are gone
Fixes
- fix(ui): accept
class,style,keyandrefon components in JSX/TSX -> the exported component types did not carry Vue'sPublicProps, so TSX rejected the universal props. Templates were never affected (#8690) - fix(QTooltip): decide the touch UX per interaction instead of per device -> mouse and pen hover show the tooltip on any device, so touchscreen laptops, tablets with a mouse and hovering styluses get hover tooltips the mobile-UA check denied them, while a touch press keeps the exact mobile behavior (#14763)
- fix(QTooltip): give a pressed stylus the touch UX -> a pencil held against the anchor got hover semantics and no selection suppression, because a pen reports the same
pointerTypewhether it hovers or touches - fix(QTooltip): ignore focus moving within the anchor -> QBtn shuffles focus to an internal helper after every press, so clicking a QBtn with a tooltip flash-hid it on desktop
- fix(useAnchor): serve context menus by capability instead of by mobile UA -> tablets with a mouse gain right-click context menus, the keyboard context-menu key works on mobile UAs, and touchscreen laptops get the same 300ms long-press with selection suppression phones have instead of engine-dependent native timing
- fix(TouchHold/TouchRepeat): suppress text selection per interaction, not per device -> a touchscreen laptop no longer shows selection artifacts during a long-press, and a mouse press on a mobile UA no longer suppresses selection it never needed
- fix(QSlider/QRange/QKnob): wire taps, presses and the keyboard on every platform -> mobile UAs rendered a focusable track that ignored arrow keys, and desktop had no click handler so assistive-tech clicks did nothing
- fix(QSlider/QRange/QKnob): hand each value to a non-syncing parent once -> a controlled model that rejects the update heard the same value re-emitted by the press, the release and the compatibility click
- fix(ui/slider): emit
changeonly when the interaction changed the value -> pressing End with the thumb already at the maximum, clicking the value the slider already had, or dragging away and back all fired a spuriouschange - fix(QKnob): emit
changeonly when a user adjustment lands a new value -> mounting, every parent model write and range clamping used to fire it, contradicting its own API description - fix(QRange): don't leave a thumb's focus ring behind after a track tap -> on touch nothing ever blurs the internal focus state, so the ring stayed on the tapped thumb through scrolling and taps elsewhere
- fix(ui/slider): keep marker tick values float-exact on fractional steps -> a fractional
stepdrifted (0.1 + 0.1 + 0.1 = 0.30000000000000004), somarker-labelsrendered the drifted number andmarker-label-*slot lookups missed - fix(ui): act on backdrop press so an open menu is dismissed alone -> with a menu open inside a QDialog, the first press on the backdrop closes only the menu on desktop too. Non-primary buttons are ignored
- fix(QInfiniteScroll): resume polling when a scroll lock releases with the page at the top -> a window-target QInfiniteScroll that mounted, was re-keyed or left
disablewhile a Dialog or overlay Drawer held the scroll lock never polled again (#18520) - fix(QInfiniteScroll): do not auto-load a window scroll target from inside a fixed-positioned subtree -> content in a Dialog or fullscreen overlay never contributes to the document's scroll extent, so every
done()triggered the next load forever (and reverse mode jumped the page behind the overlay to the bottom on mount). Such a placement now warns once, points at thescroll-targetprop and revives itself if the fixed positioning goes away (#18520) - fix(QSelect): render fall-through attributes only on the focus target -> attributes like QTable's rows-per-page
aria-labelmatched two elements and broke strict single-element queries (PlaywrightgetByLabel, Testing LibrarygetBy*); the wrapper copy was invalid ARIA as well (#18519) - fix(QSelect): always render the hidden form element, like QInput does -> a QSelect with
name/forset but a null or empty model rendered no element at all, soquerySelector('[name=x]')could not find it. Form submission and validation are unaffected (#17951) - fix(QEditor): clicking the placeholder focuses the field on Chrome -> the placeholder rule now reads the
aria-placeholderthe component already renders, and the invalidplaceholderattribute is no longer emitted (#18511) - fix(QDrawer): hide the opposite drawer again when showing one in mobile behavior -> both drawers could end up on screen at once, stacking two backdrops
- fix(QDrawer): apply
roleandaria-*attributes to theasideelement -> they landed on the inner scrolling div, so naming or re-typing the landmark through QDrawer was impossible (#18059) - fix(QField): hide shadow-text on blur while the field has an error -> an invalid field kept showing the shadow text after blur, overlapped with the label (#17155)
- fix(QInput): let the textarea line-height follow the font-size ->
.q-textareapinned its rows to 18px, so a bigger font gave cramped, overlapping lines that apps had to override with!important. The default layout is unchanged (#16772) - fix(QItem): let overline/caption labels, header labels and side sections follow the item color -> an active (
.q-router-link--active) or custom-colored item kept gray secondary text. Derived fromcurrentColorviacolor-mix()at the same emphasis levels, with the legacy values kept as fallbacks (#18300) - fix(QExpansionItem): keep the header icon/toggle colors when using
switch-toggle-side(#18008)
Other
- docs(QDate): the
eventsandoptionsarray forms (and the String handed to their function forms) are always compared asYYYY/MM/DD-- themaskprop never applies to them. Documented on the API instead of changing it; the function form remains the customization point (#16735) - docs(QDrawer):
behavior,breakpoint,show-if-above,persistentandno-mini-animationwere documented by example only. Adds a "Desktop and mobile behavior" section and correctsshow-if-above, which was described as initial-render-only when it actually re-shows the drawer every time the layout goes back above the breakpoint - Regression coverage for the capability-based interaction rework: six cross-engine sweep scenarios (tooltip pointer wiring and pen lifecycle, context-menu ownership arbitration, backdrop press, the slider tap/keyboard burst, per-interaction selection suppression) plus a touch-capable Chromium pass in the matrix, and hardened QSlider/QRange suites
Donations
Quasar Framework is an open-source MIT-licensed project made possible due to the generous contributions by sponsors and backers. If Quasar is useful in your workflow and you want to support ongoing maintenance, please consider the following: