Demos
How to import
<script lang="ts">
import { OverflowList } from '@fibrae/semi-ui-svelte';
</script>
Collapse Mode - Simple
You could use renderMode="collapse" (default) to render items.
items holds data, not nodes. Each visible item is rendered by the item snippet, with the parameter { item, index }. The overflowing items are rendered by the overflow snippet, with the parameter { items, position }; collapse mode renders it once, only when there are overflowing items, and items are the ones that do not fit.
Code
<script lang="ts">
import type { Component } from 'svelte';
import { IconAlarm, IconBookmark, IconCamera, IconDuration, IconEdit, IconFolder } from '@fibrae/semi-icons-svelte';
import { OverflowList, Slider, Tag } from '@fibrae/semi-ui-svelte';
interface Item {
key: string;
}
const icons: Record<string, Component> = {
alarm: IconAlarm,
bookmark: IconBookmark,
camera: IconCamera,
duration: IconDuration,
edit: IconEdit,
folder: IconFolder,
};
const items: Item[] = Object.keys(icons).map((key) => ({ key }));
let width = $state<number | number[]>(100);
</script>
<div>
<Slider aria-label="Container width" bind:value={width} step={1} />
<br />
<br />
<div style="width: {width}%">
<OverflowList {items}>
{#snippet item({ item })}
{@const Icon = icons[item.key]}
<Tag color="blue" style="margin-right: 8px; flex: 0 0 auto">
<Icon style="margin-right: 4px" />
<span>{item.key}</span>
</Tag>
{/snippet}
{#snippet overflow({ items: hidden })}
{#if hidden.length}
<Tag style="flex: 0 0 auto; font-variant-numeric: tabular-nums">+{hidden.length}</Tag>
{/if}
{/snippet}
</OverflowList>
</div>
</div>Collapse Mode - Direction
collapse mode supports two collapseFrom directions: start and end (default).
Code
<script lang="ts">
import type { Component } from 'svelte';
import { IconAlarm, IconBookmark, IconCamera, IconDuration, IconEdit, IconFolder } from '@fibrae/semi-icons-svelte';
import { OverflowList, Slider, Tag } from '@fibrae/semi-ui-svelte';
interface Item {
key: string;
}
const icons: Record<string, Component> = {
alarm: IconAlarm,
bookmark: IconBookmark,
camera: IconCamera,
duration: IconDuration,
edit: IconEdit,
folder: IconFolder,
};
const items: Item[] = Object.keys(icons).map((key) => ({ key }));
let width = $state<number | number[]>(100);
</script>
<div>
<Slider aria-label="Container width" bind:value={width} step={1} />
<br />
<br />
<div style="width: {width}%">
<OverflowList collapseFrom="start" {items}>
{#snippet item({ item })}
{@const Icon = icons[item.key]}
<Tag color="blue" style="margin-right: 8px; flex: 0 0 auto">
<Icon style="margin-right: 4px" />
<span>{item.key}</span>
</Tag>
{/snippet}
{#snippet overflow({ items: hidden })}
{#if hidden.length}
<Tag style="margin-right: 8px; flex: 0 0 auto; font-variant-numeric: tabular-nums">+{hidden.length}</Tag>
{/if}
{/snippet}
</OverflowList>
</div>
</div>Collapse Mode - Visible
collapse mode supports to set up minimum visible items that will not be collected.
Code
<script lang="ts">
import type { Component } from 'svelte';
import { IconAlarm, IconBookmark, IconCamera, IconDuration, IconEdit, IconFolder } from '@fibrae/semi-icons-svelte';
import { OverflowList, Slider, Tag } from '@fibrae/semi-ui-svelte';
interface Item {
key: string;
}
const icons: Record<string, Component> = {
alarm: IconAlarm,
bookmark: IconBookmark,
camera: IconCamera,
duration: IconDuration,
edit: IconEdit,
folder: IconFolder,
};
const items: Item[] = Object.keys(icons).map((key) => ({ key }));
let width = $state<number | number[]>(100);
</script>
<div>
<Slider aria-label="Container width" bind:value={width} step={1} />
<br />
<br />
<div style="width: {width}%">
<OverflowList {items} minVisibleItems={3}>
{#snippet item({ item })}
{@const Icon = icons[item.key]}
<Tag color="blue" style="margin-right: 8px; flex: 0 0 auto">
<Icon style="margin-right: 4px" />
<span>{item.key}</span>
</Tag>
{/snippet}
{#snippet overflow({ items: hidden })}
{#if hidden.length}
<Tag style="flex: 0 0 auto; font-variant-numeric: tabular-nums">+{hidden.length}</Tag>
{/if}
{/snippet}
</OverflowList>
</div>
</div>Scroll Mode
You could use renderMode="scroll" for a scrollable list.
If you need certain element in the list to scrollIntoView, use document.querySelector(`.item-cls[data-scrollkey="${key}"] to select to corresponding DOM.
In scroll mode overflow is rendered once per side, with position set to start or end and items the items scrolled out on that side. Each item is wrapped in a display: contents span, and data-scrollkey is written on, and observed from, the first element the item snippet renders, so item must output an element or the item is skipped.
Code
<script lang="ts">
import type { Component } from 'svelte';
import { IconAlarm, IconBookmark, IconCamera, IconDuration, IconEdit, IconFolder } from '@fibrae/semi-icons-svelte';
import { OverflowList, Slider, Tag } from '@fibrae/semi-ui-svelte';
interface Item {
key: string;
}
const icons: Record<string, Component> = {
alarm: IconAlarm,
bookmark: IconBookmark,
camera: IconCamera,
duration: IconDuration,
edit: IconEdit,
folder: IconFolder,
};
const items: Item[] = Object.keys(icons).map((key) => ({ key }));
let width = $state<number | number[]>(100);
</script>
<div>
<Slider aria-label="Container width" bind:value={width} step={1} />
<br />
<br />
<div style="width: {width}%">
<OverflowList {items} renderMode="scroll">
{#snippet item({ item })}
{@const Icon = icons[item.key]}
<Tag color="blue" style="margin-right: 8px; flex: 0 0 auto">
<Icon style="margin-right: 4px" />
<span>{item.key}</span>
</Tag>
{/snippet}
{#snippet overflow({ items: hidden })}
<Tag style="margin-right: 8px; margin-left: 8px; flex: 0 0 auto; font-variant-numeric: tabular-nums">+{hidden.length}</Tag>
{/snippet}
</OverflowList>
</div>
</div>API Reference
Props
| Property | Description | Type | Default |
|---|---|---|---|
| collapseFrom | Collapse direction in collapse mode: start or end. | 'start' | 'end' | "end" |
| item | Snippet for the content of one visible item, with the parameter { item, index }: the item and its position in items. Scroll mode needs the snippet to render an element, otherwise the item is skipped. | TypeSnippet<[OverflowListItemSnippetProps<T>]> | - |
| itemKey | Property name of each item's key, or a function returning it. Defaults to the key property, then the item's position in items. | TypeOverflowListKey | ((item: T) => OverflowListKey) | - |
| items | The items to render. They are data, not nodes; scroll mode requires a key on each item. | T[] | - |
| minVisibleItems | Minimum number of visible items in collapse mode. | number | 0 |
| onIntersect | Called in scroll mode when the intersection state of the items changes. | Type(res: Record<string, IntersectionObserverEntry>) => void | - |
| onOverflow | Called in collapse mode when the overflowing items change; the argument is an empty array when everything fits. | Type(overflowItems: T[]) => void | - |
| onVisibleStateChange | Called in scroll mode when the visible or hidden state of the items changes. | Type(visibleState: Map<string, boolean>) => void | - |
| overflow | Snippet for the overflowing items, with the parameter { items, position }. Collapse mode renders it once, only when there are overflowing items, with the items that do not fit; scroll mode renders it once per side, with position set to start or end and the items scrolled out on that side. | TypeSnippet<[OverflowListOverflowSnippetProps<T>]> | - |
| overflowRenderDirection | Where scroll mode renders the overflow nodes: both, start or end. Used by Tabs, not meant for end users. | 'both' | 'start' | 'end' | "both" |
| renderMode | Render mode: collapse or scroll. | 'collapse' | 'scroll' | "collapse" |
| threshold | Visible ratio at which scroll mode reports an item as overflowing. | number | 0.75 |
| wrapperClassName | Class name of the scroll wrapper in scroll mode. | string | - |
| wrapperProps | Other attributes of the scroll wrapper in scroll mode, such as a role that owns the visible items. | TypeHTMLAttributes<HTMLDivElement> | - |
| wrapperStyle | Style string of the scroll wrapper in scroll mode. | string | - |
class, style (a string) and native attributes such as aria-* land on the root element; pass the class, style and other attributes of the scroll wrapper with wrapperClassName, wrapperStyle and wrapperProps.
Accessibility
ARIA
- When
aria-labeloraria-labelledbyis passed, the root element getsrole="group"so the group of items has a readable name; without them the root has no role