Repository navigation
Version Packages - #1528
Merged
Merged
Version Packages#1528
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
tenphi
force-pushed
the
changeset-release/main
branch
from
October 16, 2026 20:20
f83f543 to
2ce4cc4
Compare
tenphi
force-pushed
the
changeset-release/main
branch
from
October 19, 2026 08:22
2ce4cc4 to
8538aee
Compare
tenphi
force-pushed
the
changeset-release/main
branch
from
October 19, 2026 08:51
8538aee to
6d4d739
Compare
This branch was successfully deployed
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.
This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.
Releases
@cube-dev/ui-kit@0.196.0
Minor Changes
ef9cccecThanks @tenphi! - Fields now render stable field chrome by default, including standalone inputs without a label, so generated validation and TagInput refusal messages stay visible and describe the control without sentinel props. UseisBareexplicitly for inline controls or controls whose parent owns their field layout; it suppresses chrome even with a label or deprecatedforceField, while preserving a supplied label for accessibility. Move whole-field layout styles tofieldStyleswhen migrating previously bare controls. An explicit emptyerrorMessagenow suppresses the deprecatedmessagefallback, and label-less fields no longer reserve a side-label column. Internal composite controls retain their compact presentation.Patch Changes
#1529
be50525cThanks @tenphi! -Button.Splitno longer styles the Buttons inside a popover, dialog or menu opened from it. Itstype,theme,sizeandisDisabledused to reach everyButtonin that overlay, so a confirm popover's Cancel button on a primary, small split turned primary and small, and was disabled whenever the split was. The split's own Buttons still inherit them, and aButton.Splitinside an overlay still styles its own Buttons. A workaround that wraps the overlay in<ButtonSplitContext.Provider value={null}>is no longer needed and can be removed.#1529
be50525cThanks @tenphi! -ComboBoxwithoutallowsCustomValueno longer selects a disabled item when focus leaves the input. Typing the label of an item indisabledKeys, or text that leaves a disabled item as the only match, used to select it on blur and report it throughonSelectionChange, although it cannot be picked with the pointer or keyboard. Such text now counts as invalid input: the input shows the selected item's label again (or nothing when no item is selected), and withclearOnBlurboth the selection and the input are cleared. A disabled item that is already selected stays selected when focus leaves. When several items share the typed label, blur now keeps the selected one, or else picks the first enabled one, instead of always taking the first.#1531
aa0de8caThanks @tenphi! -ComboBox: a press in the input opens a closed list, also when the input already has focus, for example afterTabor afterEscapeclosed the list. The list shows the options the typed text leaves, and text that matches nothing keeps it hidden, so a press that moves the caret does not change whatEntercommits. A click on the field label only focuses the input. WithpopoverTrigger="manual"the list still opens only from the chevron and the arrow keys.ComboBox: a press in the input while the list is open moves the caret and keeps the list open. It used to close the list. The chevron still toggles it.ComboBoxwithisReadOnlyno longer opens its list from the chevron, the arrow keys, a press in the input orpopoverTrigger="focus", andEnter,Escapeand blur no longer change its value or text. Read-only used to only hide the clear button.ComboBoxwithallowsCustomValuecommits the typed text trimmed, onEnterand on blur, and empty or whitespace-only text clears the selection withnullinstead of committing''.ComboBox: picking the option that is already selected, with a click orEnter, keeps it selected and closes the list. It used to clear the value.ComboBox: the input hasaria-autocomplete="list", so screen readers announce that typing filters the options.ComboBoxletsEscapeandTabreach its ancestors unless it acts on them.Escapewith the list closed and nothing to clear now closes a surrounding dialog, andTabreaches a dialog's focus containment.Escapethat closes the list or clears the value still stops at the input.ComboBox: leaving the field without editing it no longer callsonSelectionChange(null)oronInputChange. Blur reports only what it changes.ComboBox:aria-activedescendantno longer points at an option the typed text filtered out. It names a shown option or is absent.ComboBoxwithallowsCustomValue:Enterwith the list closed commits the typed text, even when it is part of an option's label, so "app" can be committed next to an "apple" option. With the list open,Enterstill picks the highlighted option.ComboBox:onOpenChangeis no longer called on mount and reports only the list showing or hiding. Typing text that matches nothing no longer reports an open and a close on every keystroke.aria-expandedfollows whether the list is shown.ComboBoxshows the selected option's label once the options load afterselectedKey, instead of the raw key, and shows the label ofdefaultSelectedKeyfrom the first paint instead of an empty input.ComboBox:Enterpressed right after typing picks the first match. It used to find nothing highlighted yet, so it picked nothing and could submit an enclosing form instead.ComboBox: the chevron and clear buttons are no longerTabstops,Tabcloses the list as focus moves on, and closing the list with the chevron returns focus to the input.ComboBoxrecognises an exact match with the same locale-aware comparison the filter uses, so text the list shows for an option, such as "ete" for "Été", selects that option on blur.ComboBoxwith a controlledselectedKeykeeps showing the controlled option's label when the parent rejects a pick. The input used to show the rejected option.ComboBoxleaves keys pressed during IME composition to the input method, so theEnterthat confirms a candidate no longer selects an option or commits half-composed text.ComboBoxwithitemsshows items that arrive while its list is open at once. It used to keep showing the previous items until the next keystroke.ComboBox,SearchComboBoxandTagInputwithsize="large"open a list of large options, asSelectdoes. A small field keeps medium options.#1531
aa0de8caThanks @tenphi! -AlertDialogis now described by its message througharia-describedby, so a screen reader reads the message together with the title when it opens. A plainDialogstill links no description by default, so a form inside it is not read aloud on open; passaria-describedbyto link one.AlertDialogwithdangernow opens with focus on Cancel, or on the dialog itself when there is no Cancel, instead of on the destructive confirm button, so an Enter pressed out of habit no longer runs it. An explicitautoFocuson the confirm action still puts focus there. Dialogs withoutdangerstill focus the confirm button.AlertDialogopened throughuseAlertDialogAPInow stays mounted until its exit animation has finished, instead of being removed 50 ms early.Dialognow contains focus from the moment it opens. A Tab pressed while it was still animating in could move focus to the page behind a modal, where it stayed.DialogTriggerwithoffset={0}now places a popover flush against its trigger instead of 8px away.DialogTriggerpopovers withisDismissable={false}no longer swallow outside presses: the control pressed receives the press, and a text field outside can take focus and be typed into, because the popover no longer holds focus. They stay open when aButtonoutside them is pressed or another popover opens, and still close when a modal, tray, fullscreen or panel dialog opens from anotherDialogTrigger.DialogTriggerpopovers anchored withtargetRefnow close when the anchor scrolls, like popovers anchored to their trigger.DialogTrigger'shideArrowis deprecated. Popovers have never rendered an arrow, so it has no effect.#1531
aa0de8caThanks @tenphi! -ItemAction:excludeFromTabOrdernow takes the action out of the Tab order. The action used to reset it, soSearchInput's clear button and other field actions that ask to stay pointer-only were Tab stops. An explicittabIndexstill wins.#1531
aa0de8caThanks @tenphi! -ItemAction,ItemButtonand otherItem-based rows: an open tooltip now adds its id to the row's ownaria-describedbyinstead of replacing it, so screen readers read both the caller's description and the tooltip.Item,ItemButton,TextItemand other rows with an automatic tooltip:tooltip={{ title: undefined }}or{{ title: null }}now falls back to the automatic title, liketooltip={{}}, instead of opening an empty bubble.#1529
be50525cThanks @tenphi! - ALayout.Panelinoverlaymode no longer closes when you focus a control inside it or a popover, menu or dialog opened from it, so its inputs and buttons can be used. Focus moving into the main content, a backdrop click and Escape still close it; focus moving into anotherLayout.Panelof the same Layout keeps it open. Opening an overlay panel now moves focus to its first control, unless focus already moved elsewhere as it opened, such as to a field withautoFocus, and closing it returns focus to the element that had it before, unless focus has moved elsewhere; a panel already open when its Layout first renders leaves page focus alone. A panel opened from a menu item now stays open, and a wrapper that focuses the panel's first control and stops its focus events is no longer needed.#1531
aa0de8caThanks @tenphi! -Select,ListBoxand the pickers built on it (FilterListBox,FilterPicker,Picker,ComboBox): a mouse press on an option now selects the option it started on when the pointer comes up inside that option's original box, even if the list moved in between, as it does while a popover is still animating in or scrolls while closing. The press used to pick the neighbouring option under the pointer, or nothing. A release over a different option no longer selects that option, and a press interrupted byEscapeor another key doesn't pick the moved option.#1529
be50525cThanks @tenphi! -ComboBox,SearchComboBoxandCommandTextArea: while the list is open, the first click on an enabled control outside it now acts on that control and closes the list, as a click on a UI KitButtonalready did. A control is a checkbox, switch, radio, text field, native button, link or any other focusable element, in the dialog, popover or menu the field sits in, or anywhere on the page when the field is in none of them. Such a click used to only close the list, so a checkbox stayed unchanged and a text field took no focus until a second click. Focus moves to the control, so the field settles its typed text first, as it does onTab. A click anywhere else still only closes the list and leaves the field focused with its text: on blank space, a dialog's surface or backdrop, or a control outside the dialog or popover the field sits in. A click on a disabled control, including a disabled UI KitButton, which used to commit the typed text, keeps the field's focus and text as well. An enabled UI KitButtonorItemButtonis still reached from anywhere.TagInputnow treats blank space in a dialog and controls outside the dialog or popover it sits in the same way; a click there used to move focus away and add the typed text as a tag.#1531
aa0de8caThanks @tenphi! -ListBoxscrolls a long (virtualized) list to the option that receives focus when that option isn't rendered yet:End,Home,Page Down, typeahead, and the selected option when the list takes focus on open or onTab. The option is then focused, and an input pointingaria-activedescendantat it (ComboBox) names an element that exists.ListBoxkeeps itsrole="listbox"element when it has no items, described by the empty label, so a label'saria-labelledbyor a search input'saria-controlsno longer points at nothing. The empty list is a Tab stop, and the list's card shows focus while it has it.ListBoxrenders "Select All" as a tri-statecheckbox(aria-checkedtrue, false or mixed) above the list instead of anoptionoutside it. It is its own Tab stop, reached withTaborShift+Taband toggled withSpace, and no list item is left outside a list. Queries for it by role change fromoptiontocheckbox; its name is unchanged.ListBoxshows "Select All" as checked once every selectable item it shows is selected, including when the items were selected one by one; disabled items don't count. The next press takes the items shown out of the selection, so selected keys that aren't among its items stay selected.ListBox,FilterListBoxandFilterPicker: under a search orfilter, "Select All" selects or deselects only the options shown, and selected options the search hides stay selected. It used to select every option, hidden ones included, and its next press cleared them all.ListBoxwithdisableSelectionTogglekeeps a re-picked option selected also whenselectionModeis left to its default, single. It used to apply only with an explicitselectionMode="single".ListBoxreports oneonSelectionChangecall per "Select All" press instead of two, and none whendisallowEmptySelectionkeeps the selection.ListBoxsection dividers are presentational, so a listbox holds only options and groups.Menu,CommandMenu,ListBoxandFilterListBoxheaders no longer carryrole="heading", which read any controls inside as part of a title, and their footers drop the invalidrole="footer".#1530
c814fafdThanks @tenphi! - InMenuandCommandMenu, the icon, label and description of a navigation item (or of a command item with inline actions) no longer sit on top of the row'srole="menuitem"anchor as pointer targets. Before, a long label covered the centre of that anchor, so a role-based browser-test click such as Playwright'sgetByRole('menuitem', { name }).click()failed with "intercepts pointer events". Now those slots let presses through to the menuitem anchor, which carries the samehref, so plain, modified, middle and right clicks anywhere on the row behave as before for users, and inline actions and controls in the prefix, suffix and actions slots stay clickable. Tests that click such an item by its label, description or icon now fail instead: a browser test reports that the anchor "intercepts pointer events", and jsdom's user-event rejects an element withpointer-events: none. Click the item by its role instead, asgetByRole('menuitem', { name }).#1531
aa0de8caThanks @tenphi! -RangeSlider:ref.current.focus()now focuses the first thumb. It used to do nothing, because the ref targeted an input no thumb rendered.Layout.Footer: only the footer of a top-levelLayoutis acontentinfolandmark now. A footer inside aLayout.Panel, a nestedLayoutor any other Layout region getsrole="none", so panel footers no longer add unnamed "content info" landmarks. An explicitrolestill wins.Picker: the trigger now describes itself with the value it shows (the selection, therenderSummaryoutput or the placeholder), so screen readers announce "Status, button, Open" instead of the label alone, and it setsaria-haspopup="dialog"for the popover it opens. Its accessible name is still the label.#1530
c814fafdThanks @tenphi! -NumberInput: asuffixnow sits next to the number, before the stepper buttons, by default, so a unit reads40 px ⌃⌄instead of40 ⌃⌄ px. This matches the documentedsuffixPositiondefault ofbefore, which previously behaved likeafter.suffixPosition="after"still places the suffix after the steppers; pass it (or move the control toactions, which always renders last) to keep the old order for a suffix that is a control rather than a unit. The docs now describesuffixPositionas the suffix's position relative to the steppers; the validation and loading icon always comes before both.#1529
be50525cThanks @tenphi! - Removing many toasts or notifications when each removal commits synchronously on its own (for example oneflushSyncper removal) no longer ends in React's "Maximum update depth exceeded" error. Each removal used to leave a state update pending after its commit, which React 19 counts as a nested update; the stack now forgets a removed item in the same render that drops its height.#1530
c814fafdThanks @tenphi! -parseAbsoluteDatenow returns a UTCZonedDateTimefor a string with a zone or offset, such as2024-01-05T00:00:00Zor2024-01-05T00:00:00+02:00, instead ofundefined. ADateInputgiven such a string as its value now shows it instead of an empty field. An ISO date-time without a zone, such as2024-01-05T10:30or2024-01-05 10:30:15, is now read as UTC wall time; it used to be read in the browser's time zone, which moved it by the browser's offset and could show the previous or next day. A malformed day00is still rejected. Date-only strings,Dateobjects and other date strings parse as before. A local workaround that parses these strings before passing them in is no longer needed.#1530
c814fafdThanks @tenphi! -<Root palette>no longer writes the palette store while it renders when the prop changes. Before, a newpalettevalue notifiedGlobalStylesand everyusePaletteValue/usePaletteConfigreader in the middle of Root's render, and React logged "Cannot update a component while rendering a different component", so hosts had to callsetPaletteConfig()themselves before changing the prop. The first mount still applies the palette during render, so the first paint and SSR output stay branded; later changes now apply in a layout effect, which still lands before paint. Changing the prop alone is enough. A<Root>that mounts while another tree is already rendered with a different palette still applies it during its first render. Because Root's layout effect runs after its descendants', asetPaletteConfig()call from a descendant's layout effect in the same commit now loses to the prop; call it from a passive effect or an event handler.#1531
aa0de8caThanks @tenphi! -Select:isReadOnlynow fixes the value. The trigger stays focusable, but the list no longer opens and typeahead and the arrow keys no longer pick another option. Before, only the clear button was hidden.Select:onOpenChangefires once per open or close, and no longer fires withfalseon mount.Select: the options in the list follow the field'ssize, so alargeSelect openslargeoptions. AsmallSelect still opensmediumoptions.Select: the divider between sections no longer hasrole="separator", which a listbox may not contain. It is presentation only and looks the same.Select:autoFocusfocuses the trigger,inputPropsreach the trigger button andloadingIndicatorreplaces the default loading icon. All three were accepted and ignored.popoverRefis typed asRefObject<HTMLElement | null>, the popover element it receives; refs to an input element still type-check.hideTriggernever had an effect and is deprecated: passrightIcon={null}to hide the caret.Select: clearing callsonSelectionChange(null)once instead of twice.Select: whileisLoadingis set the list no longer opens with nothing in it and typeahead no longer changes the value. Turning onisDisabled,isLoadingorisReadOnlywhile the list is open closes it, so the trigger no longer reportsaria-expanded="true"with no popup and the list does not reopen when the field is enabled again.Select: opening from the keyboard focuses the right option.ArrowUpopens on the last option,ArrowDown,EnterandSpaceon the selected option or the first one, never on an option focused during an earlier opening or on the bare list. The focused option is scrolled into view as the list opens.Select: the list is now the element that scrolls and that the popup's height limit applies to, soPageDownandPageUpmove about one visible page instead of jumping to the last or first option. The popup also stays within the space left in the viewport.Select: the clear button hands focus back to the trigger without opening the trigger's tooltip, so the nextEscapecloses a surrounding Dialog instead of that tooltip.#1531
aa0de8caThanks @tenphi! -TextInput,TextArea,PasswordInput,SearchInput,NumberInput:loadingIndicatoris now rendered in place of the default loading icon whileisLoadingis set. It was accepted and never shown.TextInput,TextArea,PasswordInput,SearchInput,NumberInput:inputPropsvalues fordisabled,maxLength,minLengthandautoFocus, androwson amultiLineTextInput, are no longer overwritten by the matching explicit props when those are unset. An explicit prop that is set still wins.TextInput,TextArea,PasswordInput,NumberInput: errors fromvalidatenow show the invalid style and the message after the user edits or leaves the field, so an empty field does not open in red.aria-invalidstill followsvalidatefrom the start, an explicitisInvalidstill shows at once, and an expliciterrorMessagestill replaces the returned message.TextInput,TextArea,PasswordInput,SearchInput,NumberInputand the other fields that share their input box: a press inside the field box but outside the input, such as on the prefix, an icon or a textarea's margins, now focuses the input. Presses on buttons inside the field still go to those buttons.TextInput:multiLineno longer puts input-only attributes such astype="text"on the textarea.SearchInput:onClearis now called whenEscapeclears the text, not only from the clear button.Escapekeeps clearing whether or notisClearableis set.SearchInput:isInvalidnow setsaria-invalidon the input.SearchInput: a caller'sinputRefno longer detaches the field's own ref, so the clear button returns focus to the input again.PasswordInput: the show/hide toggle is now named "Show password" and reports whether the password is visible witharia-pressed. It was named "Toggle masking" in both states.TextInput,TextArea,PasswordInput,SearchInput,NumberInput,RadioGroup,CheckboxGroup,TagInput,CommandTextArea:value={null}now clears a controlled field and keeps it controlled, and so doesisSelected={null}onCheckboxandSwitch. It used to switch the field to uncontrolled mode, which kept the last value on screen.NumberInput:wrapperPropsnow reach the field wrapper, merged with the props React Aria puts there. They were dropped.NumberInput: the stepper buttons now use the UI Kit translations. The English names stay "Increase {label}" and "Decrease {label}", or "Increase" and "Decrease" when the label is not text, and other locales now follow the UI Kit's own strings.NumberInput: pressing a stepper no longer closes a popover the field sits in.CheckboxGroup: style props andstylesnow apply to the group. They were accepted and ignored.#1531
aa0de8caThanks @tenphi! -Button: an open tooltip now joins the button's ownaria-describedbyinstead of replacing it, so a screen reader reads both the button's hint or error and the tooltip.ItemBadgedoes the same.TooltipTrigger:shouldCloseOnPress={false}now keeps the tooltip open when the trigger is pressed, andTooltip'sshouldFlip={false}now keeps the requested placement. Thedelaydefault is documented as 250ms, which is what it always was.Tooltip'sshowIconnever did anything and is now marked deprecated.Tooltip: when the page or an element containing the trigger scrolls, an open tooltip now follows its trigger while the trigger stays in view, and closes once it scrolls out of view. It used to stay where it was drawn while the trigger scrolled away.TooltipProviderandTooltipTrigger: empty tooltip content (aTooltipProvidertitleofnull,undefinedor'', or aTooltipwith no content inside aTooltipTrigger) no longer opens an empty bubble or addsaria-describedbyto the trigger.ItemBadgeandInfoBadge: a non-interactive icon badge with a name is now exposed asrole="img", so screen readers announce its name. Whenaria-labeldiffers from a plain-text tooltip, the tooltip text becomes the badge's description, so keyboard and screen reader users get it without hovering.Button: a disabled button stays natively disabled unless it has a tooltip you passed. The automatic tooltip for a truncated label used to keep it focusable, so whether a disabled button was a Tab stop changed with the window width.Button: a button that is only loading (isLoadingwithoutisDisabled) keeps keyboard focus, so pressing Enter on it no longer drops focus to the page. It is markedaria-disabledandaria-busy, stays inert, and Tab skips it until loading ends. A button that is both loading and disabled, asSubmitButtonis during a submission, is still natively disabled.#1530
c814fafdThanks @tenphi! - Atoorhrefwith leading or trailing spaces or control characters (such as" https://example.com"from data) is now read the way the browser reads a URL. Before, under a router navigation adapter,Menu.Item,CommandMenu.Item,Link,Button,ItemButtonandItemActiontook such an external URL for an app path: they rendered a router-resolved href like/ https:/example.comand a plain click navigated in-app. Now those characters are dropped first, so the link renders and opens the external URL," /pricing"goes to/pricing, and the!,@and#prefixes are recognised after leading whitespace. Atoorhrefmade only of such characters counts as empty:LinkandButtonrender a button, and aMenu.Itemwithhref=" "links to the current document likehref="". A no-break space is kept, as the browser keeps it. This is not URL sanitization: keep validating untrusted URLs before passing them, since a whitespace-wrappedjavascript:URL is now treated as external like an unwrapped one.