展示类

折叠列表

OverflowList 是一个行为组件,用于展示列表,并支持自适应来展示尽可能多的项目。因过长而溢出项目将折叠为一个元素。当检测到调整大小时,可见项将被重新计算。

代码演示

如何引入

<script setup lang="ts">
    import { OverflowList } from '@fibrous/semi-ui-vue';
</script>

折叠模式 - 默认

通过 renderMode="collapse" (默认) 来实现内容的折叠。

items 只放数据,不放节点。每个展示项用 #item="{ item, index }" 插槽渲染;溢出项用 #overflow="{ items, position }" 插槽渲染,collapse 模式只调用一次,items 是放不下的项。

0100


代码
<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 模式下支持 collapseFrom 设置折叠方向。

0100


代码
<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 模式下支持 minVisibleItems 设置最小展示的数目。

0100


代码
<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>

滚动模式

通过 renderMode="scroll" 来使用滚动模式的折叠列表。如果需要 scrollIntoView,可以通过选择器: document.querySelector(`.item-cls[data-scrollkey="${key}"] 来选取。

滚动模式下 #overflow 在两侧各调用一次,position 为 start 或 end,items 是该侧滚出可见区域的项。

0100


+0
alarm
bookmark
camera
duration
edit
folder
+0
代码
<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 参考

Props

属性说明类型默认值
collapseFromcollapse 模式的折叠方向,可选 start 或 end。"start" | "end"semiDefault("OverflowList", "collapseFrom", "end")
items渲染项目,只放数据,不放节点;scroll 模式要求每项含 key。T[]semiGlobalDefault("OverflowList", "items")
itemKey每项 key 的字段名,或取 key 的函数;默认读取 key 字段,没有时取该项在 items 中的位置。TypeOverflowListKey | ((item: T) => OverflowListKey)undefined
minVisibleItemscollapse 模式下最少展示的项数。numbersemiDefault("OverflowList", "minVisibleItems", 0)
overflowRenderDirectionscroll 模式下溢出节点的位置,可选 both、start 或 end;供 Tabs 使用,不面向使用方。"start" | "end" | "both"semiDefault("OverflowList", "overflowRenderDirection", "both")
renderMode渲染模式,可选 collapse 或 scroll。"collapse" | "scroll"semiDefault("OverflowList", "renderMode", "collapse")
thresholdscroll 模式下触发溢出回调的可见比例阈值。numbersemiDefault("OverflowList", "threshold", 0.75)
wrapperClassNamescroll 模式下滚动 wrapper 的类名。stringsemiGlobalDefault("OverflowList", "wrapperClassName")
wrapperPropsscroll 模式下滚动 wrapper 的其他属性,例如承载可见项的 role。Type(HTMLAttributes & Record<string, unknown>)semiGlobalDefault("OverflowList", "wrapperProps")
wrapperStylescroll 模式下滚动 wrapper 的样式。StyleValuesemiGlobalDefault("OverflowList", "wrapperStyle")

Events

事件说明回调参数
overflowcollapse 模式下溢出项变化时触发,全部放得下时参数为空数组。[overflowItems: T[]]
intersectscroll 模式下各项的相交状态变化时触发。Type[res: Record<string, IntersectionObserverEntry>]
visibleStateChangescroll 模式下各项的显示或隐藏状态变化时触发。Type[visibleState: Map<string, boolean>]

Slots

插槽说明作用域参数
item单个展示项的内容,参数为数据项及其在 items 中的位置。TypeOverflowListItemSlotProps<T>
overflow溢出项的内容。collapse 模式调用一次,items 为放不下的项;scroll 模式在两侧各调用一次,position 为 start 或 end,items 为该侧滚出可见区域的项。TypeOverflowListOverflowSlotProps<T>

Exposes

名称说明类型
无

class、style 与 aria-* 等原生属性经 attrs 落在根元素上;滚动 wrapper 的类名、样式和其他属性用 wrapperClassName、wrapperStyle、wrapperProps 传入。

Accessibility

ARIA

  • 传入 aria-label 或 aria-labelledby 时,根元素带 role="group",使这组项目有可读的名称;未传时根元素没有角色