packages/bui-core/src/NavBar/NavBar.tsx (80 lines of code) (raw):
import React from 'react';
import clsx from 'clsx';
import { useForkRef, useSize } from '@bifrostui/utils';
import { ArrowBackwardLargeIcon } from '@bifrostui/icons';
import { NavBarProps } from './NavBar.types';
import './NavBar.less';
const prefixCls = 'bui-navbar';
const NavBar = React.forwardRef<HTMLDivElement, NavBarProps>((props, ref) => {
const {
className,
title,
left,
leftIcon,
IconProps,
right,
fixed,
placeholder,
onClickLeft,
...otherProps
} = props;
// 计算内容区域高度,用来形成占位区域
const containerRef = React.useRef(null);
const handleForkRef = useForkRef(ref, containerRef);
const { height } = useSize(containerRef);
// 渲染左侧内容
const renderLeft = () => {
let icon: React.ReactNode;
if (leftIcon === false) {
icon = null;
} else {
icon = leftIcon ?? (
<ArrowBackwardLargeIcon
className={clsx(`${prefixCls}-icon`)}
{...IconProps}
/>
);
}
return (
<div className={`${prefixCls}-left`} onClick={onClickLeft}>
{icon}
{left}
</div>
);
};
// 渲染右侧内容
const renderRight = () => {
return <div className={`${prefixCls}-right`}>{right}</div>;
};
// 渲染导航栏
const renderNavBar = () => {
return (
<div
ref={handleForkRef}
className={clsx(className, prefixCls, {
[`${prefixCls}-fixed`]: fixed,
})}
{...otherProps}
>
{renderLeft()}
<div className={clsx(`${prefixCls}-title`, 'ellipsis')}>{title}</div>
{renderRight()}
</div>
);
};
// 渲染占位块
const renderPlaceholder = () => {
if (fixed && placeholder) {
return (
<div
className={`${prefixCls}-placeholder`}
style={{ height: height ?? 0 }}
/>
);
}
return null;
};
return (
<>
{/* 内容区域 */}
{renderNavBar()}
{/* 占位区域 */}
{renderPlaceholder()}
</>
);
});
NavBar.displayName = 'BuiNavBar';
NavBar.defaultProps = {};
export default NavBar;