Demos
How to import
<script setup lang="ts">
import { OverflowList } from '@fibrous/semi-ui-vue';
</script>
Collapse Mode - Simple
You could use renderMode="collapse" (default) to render items.
items holds data only, never nodes. Render each visible item with the #item="{ item, index }" slot and the overflowing items with the #overflow="{ items, position }" slot; in collapse mode it is called once, and items are the items that do not fit.
Code
<script setup lang="ts">
import { ref, type Component } from 'vue';
import { IconAlarm, IconBookmark, IconCamera, IconDuration, IconEdit, IconFolder } from '@fibrous/semi-icons-vue';
import { OverflowList, Slider, Tag } from '@fibrous/semi-ui-vue';
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 }));
const width = ref(100);
const changeWidth = (value: number | number[]) => {
if (typeof value === 'number') width.value = value;
};
</script>
<template>
<div>
<Slider aria-label="Container width" :modelValue="width" :step="1" @update:modelValue="changeWidth" />
<br />
<br />
<div :style="{ width: `${width}%` }">
<OverflowList :items="items">
<template #item="{ item }">
<Tag color="blue" :style="{ marginRight: '8px', flex: '0 0 auto' }">
<component :is="icons[item.key]" :style="{ marginRight: '4px' }" />
<span>{{ item.key }}</span>
</Tag>
</template>
<template #overflow="{ items: hidden }">
<Tag v-if="hidden.length" :style="{ flex: '0 0 auto', fontVariantNumeric: 'tabular-nums' }"> +{{ hidden.length }} </Tag>
</template>
</OverflowList>
</div>
</div>
</template>Collapse Mode - Direction
collapse mode supports two collapseFrom directions: start and end (default).
Code
<script setup lang="ts">
import { ref, type Component } from 'vue';
import { IconAlarm, IconBookmark, IconCamera, IconDuration, IconEdit, IconFolder } from '@fibrous/semi-icons-vue';
import { OverflowList, Slider, Tag } from '@fibrous/semi-ui-vue';
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 }));
const width = ref(100);
const changeWidth = (value: number | number[]) => {
if (typeof value === 'number') width.value = value;
};
</script>
<template>
<div>
<Slider aria-label="Container width" :modelValue="width" :step="1" @update:modelValue="changeWidth" />
<br />
<br />
<div :style="{ width: `${width}%` }">
<OverflowList collapseFrom="start" :items="items">
<template #item="{ item }">
<Tag color="blue" :style="{ marginRight: '8px', flex: '0 0 auto' }">
<component :is="icons[item.key]" :style="{ marginRight: '4px' }" />
<span>{{ item.key }}</span>
</Tag>
</template>
<template #overflow="{ items: hidden }">
<Tag v-if="hidden.length" :style="{ marginRight: '8px', flex: '0 0 auto', fontVariantNumeric: 'tabular-nums' }"> +{{ hidden.length }} </Tag>
</template>
</OverflowList>
</div>
</div>
</template>Collapse Mode - Visible
collapse mode supports to set up minimum visible items that will not be collected.
Code
<script setup lang="ts">
import { ref, type Component } from 'vue';
import { IconAlarm, IconBookmark, IconCamera, IconDuration, IconEdit, IconFolder } from '@fibrous/semi-icons-vue';
import { OverflowList, Slider, Tag } from '@fibrous/semi-ui-vue';
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 }));
const width = ref(100);
const changeWidth = (value: number | number[]) => {
if (typeof value === 'number') width.value = value;
};
</script>
<template>
<div>
<Slider aria-label="Container width" :modelValue="width" :step="1" @update:modelValue="changeWidth" />
<br />
<br />
<div :style="{ width: `${width}%` }">
<OverflowList :items="items" :minVisibleItems="3">
<template #item="{ item }">
<Tag color="blue" :style="{ marginRight: '8px', flex: '0 0 auto' }">
<component :is="icons[item.key]" :style="{ marginRight: '4px' }" />
<span>{{ item.key }}</span>
</Tag>
</template>
<template #overflow="{ items: hidden }">
<Tag v-if="hidden.length" :style="{ flex: '0 0 auto', fontVariantNumeric: 'tabular-nums' }"> +{{ hidden.length }} </Tag>
</template>
</OverflowList>
</div>
</div>
</template>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 called once per side, with position set to start or end and items being the items scrolled out on that side.
Code
<script setup lang="ts">
import { ref, type Component } from 'vue';
import { IconAlarm, IconBookmark, IconCamera, IconDuration, IconEdit, IconFolder } from '@fibrous/semi-icons-vue';
import { OverflowList, Slider, Tag } from '@fibrous/semi-ui-vue';
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 }));
const width = ref(100);
const changeWidth = (value: number | number[]) => {
if (typeof value === 'number') width.value = value;
};
</script>
<template>
<div>
<Slider aria-label="Container width" :modelValue="width" :step="1" @update:modelValue="changeWidth" />
<br />
<br />
<div :style="{ width: `${width}%` }">
<OverflowList :items="items" renderMode="scroll">
<template #item="{ item }">
<Tag color="blue" :style="{ marginRight: '8px', flex: '0 0 auto' }">
<component :is="icons[item.key]" :style="{ marginRight: '4px' }" />
<span>{{ item.key }}</span>
</Tag>
</template>
<template #overflow="{ items: hidden }">
<Tag
:style="{
marginRight: '8px',
marginLeft: '8px',
flex: '0 0 auto',
fontVariantNumeric: 'tabular-nums',
}"
>
+{{ hidden.length }}
</Tag>
</template>
</OverflowList>
</div>
</div>
</template>API Reference
Props
| Property | Description | Type | Default |
|---|---|---|---|
| collapseFrom | Collapse direction in collapse mode: start or end. | "start" | "end" | semiDefault("OverflowList", "collapseFrom", "end") |
| items | The items to render. They are data, not nodes; scroll mode requires a key on each item. | T[] | semiGlobalDefault("OverflowList", "items") |
| 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) | undefined |
| minVisibleItems | Minimum number of visible items in collapse mode. | number | semiDefault("OverflowList", "minVisibleItems", 0) |
| overflowRenderDirection | Where scroll mode renders the overflow nodes: both, start or end. Used by Tabs, not meant for end users. | "start" | "end" | "both" | semiDefault("OverflowList", "overflowRenderDirection", "both") |
| renderMode | Render mode: collapse or scroll. | "collapse" | "scroll" | semiDefault("OverflowList", "renderMode", "collapse") |
| threshold | Visible ratio at which scroll mode reports an item as overflowing. | number | semiDefault("OverflowList", "threshold", 0.75) |
| wrapperClassName | Class name of the scroll wrapper in scroll mode. | string | semiGlobalDefault("OverflowList", "wrapperClassName") |
| wrapperProps | Other attributes of the scroll wrapper in scroll mode, such as a role that owns the visible items. | Type(HTMLAttributes & Record<string, unknown>) | semiGlobalDefault("OverflowList", "wrapperProps") |
| wrapperStyle | Style of the scroll wrapper in scroll mode. | StyleValue | semiGlobalDefault("OverflowList", "wrapperStyle") |
Events
| Event | Description | Callback parameters |
|---|---|---|
| overflow | Emitted in collapse mode when the overflowing items change; the argument is an empty array when everything fits. | [overflowItems: T[]] |
| intersect | Emitted in scroll mode when the intersection state of the items changes. | Type[res: Record<string, IntersectionObserverEntry>] |
| visibleStateChange | Emitted in scroll mode when the visible or hidden state of the items changes. | Type[visibleState: Map<string, boolean>] |
Slots
| Slot | Description | Scope parameters |
|---|---|---|
| item | Content of one visible item, with the item and its position in items. | TypeOverflowListItemSlotProps<T> |
| overflow | Content for the overflowing items. Collapse mode calls it once with the items that do not fit; scroll mode calls it once per side, with position set to start or end and the items scrolled out on that side. | TypeOverflowListOverflowSlotProps<T> |
Exposes
| Name | Description | Type |
|---|---|---|
| None |
class, style and native attributes such as aria-* land on the root element through attrs; pass the scroll wrapper's class, style and other attributes 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