first commit

This commit is contained in:
2026-03-31 10:02:03 +08:00
commit 9cd3564443
21 changed files with 7617 additions and 0 deletions
+70
View File
@@ -0,0 +1,70 @@
.height_40 {
height: 40px;
}
.height_40_center {
height: 40px;
line-height: 40px;
}
.display_inline_block {
display: inline-block;
}
.text_center {
text-align: center;
}
.width_300 {
width: 300px;
}
.width_400 {
width: 400px;
}
.margin_3_0 {
margin: 3px 0;
}
.margin_10_20 {
margin: 10px 20px;
}
.margin_10_0 {
margin: 10px 0;
}
.margin_0_20 {
margin: 0 20px;
}
.margin_0_10 {
margin: 0 10px;
}
.margin_10_10 {
margin: 10px;
}
.margin_20_10 {
margin: 20px 10px;
}
.margin_0_5 {
margin: 0 5px;
}
.width_600 {
width: 600px;
}
.margin_left_600 {
margin-left: 600px;
}
.right-align-container {
margin-left: auto;
display: flex;
align-items: center;
}
+148
View File
@@ -0,0 +1,148 @@
// import { useState } from 'react'
import './App.css'
import { HomeOutlined, SettingOutlined, ApiOutlined, FolderOutlined, ClearOutlined, UserOutlined, CommentOutlined, AlertOutlined, UploadOutlined } from '@ant-design/icons';
import type { MenuProps } from 'antd';
import { Menu } from 'antd';
import React, { useState } from 'react';
import { Input, Avatar } from 'antd';
import { SearchOutlined } from '@ant-design/icons';
const items: MenuProps['items'] = [
{
label: '主页',
key: 'home',
icon: <HomeOutlined />,
},
{
label: '工具大全',
key: 'tools',
icon: <ApiOutlined />,
},
{
label: '文章资源',
key: 'articles',
icon: <FolderOutlined />,
},
{
label: '消息',
key: 'xx',
icon: <CommentOutlined />,
children:[
{
label: '回复我的',
key: 'xx1',
},
{
label: '@我的',
key: 'xx2',
},
{
label: '收到的赞',
key: 'xx3',
},
{
label: '系统消息',
key: 'xx4',
},
{
label: '我的消息',
key: 'xx5',
}
]
},
{
label: 'bug反馈',
key: 'bug',
icon: <AlertOutlined />,
},
{
label: (<Input
placeholder="请输入搜索内容"
className='width_600 height_40 margin_3_0 margin_left_600'
prefix={<SearchOutlined />}
/>),
key: 'search',
disabled: true,
className: "right-align-container",
},
{
label: (<span className='margin_0_20' >
<Avatar size={40} icon={<UserOutlined />} className='margin_3_0'/>
<span className='height_40_center display_inline_block margin_0_10' >
用户: 10086
</span>
</span>),
key: 'home',
children: [
{
className: "width_300",
type: 'group',
label: (
<div className='height_40_center text_center'>用户10086</div>
),
children: [
{
label: '个人中心',
key: 'setting:1',
icon: <UserOutlined />
},
{
label: '个人设置',
key: 'setting:2',
icon: <SettingOutlined />,
},
{
label: '浏览历史',
key: 'setting:2',
icon: <ClearOutlined />
},
{
label: (
<div style={{
borderBottom: "1px #eee solid",
height:"20px"
}}></div>
),
disabled: true,
key: 'divider',
},
{
label: '退出登录',
key: 'setting:3',
icon: <UploadOutlined />
}
],
}
],
className: "right-align-container",
},
];
const App: React.FC = () => {
const [current, setCurrent] = useState('mail');
const onClick: MenuProps['onClick'] = e => {
console.log('click ', e);
setCurrent(e.key);
};
return (
<div style={{
borderBottom: "1px solid #eee",
margin: "10px 10px"
}}>
<Menu onClick={onClick} selectedKeys={[current]} mode="horizontal" items={items} style = {{
border: "0"
}} />
</div>
);
};
export default App;
+108
View File
@@ -0,0 +1,108 @@
"use client"
import type { IconButtonProps, SpanProps } from "@chakra-ui/react"
import { ClientOnly, IconButton, Skeleton, Span } from "@chakra-ui/react"
import { ThemeProvider, useTheme } from "next-themes"
import type { ThemeProviderProps } from "next-themes"
import * as React from "react"
import { LuMoon, LuSun } from "react-icons/lu"
export interface ColorModeProviderProps extends ThemeProviderProps {}
export function ColorModeProvider(props: ColorModeProviderProps) {
return (
<ThemeProvider attribute="class" disableTransitionOnChange {...props} />
)
}
export type ColorMode = "light" | "dark"
export interface UseColorModeReturn {
colorMode: ColorMode
setColorMode: (colorMode: ColorMode) => void
toggleColorMode: () => void
}
export function useColorMode(): UseColorModeReturn {
const { resolvedTheme, setTheme, forcedTheme } = useTheme()
const colorMode = forcedTheme || resolvedTheme
const toggleColorMode = () => {
setTheme(resolvedTheme === "dark" ? "light" : "dark")
}
return {
colorMode: colorMode as ColorMode,
setColorMode: setTheme,
toggleColorMode,
}
}
export function useColorModeValue<T>(light: T, dark: T) {
const { colorMode } = useColorMode()
return colorMode === "dark" ? dark : light
}
export function ColorModeIcon() {
const { colorMode } = useColorMode()
return colorMode === "dark" ? <LuMoon /> : <LuSun />
}
interface ColorModeButtonProps extends Omit<IconButtonProps, "aria-label"> {}
export const ColorModeButton = React.forwardRef<
HTMLButtonElement,
ColorModeButtonProps
>(function ColorModeButton(props, ref) {
const { toggleColorMode } = useColorMode()
return (
<ClientOnly fallback={<Skeleton boxSize="9" />}>
<IconButton
onClick={toggleColorMode}
variant="ghost"
aria-label="Toggle color mode"
size="sm"
ref={ref}
{...props}
css={{
_icon: {
width: "5",
height: "5",
},
}}
>
<ColorModeIcon />
</IconButton>
</ClientOnly>
)
})
export const LightMode = React.forwardRef<HTMLSpanElement, SpanProps>(
function LightMode(props, ref) {
return (
<Span
color="fg"
display="contents"
className="chakra-theme light"
colorPalette="gray"
colorScheme="light"
ref={ref}
{...props}
/>
)
},
)
export const DarkMode = React.forwardRef<HTMLSpanElement, SpanProps>(
function DarkMode(props, ref) {
return (
<Span
color="fg"
display="contents"
className="chakra-theme dark"
colorPalette="gray"
colorScheme="dark"
ref={ref}
{...props}
/>
)
},
)
+15
View File
@@ -0,0 +1,15 @@
"use client"
import { ChakraProvider, defaultSystem } from "@chakra-ui/react"
import {
ColorModeProvider,
type ColorModeProviderProps,
} from "./color-mode"
export function Provider(props: ColorModeProviderProps) {
return (
<ChakraProvider value={defaultSystem}>
<ColorModeProvider {...props} />
</ChakraProvider>
)
}
+43
View File
@@ -0,0 +1,43 @@
"use client"
import {
Toaster as ChakraToaster,
Portal,
Spinner,
Stack,
Toast,
createToaster,
} from "@chakra-ui/react"
export const toaster = createToaster({
placement: "bottom-end",
pauseOnPageIdle: true,
})
export const Toaster = () => {
return (
<Portal>
<ChakraToaster toaster={toaster} insetInline={{ mdDown: "4" }}>
{(toast) => (
<Toast.Root width={{ md: "sm" }}>
{toast.type === "loading" ? (
<Spinner size="sm" color="blue.solid" />
) : (
<Toast.Indicator />
)}
<Stack gap="1" flex="1" maxWidth="100%">
{toast.title && <Toast.Title>{toast.title}</Toast.Title>}
{toast.description && (
<Toast.Description>{toast.description}</Toast.Description>
)}
</Stack>
{toast.action && (
<Toast.ActionTrigger>{toast.action.label}</Toast.ActionTrigger>
)}
{toast.closable && <Toast.CloseTrigger />}
</Toast.Root>
)}
</ChakraToaster>
</Portal>
)
}
+46
View File
@@ -0,0 +1,46 @@
import { Tooltip as ChakraTooltip, Portal } from "@chakra-ui/react"
import * as React from "react"
export interface TooltipProps extends ChakraTooltip.RootProps {
showArrow?: boolean
portalled?: boolean
portalRef?: React.RefObject<HTMLElement | null>
content: React.ReactNode
contentProps?: ChakraTooltip.ContentProps
disabled?: boolean
}
export const Tooltip = React.forwardRef<HTMLDivElement, TooltipProps>(
function Tooltip(props, ref) {
const {
showArrow,
children,
disabled,
portalled = true,
content,
contentProps,
portalRef,
...rest
} = props
if (disabled) return children
return (
<ChakraTooltip.Root {...rest}>
<ChakraTooltip.Trigger asChild>{children}</ChakraTooltip.Trigger>
<Portal disabled={!portalled} container={portalRef}>
<ChakraTooltip.Positioner>
<ChakraTooltip.Content ref={ref} {...contentProps}>
{showArrow && (
<ChakraTooltip.Arrow>
<ChakraTooltip.ArrowTip />
</ChakraTooltip.Arrow>
)}
{content}
</ChakraTooltip.Content>
</ChakraTooltip.Positioner>
</Portal>
</ChakraTooltip.Root>
)
},
)
View File
+11
View File
@@ -0,0 +1,11 @@
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import './index.css'
import 'antd/dist/antd.css';
import App from './App.tsx'
createRoot(document.getElementById('root')!).render(
<StrictMode>
<App />
</StrictMode>,
)