mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2026-01-16 05:10:34 +00:00
Add background-aware styling to sidebar and usage pie
Updated sidebar, navigation list, and usage pie components to adjust their styles based on the presence of a custom background image. This improves visual integration when a background image is set, ensuring text and UI elements remain readable and aesthetically consistent.
This commit is contained in:
parent
a34a86288b
commit
afed164ba1
@ -1,9 +1,11 @@
|
|||||||
import { Input } from '@heroui/input';
|
import { Input } from '@heroui/input';
|
||||||
|
import { useLocalStorage } from '@uidotdev/usehooks';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import { AnimatePresence, motion } from 'motion/react';
|
import { AnimatePresence, motion } from 'motion/react';
|
||||||
import { useMemo, useState } from 'react';
|
import { useMemo, useState } from 'react';
|
||||||
import { TbChevronRight, TbFolder, TbSearch } from 'react-icons/tb';
|
import { TbChevronRight, TbFolder, TbSearch } from 'react-icons/tb';
|
||||||
|
|
||||||
|
import key from '@/const/key';
|
||||||
import oneBotHttpApiGroup from '@/const/ob_api/group';
|
import oneBotHttpApiGroup from '@/const/ob_api/group';
|
||||||
import oneBotHttpApiMessage from '@/const/ob_api/message';
|
import oneBotHttpApiMessage from '@/const/ob_api/message';
|
||||||
import oneBotHttpApiSystem from '@/const/ob_api/system';
|
import oneBotHttpApiSystem from '@/const/ob_api/system';
|
||||||
@ -22,6 +24,8 @@ const OneBotApiNavList: React.FC<OneBotApiNavListProps> = (props) => {
|
|||||||
const { data, selectedApi, onSelect, openSideBar, onToggle } = props;
|
const { data, selectedApi, onSelect, openSideBar, onToggle } = props;
|
||||||
const [searchValue, setSearchValue] = useState('');
|
const [searchValue, setSearchValue] = useState('');
|
||||||
const [expandedGroups, setExpandedGroups] = useState<string[]>([]);
|
const [expandedGroups, setExpandedGroups] = useState<string[]>([]);
|
||||||
|
const [backgroundImage] = useLocalStorage<string>(key.backgroundImage, '');
|
||||||
|
const hasBackground = !!backgroundImage;
|
||||||
|
|
||||||
const groups = useMemo(() => {
|
const groups = useMemo(() => {
|
||||||
const rawGroups = [
|
const rawGroups = [
|
||||||
@ -70,7 +74,9 @@ const OneBotApiNavList: React.FC<OneBotApiNavListProps> = (props) => {
|
|||||||
// Mobile: absolute position, drawer style
|
// Mobile: absolute position, drawer style
|
||||||
// Desktop: relative position, pushing content
|
// Desktop: relative position, pushing content
|
||||||
'absolute md:relative left-0 top-0',
|
'absolute md:relative left-0 top-0',
|
||||||
'bg-white/80 dark:bg-black/80 md:bg-transparent backdrop-blur-2xl md:backdrop-blur-none'
|
hasBackground
|
||||||
|
? 'bg-white/10 dark:bg-black/40 backdrop-blur-xl md:bg-transparent md:backdrop-blur-none'
|
||||||
|
: 'bg-white/80 dark:bg-black/40 backdrop-blur-xl md:bg-transparent md:backdrop-blur-none'
|
||||||
)}
|
)}
|
||||||
initial={false}
|
initial={false}
|
||||||
animate={{
|
animate={{
|
||||||
@ -139,7 +145,7 @@ const OneBotApiNavList: React.FC<OneBotApiNavListProps> = (props) => {
|
|||||||
className={clsx(
|
className={clsx(
|
||||||
'flex flex-col gap-0.5 px-3 py-2 rounded-lg cursor-pointer transition-all border border-transparent select-none',
|
'flex flex-col gap-0.5 px-3 py-2 rounded-lg cursor-pointer transition-all border border-transparent select-none',
|
||||||
isSelected
|
isSelected
|
||||||
? 'bg-primary/20 border-primary/20 shadow-sm'
|
? (hasBackground ? '' : 'bg-primary/20 border-primary/20 shadow-sm')
|
||||||
: 'hover:bg-white/5'
|
: 'hover:bg-white/5'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|||||||
@ -1,10 +1,12 @@
|
|||||||
import { Button } from '@heroui/button';
|
import { Button } from '@heroui/button';
|
||||||
|
import { useLocalStorage } from '@uidotdev/usehooks';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import { AnimatePresence, motion } from 'motion/react';
|
import { AnimatePresence, motion } from 'motion/react';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { IoMdLogOut } from 'react-icons/io';
|
import { IoMdLogOut } from 'react-icons/io';
|
||||||
import { MdDarkMode, MdLightMode } from 'react-icons/md';
|
import { MdDarkMode, MdLightMode } from 'react-icons/md';
|
||||||
|
|
||||||
|
import key from '@/const/key';
|
||||||
import useAuth from '@/hooks/auth';
|
import useAuth from '@/hooks/auth';
|
||||||
import useDialog from '@/hooks/use-dialog';
|
import useDialog from '@/hooks/use-dialog';
|
||||||
import { useTheme } from '@/hooks/use-theme';
|
import { useTheme } from '@/hooks/use-theme';
|
||||||
@ -23,6 +25,9 @@ const SideBar: React.FC<SideBarProps> = (props) => {
|
|||||||
const { toggleTheme, isDark } = useTheme();
|
const { toggleTheme, isDark } = useTheme();
|
||||||
const { revokeAuth } = useAuth();
|
const { revokeAuth } = useAuth();
|
||||||
const dialog = useDialog();
|
const dialog = useDialog();
|
||||||
|
const [backgroundImage] = useLocalStorage<string>(key.backgroundImage, '');
|
||||||
|
const hasBackground = !!backgroundImage;
|
||||||
|
|
||||||
const onRevokeAuth = () => {
|
const onRevokeAuth = () => {
|
||||||
dialog.confirm({
|
dialog.confirm({
|
||||||
title: '退出登录',
|
title: '退出登录',
|
||||||
@ -48,7 +53,9 @@ const SideBar: React.FC<SideBarProps> = (props) => {
|
|||||||
<motion.div
|
<motion.div
|
||||||
className={clsx(
|
className={clsx(
|
||||||
'overflow-hidden fixed top-0 left-0 h-full z-50 md:static md:shadow-none rounded-r-2xl md:rounded-none',
|
'overflow-hidden fixed top-0 left-0 h-full z-50 md:static md:shadow-none rounded-r-2xl md:rounded-none',
|
||||||
'bg-content1/70 backdrop-blur-xl backdrop-saturate-150 shadow-xl',
|
hasBackground
|
||||||
|
? 'bg-transparent backdrop-blur-md'
|
||||||
|
: 'bg-content1/70 backdrop-blur-xl backdrop-saturate-150 shadow-xl',
|
||||||
'md:bg-transparent md:backdrop-blur-none md:backdrop-saturate-100 md:shadow-none'
|
'md:bg-transparent md:backdrop-blur-none md:backdrop-saturate-100 md:shadow-none'
|
||||||
)}
|
)}
|
||||||
initial={{ width: 0 }}
|
initial={{ width: 0 }}
|
||||||
|
|||||||
@ -142,11 +142,13 @@ const SystemStatusDisplay: React.FC<SystemStatusDisplayProps> = ({ data }) => {
|
|||||||
systemUsage={Number(data?.cpu.usage.system) || 0}
|
systemUsage={Number(data?.cpu.usage.system) || 0}
|
||||||
processUsage={Number(data?.cpu.usage.qq) || 0}
|
processUsage={Number(data?.cpu.usage.qq) || 0}
|
||||||
title='CPU占用'
|
title='CPU占用'
|
||||||
|
hasBackground={hasBackground}
|
||||||
/>
|
/>
|
||||||
<UsagePie
|
<UsagePie
|
||||||
systemUsage={memoryUsage.system}
|
systemUsage={memoryUsage.system}
|
||||||
processUsage={memoryUsage.qq}
|
processUsage={memoryUsage.qq}
|
||||||
title='内存占用'
|
title='内存占用'
|
||||||
|
hasBackground={hasBackground}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</CardBody>
|
</CardBody>
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import React, { useMemo } from 'react';
|
import React, { useMemo } from 'react';
|
||||||
|
import clsx from 'clsx';
|
||||||
|
|
||||||
import { useTheme } from '@/hooks/use-theme';
|
import { useTheme } from '@/hooks/use-theme';
|
||||||
|
|
||||||
@ -6,12 +7,14 @@ interface UsagePieProps {
|
|||||||
systemUsage: number;
|
systemUsage: number;
|
||||||
processUsage: number;
|
processUsage: number;
|
||||||
title?: string;
|
title?: string;
|
||||||
|
hasBackground?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const UsagePie: React.FC<UsagePieProps> = ({
|
const UsagePie: React.FC<UsagePieProps> = ({
|
||||||
systemUsage,
|
systemUsage,
|
||||||
processUsage,
|
processUsage,
|
||||||
title,
|
title,
|
||||||
|
hasBackground,
|
||||||
}) => {
|
}) => {
|
||||||
const { theme } = useTheme();
|
const { theme } = useTheme();
|
||||||
|
|
||||||
@ -91,15 +94,24 @@ const UsagePie: React.FC<UsagePieProps> = ({
|
|||||||
{/* Center Content */}
|
{/* Center Content */}
|
||||||
<div className="absolute inset-0 flex flex-col items-center justify-center pointer-events-none select-none">
|
<div className="absolute inset-0 flex flex-col items-center justify-center pointer-events-none select-none">
|
||||||
{title && (
|
{title && (
|
||||||
<span className="text-[10px] text-default-500 font-medium mb-0.5 opacity-80 uppercase tracking-widest scale-90">
|
<span className={clsx(
|
||||||
|
"text-[10px] font-medium mb-0.5 opacity-80 uppercase tracking-widest scale-90",
|
||||||
|
hasBackground ? 'text-white/80' : 'text-default-500 dark:text-default-400'
|
||||||
|
)}>
|
||||||
{title}
|
{title}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
<div className="flex items-baseline gap-0.5">
|
<div className="flex items-baseline gap-0.5">
|
||||||
<span className="text-2xl font-bold font-mono tracking-tight text-default-900 dark:text-gray-100">
|
<span className={clsx(
|
||||||
|
"text-2xl font-bold font-mono tracking-tight",
|
||||||
|
hasBackground ? 'text-white' : 'text-default-900 dark:text-white'
|
||||||
|
)}>
|
||||||
{Math.round(cleanSystem)}
|
{Math.round(cleanSystem)}
|
||||||
</span>
|
</span>
|
||||||
<span className="text-xs text-default-400 font-bold">%</span>
|
<span className={clsx(
|
||||||
|
"text-xs font-bold",
|
||||||
|
hasBackground ? 'text-white/60' : 'text-default-400 dark:text-default-500'
|
||||||
|
)}>%</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user