|
|
@@ -0,0 +1,185 @@
|
|
|
+import React from 'react'
|
|
|
+import { View, Text } from '@tarojs/components'
|
|
|
+import { cn } from '@/utils/cn'
|
|
|
+import Taro from '@tarojs/taro'
|
|
|
+
|
|
|
+export interface NavbarProps {
|
|
|
+ title?: string
|
|
|
+ leftText?: string
|
|
|
+ leftIcon?: string
|
|
|
+ rightText?: string
|
|
|
+ rightIcon?: string
|
|
|
+ backgroundColor?: string
|
|
|
+ textColor?: string
|
|
|
+ border?: boolean
|
|
|
+ fixed?: boolean
|
|
|
+ placeholder?: boolean
|
|
|
+ onClickLeft?: () => void
|
|
|
+ onClickRight?: () => void
|
|
|
+ children?: React.ReactNode
|
|
|
+ className?: string
|
|
|
+}
|
|
|
+
|
|
|
+const systemInfo = Taro.getSystemInfoSync()
|
|
|
+const menuButtonInfo = Taro.getMenuButtonBoundingClientRect()
|
|
|
+
|
|
|
+// 计算导航栏高度
|
|
|
+const NAVBAR_HEIGHT = 44
|
|
|
+const STATUS_BAR_HEIGHT = systemInfo.statusBarHeight || 0
|
|
|
+const TOTAL_HEIGHT = STATUS_BAR_HEIGHT + NAVBAR_HEIGHT
|
|
|
+
|
|
|
+export const Navbar: React.FC<NavbarProps> = ({
|
|
|
+ title,
|
|
|
+ leftText,
|
|
|
+ leftIcon = 'i-heroicons-chevron-left-20-solid',
|
|
|
+ rightText,
|
|
|
+ rightIcon,
|
|
|
+ backgroundColor = 'bg-white',
|
|
|
+ textColor = 'text-gray-900',
|
|
|
+ border = true,
|
|
|
+ fixed = true,
|
|
|
+ placeholder = true,
|
|
|
+ onClickLeft,
|
|
|
+ onClickRight,
|
|
|
+ children,
|
|
|
+ className,
|
|
|
+}) => {
|
|
|
+ // 处理左侧点击
|
|
|
+ const handleLeftClick = () => {
|
|
|
+ if (onClickLeft) {
|
|
|
+ onClickLeft()
|
|
|
+ } else {
|
|
|
+ // 默认返回上一页
|
|
|
+ Taro.navigateBack()
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 渲染左侧内容
|
|
|
+ const renderLeft = () => {
|
|
|
+ if (children) return null
|
|
|
+
|
|
|
+ return (
|
|
|
+ <View
|
|
|
+ className="absolute left-3 top-0 bottom-0 flex items-center z-10"
|
|
|
+ style={{ height: NAVBAR_HEIGHT }}
|
|
|
+ onClick={handleLeftClick}
|
|
|
+ >
|
|
|
+ <View className="flex items-center">
|
|
|
+ {leftIcon && (
|
|
|
+ <View className={cn(leftIcon, 'w-5 h-5', textColor)} />
|
|
|
+ )}
|
|
|
+ {leftText && (
|
|
|
+ <Text className={cn('ml-1 text-sm', textColor)}>{leftText}</Text>
|
|
|
+ )}
|
|
|
+ </View>
|
|
|
+ </View>
|
|
|
+ )
|
|
|
+ }
|
|
|
+
|
|
|
+ // 渲染右侧内容
|
|
|
+ const renderRight = () => {
|
|
|
+ if (!rightText && !rightIcon) return null
|
|
|
+
|
|
|
+ return (
|
|
|
+ <View
|
|
|
+ className="absolute right-3 top-0 bottom-0 flex items-center z-10"
|
|
|
+ style={{ height: NAVBAR_HEIGHT }}
|
|
|
+ onClick={onClickRight}
|
|
|
+ >
|
|
|
+ <View className="flex items-center">
|
|
|
+ {rightText && (
|
|
|
+ <Text className={cn('mr-1 text-sm', textColor)}>{rightText}</Text>
|
|
|
+ )}
|
|
|
+ {rightIcon && (
|
|
|
+ <View className={cn(rightIcon, 'w-5 h-5', textColor)} />
|
|
|
+ )}
|
|
|
+ </View>
|
|
|
+ </View>
|
|
|
+ )
|
|
|
+ }
|
|
|
+
|
|
|
+ // 渲染标题
|
|
|
+ const renderTitle = () => {
|
|
|
+ if (children) return children
|
|
|
+
|
|
|
+ return (
|
|
|
+ <Text className={cn('text-base font-semibold', textColor)}>
|
|
|
+ {title}
|
|
|
+ </Text>
|
|
|
+ )
|
|
|
+ }
|
|
|
+
|
|
|
+ // 导航栏样式
|
|
|
+ const navbarStyle = {
|
|
|
+ height: TOTAL_HEIGHT,
|
|
|
+ paddingTop: STATUS_BAR_HEIGHT,
|
|
|
+ }
|
|
|
+
|
|
|
+ return (
|
|
|
+ <>
|
|
|
+ <View
|
|
|
+ className={cn(
|
|
|
+ 'relative w-full',
|
|
|
+ backgroundColor,
|
|
|
+ border && 'border-b border-gray-200',
|
|
|
+ fixed && 'fixed top-0 left-0 right-0 z-50',
|
|
|
+ className
|
|
|
+ )}
|
|
|
+ style={navbarStyle}
|
|
|
+ >
|
|
|
+ {/* 导航栏内容 */}
|
|
|
+ <View
|
|
|
+ className="relative flex items-center justify-center"
|
|
|
+ style={{ height: NAVBAR_HEIGHT }}
|
|
|
+ >
|
|
|
+ {renderLeft()}
|
|
|
+ {renderTitle()}
|
|
|
+ {renderRight()}
|
|
|
+ </View>
|
|
|
+ </View>
|
|
|
+
|
|
|
+ {/* 占位元素 */}
|
|
|
+ {fixed && placeholder && (
|
|
|
+ <View style={{ height: TOTAL_HEIGHT }} />
|
|
|
+ )}
|
|
|
+ </>
|
|
|
+ )
|
|
|
+}
|
|
|
+
|
|
|
+// 预设样式
|
|
|
+export const NavbarPresets = {
|
|
|
+ // 默认白色导航栏
|
|
|
+ default: {
|
|
|
+ backgroundColor: 'bg-white',
|
|
|
+ textColor: 'text-gray-900',
|
|
|
+ border: true,
|
|
|
+ },
|
|
|
+
|
|
|
+ // 深色导航栏
|
|
|
+ dark: {
|
|
|
+ backgroundColor: 'bg-gray-900',
|
|
|
+ textColor: 'text-white',
|
|
|
+ border: true,
|
|
|
+ },
|
|
|
+
|
|
|
+ // 透明导航栏
|
|
|
+ transparent: {
|
|
|
+ backgroundColor: 'bg-transparent',
|
|
|
+ textColor: 'text-white',
|
|
|
+ border: false,
|
|
|
+ },
|
|
|
+
|
|
|
+ // 主色调导航栏
|
|
|
+ primary: {
|
|
|
+ backgroundColor: 'bg-blue-500',
|
|
|
+ textColor: 'text-white',
|
|
|
+ border: false,
|
|
|
+ },
|
|
|
+}
|
|
|
+
|
|
|
+// 快捷创建函数
|
|
|
+export const createNavbar = (preset: keyof typeof NavbarPresets) => {
|
|
|
+ return NavbarPresets[preset]
|
|
|
+}
|
|
|
+
|
|
|
+export default Navbar
|