页面布局调整
This commit is contained in:
1 parent
139dfb76e4
commit
e6ad3c414f
7 files changed
+144
-49
No files matched your search
@@ -139,7 +139,7 @@ function SidebarProvider({
|
||||
} as React.CSSProperties
|
||||
}
|
||||
className={cn(
|
||||
"group/sidebar-wrapper has-data-[variant=inset]:bg-sidebar flex min-h-svh w-full",
|
||||
"group/sidebar-wrapper has-data-[variant=inset]:bg-sidebar flex h-full w-full",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
@@ -229,7 +229,7 @@ function Sidebar({
|
||||
<div
|
||||
data-slot="sidebar-container"
|
||||
className={cn(
|
||||
"fixed inset-y-0 z-10 hidden h-svh w-(--sidebar-width) transition-[left,right,width] duration-200 ease-linear md:flex",
|
||||
"fixed top-16 bottom-0 z-10 hidden w-(--sidebar-width) transition-[left,right,width] duration-200 ease-linear md:flex",
|
||||
side === "left"
|
||||
? "left-0 group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)]"
|
||||
: "right-0 group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]",
|
||||
@@ -309,7 +309,7 @@ function SidebarInset({ className, ...props }: React.ComponentProps<"main">) {
|
||||
<main
|
||||
data-slot="sidebar-inset"
|
||||
className={cn(
|
||||
"bg-[#fffdfa] relative flex w-full flex-1 flex-col",
|
||||
"bg-background relative flex w-full flex-1 flex-col",
|
||||
"md:peer-data-[variant=inset]:m-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow-sm md:peer-data-[variant=inset]:peer-data-[state=collapsed]:ml-2",
|
||||
className,
|
||||
)}
|
||||
|
||||
@@ -449,7 +449,7 @@ export function InputBox({
|
||||
<button
|
||||
key={q.id}
|
||||
type="button"
|
||||
className="rounded-full border border-[#e4e4e7] bg-white px-4 py-2 text-sm text-[#18181b] shadow-none transition-colors hover:bg-[#f4f4f5] cursor-pointer"
|
||||
className="rounded-full border border-[#e4e4e7] bg-white px-4 py-2 text-sm text-[#18181b] shadow-none transition-colors hover:bg-[#f4f4f5] cursor-pointer dark:border-slate-600 dark:bg-slate-700/50 dark:text-slate-300 dark:hover:bg-slate-700"
|
||||
onClick={() => {
|
||||
textInput.setInput(q.content);
|
||||
setFollowupsHidden(true);
|
||||
@@ -495,7 +495,7 @@ export function InputBox({
|
||||
)}
|
||||
<PromptInput
|
||||
className={cn(
|
||||
"rounded-[1.85rem] border border-[#eadfce] bg-white shadow-[0_24px_70px_-34px_rgba(120,83,42,0.32)] ring-1 ring-[#f6efe5] transition-all duration-300 ease-out *:data-[slot='input-group']:rounded-[1.85rem]",
|
||||
"rounded-[1.85rem] border border-[#eadfce] bg-white shadow-[0_24px_70px_-34px_rgba(120,83,42,0.32)] ring-1 ring-[#f6efe5] transition-all duration-300 ease-out *:data-[slot='input-group']:rounded-[1.85rem] dark:bg-slate-800 dark:border-slate-700 dark:ring-slate-700 dark:shadow-none",
|
||||
className,
|
||||
)}
|
||||
disabled={disabled}
|
||||
@@ -510,7 +510,7 @@ export function InputBox({
|
||||
<PromptInputBody className="absolute top-0 right-0 left-0 z-3">
|
||||
<PromptInputTextarea
|
||||
className={cn(
|
||||
"size-full px-2 py-1 text-[15px] leading-7 placeholder:text-[#b7ab9a]",
|
||||
"size-full px-2 py-1 text-[15px] leading-7 placeholder:text-[#b7ab9a] dark:placeholder:text-slate-500",
|
||||
)}
|
||||
disabled={disabled}
|
||||
placeholder={t.inputBox.placeholder}
|
||||
@@ -518,7 +518,7 @@ export function InputBox({
|
||||
defaultValue={initialValue}
|
||||
/>
|
||||
</PromptInputBody>
|
||||
<PromptInputFooter className="flex items-center border-t border-[#f4ede4] px-2 pt-2.5 pb-1.5">
|
||||
<PromptInputFooter className="flex items-center border-t border-[#f4ede4] dark:border-slate-700 px-2 pt-2.5 pb-1.5">
|
||||
<PromptInputTools className="gap-1.5">
|
||||
{/* TODO: Add more connectors here
|
||||
<PromptInputActionMenu>
|
||||
@@ -529,7 +529,7 @@ export function InputBox({
|
||||
/>
|
||||
</PromptInputActionMenuContent>
|
||||
</PromptInputActionMenu> */}
|
||||
<AddAttachmentsButton className="rounded-full border border-[#eee3d5] bg-[#fffaf5] px-2.5! shadow-none hover:bg-white" />
|
||||
<AddAttachmentsButton className="rounded-full border border-[#eee3d5] bg-[#fffaf5] px-2.5! shadow-none hover:bg-white dark:border-slate-600 dark:bg-slate-700/50 dark:text-slate-300 dark:hover:bg-slate-700" />
|
||||
<PromptInputActionMenu>
|
||||
<ModeHoverGuide
|
||||
mode={
|
||||
@@ -541,7 +541,7 @@ export function InputBox({
|
||||
: "flash"
|
||||
}
|
||||
>
|
||||
<PromptInputActionMenuTrigger className="gap-1.5! rounded-full border border-[#eee3d5] bg-[#fffaf5] px-3! text-[#7e6a57] shadow-none hover:bg-white">
|
||||
<PromptInputActionMenuTrigger className="gap-1.5! rounded-full border border-[#eee3d5] bg-[#fffaf5] px-3! text-[#7e6a57] shadow-none hover:bg-white dark:border-slate-600 dark:bg-slate-700/50 dark:text-slate-300 dark:hover:bg-slate-700">
|
||||
<div>
|
||||
{context.mode === "flash" && <ZapIcon className="size-3" />}
|
||||
{context.mode === "thinking" && (
|
||||
@@ -703,7 +703,7 @@ export function InputBox({
|
||||
</PromptInputActionMenu>
|
||||
{supportReasoningEffort && context.mode !== "flash" && (
|
||||
<PromptInputActionMenu>
|
||||
<PromptInputActionMenuTrigger className="gap-1.5! rounded-full border border-[#eee3d5] bg-[#fffaf5] px-3! text-[#7e6a57] shadow-none hover:bg-white">
|
||||
<PromptInputActionMenuTrigger className="gap-1.5! rounded-full border border-[#eee3d5] bg-[#fffaf5] px-3! text-[#7e6a57] shadow-none hover:bg-white dark:border-slate-600 dark:bg-slate-700/50 dark:text-slate-300 dark:hover:bg-slate-700">
|
||||
<div className="text-xs font-normal">
|
||||
{t.inputBox.reasoningEffort}:
|
||||
{context.reasoning_effort === "minimal" &&
|
||||
@@ -824,7 +824,7 @@ export function InputBox({
|
||||
onOpenChange={setModelDialogOpen}
|
||||
>
|
||||
<ModelSelectorTrigger asChild>
|
||||
<PromptInputButton className="rounded-full border border-[#eee3d5] bg-[#fffaf5] px-3 shadow-none hover:bg-white">
|
||||
<PromptInputButton className="rounded-full border border-[#eee3d5] bg-[#fffaf5] px-3 shadow-none hover:bg-white dark:border-slate-600 dark:bg-slate-700/50 dark:text-slate-300 dark:hover:bg-slate-700">
|
||||
<div className="flex min-w-0 flex-col items-start text-left">
|
||||
<ModelSelectorName className="text-xs font-normal">
|
||||
{selectedModel?.display_name}
|
||||
@@ -858,7 +858,7 @@ export function InputBox({
|
||||
</ModelSelectorContent>
|
||||
</ModelSelector>
|
||||
<PromptInputSubmit
|
||||
className="rounded-full border-[#e7d9c7] bg-white shadow-[0_10px_24px_-18px_rgba(120,83,42,0.34)]"
|
||||
className="rounded-full border-[#e7d9c7] bg-white shadow-[0_10px_24px_-18px_rgba(120,83,42,0.34)] dark:bg-blue-500 dark:border-blue-500 dark:text-white dark:hover:bg-blue-400 dark:shadow-none"
|
||||
disabled={disabled}
|
||||
variant="outline"
|
||||
status={status}
|
||||
@@ -866,7 +866,7 @@ export function InputBox({
|
||||
</PromptInputTools>
|
||||
</PromptInputFooter>
|
||||
{!isNewThread && (
|
||||
<div className="absolute right-0 -bottom-[17px] left-0 z-0 h-4 bg-[#fffdfa]"></div>
|
||||
<div className="absolute right-0 -bottom-[17px] left-0 z-0 h-4 bg-[#fffdfa] dark:bg-background"></div>
|
||||
)}
|
||||
</PromptInput>
|
||||
|
||||
|
||||
@@ -39,16 +39,16 @@ const themes: Record<ThemeType, ThemeConfig> = {
|
||||
textSecondary: 'slate-400',
|
||||
primary: 'blue-500',
|
||||
primaryHover: 'blue-400',
|
||||
border: 'blue-800',
|
||||
accent: 'cyan-400',
|
||||
border: 'slate-700',
|
||||
accent: 'blue-600',
|
||||
success: 'emerald-500',
|
||||
warning: 'amber-500',
|
||||
error: 'rose-500',
|
||||
card: 'slate-800',
|
||||
cardHover: 'slate-700',
|
||||
input: 'slate-800',
|
||||
inputBorder: 'blue-800',
|
||||
overlay: 'slate-900/50',
|
||||
inputBorder: 'slate-600',
|
||||
overlay: 'slate-900/80',
|
||||
},
|
||||
},
|
||||
light: {
|
||||
|
||||
@@ -4,6 +4,7 @@ import { Navigate, Route, Routes } from "react-router-dom";
|
||||
import { PageSidebar } from "@/components/page-sidebar";
|
||||
|
||||
import WorkspaceRoutes from "./WorkspaceRoutes";
|
||||
import Header from "@/strategy-components/Header";
|
||||
|
||||
// 设为 true 时隐藏侧边栏(开发中,暂未完成)
|
||||
const SIDEBAR_ENABLED = false;
|
||||
@@ -12,18 +13,20 @@ function PageLayout() {
|
||||
const [collapsed, setCollapsed] = useState(false);
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-muted/20">
|
||||
<div className="h-screen flex bg-muted/20">
|
||||
{SIDEBAR_ENABLED && (
|
||||
<PageSidebar
|
||||
collapsed={collapsed}
|
||||
onToggleCollapsed={() => setCollapsed((prev) => !prev)}
|
||||
/>
|
||||
)}
|
||||
<main
|
||||
className={`min-h-screen transition-[padding] duration-300 ${
|
||||
!SIDEBAR_ENABLED ? "" : collapsed ? "pl-16" : "pl-16 md:pl-64"
|
||||
<div
|
||||
className={`flex flex-col flex-1 overflow-hidden transition-[padding] duration-300 ${
|
||||
!SIDEBAR_ENABLED ? "" : collapsed ? "pl-16" : "pl-64"
|
||||
}`}
|
||||
>
|
||||
<Header />
|
||||
<main className="flex-1 overflow-hidden">
|
||||
<Routes>
|
||||
<Route index element={<Navigate to="workspace" replace />} />
|
||||
<Route
|
||||
@@ -38,6 +41,7 @@ function PageLayout() {
|
||||
</Routes>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ function WorkspaceLayout({
|
||||
|
||||
return (
|
||||
<SidebarProvider
|
||||
className="h-screen w-full overflow-x-hidden [&_[data-slot=sidebar-container]]:left-[var(--page-sidebar-width)]"
|
||||
className="h-full w-full overflow-x-hidden [&_[data-slot=sidebar-container]]:left-[var(--page-sidebar-width)]"
|
||||
style={
|
||||
{
|
||||
"--page-sidebar-width": pageSidebarWidth,
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
import React from 'react';
|
||||
import { Bell, Search, User, ChevronDown, Moon, Sun, Palette } from 'lucide-react';
|
||||
import { useTheme } from '../contexts/ThemeContext';
|
||||
|
||||
const Header: React.FC = () => {
|
||||
const { theme, toggleTheme } = useTheme();
|
||||
const isDark = theme === 'dark';
|
||||
|
||||
return (
|
||||
<header className={`h-16 flex items-center justify-between px-6 theme-transition ${
|
||||
isDark
|
||||
? 'bg-slate-900/50 backdrop-blur-xl border-b border-blue-800/30'
|
||||
: 'bg-red-600 border-b border-red-700'
|
||||
}`}>
|
||||
{/* 左侧 - 搜索框 */}
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="relative">
|
||||
<Search className={`absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 ${isDark ? 'text-slate-500' : 'text-red-200'}`} />
|
||||
<input
|
||||
type="text"
|
||||
placeholder="搜索场景、智能体、任务..."
|
||||
className={`w-80 pl-10 pr-4 py-2 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-white/20 transition-all duration-200 theme-transition ${
|
||||
isDark
|
||||
? 'bg-slate-800/50 border border-blue-800/30 text-white placeholder-slate-500'
|
||||
: 'bg-red-700 border border-red-800 text-white placeholder-red-200'
|
||||
}`}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 右侧 - 用户信息和通知 */}
|
||||
<div className="flex items-center gap-4">
|
||||
{/* 主题切换按钮 */}
|
||||
<button
|
||||
onClick={toggleTheme}
|
||||
className={`p-2 rounded-lg transition-all duration-200 ${
|
||||
isDark
|
||||
? 'hover:bg-slate-800/50 text-slate-400 hover:text-white'
|
||||
: 'hover:bg-red-500 text-white'
|
||||
}`}
|
||||
title={isDark ? '切换到红白主题' : '切换到深色主题'}
|
||||
>
|
||||
{isDark ? (
|
||||
<Palette className="w-5 h-5" />
|
||||
) : (
|
||||
<Moon className="w-5 h-5" />
|
||||
)}
|
||||
</button>
|
||||
|
||||
{/* 通知 */}
|
||||
<button className={`relative p-2 rounded-lg transition-colors ${
|
||||
isDark ? 'hover:bg-slate-800/50' : 'hover:bg-red-500'
|
||||
}`}>
|
||||
<Bell className={`w-5 h-5 ${isDark ? 'text-slate-400' : 'text-white'}`} />
|
||||
<span className={`absolute top-1 right-1 w-2 h-2 rounded-full ${isDark ? 'bg-cyan-500' : 'bg-white'}`} />
|
||||
</button>
|
||||
|
||||
{/* 分隔线 */}
|
||||
<div className={`w-px h-8 ${isDark ? 'bg-blue-800/30' : 'bg-red-500'}`} />
|
||||
|
||||
{/* 用户信息 */}
|
||||
<button className={`flex items-center gap-3 px-3 py-1.5 rounded-lg transition-colors ${
|
||||
isDark ? 'hover:bg-slate-800/50' : 'hover:bg-red-500'
|
||||
}`}>
|
||||
<div className={`w-8 h-8 rounded-full flex items-center justify-center ${
|
||||
isDark
|
||||
? 'bg-gradient-to-br from-blue-500 to-cyan-400'
|
||||
: 'bg-white'
|
||||
}`}>
|
||||
<User className={`w-4 h-4 ${isDark ? 'text-white' : 'text-red-600'}`} />
|
||||
</div>
|
||||
<div className="text-left">
|
||||
<p className={`text-sm font-medium ${isDark ? 'text-white' : 'text-white'}`}>张策略</p>
|
||||
<p className={`text-xs ${isDark ? 'text-blue-400/60' : 'text-red-200'}`}>策略分析师</p>
|
||||
</div>
|
||||
<ChevronDown className={`w-4 h-4 ${isDark ? 'text-slate-500' : 'text-white'}`} />
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
);
|
||||
};
|
||||
|
||||
export default Header;
|
||||
@@ -243,7 +243,7 @@
|
||||
--workspace-brand: #d92121;
|
||||
--workspace-brand-foreground: #ffffff;
|
||||
--radius: 0.75rem;
|
||||
--background: oklch(0.985 0.004 95);
|
||||
--background: oklch(1 0 0);
|
||||
--foreground: oklch(0.22 0.02 25);
|
||||
--card: oklch(1 0.002 95);
|
||||
--card-foreground: oklch(0.22 0.02 25);
|
||||
@@ -277,39 +277,39 @@
|
||||
}
|
||||
|
||||
.dark {
|
||||
--workspace-brand: #e11d1d;
|
||||
--workspace-brand: #3b82f6;
|
||||
--workspace-brand-foreground: #ffffff;
|
||||
--background: oklch(0.22 0.015 25);
|
||||
--foreground: oklch(0.96 0.01 95);
|
||||
--card: oklch(0.26 0.018 25);
|
||||
--card-foreground: oklch(0.96 0.01 95);
|
||||
--popover: oklch(0.24 0.018 25);
|
||||
--popover-foreground: oklch(0.96 0.01 95);
|
||||
--primary: oklch(0.62 0.17 27);
|
||||
--primary-foreground: oklch(0.12 0.02 25);
|
||||
--secondary: oklch(0.32 0.02 25);
|
||||
--secondary-foreground: oklch(0.96 0.01 95);
|
||||
--muted: oklch(0.3 0.02 25);
|
||||
--muted-foreground: oklch(0.72 0.02 95);
|
||||
--accent: oklch(0.34 0.06 25);
|
||||
--accent-foreground: oklch(0.96 0.01 95);
|
||||
--background: oklch(0.208 0.042 264);
|
||||
--foreground: oklch(0.96 0.005 240);
|
||||
--card: oklch(0.265 0.04 260);
|
||||
--card-foreground: oklch(0.96 0.005 240);
|
||||
--popover: oklch(0.245 0.04 262);
|
||||
--popover-foreground: oklch(0.96 0.005 240);
|
||||
--primary: oklch(0.623 0.214 259);
|
||||
--primary-foreground: oklch(0.99 0 0);
|
||||
--secondary: oklch(0.32 0.038 260);
|
||||
--secondary-foreground: oklch(0.96 0.005 240);
|
||||
--muted: oklch(0.30 0.035 260);
|
||||
--muted-foreground: oklch(0.68 0.02 240);
|
||||
--accent: oklch(0.35 0.06 260);
|
||||
--accent-foreground: oklch(0.96 0.005 240);
|
||||
--destructive: oklch(0.704 0.191 22.216);
|
||||
--border: oklch(1 0 0 / 12%);
|
||||
--input: oklch(1 0 0 / 14%);
|
||||
--ring: oklch(0.62 0.17 27 / 0.45);
|
||||
--ring: oklch(0.623 0.214 259 / 0.45);
|
||||
--chart-1: oklch(0.488 0.243 264.376);
|
||||
--chart-2: oklch(0.696 0.17 162.48);
|
||||
--chart-3: oklch(0.769 0.188 70.08);
|
||||
--chart-4: oklch(0.627 0.265 303.9);
|
||||
--chart-5: oklch(0.645 0.246 16.439);
|
||||
--sidebar: oklch(0.2 0.02 25);
|
||||
--sidebar-foreground: oklch(0.94 0.01 95);
|
||||
--sidebar-primary: oklch(0.62 0.17 27);
|
||||
--sidebar: oklch(0.185 0.04 265);
|
||||
--sidebar-foreground: oklch(0.94 0.005 240);
|
||||
--sidebar-primary: oklch(0.623 0.214 259);
|
||||
--sidebar-primary-foreground: oklch(0.99 0 0);
|
||||
--sidebar-accent: oklch(0.3 0.05 25);
|
||||
--sidebar-accent-foreground: oklch(0.96 0.01 95);
|
||||
--sidebar-accent: oklch(0.30 0.055 260);
|
||||
--sidebar-accent-foreground: oklch(0.96 0.005 240);
|
||||
--sidebar-border: oklch(1 0 0 / 10%);
|
||||
--sidebar-ring: oklch(0.62 0.17 27 / 0.45);
|
||||
--sidebar-ring: oklch(0.623 0.214 259 / 0.45);
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
@@ -430,19 +430,27 @@
|
||||
}
|
||||
|
||||
.workspace-shell {
|
||||
background:
|
||||
radial-gradient(circle at top right, rgb(255 214 214 / 0.72), transparent 18%),
|
||||
linear-gradient(180deg, #fbf7f4 0%, #f6efea 100%);
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.dark .workspace-shell {
|
||||
background: var(--background);
|
||||
}
|
||||
|
||||
.workspace-panel {
|
||||
border: 1px solid #f0d7d0;
|
||||
background: linear-gradient(180deg, rgb(255 253 251 / 0.98), rgb(255 247 244 / 0.98));
|
||||
background: #ffffff;
|
||||
box-shadow:
|
||||
0 32px 72px -46px rgb(98 63 42 / 0.35),
|
||||
0 12px 28px -22px rgb(170 91 75 / 0.24);
|
||||
}
|
||||
|
||||
.dark .workspace-panel {
|
||||
border: 1px solid oklch(1 0 0 / 10%);
|
||||
background: var(--card);
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.workspace-user-bubble {
|
||||
max-width: min(82%, 42rem);
|
||||
border: 1px solid rgb(255 255 255 / 0.14);
|
||||
|
||||
Reference in new issue
Block a user