This release extends fluid forms across the input stack, adds new layout and input primitives, ships tabs and content-switcher variants, strengthens DataTable filtering and row-state tooling, surfaces dismissal reasons on overlay close events, improves UI Shell responsive navigation, lands accessibility fixes in tables, menus, and forms, cuts listener overhead with open-state gating on virtualized menus, and trims the CSS bundle ~7% by aligning with the Svelte 5 browser baseline.
173 changes in this release:
| Category | Count |
|---|---|
| Breaking changes | 2 |
| Features | 91 |
| Bug fixes | 65 |
| Performance | 15 |
Full Changelog: v0.108.1...v0.109.0
Fluid form support across inputs
Most list-box and text-based inputs now support the fluid variant for full-width, label-embedded forms. Set fluid on the control, or wrap fields in FluidForm. Each fluid control has a matching Fluid*Skeleton for loading states.
Works on TextInput, TextArea, NumberInput, Select, Dropdown, ComboBox, MultiSelect, DatePicker, TimePicker, Search, CopyInput, and PinCodeInput.
<script>
import { FluidForm, TextInput, Dropdown } from "carbon-components-svelte";
</script>
<FluidForm>
<TextInput fluid labelText="Application name" placeholder="customer-portal" />
<Dropdown
fluid
labelText="Region"
selectedId="us-east"
items={[
{ id: "us-east", text: "US East" },
{ id: "eu-de", text: "EU Germany" },
]}
/>
</FluidForm>
PinCodeInput: segmented verification codes
New component for OTP and MFA flows. Segments advance on input, support paste across the row, and emit change, complete, clear, and paste events. Supports numeric and alphanumeric modes, masking, xs size, fluid layout, and skeleton states.
See the PinCodeInput docs.
<script>
import { PinCodeInput } from "carbon-components-svelte";
</script>
<PinCodeInput
count={6}
labelText="Verification code"
on:complete={(e) => console.log("complete", e.detail)}
/>
CopyInput: read-only copyable values
New field for API tokens, endpoint URLs, and other labeled copy targets. Supports async copy, password obscuring with optional reveal, truncation, helper text, and the fluid variant. Prefetch on hover with on:mouseenter:copy-button.
See CopyInput async copy and fluid layout.
<script>
import { CopyInput } from "carbon-components-svelte";
let cachedToken = null;
async function copyToken() {
if (!cachedToken) {
cachedToken = await fetchApiToken();
}
await navigator.clipboard.writeText(cachedToken);
}
</script>
<CopyInput
labelText="API token"
type="password"
value="sk-••••••••"
copy={copyToken}
/>
Text and Box: typography and layout primitives
Text wraps Carbon type styles (body-01, heading-03, expressive variants, color tokens) with optional maxWidth and truncation. Box provides token-driven spacing, borders, and width utilities. Truncate adds a lines prop for multi-line ellipsis.
See Text, Box, and Truncate multiline.
<script>
import { Box, Text, Truncate } from "carbon-components-svelte";
</script>
<Box padding={5} border>
<Text type="heading-03">Workspace settings</Text>
<Truncate lines={2}>
Long description text that clamps to two lines before showing an ellipsis.
</Truncate>
</Box>
Tabs: dismissible and icon-only
dismissible renders a close button on each tab; handle on:dismiss to remove tabs from your data. Icon-only tabs show a tooltip from the label. The Tab default slot receives selected for conditional styling.
See dismissible tabs and icon-only tabs.
<script>
import { Tab, Tabs } from "carbon-components-svelte";
import Folder from "carbon-icons-svelte/lib/Folder.svelte";
let tabs = [
{ id: "a", label: "Overview", icon: Folder },
{ id: "b", label: "Settings", icon: Folder },
];
</script>
<Tabs dismissible type="container" on:dismiss={(e) => {
tabs = tabs.filter((tab) => tab.id !== e.detail.id);
}}>
{#each tabs as tab (tab.id)}
<Tab id={tab.id} label={tab.label} icon={tab.icon} />
{/each}
</Tabs>
DataTable: row state, sticky header, and filtering
Four related APIs for data-heavy UIs:
filterMode="hide"keeps non-matching rows mounted (hidden with CSS) so in-row inputs and menus keep state. No effect whenpageSizeor virtualization is enabled.highlightedRowIdsvisually marks rows (e.g. while an overflow menu is open).stickyHeaderMaxHeightcaps the scrollable body under a sticky header (number = px, or a CSS length string).refreshRow(id)/refreshCells()re-derive cell display after in-place row edits without replacing therowsarray.
See filtering strategy, highlighted row, sticky max height, and editable cells.
<script>
import { DataTable, Toolbar, ToolbarContent, ToolbarSearch } from "carbon-components-svelte";
let table;
let searchValue = "";
let rows = [{ id: "1", name: "Alpha", note: "" }];
</script>
<DataTable
bind:this={table}
stickyHeader
stickyHeaderMaxHeight="20rem"
filterMode="hide"
headers={[{ key: "name", value: "Name" }, { key: "note", value: "Note" }]}
{rows}
>
<Toolbar>
<ToolbarContent>
<ToolbarSearch bind:value={searchValue} />
</ToolbarContent>
</Toolbar>
</DataTable>
close events with dismissal trigger
Overlays and menus now surface why they closed. Listen for on:close and read e.detail.trigger:
- List boxes:
"selection","outside-click","escape-key","blur","toggle" - Modals:
"escape-key","outside-click","close-button","programmatic" - Overflow menu: cancelable
closebeforeopenflips
Applies to ComboBox, Dropdown, MultiSelect, OverflowMenu, ContextMenu, DatePicker, Popover, and UI Shell (HeaderAction, HeaderNavMenu, HeaderSearch).
<Dropdown
labelText="Status"
items={items}
on:close={(e) => {
if (e.detail.trigger === "outside-click") saveDraft();
}}
/>Modal and ComposedModal: fullWidth and programmatic close
fullWidth removes body padding so tables and fluid forms span edge to edge. Close events include trigger: "programmatic" when you call the close handler from code. Both variants dispatch a cancelable close event — call e.preventDefault() to keep the dialog open.
See Modal full width and prevent default close.
<script>
import { ComposedModal, ModalBody, ModalHeader } from "carbon-components-svelte";
let open = true;
</script>
<ComposedModal
bind:open
fullWidth
on:close={(e) => {
if (e.detail.trigger === "outside-click") e.preventDefault();
}}
>
<ModalHeader title="Audit log" />
<ModalBody><!-- table or fluid form --></ModalBody>
</ComposedModal>
UI Shell: responsive header nav and badges
HeaderSideNavItems duplicates header navigation links into the side nav below the large breakpoint (66rem), separated from regular side nav items with a divider. HeaderGlobalAction and icon-only Button support a badge slot for composing BadgeIndicator (notification dots and counts).
See HeaderSideNavItems and BadgeIndicator in UI Shell.
<script>
import {
BadgeIndicator,
Header,
HeaderGlobalAction,
HeaderNav,
HeaderNavItem,
HeaderSideNavItems,
SideNav,
SideNavItems,
} from "carbon-components-svelte";
import Notification from "carbon-icons-svelte/lib/Notification.svelte";
</script>
<Header>
<HeaderNav>
<HeaderNavItem href="/reports" text="Reports" />
</HeaderNav>
<HeaderGlobalAction aria-label="Notifications">
<svelte:fragment slot="badge">
<BadgeIndicator count={3} />
</svelte:fragment>
<Notification size={20} />
</HeaderGlobalAction>
</Header>
<SideNav>
<SideNavItems>
<HeaderSideNavItems>
<HeaderNavItem href="/reports" text="Reports" />
</HeaderSideNavItems>
</SideNavItems>
</SideNav>
ContentSwitcher: icon-only and low contrast
Switch supports an icon-only variant for compact toolbars. Low contrast styling softens the control for secondary contexts. Combine both for dense, muted toggle groups.
See icon-only and low contrast.
<script>
import { ContentSwitcher, Switch } from "carbon-components-svelte";
import Grid from "carbon-icons-svelte/lib/Grid.svelte";
import List from "carbon-icons-svelte/lib/List.svelte";
</script>
<ContentSwitcher size="sm" lowContrast>
<Switch icon={Grid} text="Grid" />
<Switch icon={List} text="List" />
</ContentSwitcher>
List-box slot context: selected and highlighted
Customize item rendering in ComboBox, Dropdown, and MultiSelect without re-deriving selection state. The default slot exposes let:item, let:index, let:selected, and let:highlighted.
<ComboBox labelText="Contact" items={items} let:item let:selected let:highlighted>
<span class:bx--list-box__menu-item__selected={selected}>
{item.text}
{#if highlighted}<span class="sr-only">, highlighted</span>{/if}
</span>
</ComboBox>Performance: open-state listener gating
Dismiss handlers no longer register window listeners for every closed menu on the page. Components attach outside-click, Escape, drag, and hover listeners only while open. A shared dismiss utility pools listeners by event type and options.
- ComboBox, Dropdown, MultiSelect, OverflowMenu, Popover: outside-click only while open
- Context menu: outside-click, Escape, and submenu hover gated on open state
- Date picker: outside-click only while calendar is open; caches top-layer ancestor
- Slider / RangeSlider: drag listeners only while dragging
- Tooltips, UI Shell header: Escape and outside-interaction gated on open state
xs size on compact controls
Several form and chrome components now support size="xs" for dense toolbars, tables, and utility panels. Pair Toolbar and Pagination at xs with a compact DataTable, or shrink individual fields where horizontal space is tight.
Works on Search, TextInput, Select, PasswordInput, PinCodeInput, Pagination, Toolbar, and OverflowMenu.
<script>
import {
OverflowMenu,
OverflowMenuItem,
Pagination,
Search,
TextInput,
Toolbar,
ToolbarContent,
} from "carbon-components-svelte";
</script>
<Toolbar size="xs">
<ToolbarContent>
<Search size="xs" placeholder="Filter rows..." />
<TextInput size="xs" hideLabel labelText="Status" placeholder="Any" />
<OverflowMenu size="xs" flipped>
<OverflowMenuItem text="Export" />
</OverflowMenu>
</ToolbarContent>
</Toolbar>
<Pagination size="xs" totalItems={102} pageSizes={[10, 20, 50]} />
StructuredList: multiple selection
Structured lists now support selecting more than one row. Set multiple on StructuredList and bind selected to an array of row values instead of a single string.
<script>
import {
StructuredList,
StructuredListBody,
StructuredListCell,
StructuredListHead,
StructuredListInput,
StructuredListRow,
} from "carbon-components-svelte";
let selected = ["postgresql-value", "redis-value"];
</script>
<StructuredList selection multiple bind:selected>
<StructuredListHead>
<StructuredListRow head>
<StructuredListCell head>Name</StructuredListCell>
<StructuredListCell head>Type</StructuredListCell>
<StructuredListCell head>{""}</StructuredListCell>
</StructuredListRow>
</StructuredListHead>
<StructuredListBody>
<StructuredListRow label for="postgresql">
<StructuredListCell>PostgreSQL</StructuredListCell>
<StructuredListCell>Relational</StructuredListCell>
<StructuredListInput id="postgresql" value="postgresql-value" title="PostgreSQL" name="database" />
<StructuredListCell />
</StructuredListRow>
<!-- additional rows -->
</StructuredListBody>
</StructuredList>
BadgeIndicator: notification dots and counts
New BadgeIndicator component for unread activity on icon-only buttons. Omit count for a presence dot, pass a number for a capped badge (999+), or pass a string to control the label yourself. Compose it through the badge slot on Button or HeaderGlobalAction.
See the BadgeIndicator docs and count variants.
<script>
import { BadgeIndicator, Button } from "carbon-components-svelte";
import Notification from "carbon-icons-svelte/lib/Notification.svelte";
</script>
<Button kind="ghost" icon={Notification} iconDescription="Notifications">
<BadgeIndicator slot="badge" count={4} />
</Button>
More in this release
- Local/session storage:
sync={false}opts out of cross-tabstorageevents; object and array mutations now persist correctly
Breaking changes
AccordionItem: iconDescription renamed to ariaLabel
The heading button prop is now ariaLabel. The decorative chevron no longer carries its own aria-label. Search your codebase for iconDescription on AccordionItem and rename it.
CSS: Svelte 5 browser baseline (~7% smaller bundle)
Older browser targets are dropped to match the Svelte 5 baseline (#3235). :has() selectors are replaced with marker classes (#3256). Verify layouts in your supported browsers after upgrading.
What's Changed
Breaking Changes
- fix(accordion-item)!: rename
iconDescriptiontoariaLabelfor heading button by @metonym in 72431ea - fix(css)!: drop older browser support (match Svelte 5 baseline) for ~7% size decrease by @metonym in #3235
Features
- feat(badge-indicator): add
BadgeIndicatorby @metonym in f5959b6 - feat(box): add Box component and utility container classes by @metonym in 8e15cc9
- feat(button): add
badgeslot to composeBadgeIndicatorwith icon-only button by @metonym in 7df0a82 - feat(button): support
portalTooltipby @metonym in df3454c - feat(code-button): add
refprop for button reference by @metonym in 0ae19ad - feat(code-snippet): add
codeLabelprop for container aria-label by @metonym in #3188 - feat(code-snippet): add
copyRefprop for copy button reference by @metonym in fbf202a - feat(combo-box): add
fluidprop for fluid form support by @metonym in 6b883af - feat(combo-box): add
iconandiconRightby @metonym in 25493ca - feat(combo-box): add FluidComboBoxSkeleton component by @metonym in 5d8bd6f
- feat(combo-box): dispatch
closeevent with dismissaltriggerby @metonym in #3313 - feat(combo-box): pass
selectedandhighlightedto default slot by @metonym in 8e5068f - feat(composed-modal): add "programmatic" close trigger by @metonym in 4a8cc29
- feat(composed-modal): add
fullWidthprop by @metonym in b07213a - feat(content-switcher):
Switchsupports icon-only variant by @metonym in 91458e8 - feat(content-switcher): support icon-only, low contrast variant by @metonym in 4bbe2e3
- feat(content-switcher): support low contrast variant by @metonym in c0f3fec
- feat(context-menu):
closeevent surfaces dismissaltriggerby @metonym in #3309 - feat(copy-input): add
CopyInputby @metonym in 3cda4e1 - feat(copy-input): add
fluidprop for fluid form support by @metonym in 1a3da64 - feat(copy-input): add FluidCopyInputSkeleton component by @metonym in 9288ab0
- feat(data-table): add
highlightedRowIdsby @metonym in ec97d3b - feat(data-table): add
stickyHeaderMaxHeightprop for sticky header by @metonym in cfd5447 - feat(data-table): add filterMode="hide" to preserve row state while filtering by @metonym in a81d64e
- feat(data-table): add refreshRow/refreshCells to re-derive cells after in-place edits by @metonym in 0b7e503
- feat(data-table): inherit
Toolbarsize from parentDataTableby @metonym in 5edbc03 - feat(date-picker):
closeevent surfaces dismissaltriggerby @metonym in e1a876b - feat(date-picker): add
fluidprop for fluid form support by @metonym in e088bed - feat(date-picker): add FluidDatePickerSkeleton component by @metonym in ac7eede
- feat(dropdown): add
fluidprop for fluid form support by @metonym in d8c85eb - feat(dropdown): add
iconandiconRightby @metonym in 8b32baf - feat(dropdown): add FluidDropdownSkeleton component by @metonym in 3d84cfd
- feat(dropdown): dispatch
closeevent with dismissaltriggerby @metonym in #3312 - feat(dropdown): pass
selectedandhighlightedto default slot by @metonym in 11bd316 - feat(expandable-tile): forward focus/blur events by @metonym in #3174
- feat(file-uploader-drop-container): dispatch
rejectedevent by @metonym in #3187 - feat(file-uploader-skeleton): add
hideLabelTitleandhideLabelDescriptionprops by @metonym in 9dc56d3 - feat(header-search): pass
selectedto result slot by @metonym in 41bcab1 - feat(local-storage): add
syncprop to opt out of storage event sync by @metonym in 303b193 - feat(modal): add "programmatic" close trigger by @metonym in e85b563
- feat(modal): add
fullWidthprop by @metonym in 16fce32 - feat(multi-select): add
fluidprop for fluid form support by @metonym in d84c56e - feat(multi-select): add FluidMultiSelectSkeleton component by @metonym in 22eba4c
- feat(multi-select): dispatch
closeevent with dismissaltriggerby @metonym in #3314 - feat(multi-select): pass
selectedandhighlightedto default slot by @metonym in 6da1395 - feat(number-input): add
fluidprop for fluid form support by @metonym in afff038 - feat(number-input): add FluidNumberInputSkeleton component by @metonym in 0f3031b
- feat(overflow-menu-item): support
iconandiconRightby @metonym in a3e794e - feat(overflow-menu):
closeevent surfaces dismissaltriggerby @metonym in #3311 - feat(overflow-menu): support
xssize by @metonym in 5c7f382 - feat(pagination-skeleton): add
sizeprop by @metonym in 516f2bd - feat(pagination): add
sizeprop by @metonym in c7c7149 - feat(pagination): add
xssize by @metonym in 2fd445f - feat(pagination): add
xssize by @metonym in a4084f0 - feat(password-input): add
PasswordInputSkeletonby @metonym in b740a44 - feat(password-input): support
xssize by @metonym in d70270b - feat(pin-code-input): add
fluidprop for fluid form support by @metonym in 280a451 - feat(pin-code-input): add
PinCodeInputby @metonym in 9480360 - feat(pin-code-input): add
PinCodeInputSkeletonby @metonym in c6fc2eb - feat(pin-code-input): add FluidPinCodeInputSkeleton component by @metonym in db3c199
- feat(pin-code-input): support
xssize by @metonym in 81272a7 - feat(popover): dispatch
closewhencloseOnOutsideClickauto-closes by @metonym in #3319 - feat(search-skeleton): add
hideLabelprop by @metonym in e5f570a - feat(search): add
fluidprop for fluid form support by @metonym in c1427b4 - feat(search): add FluidSearchSkeleton component by @metonym in dfda530
- feat(search): support
xssize by @metonym in c2780cb - feat(select): add
fluidprop for fluid form support by @metonym in b29cabe - feat(select): add FluidSelectSkeleton component by @metonym in 03796f6
- feat(select): support
xssize by @metonym in 15b6131 - feat(session-storage): add
syncprop to opt out of storage event sync by @metonym in 535a999 - feat(stack): add
wrapprop for flex-wrap support by @metonym in d00fce6 - feat(structured-list): support
multipleselection by @metonym in 13c1cd9 - feat(tabs): pass
selectedto Tab default slot by @metonym in 986ca51 - feat(tabs): support dismissible tabs by @metonym in a7d7bd1
- feat(tabs): support icon-only variant by @metonym in 1661cb9
- feat(tag): add
inlineprop by @metonym in a8995f4 - feat(text-area): add
fluidprop for fluid form support by @metonym in ee85a7a - feat(text-area): add FluidTextAreaSkeleton component by @metonym in b23dfdd
- feat(text-input): add
fluidprop for fluid form support by @metonym in ad01613 - feat(text-input): add FluidTextInputSkeleton component by @metonym in e7bc62d
- feat(text-input): support
xssize by @metonym in 9367e64 - feat(text): add
Textcomponent and utility typography classes by @metonym in e58163d - feat(time-picker): add
fluidprop for fluid form support by @metonym in e69c022 - feat(time-picker): add FluidTimePickerSkeleton component by @metonym in aa3c1b0
- feat(toolbar): add "xs" size by @metonym in b24f2f2
- feat(truncation): add
linesprop for multi-line support by @metonym in 9d89681 - feat(ui-shell):
HeaderActionclose event surfaces dismissaltriggerby @metonym in #3310 - feat(ui-shell):
HeaderGlobalActionsupportsbadgeslot by @metonym in 15f3914 - feat(ui-shell):
HeaderNavMenudispatchescloseevent by @metonym in #3308 - feat(ui-shell):
HeaderSearchdispatchescloseevent by @metonym in #3318 - feat(ui-shell): add
HeaderSideNavItemsfor responsive header navigation by @metonym in 6de282a
Bug Fixes
- fix(accordion-item): remove chevron aria-label by @metonym in 69b0305
- fix(biome): enforce useSvelteRequireEachKey by @metonym in 57a0c4b
- fix(breadcrumb): fix overflow menu carets for small sizes by @metonym in #3228
- fix(checkbox): preserve consumer title and stop mutating the prop by @metonym in 122cb88
- fix(code-snippet): avoid overwriting consumer-controlled
showMoreLessprop by @metonym in #3191 - fix(code-snippet): close portalled tooltip after feedback timeout by @metonym in bbd144a
- fix(code-snippet): suppress native copy feedback caret for portalled tooltips for inline type by @metonym in 05044ca
- fix(combo-box): add arrow key support for opening/closing the menu by @b-r-i-a-n-w-e-s-t in #3254
- fix(combo-box): clear hover highlight when cursor leaves the menu by @metonym in 0247728
- fix(combo-box): derive virtualized item height from size by @metonym in 3987ef1
- fix(combo-box): remove invalid listbox role from the root element by @b-r-i-a-n-w-e-s-t in #3262
- fix(combo-box): scope option ids per instance by @metonym in #3176
- fix(composed-modal): add keyed each for secondary buttons by @metonym in 975e7d5
- fix(content-switcher): skip disabled switches during keyboard navigation by @metonym in #3204
- fix(copy-button): close portalled tooltip after feedback timeout by @metonym in c8a9d56
- fix(css): replace
:has()with marker classes for browser baseline by @metonym in #3256 - fix(data-table): associate cells with column headers by @metonym in #3162
- fix(data-table): scope expandable row ids per instance by @metonym in #3178
- fix(data-table): sticky header supports empty column and column menu by @metonym in #3301
- fix(dropdown): add Alt+Arrow support for opening/closing the menu by @metonym in #3257
- fix(dropdown): clear hover highlight when cursor leaves the menu by @metonym in 01f24d3
- fix(dropdown): derive virtualized item height from size by @metonym in ff17f9c
- fix(dropdown): scope option ids per instance by @metonym in #3177
- fix(expandable-tile): add aria-label to chevron toggle button by @metonym in #3306
- fix(expandable-tile): link
aria-controlsto below-the-fold content by @metonym in #3305 - fix(expandable-tile): resize if bound element changes by @metonym in #3180
- fix(expandable-tile): stop measurements clobbering bound props by @metonym in #3197
- fix(file-uploader-button): join
acceptexplicitly if array by @metonym in 2e81e7d - fix(file-uploader-drop-container): join
acceptexplicitly if array by @metonym in a7596f3 - fix(file-uploader): consolidate button role onto drop container label by @metonym in #3307
- fix(file-uploader): expose
aria-disabledon drop container by @metonym in #3194 - fix(local-storage): persist object and array value mutations by @metonym in 929590c
- fix(local-storage): sync cross-tab key removal by @metonym in 2681639
- fix(modal): add keyed each for secondary buttons by @metonym in 07d4cd7
- fix(modal): prevent Enter on Cancel from also firing the primary action by @wickning1 in #3279
- fix(multi-select): add Alt+Arrow support for opening/closing the menu by @metonym in #3258
- fix(multi-select): clear hover highlight when cursor leaves the menu by @metonym in 7545f77
- fix(multi-select): derive virtualized item height from size by @metonym in 9ecd4b9
- fix(multi-select): fix selection if
portalMenuistrueby @metonym in #3185 - fix(multi-select): open menu when the field label is clicked by @metonym in #3260
- fix(multi-select): restore focus outline on the field by @metonym in #3259
- fix(multi-select): scope checkbox ids per instance by @metonym in #3175
- fix(multi-select): scope option ids per instance by @metonym in #3179
- fix(overflow-menu): dispatch cancelable
closebefore flippingopenby @metonym in 027b979 - fix(overflow-menu): non-portalled
ulis a sibling of the menu button by @metonym in #3189 - fix(overflow-menu): prevent scroll jump when opening portalled menu by @metonym in #3338
- fix(pagination-nav): add keyed each for overflow options by @metonym in 9992b54
- fix(pagination-nav): add keyed each for page items by @metonym in be59b86
- fix(pagination): cap rendered page options at
pageWindowby @metonym in #3005 - fix(pagination): make
pagesUnknownactually navigable by @metonym in 9db0432 - fix(pagination): portal next/prev button tooltips by @metonym in 0104782
- fix(range-slider): dispatch
changefrom commit gestures, not reactive block by @metonym in 6545d39 - fix(session-storage): persist object and array value mutations by @metonym in b28b872
- fix(session-storage): sync cross-tab key removal by @metonym in 22fea38
- fix(skeleton-text): add keyed each for paragraph lines by @metonym in db124d2
- fix(slider): clamp keyboard value and dispatch
changefrom commit gestures by @metonym in 66667cf - fix(tabs): add keyed each in TabsSkeleton by @metonym in b3721ae
- fix(tabs): support Home/End keyboard shortcuts by @metonym in #3208
- fix(tabs): user-provided
hrefshould not prevent default behavior by @metonym in 12e95d1 - fix(tree-view): prevent arrow keys from scrolling the page by @metonym in #3165
- fix(tree-view): scope internal node ids per instance by @metonym in #3209
- fix(utils): apply maxItems cap in scrollHighlightedIntoView by @metonym in 865a489
- fix(utils): clamp virtualize
scrollTopto the scrollable range by @metonym in #3236 - fix(utils): render unvirtualized when itemHeight is non-positive by @metonym in ca3e2ad
Performance
- perf(combo-box): register outside-click listener only while open by @metonym in 2849c2a
- perf(context-menu): gate outside-click and Escape listeners on open by @metonym in 08d0a5e
- perf(context-menu): register option hover listener only while submenu open by @metonym in 94b9d8f
- perf(date-picker): cache top-layer ancestor for outside-click checks by @metonym in 08623ba
- perf(date-picker): register outside-click listener only while calendar is open by @metonym in 61dc601
- perf(dismiss): pool window listeners by type, options by @metonym in 356654a
- perf(dropdown): register outside-click listener only while open by @metonym in 5e9bcb0
- perf(multi-select): register outside-interaction listeners only while open by @metonym in aabc309
- perf(overflow-menu): register outside-click listener only while open by @metonym in 6afb3f8
- perf(popover): register outside-click listener only while open by @metonym in 9494e0c
- perf(range-slider): register drag listeners only while dragging by @metonym in 3b63e25
- perf(slider): register drag listeners only while dragging by @metonym in a626f77
- perf(tooltip-definition): register Escape listener only while open by @metonym in 37c99af
- perf(tooltip-icon): register Escape listener only while open by @metonym in 3bbbf09
- perf(ui-shell): register Header outside-interaction listeners only while open by @metonym in 52f5222