代码演示
如何引入
import { OverflowList } from '@fibrous/semi-ui-react';
折叠模式 - 默认
通过 renderMode="collapse" (默认) 来实现内容的折叠。
代码
import { useState, type ReactNode } from 'react';
import { IconAlarm, IconBookmark, IconCamera, IconDuration, IconEdit, IconFolder } from '@fibrous/semi-icons-react';
import { OverflowList, Tag, Slider } from '@fibrous/semi-ui-react';
interface Item {
icon: ReactNode;
key: string;
}
export default function OverflowListDemo() {
const [width, setWidth] = useState(100);
const renderOverflow = (items: Item[]) => {
return items.length ? <Tag style={{ flex: '0 0 auto', fontVariantNumeric: 'tabular-nums' }}>+{items.length}</Tag> : null;
};
const renderItem = (item: Item) => {
return (
<Tag color="blue" key={item.key} style={{ marginRight: 8, flex: '0 0 auto' }}>
{item.icon}
{item.key}
</Tag>
);
};
const items: Item[] = [
{ icon: <IconAlarm style={{ marginRight: 4 }} />, key: 'alarm' },
{ icon: <IconBookmark style={{ marginRight: 4 }} />, key: 'bookmark' },
{ icon: <IconCamera style={{ marginRight: 4 }} />, key: 'camera' },
{ icon: <IconDuration style={{ marginRight: 4 }} />, key: 'duration' },
{ icon: <IconEdit style={{ marginRight: 4 }} />, key: 'edit' },
{ icon: <IconFolder style={{ marginRight: 4 }} />, key: 'folder' },
];
return (
<div>
<Slider aria-label="Container width" step={1} value={width} onChange={(value) => typeof value === 'number' && setWidth(value)} />
<br />
<br />
<div style={{ width: `${width}%` }}>
<OverflowList items={items} overflowRenderer={renderOverflow} visibleItemRenderer={renderItem} />
</div>
</div>
);
}折叠模式 - 方向
collapse 模式下支持 collapseFrom 设置折叠方向。
代码
import { useState, type ReactNode } from 'react';
import { IconAlarm, IconBookmark, IconCamera, IconDuration, IconEdit, IconFolder } from '@fibrous/semi-icons-react';
import { OverflowList, Tag, Slider } from '@fibrous/semi-ui-react';
interface Item {
icon: ReactNode;
key: string;
}
export default function OverflowListDemo() {
const [width, setWidth] = useState(100);
const renderOverflow = (items: Item[]) => {
return items.length ? <Tag style={{ marginRight: 8, flex: '0 0 auto', fontVariantNumeric: 'tabular-nums' }}>+{items.length}</Tag> : null;
};
const renderItem = (item: Item) => {
return (
<Tag color="blue" key={item.key} style={{ marginRight: 8, flex: '0 0 auto' }}>
{item.icon}
{item.key}
</Tag>
);
};
const items: Item[] = [
{ icon: <IconAlarm style={{ marginRight: 4 }} />, key: 'alarm' },
{ icon: <IconBookmark style={{ marginRight: 4 }} />, key: 'bookmark' },
{ icon: <IconCamera style={{ marginRight: 4 }} />, key: 'camera' },
{ icon: <IconDuration style={{ marginRight: 4 }} />, key: 'duration' },
{ icon: <IconEdit style={{ marginRight: 4 }} />, key: 'edit' },
{ icon: <IconFolder style={{ marginRight: 4 }} />, key: 'folder' },
];
return (
<div>
<Slider aria-label="Container width" step={1} value={width} onChange={(value) => typeof value === 'number' && setWidth(value)} />
<br />
<br />
<div style={{ width: `${width}%` }}>
<OverflowList items={items} collapseFrom="start" overflowRenderer={renderOverflow} visibleItemRenderer={renderItem} />
</div>
</div>
);
}折叠模式 - 最小展示的数目
collapse 模式下支持 minVisibleItems 设置最小展示的数目。
代码
import { useState, type ReactNode } from 'react';
import { IconAlarm, IconBookmark, IconCamera, IconDuration, IconEdit, IconFolder } from '@fibrous/semi-icons-react';
import { OverflowList, Tag, Slider } from '@fibrous/semi-ui-react';
interface Item {
icon: ReactNode;
key: string;
}
export default function OverflowListDemo() {
const [width, setWidth] = useState(100);
const renderOverflow = (items: Item[]) => {
return items.length ? <Tag style={{ flex: '0 0 auto', fontVariantNumeric: 'tabular-nums' }}>+{items.length}</Tag> : null;
};
const renderItem = (item: Item) => {
return (
<Tag color="blue" key={item.key} style={{ marginRight: 8, flex: '0 0 auto' }}>
{item.icon}
{item.key}
</Tag>
);
};
const items: Item[] = [
{ icon: <IconAlarm style={{ marginRight: 4 }} />, key: 'alarm' },
{ icon: <IconBookmark style={{ marginRight: 4 }} />, key: 'bookmark' },
{ icon: <IconCamera style={{ marginRight: 4 }} />, key: 'camera' },
{ icon: <IconDuration style={{ marginRight: 4 }} />, key: 'duration' },
{ icon: <IconEdit style={{ marginRight: 4 }} />, key: 'edit' },
{ icon: <IconFolder style={{ marginRight: 4 }} />, key: 'folder' },
];
return (
<div>
<Slider aria-label="Container width" step={1} value={width} onChange={(value) => typeof value === 'number' && setWidth(value)} />
<br />
<br />
<div style={{ width: `${width}%` }}>
<OverflowList items={items} minVisibleItems={3} overflowRenderer={renderOverflow} visibleItemRenderer={renderItem} />
</div>
</div>
);
}滚动模式
通过 renderMode="scroll" 来使用滚动模式的折叠列表。如果需要 scrollIntoView,可以通过选择器: document.querySelector(`.item-cls[data-scrollkey="${key}"] 来选取。
+0
alarm
bookmark
camera
duration
edit
folder
+0
代码
import { useState, type ReactNode } from 'react';
import { IconAlarm, IconBookmark, IconCamera, IconDuration, IconEdit, IconFolder } from '@fibrous/semi-icons-react';
import { OverflowList, Tag, Slider } from '@fibrous/semi-ui-react';
interface Item {
icon: ReactNode;
key: string;
}
export default function OverflowListDemo() {
const [width, setWidth] = useState(100);
const renderHiddenCount = (hiddenItems: Item[]) => <Tag style={{ marginRight: 8, marginLeft: 8, flex: '0 0 auto', fontVariantNumeric: 'tabular-nums' }}>+{hiddenItems.length}</Tag>;
const renderOverflow = ([start, end]: [Item[], Item[]]): [ReactNode, ReactNode] => [renderHiddenCount(start), renderHiddenCount(end)];
const renderItem = (item: Item) => {
return (
<Tag key={item.key} color="blue" style={{ marginRight: 8, flex: '0 0 auto' }}>
{item.icon}
{item.key}
</Tag>
);
};
const items: Item[] = [
{ icon: <IconAlarm style={{ marginRight: 4 }} />, key: 'alarm' },
{ icon: <IconBookmark style={{ marginRight: 4 }} />, key: 'bookmark' },
{ icon: <IconCamera style={{ marginRight: 4 }} />, key: 'camera' },
{ icon: <IconDuration style={{ marginRight: 4 }} />, key: 'duration' },
{ icon: <IconEdit style={{ marginRight: 4 }} />, key: 'edit' },
{ icon: <IconFolder style={{ marginRight: 4 }} />, key: 'folder' },
];
return (
<div>
<Slider aria-label="Container width" step={1} value={width} onChange={(value) => typeof value === 'number' && setWidth(value)} />
<br />
<br />
<div style={{ width: `${width}%` }}>
<OverflowList items={items} renderMode="scroll" overflowRenderer={renderOverflow} visibleItemRenderer={renderItem} />
</div>
</div>
);
}API 参考
Props
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| className | 根元素的类名。 | string | - |
| collapseFrom | collapse 模式的折叠方向,可选 start 或 end。 | 'start' | 'end' | "end" |
| itemKey | 每项 key 的字段名,或取 key 的函数;默认读取 key 字段,没有时取该项在 items 中的位置。 | Typestring | number | ((item: T) => string | number) | - |
| items | 渲染项目,只放数据,不放节点,节点由 visibleItemRenderer 渲染;scroll 模式要求每项含 key 字段(或由 itemKey 指定的字段)。 | TypeArray<T> | [] |
| minVisibleItems | collapse 模式下最少展示的项数,这些项即使放不下也不会折叠。 | number | 0 |
| onIntersect | scroll 模式下各项的相交状态变化时调用,参数以 key 为索引,值为对应项的 IntersectionObserverEntry。 | Type(res: { [key: string]: IntersectionObserverEntry }) => void | - |
| onOverflow | collapse 模式下溢出项变化时调用,全部放得下时以空数组调用。 | Type(overflowItems: Array<T>) => void | Type() => null |
| onVisibleStateChange | scroll 模式下各项的显示或隐藏状态变化时调用,参数为以 key 为索引的 Map。 | Type(visibleState: Map<string, boolean>) => void | - |
| overflowRenderDirection | scroll 模式下两侧溢出节点的位置,可选 both、start 或 end;供 Tabs 使用,不面向使用方。 | 'both' | 'start' | 'end' | "both" |
| overflowRenderer | 渲染溢出项。collapse 模式下参数为放不下的项,返回一个溢出节点;scroll 模式下参数为 [start, end] 两组项,返回两侧各一个节点。 | Type((overflowItems: Array<T>) => ReactNode) | ((overflowItems: [Array<T>, Array<T>]) => [ReactNode, ReactNode]) | Type(): ReactElement => null |
| ref | 根元素的引用。 | TypeReact.Ref<HTMLDivElement> | - |
| renderMode | 渲染模式,可选 collapse 或 scroll。 | 'collapse' | 'scroll' | "collapse" |
| style | 根元素的样式。 | CSSProperties | - |
| threshold | scroll 模式下触发相交回调的可见比例阈值。 | number | 0.75 |
| visibleItemRenderer | 渲染单个可见项并返回该项的 React 元素,参数 index 为该项在 items 中的位置。scroll 模式下该元素会被观察,并写入 data-scrollkey。 | Type(item: T, index: number) => ReactElement | Type(): ReactElement => null |
| wrapperClassName | scroll 模式下滚动 wrapper 的类名。 | string | - |
| wrapperProps | scroll 模式下滚动 wrapper 的其他属性,例如承载可见项的 role;其中的 className 与 style 会被 wrapperClassName、wrapperStyle 覆盖。 | TypeHTMLAttributes<HTMLDivElement> | - |
| wrapperStyle | scroll 模式下滚动 wrapper 的样式,传入样式对象。 | CSSProperties | - |
其他原生属性(如 aria-*、id、data-*、onClick)落在根元素上。
Accessibility
ARIA
- 传入
aria-label或aria-labelledby时,根元素带role="group",使这组项目有可读的名称;未传时根元素没有角色