This release adds 12 new components for action menus, header search, user avatar and profile chrome, overlays, vertical tabs, and status indicators. Also in this release: combo box typeahead accept on blur and arrow keys, portalled copy feedback by default, month picking on the date picker, xs sizing across list boxes, scrollable overflow tabs, and accessibility fixes in tooltips, selects, and tree views.
71 changes in this release:
| Category | Count |
|---|---|
| Breaking changes | 6 |
| Features | 43 |
| Bug fixes | 21 |
| Performance | 1 |
Full Changelog: v0.109.0...v0.110.0
Menu, MenuButton, and ComboButton: action menus
New menu primitives for labeled dropdowns and split buttons. Menu and MenuItem are low-level building blocks with sizes, icons, danger styling, dividers, and nested submenus. MenuButton wraps a labeled trigger; ComboButton pairs a primary action with a chevron menu for related secondary actions.
See Menu, MenuButton, and ComboButton.
<script>
import { ComboButton, MenuButton, MenuItem } from "carbon-components-svelte";
</script>
<MenuButton labelText="Actions" size="xs">
<MenuItem on:click={() => console.log("Cut")}>Cut</MenuItem>
<MenuItem on:click={() => console.log("Copy")}>Copy</MenuItem>
</MenuButton>
<ComboButton labelText="Save" on:click={() => console.log("Save")}>
<MenuItem on:click={() => console.log("Save as")}>Save as</MenuItem>
<MenuItem on:click={() => console.log("Save a copy")}>Save a copy</MenuItem>
</ComboButton>
SearchMenu and HeaderSearch
SearchMenu filters and highlights typeahead suggestions with grouped results, keyboard navigation, and configurable fuzzy matching. Compose it into HeaderSearch through the menu slot for global header search, or use it standalone in docs and app chrome.
See SearchMenu and HeaderSearch menu slot.
<script>
import { HeaderSearch, SearchMenu, SearchMenuItem } from "carbon-components-svelte";
</script>
<HeaderSearch placeholder="Search docs">
<SearchMenu slot="menu" let:value>
<SearchMenuItem text="DataTable filtering" href="/components/DataTable#filtering" />
<SearchMenuItem text="Fluid forms" href="/components/FluidForm" />
</SearchMenu>
</HeaderSearch>
UserAvatar, UserAvatarGroup, and ProfileMenu
UserAvatar renders photos, initials, or a default icon with optional auto background color from the user's name. UserAvatarGroup stacks avatars with overflow and configurable stackOrder. ProfileMenu composes both into the UI Shell header for account switching and profile actions.
See UserAvatar, UserAvatarGroup, and ProfileMenu.
<script>
import {
ProfileMenu,
ProfileMenuHeader,
ProfileMenuItem,
ProfileMenuList,
UserAvatar,
} from "carbon-components-svelte";
</script>
<ProfileMenu iconDescription="Profile">
<UserAvatar slot="avatar" size="md" name="Monica Hall" />
<ProfileMenuHeader name="Monica Hall" username="mhall">
<UserAvatar slot="avatar" size="lg" name="Monica Hall" />
</ProfileMenuHeader>
<ProfileMenuList>
<ProfileMenuItem href="/settings">Settings</ProfileMenuItem>
<ProfileMenuItem href="/logout">Log out</ProfileMenuItem>
</ProfileMenuList>
</ProfileMenu>
Dialog, Toggletip, and Disclosure
Three lightweight overlay and disclosure primitives. Dialog wraps the native <dialog> element for modal and non-modal overlays. Toggletip opens contextual content on click with optional footer actions. Disclosure shows and hides a section from a single trigger.
See Dialog, Toggletip, and Disclosure.
<script>
import { Dialog, Disclosure, Toggletip, ToggletipFooter, Button } from "carbon-components-svelte";
let open = false;
</script>
<Disclosure summary="Show shipping details">
<p>Orders ship within 2 business days.</p>
</Disclosure>
<Toggletip labelText="Retention">
Data is retained for 90 days.
<ToggletipFooter>
<Button kind="ghost" size="sm">Learn more</Button>
</ToggletipFooter>
</Toggletip>
<Button on:click={() => (open = true)}>Open dialog</Button>
<Dialog bind:open modal aria-label="Confirm action">
<p>Are you sure?</p>
</Dialog>
TabsVertical and scrollable overflow tabs
TabsVertical places the tab list beside the panel on medium breakpoints and up, with sm/md/lg sizes and a matching skeleton. Horizontal Tabs now scroll overflowing tabs instead of collapsing to a mobile dropdown.
See vertical tabs and overflow scrolling.
<script>
import { Tab, TabContent, Tabs, TabsVertical } from "carbon-components-svelte";
</script>
<TabsVertical size="md">
<Tab label="Dashboard" />
<Tab label="Monitoring" />
<Tab label="Activity" />
<svelte:fragment slot="content">
<TabContent>Dashboard content</TabContent>
<TabContent>Monitoring content</TabContent>
<TabContent>Activity content</TabContent>
</svelte:fragment>
</TabsVertical>
<Tabs type="container">
<!-- many tabs scroll horizontally on narrow viewports -->
</Tabs>
ComboBox typeahead accept and fuzzy highlighting
Typeahead now accepts inline suggestions on Tab, focus out, and Right/End keys. Set aria-autocomplete="both" automatically when typeahead is enabled. Export fuzzyMatch and highlightSegments from the package for custom filter and highlight rendering in ComboBox, Dropdown, and MultiSelect slots.
See typeahead and highlight matches.
<script>
import { ComboBox, fuzzyMatch, highlightSegments } from "carbon-components-svelte";
const items = [
{ id: "blueberry", text: "Blueberry" },
{ id: "blackberry", text: "Blackberry" },
];
</script>
<ComboBox
typeahead
autoHighlight="first-match"
labelText="Fruit"
{items}
shouldFilterItem={(item, value) => fuzzyMatch(item.text, value).matched}
let:item
let:value
>
{#each highlightSegments(item.text, fuzzyMatch(item.text, value).indices) as segment}
{#if segment.highlighted}<strong>{segment.text}</strong>{:else}{segment.text}{/if}
{/each}
</ComboBox>Portalled copy feedback by default
CopyButton, CopyInput, and CodeSnippet now render the "Copied!" feedback in a body-level portal by default instead of the inline .bx--copy-btn__feedback caret. Pass portalTooltip={false} to restore the previous inline markup. CopyButton also supports ghost kind, sizes, and a hover tooltip; CopyInput adds tooltip position and alignment.
See CopyButton, CopyInput, and CodeSnippet.
<script>
import { CopyButton, CopyInput } from "carbon-components-svelte";
</script>
<CopyButton kind="ghost" size="sm" feedback="Copied" text="sk-abc123" />
<CopyInput
labelText="API token"
value="sk-abc123"
tooltipPosition="top"
tooltipAlignment="end"
/>IconIndicator, ShapeIndicator, and TagSet
Status and layout primitives for dense UIs. IconIndicator and ShapeIndicator communicate semantic state beside labels. TagSet measures available width and collapses overflow tags into a "+N" tooltip.
See IconIndicator, ShapeIndicator, and TagSet.
<script>
import { IconIndicator, ShapeIndicator, Tag, TagSet } from "carbon-components-svelte";
</script>
<IconIndicator kind="failed" labelText="Sync failed" />
<ShapeIndicator kind="caution" labelText="Needs review" />
<TagSet>
<Tag type="blue">React</Tag>
<Tag type="purple">Svelte</Tag>
<Tag type="red">Angular</Tag>
</TagSet>
DatePicker: month type
Pick a month and year without day-level granularity. Set type="month" on DatePicker for billing cycles, reporting periods, and other month-scoped forms.
See month picker.
<script>
import { DatePicker, DatePickerInput } from "carbon-components-svelte";
</script>
<DatePicker type="month">
<DatePickerInput labelText="Billing period" placeholder="mm/yyyy" />
</DatePicker>
xs size on list-box controls
ComboBox, Dropdown, and MultiSelect now support size="xs" alongside the shared list-box sizing. Pair them with compact toolbars and dense table chrome.
See ComboBox sizes, Dropdown sizes, and MultiSelect sizes.
<script>
import { ComboBox, Dropdown, MultiSelect } from "carbon-components-svelte";
</script>
<ComboBox size="xs" labelText="Owner" items={owners} />
<Dropdown size="xs" labelText="Status" items={statuses} />
<MultiSelect size="xs" labelText="Tags" items={tags} />
hideAtBreakpoint action
Hide elements at or below a Carbon breakpoint without CSS media queries in every component. Use use:hideAtBreakpoint from the breakpoint utilities.
See hideAtBreakpoint.
<script>
import { hideAtBreakpoint } from "carbon-components-svelte";
</script>
<p use:hideAtBreakpoint={{ below: "md" }}>Hidden below the medium breakpoint.</p>Link: muted variant and size-aware icons
Link adds a muted variant that inherits surrounding text color, makes "md" an explicit size, and scales icons with tighter gaps at each size tier.
See muted link and icon scaling.
<script>
import { Link } from "carbon-components-svelte";
import Launch from "carbon-icons-svelte/lib/Launch.svelte";
</script>
<p class="bx--text-secondary">
See also <Link href="/docs" muted>related documentation</Link>.
</p>
<Link href="https://example.com" icon={Launch} size="sm">External</Link>
TreeView: aggregate selection and expansion events
Listen for select:change and toggle:change on the root TreeView to react to selection and expansion across the whole tree without wiring every node.
See TreeView events.
<script>
import { TreeView } from "carbon-components-svelte";
const nodes = [
{ id: 0, text: "Analytics" },
{ id: 1, text: "Blockchain", nodes: [{ id: 2, text: "Platform" }] },
];
</script>
<TreeView
labelText="Products"
{nodes}
on:select:change={(e) => console.log("selected", e.detail)}
on:toggle:change={(e) => console.log("expanded", e.detail)}
/>More in this release
CodeSnippet: mask gradient on single/multi-line variants; dynamic expand button when content overflows;tooltipPositionandtooltipAlignmentHeaderNavItem: optional trailingiconfor external linksHeaderSearch:labelText,placeholder,icon, andcloseButtonLabelTextpropsButton: forwardson:mousedown; skips tooltip wheniconDescriptionis emptyMultiSelect: read-only fields are reviewable (no longerdisabled); retainsselectedIdswhen items clearSelect/ComboBox: preserve displayed values across async option loadingFloatingPortal: tooltip caret stays anchored on content resize; flipped sides stay stableDataTable: O(1) expanded-row lookups with aSetinternally
Breaking changes
Copy feedback: portalled by default
CopyButton, CopyInput, and CodeSnippet now render the "Copied!" feedback in a body-level portal by default. Pass portalTooltip={false} on each component to restore the previous inline .bx--copy-btn__feedback caret.
Tabs: scrollable overflow replaces mobile dropdown
Horizontal Tabs no longer collapse to a dropdown on narrow viewports. Overflowing tabs scroll horizontally instead. Review layouts that relied on the old mobile select behavior.
StructuredList: auto-rendered selection icon
Selection rows now render the checkmark column automatically. Remove any manually placed checkmark cell to avoid a duplicate. Customize the icon with the selectionIcon slot.
FloatingPortal: lockDirection is now an enum
lockDirection accepts "none", "before-flip", or "after-flip" instead of a boolean. Update callers that passed true/false.
HeaderAction: panel transition is opt-in
HeaderAction panels no longer animate by default. Pass transition:slide (or another Svelte transition) to restore motion.
What's Changed
Breaking Changes
- feat(code-snippet)!: portal the feedback tooltip by default by @metonym in 51f3d6a
- feat(copy-button)!: portal the feedback tooltip by default by @metonym in 27e2ef9
- fix(floating-portal)!: change
lockDirectionto enum by @metonym in 787404b - feat(structured-list)!: customizable, auto-rendered selection icon by @metonym in 9785256
- feat(tabs)!: replace mobile dropdown with scrollable overflow tabs by @metonym in 17c6c59
- fix(ui-shell)!: do not animate
HeaderActionpanel by default by @metonym in 64a584f
Features
- feat(breakpoint): add hideAtBreakpoint action by @metonym in 3bbcff2
- feat(button): forward on:mousedown, skip tooltip when iconDescription is empty by @metonym in 5d35cdc
- feat(code-snippet): add mask gradient for single/multi-line variants (#3343) by @metonym in 22ec08b
- feat(code-snippet): portal the feedback tooltip by default by @metonym in 51f3d6a
- feat(code-snippet): support tooltipPosition and tooltipAlignment by @metonym in 35ccb7f
- feat(combo-box): accept inline typeahead suggestion in place on Right/End by @metonym in 9492ff9
- feat(combo-box): accept typeahead suggestion on focus out by @metonym in 67cf88c
- feat(combo-box): add xs size by @metonym in 3bddd31
- feat(combo-button): add
ComboButtoncomponent by @metonym in 66334af - feat(copy-button): add ghost kind, sizes, and a hover tooltip by @metonym in b3c30a8
- feat(copy-button): portal the feedback tooltip by default by @metonym in 27e2ef9
- feat(copy-input): add tooltip position and alignment by @metonym in f057186
- feat(date-picker): add "month" type by @metonym in 9f833b2
- feat(dialog): add
Dialogcomponent by @metonym in 56cba4d - feat(disclosure): add
Disclosurecomponent by @metonym in f8ebc2a - feat(dropdown): add xs size by @metonym in 7841161
- feat(header-search): support closeButtonLabelText prop by @metonym in 98582a8
- feat(header-search): support icon prop override by @metonym in 31eaee4
- feat(header-search): support labelText prop by @metonym in c69776c
- feat(header-search): support placeholder prop by @metonym in 745e7df
- feat(icon-indicator): add
IconIndicatorcomponent by @metonym in 514a18f - feat(link): add muted variant that inherits text color by @metonym in c540235
- feat(link): make medium size explicit ("md") by @metonym in 8332ba2
- feat(link): scale icon and tighten gap to match link size by @metonym in 6d53da4
- feat(list-box): add xs size by @metonym in 9cd97eb
- feat(menu-button): add MenuButton component by @metonym in a23150a
- feat(menu): add
MenuandMenuItemprimitives by @metonym in d845af4 - feat(multi-select): add xs size by @metonym in a59624e
- feat(search-menu): add
SearchMenuby @metonym in 577bca5 - feat(shape-indicator): add
ShapeIndicatorcomponent by @metonym in 682b512 - feat(tabs-vertical): add
TabsVerticalcomponent by @metonym in 02bbd96 - feat(tabs-vertical): add
TabsVerticalSkeletonby @metonym in c6a1082 - feat(tabs):
TabsVerticalsupports sm/md/lg sizes by @metonym in 77edafd - feat(tag-set): add
TagSetcomponent by @metonym in c59fe9f - feat(toggletip): add
Toggletipby @metonym in 146fa3e - feat(tree-view): add
select:changeaggregate selection event by @metonym in cc4a813 - feat(tree-view): add
toggle:changeaggregate expansion event by @metonym in f5c665b - feat(ui-shell):
HeaderNavItemsupports icon by @metonym in 5f0e93f - feat(ui-shell):
HeaderSearchsupportsSearchMenucomposition by @metonym in c061221 - feat(ui-shell): add
ProfileMenuby @metonym in 2552a6a - feat(user-avatar-group): add
UserAvatarGroupby @metonym in b61c7c7 - feat(user-avatar): add
UserAvatarby @metonym in 61c6de5 - feat(user-avatar): add auto background color by @metonym in 95c0390
Bug Fixes
- fix(code-snippet): multi-line variant dynamically shows expand button based on content height by @metonym in 0f0dce8
- fix(combo-box): decouple hover highlight from Enter selection by @metonym in c3ec9a0
- fix(combo-box): only inline-complete typeahead on a prefix match by @metonym in 7345732
- fix(combo-box): preserve displayed selection across async items changes by @b-r-i-a-n-w-e-s-t in 701382e
- fix(combo-box): set aria-autocomplete to "both" with typeahead by @metonym in 0b99228
- fix(dropdown): decouple hover highlight from Enter selection by @metonym in 47665df
- fix(dropdown): prevent page scroll when opening menu with Space (#3346) by @metonym in 00f87c7
- fix(floating-portal): change
lockDirectionto enum by @metonym in 787404b - fix(floating-portal): keep a flipped tooltip side stable across content resize by @metonym in f108385
- fix(floating-portal): keep the tooltip caret on the anchor when content resizes by @metonym in a11d65c
- fix(list-box): scope highlighted-item scroll to the menu, not the page by @metonym in 1f91144
- fix(multi-select): decouple hover highlight from Enter selection by @metonym in 01c14e8
- fix(multi-select): make read-only reviewable, drop disabled semantics (#3359) by @b-r-i-a-n-w-e-s-t in f7a67f5
- fix(multi-select): retain selectedIds when items list clears by @b-r-i-a-n-w-e-s-t in 5d59f81
- fix(select): re-assert native value when an option unmounts (#3392) by @b-r-i-a-n-w-e-s-t in 4a2c722
- fix(select): re-assert native value when options mount async by @b-r-i-a-n-w-e-s-t in 9e60780
- fix(tooltip): give the interactive tooltip dialog an accessible name by @metonym in 647e7c7
- fix(tooltip): keep mouse hover from stealing focus into TooltipFooter by @metonym in ee54b73
- fix(tree-view): dispatch select/toggle/focus with correct state by @metonym in 187c9d0
- fix(ui-shell): do not animate
HeaderActionpanel by default by @metonym in 64a584f - fix(utils): defer dismiss() window listener registration past the enabling click by @metonym in f411e26