github carbon-design-system/carbon-components-svelte v0.110.0

4 hours ago

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>
menu-button combo-button

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>
search-menu header-search

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>
user-avatar user-avatar-group profile-menu

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>
toggletip disclosure

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>
tabs-vertical tabs-overflow

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>
iconindicator 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>
datepicker-month

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} />
combobox-xs

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>
link-muted link-icon

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; tooltipPosition and tooltipAlignment
  • HeaderNavItem: optional trailing icon for external links
  • HeaderSearch: labelText, placeholder, icon, and closeButtonLabelText props
  • Button: forwards on:mousedown; skips tooltip when iconDescription is empty
  • MultiSelect: read-only fields are reviewable (no longer disabled); retains selectedIds when items clear
  • Select / ComboBox: preserve displayed values across async option loading
  • FloatingPortal: tooltip caret stays anchored on content resize; flipped sides stay stable
  • DataTable: O(1) expanded-row lookups with a Set internally

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 lockDirection to 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 HeaderAction panel by default by @metonym in 64a584f

Features

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 lockDirection to 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 HeaderAction panel by default by @metonym in 64a584f
  • fix(utils): defer dismiss() window listener registration past the enabling click by @metonym in f411e26

Performance

Don't miss a new carbon-components-svelte release

NewReleases is sending notifications on new releases.