Files
gongxue-base/apps/admin/src/components/BackTop.tsx

42 lines
1.3 KiB
TypeScript

import { useEffect, useState } from 'react';
import { Button, Tooltip } from 'antd';
import { VerticalAlignTopOutlined } from '@ant-design/icons';
import { useEventCallback, useEventListener } from 'usehooks-ts';
/**
* 全局「回到顶部」浮动按钮:长列表滚动超过 400px 后出现。
* 尊重系统「减少动态效果」偏好,平滑滚动仅在未开启该偏好时使用。
*/
export const BackTop: React.FC<{ threshold?: number }> = ({ threshold = 400 }) => {
const [visible, setVisible] = useState(false);
const updateVisible = useEventCallback(() => setVisible(window.scrollY > threshold));
useEffect(() => {
updateVisible();
}, [threshold, updateVisible]);
useEventListener('scroll', updateVisible, undefined, { passive: true });
if (!visible) return null;
const scrollToTop = () => {
const reduceMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
window.scrollTo({ top: 0, behavior: reduceMotion ? 'auto' : 'smooth' });
};
return (
<Tooltip title="回到顶部">
<Button
type="primary"
shape="circle"
icon={<VerticalAlignTopOutlined />}
aria-label="回到顶部"
onClick={scrollToTop}
style={{ position: 'fixed', right: 24, bottom: 48, zIndex: 1000 }}
/>
</Tooltip>
);
};
export default BackTop;