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

9 hours ago

DataTable: table-level sort and on:sort for server-driven sorting

For custom sorting, you can now provide a top-level sort comparator on the table that applies to every sortable column unless a header defines its own.

For server-side sorting, listen with on:sort: the event includes detail.key (column) and detail.direction. Call preventDefault() so the table does not reorder rows in the browser; fetch sorted data from your API (or a loader), assign rows, and keep sortKey / sortDirection in sync with what the server used.

See the DataTable docs.

<script>
  import { DataTable } from "carbon-components-svelte";

  let headers = [
    { key: "name", value: "Name" },
    { key: "port", value: "Port" },
  ];
  let rows = [
    { id: "a", name: "Item A", port: 443 },
    { id: "b", name: "Item B", port: 80 },
  ];
  let sortKey = null;
  let sortDirection = "none";
</script>

<DataTable
  sortable
  bind:sortKey
  bind:sortDirection
  {headers}
  {rows}
  sort={(a, b, { key }) => (key === "port" ? a - b : String(a).localeCompare(String(b)))}
  on:sort={(e) => {
    // Server-side sorting
    e.preventDefault();
    sortKey = e.detail.key;
    sortDirection = e.detail.direction;
    await loadRows({ sortKey: detail.key, sortDirection: detail.direction });
    rows = result;
  }}
/>

TreeView: multiselect and link nodes

multiselect with bind:selectedIds supports Ctrl/Cmd/Shift-style selection; multiselectMode controls whether a gesture selects a single node, a subtree, or related groups. Nodes may set href so the label is a real link (e.g. file browser or docs tree) while keeping tree semantics.

See the TreeView docs.

<script>
  import { TreeView } from "carbon-components-svelte";

  let selectedIds = [];
  let nodes = [
    {
      id: "1",
      text: "Docs",
      href: "/docs",
      nodes: [{ id: "2", text: "Guide", href: "/docs/guide" }],
    },
  ];
</script>

<TreeView {nodes} multiselect bind:selectedIds />
TreeView multiselect

UI Shell: classic theme

v0.105.0 fully themed the UI Shell.

Header and SideNav now accept theme="classic" for the mixed shell look (Gray 100 header with White side nav), matching Carbon's classic UI shell guidance. Closes #2836.

Note: you must use the all.css StyleSheet since it uses CSS variables.

<script>
  import "carbon-components-svelte/css/all.css";
  import { Header, SideNav, SideNavItems, SideNavLink } from "carbon-components-svelte";
</script>

<Header theme="classic" />
<SideNav theme="classic">
  <SideNavItems>
    <SideNavLink href="/" text="Home" />
  </SideNavItems>
</SideNav>
UI Shell classic

ComboBox: reopen after clear (openOnClear)

By default, the menu closes immediately when the value is cleared.

Set openOnClear to true to keep the list open after the user clears the field, so they can choose another option without having to click the trigger again.

See the ComboBox docs.

ComboBox open on clear

ComboBox: typeahead with custom filter (shouldFilterItem)

Built-in typeahead now respects shouldFilterItem, so filtering can follow your own rules: extra fields, aliases, diacritics, fuzzy matching, or anything beyond the default label substring behavior.

See the ComboBox docs.

<script>
  import { ComboBox } from "carbon-components-svelte";
</script>

<ComboBox
  shouldFilterItem={(item, value) => {
    const q = value.trim().toLowerCase();
    if (!q) return true;
    return item.text.toLowerCase().includes(q);
  }}
  labelText="Country"
  placeholder="Search or select"
  items={[
    { id: "us", text: "United States" },
    { id: "ca", text: "Canada" },
  ]}
/>
ComboBox typeahead custom

ComboBox: auto-highlight first match (autoHighlight)

By default, no list item is highlighting when filtering values.

Set autoHighlight="first-match" so the first row that survives filtering is highlighted as the user types, reducing the use of arrow keys and providing a smoother keyboard path from search to selection.

See the ComboBox docs.

<script>
  import { ComboBox } from "carbon-components-svelte";
</script>

<ComboBox
  autoHighlight="first-match"
  labelText="Contact"
  placeholder="Select contact method"
  items={[
    { id: "0", text: "Slack" },
    { id: "1", text: "Email" },
    { id: "2", text: "Fax" },
  ]}
/>
ComboBox first match

Dropdown: optional selectedId

selectedId can be omitted for an empty initial state, useful for placeholders and "choose one" flows without the need for a sentinel value.

See the Dropdown docs.

<script>
  import { Dropdown } from "carbon-components-svelte";
</script>

<Dropdown
  titleText="Role"
  label="Select a role"
  items={[
    { id: "admin", text: "Admin" },
    { id: "user", text: "User" },
  ]}
  on:select={({ detail }) => console.log(detail.selectedId)}
/>

Tag: large size

size="lg" aligns tags with other large Carbon controls when density or touch targets need to match the rest of the form.

See the Tag docs.

<script>
  import { Tag } from "carbon-components-svelte";
</script>

<Tag size="lg">Large tag</Tag>
Tag large

Performance: faster list components and leaner DataTable

Several hot paths now use Map / Set for O(1) id and index lookups instead of repeated linear scans; ComboBox, Dropdown, and MultiSelect benefit most on long lists (especially virtualized lists containing thousands of items).

  • DataTable does less redundant work: virtualized tables avoid re-running scroll setup on every reactive tick, row updates are guarded when the array reference is unchanged, and header-driven cell maps rebuild only when headers change. An unused header-key reactive variable was removed.
  • Dropdown, MultiSelect, and ComboBox use Maps to track items for O(1) lookups for finding items (e.g., highlighting).
  • MultiSelect avoids an extra sort pass when selectionFeedback="top"
  • NumberInput caches Intl.NumberFormat per locale, to avoid computing per keystroke.
  • TreeView drops unused reactive tree-walker setup.

These changes are incremental per interaction but benefit dense UIs and large datasets.


What's Changed

  • feat(combo-box): add openOnClear by @metonym in #2861
  • feat(combo-box): support auto-highlighting the first match by @metonym in #2859
  • feat(combo-box): typeahead supports custom shouldFilterItem by @metonym in #2862
  • feat(data-table): add top-level sort prop by @metonym in #2835
  • feat(data-table): dispatch sort event by @metonym in #2829
  • feat(dropdown): selectedId is optional by @metonym in #2814
  • feat(tag): support large size by @metonym in #2818
  • feat(theme): support rendering as a Dropdown by @metonym in #2815
  • feat(tree-view): support multiselect by @metonym in #2852
  • feat(tree-view): support links by @metonym in #2811
  • feat(ui-shell): support classic theme by @metonym in #2850
  • fix(combo-box): do not auto-select partial match when pressing "Enter" by @metonym in #2847
  • fix(combo-box): do not trap focus when clicking outside element by @metonym in #2846
  • fix(dropdown): button uses combobox role, apply missing ARIA attributes by @metonym in #2840
  • fix(dropdown): do not spread translateWithId to raw button element by @metonym in #2838
  • fix(dropdown): selected item has checkmark icon by @metonym in #2813
  • fix(list-box): add missing "lg" size mapping by @metonym in #2844
  • fix(multi-select): Backspace/Delete should clear selection by @metonym in #2837
  • fix(multi-select): fix typo in size prop description by @metonym in #2845
  • fix(multi-select): invalid/warn, filterable variant should only render one icon by @metonym in #2831
  • fix(multi-select): narrow itemToString return type by @metonym in #2848
  • fix(multi-select): sortItem comparator returns a number, not Item by @metonym in #2830
  • fix(number-input): remove pattern for number type input by @metonym in #2842
  • fix(number-input): text mode should also apply min/max/step attributes to input by @metonym in #2841
  • fix(tree-view): escape node ID when using querySelector for focusing by @metonym in #2843
  • fix(tree-view): expandNodes should expand all by default by @metonym in #2849
  • fix: prevent infinite loop when all items are disabled by @metonym in #2824
  • perf(data-table): avoid virtualized scroll set-up after any reactive update by @metonym in #2822
  • perf(data-table): guard rows assignment with reference check by @metonym in #2826
  • perf(data-table): rebuild tableCellsByRowId for changed headers only by @metonym in #2821
  • perf(data-table): remove unused thKeys computation by @metonym in #2820
  • perf(multi-select): avoid double re-sort for selectionFeedback="top" by @metonym in #2832
  • perf(multi-select): optimize isSelectAll logic by @metonym in #2828
  • perf(number-input): cache Intl.NumberFormat locale usage by @metonym in #2833
  • perf(tree-view): remove unused tree walker reactive initialization by @metonym in #2823
  • perf: use Set/Map for O(1) lookups in hot paths by @metonym in #2825

Full Changelog: v0.105.1...v0.106.0

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

NewReleases is sending notifications on new releases.