feat(workspace): add red theme assets and adapt workspace styles
This commit is contained in:
1 parent
760b88d6f1
commit
2fa7000ff7
13 files changed
+95
-125
No files matched your search
Binary file not shown.
|
After Width: | Height: | Size: 39 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 33 KiB |
@@ -27,7 +27,9 @@ import {
|
|||||||
|
|
||||||
const SIDEBAR_COOKIE_NAME = "sidebar_state";
|
const SIDEBAR_COOKIE_NAME = "sidebar_state";
|
||||||
const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7;
|
const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7;
|
||||||
const SIDEBAR_WIDTH = "16rem";
|
// Keep the workbench navigation compact across every theme. The visual theme
|
||||||
|
// only changes tokens; the information density should remain consistent.
|
||||||
|
const SIDEBAR_WIDTH = "14rem";
|
||||||
const SIDEBAR_WIDTH_MOBILE = "18rem";
|
const SIDEBAR_WIDTH_MOBILE = "18rem";
|
||||||
const SIDEBAR_WIDTH_ICON = "3rem";
|
const SIDEBAR_WIDTH_ICON = "3rem";
|
||||||
const SIDEBAR_KEYBOARD_SHORTCUT = "b";
|
const SIDEBAR_KEYBOARD_SHORTCUT = "b";
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { BotIcon, SparklesIcon } from "lucide-react";
|
import { useTheme } from "@/contexts/ThemeContext";
|
||||||
|
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
type AgentBrandIconProps = {
|
type AgentBrandIconProps = {
|
||||||
@@ -12,27 +11,15 @@ type AgentBrandIconProps = {
|
|||||||
const SIZE_STYLES = {
|
const SIZE_STYLES = {
|
||||||
nav: {
|
nav: {
|
||||||
frame: "size-[22px] rounded-md",
|
frame: "size-[22px] rounded-md",
|
||||||
bot: "size-3.5",
|
|
||||||
badge: "-right-1 -top-1 size-2.5",
|
|
||||||
sparkle: "size-1.5",
|
|
||||||
},
|
},
|
||||||
sm: {
|
sm: {
|
||||||
frame: "size-10 rounded-full",
|
frame: "size-10 rounded-full",
|
||||||
bot: "size-[18px]",
|
|
||||||
badge: "-right-1 -top-1 size-3.5",
|
|
||||||
sparkle: "size-2",
|
|
||||||
},
|
},
|
||||||
md: {
|
md: {
|
||||||
frame: "size-12 rounded-full",
|
frame: "size-12 rounded-full",
|
||||||
bot: "size-6",
|
|
||||||
badge: "-right-1 -top-1 size-4",
|
|
||||||
sparkle: "size-2.5",
|
|
||||||
},
|
},
|
||||||
lg: {
|
lg: {
|
||||||
frame: "size-16 rounded-full",
|
frame: "size-16 rounded-full",
|
||||||
bot: "size-7",
|
|
||||||
badge: "-right-1 -top-1 size-[18px]",
|
|
||||||
sparkle: "size-3",
|
|
||||||
},
|
},
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
@@ -41,50 +28,26 @@ export function AgentBrandIcon({
|
|||||||
size = "md",
|
size = "md",
|
||||||
}: AgentBrandIconProps) {
|
}: AgentBrandIconProps) {
|
||||||
const styles = SIZE_STYLES[size];
|
const styles = SIZE_STYLES[size];
|
||||||
const showBadge = size === "nav";
|
const { theme } = useTheme();
|
||||||
|
const avatarSrc =
|
||||||
if (size !== "nav") {
|
theme === "light" ? "/agent-avatar-red.png" : "/agent-avatar.png";
|
||||||
return (
|
|
||||||
<span
|
|
||||||
aria-hidden="true"
|
|
||||||
data-agent-brand-icon={size}
|
|
||||||
className={cn(
|
|
||||||
"relative inline-flex shrink-0 overflow-hidden rounded-full",
|
|
||||||
styles.frame,
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
src="/agent-avatar.png"
|
|
||||||
alt=""
|
|
||||||
className="size-full object-contain"
|
|
||||||
draggable={false}
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span
|
<span
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
data-agent-brand-icon={size}
|
data-agent-brand-icon={size}
|
||||||
className={cn(
|
className={cn(
|
||||||
"relative inline-flex shrink-0 items-center justify-center border border-blue-100 bg-[radial-gradient(circle_at_35%_30%,#ffffff_0%,#edf4ff_46%,#dce9ff_100%)] text-[#1f5fdb] shadow-[0_8px_22px_rgba(37,99,235,0.13),inset_0_1px_0_rgba(255,255,255,0.9)] dark:border-blue-400/30 dark:bg-blue-500/20 dark:text-blue-300",
|
"relative inline-flex shrink-0 overflow-hidden rounded-full",
|
||||||
styles.frame,
|
styles.frame,
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<BotIcon className={styles.bot} strokeWidth={1.9} />
|
<img
|
||||||
{showBadge && (
|
src={avatarSrc}
|
||||||
<span
|
alt=""
|
||||||
className={cn(
|
className="size-full object-contain"
|
||||||
"absolute flex items-center justify-center rounded-full bg-gradient-to-br from-[#4b91ff] to-[#1858db] text-white shadow-sm ring-2 ring-white dark:ring-slate-950",
|
draggable={false}
|
||||||
styles.badge,
|
/>
|
||||||
)}
|
|
||||||
>
|
|
||||||
<SparklesIcon className={styles.sparkle} strokeWidth={2.4} />
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -567,7 +567,7 @@ export function AgentCard({ agent, layout = "card", onPublisherClick }: AgentCar
|
|||||||
{isFromOthers && (
|
{isFromOthers && (
|
||||||
<Badge
|
<Badge
|
||||||
variant="outline"
|
variant="outline"
|
||||||
className="border-blue-200 bg-blue-50/60 text-xs text-blue-700 dark:border-blue-800 dark:bg-blue-500/10 dark:text-blue-300"
|
className="border-primary/20 bg-primary/5 text-primary text-xs dark:border-primary/40 dark:bg-primary/10 dark:text-primary"
|
||||||
title={agent.user_id ? `来自用户 ${agent.user_id}` : "已发布"}
|
title={agent.user_id ? `来自用户 ${agent.user_id}` : "已发布"}
|
||||||
>
|
>
|
||||||
来自他人
|
来自他人
|
||||||
@@ -576,7 +576,7 @@ export function AgentCard({ agent, layout = "card", onPublisherClick }: AgentCar
|
|||||||
{(isOwned || isAdmin) && !isBuiltin && agent.published && !agent.is_private && (
|
{(isOwned || isAdmin) && !isBuiltin && agent.published && !agent.is_private && (
|
||||||
<Badge
|
<Badge
|
||||||
variant="outline"
|
variant="outline"
|
||||||
className="border-sky-200 bg-sky-50/60 text-xs text-sky-700 dark:border-sky-800 dark:bg-sky-500/10 dark:text-sky-300"
|
className="border-primary/20 bg-primary/5 text-primary text-xs dark:border-primary/40 dark:bg-primary/10 dark:text-primary"
|
||||||
title="该智能体已对所有用户可见"
|
title="该智能体已对所有用户可见"
|
||||||
>
|
>
|
||||||
<GlobeIcon className="size-3" />
|
<GlobeIcon className="size-3" />
|
||||||
@@ -675,7 +675,7 @@ export function AgentCard({ agent, layout = "card", onPublisherClick }: AgentCar
|
|||||||
<Badge
|
<Badge
|
||||||
key={`tg:${group}`}
|
key={`tg:${group}`}
|
||||||
variant="outline"
|
variant="outline"
|
||||||
className="border-0 bg-[#f1f5ff] px-2.5 py-1 text-xs font-normal text-[#2166e8] hover:bg-[#e9f0ff]"
|
className="border-0 bg-primary/5 text-primary hover:bg-primary/10 px-2.5 py-1 text-xs font-normal"
|
||||||
>
|
>
|
||||||
{desensitize(group)}
|
{desensitize(group)}
|
||||||
</Badge>
|
</Badge>
|
||||||
@@ -687,7 +687,7 @@ export function AgentCard({ agent, layout = "card", onPublisherClick }: AgentCar
|
|||||||
<Badge
|
<Badge
|
||||||
key={`sk:${skill}`}
|
key={`sk:${skill}`}
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
className="cursor-pointer border-0 bg-[#f1f5ff] px-2.5 py-1 text-xs font-normal text-[#2166e8] hover:bg-[#e9f0ff]"
|
className="bg-primary/5 text-primary hover:bg-primary/10 cursor-pointer border-0 px-2.5 py-1 text-xs font-normal"
|
||||||
title={t.settings.skills.viewDetailAction}
|
title={t.settings.skills.viewDetailAction}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
@@ -841,8 +841,8 @@ export function AgentCard({ agent, layout = "card", onPublisherClick }: AgentCar
|
|||||||
size="sm"
|
size="sm"
|
||||||
className={cn(
|
className={cn(
|
||||||
isList
|
isList
|
||||||
? "shrink-0 rounded-xl bg-[#1f63e9] px-4 font-medium text-white hover:bg-[#1857d4]"
|
? "bg-primary hover:bg-primary/90 shrink-0 rounded-xl px-4 font-medium text-primary-foreground"
|
||||||
: "h-11 w-full rounded-lg border-[#b9d1ff] bg-white font-medium text-[#135ee8] shadow-none hover:border-[#79a8ff] hover:bg-[#f7faff] hover:text-[#135ee8] dark:border-blue-700 dark:bg-slate-900 dark:text-blue-300",
|
: "border-primary/35 text-primary hover:border-primary/55 hover:bg-primary/5 h-11 w-full rounded-lg bg-white font-medium shadow-none dark:bg-slate-900 dark:text-primary",
|
||||||
)}
|
)}
|
||||||
onClick={handleChat}
|
onClick={handleChat}
|
||||||
>
|
>
|
||||||
@@ -857,8 +857,8 @@ export function AgentCard({ agent, layout = "card", onPublisherClick }: AgentCar
|
|||||||
私密
|
私密
|
||||||
</Badge>
|
</Badge>
|
||||||
) : agent.published || isBuiltin ? (
|
) : agent.published || isBuiltin ? (
|
||||||
<Badge className="border-0 bg-blue-50 px-2.5 py-1 text-xs font-normal text-blue-600 hover:bg-blue-50 dark:bg-blue-500/15 dark:text-blue-300">
|
<Badge className="border-0 bg-primary/5 text-primary hover:bg-primary/5 px-2.5 py-1 text-xs font-normal dark:bg-primary/15 dark:text-primary">
|
||||||
<span className="mr-1.5 size-1.5 rounded-full bg-blue-500" />
|
<span className="bg-primary mr-1.5 size-1.5 rounded-full" />
|
||||||
已发布
|
已发布
|
||||||
</Badge>
|
</Badge>
|
||||||
) : (
|
) : (
|
||||||
@@ -944,15 +944,15 @@ export function AgentCard({ agent, layout = "card", onPublisherClick }: AgentCar
|
|||||||
const cardLayout = (
|
const cardLayout = (
|
||||||
<Card
|
<Card
|
||||||
className={cn(
|
className={cn(
|
||||||
"group flex min-h-[366px] min-w-0 flex-col gap-0 overflow-hidden rounded-2xl border-slate-200/90 bg-white py-0 shadow-[0_5px_18px_rgba(15,23,42,0.035)] transition-[background-color,border-color,box-shadow] duration-200 hover:!border-[#b8d1ff] hover:!bg-[linear-gradient(135deg,rgba(239,246,255,0.92)_0%,rgba(255,255,255,0.98)_48%,#fff_100%)] hover:!ring-1 hover:!ring-[#e2edff] hover:shadow-[0_8px_24px_rgba(37,99,235,0.07)] dark:border-slate-800 dark:bg-slate-900",
|
"group flex min-h-[334px] min-w-0 flex-col gap-0 overflow-hidden rounded-2xl border-slate-200/90 bg-white py-0 shadow-[0_5px_18px_rgba(15,23,42,0.035)] transition-[background-color,border-color,box-shadow] duration-200 hover:!border-primary/30 hover:!bg-primary/5 hover:!ring-1 hover:!ring-primary/10 hover:shadow-[0_8px_24px_rgba(15,23,42,0.08)] dark:border-slate-800 dark:bg-slate-900",
|
||||||
agent.featured_order != null && "border-blue-300 ring-1 ring-blue-100 dark:border-blue-700 dark:ring-blue-900/40",
|
agent.featured_order != null && "border-primary/40 ring-1 ring-primary/15 dark:border-primary/45 dark:ring-primary/20",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<CardHeader className="min-w-0 gap-0 px-5 pt-5 pb-2">
|
<CardHeader className="min-w-0 gap-0 px-5 pt-5 pb-2">
|
||||||
{agent.featured_order != null ? (
|
{agent.featured_order != null ? (
|
||||||
<>
|
<>
|
||||||
<div className="mb-1 flex h-7 items-center justify-between">
|
<div className="mb-1 flex h-7 items-center justify-between">
|
||||||
<Badge className="border border-blue-200 bg-blue-50 px-2.5 py-1 text-xs font-medium text-blue-600 hover:bg-blue-50 dark:border-blue-800 dark:bg-blue-500/15 dark:text-blue-300">
|
<Badge className="border border-primary/20 bg-primary/5 text-primary hover:bg-primary/5 px-2.5 py-1 text-xs font-medium dark:border-primary/40 dark:bg-primary/15 dark:text-primary">
|
||||||
<SparklesIcon className="mr-1 size-3.5 fill-current" />
|
<SparklesIcon className="mr-1 size-3.5 fill-current" />
|
||||||
推荐
|
推荐
|
||||||
</Badge>
|
</Badge>
|
||||||
@@ -991,7 +991,7 @@ export function AgentCard({ agent, layout = "card", onPublisherClick }: AgentCar
|
|||||||
</CardContent>
|
</CardContent>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<CardFooter className="mt-auto flex flex-col items-stretch gap-10 px-5 pt-2 pb-4">
|
<CardFooter className="mt-auto flex flex-col items-stretch gap-4 px-5 pt-2 pb-4">
|
||||||
<div className="flex min-w-0 items-center gap-3">
|
<div className="flex min-w-0 items-center gap-3">
|
||||||
{cardStatusBadge}
|
{cardStatusBadge}
|
||||||
<span
|
<span
|
||||||
@@ -1008,7 +1008,7 @@ export function AgentCard({ agent, layout = "card", onPublisherClick }: AgentCar
|
|||||||
);
|
);
|
||||||
|
|
||||||
const listLayout = (
|
const listLayout = (
|
||||||
<div className="group flex min-w-0 items-center gap-4 rounded-2xl border border-slate-200/90 bg-white p-4 shadow-[0_8px_24px_rgba(15,23,42,0.04)] transition-all hover:border-blue-200 hover:shadow-[0_12px_32px_rgba(37,99,235,0.09)] dark:border-slate-800 dark:bg-slate-900">
|
<div className="group flex min-w-0 items-center gap-4 rounded-2xl border border-slate-200/90 bg-white p-4 shadow-[0_8px_24px_rgba(15,23,42,0.04)] transition-all hover:border-primary/25 hover:shadow-[0_12px_32px_rgba(15,23,42,0.09)] dark:border-slate-800 dark:bg-slate-900">
|
||||||
<AgentBrandIcon className="agent-avatar" size="md" />
|
<AgentBrandIcon className="agent-avatar" size="md" />
|
||||||
<div className="min-w-0 flex-1 overflow-hidden">
|
<div className="min-w-0 flex-1 overflow-hidden">
|
||||||
<div className="flex min-w-0 items-center gap-2">
|
<div className="flex min-w-0 items-center gap-2">
|
||||||
|
|||||||
@@ -271,17 +271,17 @@ export function AgentGallery() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const renderEmpty = (description: string, showNewButton = false) => (
|
const renderEmpty = (description: string, showNewButton = false) => (
|
||||||
<div className="flex h-72 flex-col items-center justify-center gap-3 rounded-2xl border border-dashed border-blue-200 bg-white/70 text-center shadow-[0_12px_36px_rgba(37,99,235,0.05)] dark:border-blue-900 dark:bg-slate-900/70">
|
<div className="flex h-72 flex-col items-center justify-center gap-3 rounded-2xl border border-dashed border-primary/25 bg-white/70 text-center shadow-[0_12px_36px_rgba(15,23,42,0.05)] dark:border-primary/40 dark:bg-slate-900/70">
|
||||||
<AgentBrandIcon size="lg" />
|
<AgentBrandIcon size="lg" />
|
||||||
<div>
|
<div>
|
||||||
<p className="font-medium dark:text-[#AACEFF]">{t.agents.emptyTitle}</p>
|
<p className="font-medium">{t.agents.emptyTitle}</p>
|
||||||
<p className="text-muted-foreground mt-1 text-sm dark:text-[#55A6FE]">
|
<p className="text-muted-foreground mt-1 text-sm">
|
||||||
{description}
|
{description}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
{showNewButton && (
|
{showNewButton && (
|
||||||
<Button
|
<Button
|
||||||
className="mt-2 rounded-xl bg-[#1f63e9] px-5 shadow-[0_8px_20px_rgba(31,99,233,0.22)] hover:bg-[#1857d4] dark:border-[#2580FF] dark:bg-[#2580FF] dark:text-white dark:hover:border-[#2580FF] dark:hover:bg-[#2580FF]/90 dark:hover:text-white"
|
className="bg-primary hover:bg-primary/90 mt-2 rounded-xl px-5 text-primary-foreground shadow-[0_8px_20px_rgba(15,23,42,0.16)]"
|
||||||
onClick={handleNewAgent}
|
onClick={handleNewAgent}
|
||||||
>
|
>
|
||||||
<PlusIcon className="mr-1.5 h-4 w-4" />
|
<PlusIcon className="mr-1.5 h-4 w-4" />
|
||||||
@@ -368,20 +368,20 @@ export function AgentGallery() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex size-full min-h-0 flex-col overflow-hidden border-y border-r border-slate-200/80 bg-white dark:border-slate-800 dark:bg-slate-950">
|
<div className="flex size-full min-h-0 flex-col overflow-hidden bg-white dark:bg-slate-950">
|
||||||
{/* Page header */}
|
{/* Page header */}
|
||||||
<div className="flex shrink-0 items-start justify-between px-[38px] pt-[45px] pb-[38px]">
|
<div className="flex shrink-0 items-start justify-between px-5 pt-7 pb-6 sm:px-8">
|
||||||
<div>
|
<div>
|
||||||
<h1 className="text-[28px] leading-none font-semibold tracking-[-0.03em] text-slate-950 dark:text-white">
|
<h1 className="text-[26px] leading-none font-semibold tracking-[-0.03em] text-slate-950 dark:text-white">
|
||||||
{t.agents.title}
|
{t.agents.title}
|
||||||
</h1>
|
</h1>
|
||||||
<p className="mt-4 text-[15px] text-slate-500 dark:text-slate-400">
|
<p className="mt-2.5 text-[15px] text-slate-500 dark:text-slate-400">
|
||||||
创建并管理专属的 AI 智能体,助力更高效的工作与决策。
|
创建并管理专属的 AI 智能体,助力更高效的工作与决策。
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<Button
|
<Button
|
||||||
onClick={handleNewAgent}
|
onClick={handleNewAgent}
|
||||||
className="h-12 w-[154px] rounded-lg bg-gradient-to-r from-[#2467ea] to-[#0f54ed] px-0 text-[15px] font-medium shadow-[0_9px_22px_rgba(31,99,233,0.22)] hover:brightness-105"
|
className="bg-primary hover:bg-primary/90 h-11 w-[148px] rounded-xl px-0 text-[15px] font-medium text-primary-foreground shadow-[0_9px_22px_rgba(15,23,42,0.16)]"
|
||||||
>
|
>
|
||||||
<PlusIcon className="mr-2 h-[18px] w-[18px]" />
|
<PlusIcon className="mr-2 h-[18px] w-[18px]" />
|
||||||
{t.agents.newAgent}
|
{t.agents.newAgent}
|
||||||
@@ -401,12 +401,12 @@ export function AgentGallery() {
|
|||||||
}}
|
}}
|
||||||
className="flex min-h-0 flex-1 flex-col overflow-hidden"
|
className="flex min-h-0 flex-1 flex-col overflow-hidden"
|
||||||
>
|
>
|
||||||
<div className="shrink-0 px-[38px]">
|
<div className="shrink-0 px-5 sm:px-8">
|
||||||
<div className="flex min-h-14 flex-col gap-3 border-b border-slate-200/90 lg:flex-row lg:items-end lg:justify-between dark:border-slate-800">
|
<div className="flex min-h-12 flex-col gap-3 border-b border-slate-200/90 lg:flex-row lg:items-end lg:justify-between dark:border-slate-800">
|
||||||
<TabsList variant="line" className="h-auto w-auto max-w-full flex-wrap justify-start self-start rounded-none border-0 bg-transparent p-0">
|
<TabsList variant="line" className="h-auto w-auto max-w-full flex-wrap justify-start self-start rounded-none border-0 bg-transparent p-0">
|
||||||
<TabsTrigger
|
<TabsTrigger
|
||||||
value="mine"
|
value="mine"
|
||||||
className="h-14 rounded-none border-x-0 border-t-0 border-b-2 border-transparent bg-transparent px-3 text-[15px] shadow-none after:hidden data-[state=active]:border-x-0 data-[state=active]:border-t-0 data-[state=active]:!border-b-[#2166e8] data-[state=active]:bg-transparent data-[state=active]:text-[#2166e8] data-[state=active]:!shadow-none"
|
className="h-12 rounded-none border-x-0 border-t-0 border-b-2 border-transparent bg-transparent px-3 text-[15px] shadow-none after:hidden data-[state=active]:border-x-0 data-[state=active]:border-t-0 data-[state=active]:!border-b-primary data-[state=active]:bg-transparent data-[state=active]:text-primary data-[state=active]:!shadow-none"
|
||||||
>
|
>
|
||||||
我的
|
我的
|
||||||
</TabsTrigger>
|
</TabsTrigger>
|
||||||
@@ -415,7 +415,7 @@ export function AgentGallery() {
|
|||||||
key={sq.id}
|
key={sq.id}
|
||||||
value={sq.id}
|
value={sq.id}
|
||||||
title={sq.description || sq.name}
|
title={sq.description || sq.name}
|
||||||
className="h-14 rounded-none border-x-0 border-t-0 border-b-2 border-transparent bg-transparent px-5 text-[15px] shadow-none after:hidden data-[state=active]:border-x-0 data-[state=active]:border-t-0 data-[state=active]:!border-b-[#2166e8] data-[state=active]:bg-transparent data-[state=active]:text-[#2166e8] data-[state=active]:!shadow-none"
|
className="h-12 rounded-none border-x-0 border-t-0 border-b-2 border-transparent bg-transparent px-5 text-[15px] shadow-none after:hidden data-[state=active]:border-x-0 data-[state=active]:border-t-0 data-[state=active]:!border-b-primary data-[state=active]:bg-transparent data-[state=active]:text-primary data-[state=active]:!shadow-none"
|
||||||
>
|
>
|
||||||
{sq.name}
|
{sq.name}
|
||||||
</TabsTrigger>
|
</TabsTrigger>
|
||||||
@@ -423,7 +423,7 @@ export function AgentGallery() {
|
|||||||
{privateFeatureAvailable && (
|
{privateFeatureAvailable && (
|
||||||
<TabsTrigger
|
<TabsTrigger
|
||||||
value="private"
|
value="private"
|
||||||
className="h-14 rounded-none border-x-0 border-t-0 border-b-2 border-transparent bg-transparent px-5 text-[15px] shadow-none after:hidden data-[state=active]:border-x-0 data-[state=active]:border-t-0 data-[state=active]:!border-b-[#2166e8] data-[state=active]:bg-transparent data-[state=active]:text-[#2166e8] data-[state=active]:!shadow-none"
|
className="h-12 rounded-none border-x-0 border-t-0 border-b-2 border-transparent bg-transparent px-5 text-[15px] shadow-none after:hidden data-[state=active]:border-x-0 data-[state=active]:border-t-0 data-[state=active]:!border-b-primary data-[state=active]:bg-transparent data-[state=active]:text-primary data-[state=active]:!shadow-none"
|
||||||
>
|
>
|
||||||
<LockIcon className="mr-1 h-3.5 w-3.5" />
|
<LockIcon className="mr-1 h-3.5 w-3.5" />
|
||||||
私密广场
|
私密广场
|
||||||
@@ -433,7 +433,7 @@ export function AgentGallery() {
|
|||||||
<TabsTrigger
|
<TabsTrigger
|
||||||
value="builtin"
|
value="builtin"
|
||||||
title="内置/功能型智能体(仅管理员可见)"
|
title="内置/功能型智能体(仅管理员可见)"
|
||||||
className="h-14 rounded-none border-x-0 border-t-0 border-b-2 border-transparent bg-transparent px-5 text-[15px] shadow-none after:hidden data-[state=active]:border-x-0 data-[state=active]:border-t-0 data-[state=active]:!border-b-[#2166e8] data-[state=active]:bg-transparent data-[state=active]:text-[#2166e8] data-[state=active]:!shadow-none"
|
className="h-12 rounded-none border-x-0 border-t-0 border-b-2 border-transparent bg-transparent px-5 text-[15px] shadow-none after:hidden data-[state=active]:border-x-0 data-[state=active]:border-t-0 data-[state=active]:!border-b-primary data-[state=active]:bg-transparent data-[state=active]:text-primary data-[state=active]:!shadow-none"
|
||||||
>
|
>
|
||||||
<BotIcon className="mr-1 h-3.5 w-3.5" />
|
<BotIcon className="mr-1 h-3.5 w-3.5" />
|
||||||
内置智能体
|
内置智能体
|
||||||
@@ -441,24 +441,24 @@ export function AgentGallery() {
|
|||||||
)}
|
)}
|
||||||
</TabsList>
|
</TabsList>
|
||||||
{showSearchBar && (
|
{showSearchBar && (
|
||||||
<div className="flex flex-wrap items-center justify-end gap-5 pb-2.5">
|
<div className="flex flex-wrap items-center justify-end gap-3 pb-2">
|
||||||
<div className="relative w-[350px] max-w-full">
|
<div className="relative w-[320px] max-w-full">
|
||||||
<SearchIcon className="pointer-events-none absolute top-1/2 left-3.5 size-[18px] -translate-y-1/2 text-slate-500" />
|
<SearchIcon className="pointer-events-none absolute top-1/2 left-3.5 size-[18px] -translate-y-1/2 text-slate-500" />
|
||||||
<Input
|
<Input
|
||||||
value={search}
|
value={search}
|
||||||
onChange={(event) => setSearch(event.target.value)}
|
onChange={(event) => setSearch(event.target.value)}
|
||||||
placeholder="搜索智能体名称或描述"
|
placeholder="搜索智能体名称或描述"
|
||||||
className="h-12 rounded-xl border-slate-200 bg-white pl-11 text-sm shadow-none placeholder:text-slate-400 focus-visible:border-blue-400 focus-visible:ring-blue-100 dark:border-slate-700 dark:bg-slate-900"
|
className="h-11 rounded-xl border-slate-200 bg-white pl-11 text-sm shadow-none placeholder:text-slate-400 focus-visible:border-primary/50 focus-visible:ring-primary/15 dark:border-slate-700 dark:bg-slate-900"
|
||||||
/>
|
/>
|
||||||
{(activeTab === "private" ? isPrivateFetching : mainFetching) && (
|
{(activeTab === "private" ? isPrivateFetching : mainFetching) && (
|
||||||
<Loader2 className="absolute top-1/2 right-3.5 size-4 -translate-y-1/2 animate-spin text-blue-500" />
|
<Loader2 className="text-primary absolute top-1/2 right-3.5 size-4 -translate-y-1/2 animate-spin" />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<Select
|
<Select
|
||||||
value={statusFilter}
|
value={statusFilter}
|
||||||
onValueChange={(value) => setStatusFilter(value as AgentStatusFilter)}
|
onValueChange={(value) => setStatusFilter(value as AgentStatusFilter)}
|
||||||
>
|
>
|
||||||
<SelectTrigger className="h-12 w-[156px] rounded-xl border-slate-200 px-4 text-sm shadow-none dark:border-slate-700">
|
<SelectTrigger className="h-11 w-[150px] rounded-xl border-slate-200 px-4 text-sm shadow-none dark:border-slate-700">
|
||||||
<SelectValue />
|
<SelectValue />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent position="popper" side="bottom" sideOffset={4}>
|
<SelectContent position="popper" side="bottom" sideOffset={4}>
|
||||||
@@ -471,7 +471,7 @@ export function AgentGallery() {
|
|||||||
</Select>
|
</Select>
|
||||||
<Select value={sort} onValueChange={(v) => setSort(v as AgentSort)}>
|
<Select value={sort} onValueChange={(v) => setSort(v as AgentSort)}>
|
||||||
<SelectTrigger
|
<SelectTrigger
|
||||||
className="h-12 w-[156px] rounded-xl border-slate-200 px-4 text-sm shadow-none dark:border-slate-700"
|
className="h-11 w-[150px] rounded-xl border-slate-200 px-4 text-sm shadow-none dark:border-slate-700"
|
||||||
title="排序"
|
title="排序"
|
||||||
>
|
>
|
||||||
<ArrowDownUpIcon className="mr-1 size-4 text-slate-500" />
|
<ArrowDownUpIcon className="mr-1 size-4 text-slate-500" />
|
||||||
@@ -506,7 +506,7 @@ export function AgentGallery() {
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => setPublisher(null)}
|
onClick={() => setPublisher(null)}
|
||||||
className="inline-flex items-center gap-1 rounded-full bg-blue-50 px-3 py-1 text-xs font-medium text-blue-700 transition-colors hover:bg-blue-100 dark:bg-blue-500/15 dark:text-blue-300"
|
className="bg-primary/5 text-primary hover:bg-primary/10 inline-flex items-center gap-1 rounded-full px-3 py-1 text-xs font-medium transition-colors dark:bg-primary/15 dark:text-primary"
|
||||||
title="点击清除发布者筛选"
|
title="点击清除发布者筛选"
|
||||||
>
|
>
|
||||||
{publisher.label}
|
{publisher.label}
|
||||||
@@ -514,7 +514,7 @@ export function AgentGallery() {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="py-5 text-[15px] text-slate-600 dark:text-slate-300">
|
<div className="py-4 text-[15px] text-slate-600 dark:text-slate-300">
|
||||||
共 {activeTotal} 个智能体
|
共 {activeTotal} 个智能体
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -523,7 +523,7 @@ export function AgentGallery() {
|
|||||||
<TabsContent
|
<TabsContent
|
||||||
key={sq.id}
|
key={sq.id}
|
||||||
value={sq.id}
|
value={sq.id}
|
||||||
className="mt-0 flex-1 overflow-y-auto px-[38px] pb-8"
|
className="mt-0 flex-1 overflow-y-auto px-5 pb-6 sm:px-8"
|
||||||
>
|
>
|
||||||
{renderListBody({
|
{renderListBody({
|
||||||
list: mainAgents,
|
list: mainAgents,
|
||||||
@@ -536,7 +536,7 @@ export function AgentGallery() {
|
|||||||
</TabsContent>
|
</TabsContent>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
<TabsContent value="mine" className="mt-0 flex-1 overflow-y-auto px-[38px] pb-8">
|
<TabsContent value="mine" className="mt-0 flex-1 overflow-y-auto px-5 pb-6 sm:px-8">
|
||||||
{renderListBody({
|
{renderListBody({
|
||||||
list: mainAgents,
|
list: mainAgents,
|
||||||
total: mainTotal,
|
total: mainTotal,
|
||||||
@@ -549,7 +549,7 @@ export function AgentGallery() {
|
|||||||
</TabsContent>
|
</TabsContent>
|
||||||
|
|
||||||
{isAdmin && (
|
{isAdmin && (
|
||||||
<TabsContent value="builtin" className="mt-0 flex-1 overflow-y-auto px-[38px] pb-8">
|
<TabsContent value="builtin" className="mt-0 flex-1 overflow-y-auto px-5 pb-6 sm:px-8">
|
||||||
{renderListBody({
|
{renderListBody({
|
||||||
list: mainAgents,
|
list: mainAgents,
|
||||||
total: mainTotal,
|
total: mainTotal,
|
||||||
@@ -564,7 +564,7 @@ export function AgentGallery() {
|
|||||||
{privateFeatureAvailable && (
|
{privateFeatureAvailable && (
|
||||||
<TabsContent
|
<TabsContent
|
||||||
value="private"
|
value="private"
|
||||||
className="mt-0 flex-1 overflow-y-auto px-[38px] pb-8"
|
className="mt-0 flex-1 overflow-y-auto px-5 pb-6 sm:px-8"
|
||||||
>
|
>
|
||||||
{renderPrivateTab()}
|
{renderPrivateTab()}
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import type { MouseEvent } from "react";
|
|||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
|
import { useTheme } from "@/contexts/ThemeContext";
|
||||||
|
|
||||||
import { AgentBrandIcon } from "./agents/agent-brand-icon";
|
import { AgentBrandIcon } from "./agents/agent-brand-icon";
|
||||||
import { RecentChatList } from "./recent-chat-list";
|
import { RecentChatList } from "./recent-chat-list";
|
||||||
@@ -63,6 +64,8 @@ export function CmChatSidebar({
|
|||||||
}) {
|
}) {
|
||||||
const pathname = usePathname();
|
const pathname = usePathname();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const { theme } = useTheme();
|
||||||
|
const brandLogoSrc = theme === "light" ? "/cm-assistant-logo-red.png" : "/cm-assistant-logo.png";
|
||||||
|
|
||||||
const handleNewChat = (event: MouseEvent<HTMLAnchorElement>) => {
|
const handleNewChat = (event: MouseEvent<HTMLAnchorElement>) => {
|
||||||
if (event.metaKey || event.ctrlKey || event.shiftKey || event.button === 1) return;
|
if (event.metaKey || event.ctrlKey || event.shiftKey || event.button === 1) return;
|
||||||
@@ -78,10 +81,10 @@ export function CmChatSidebar({
|
|||||||
onClick={onCollapse}
|
onClick={onCollapse}
|
||||||
aria-label="展开侧边栏"
|
aria-label="展开侧边栏"
|
||||||
title="展开侧边栏"
|
title="展开侧边栏"
|
||||||
className="mx-auto mt-2 flex size-11 shrink-0 items-center justify-center rounded-xl transition-colors hover:bg-slate-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500/40 dark:hover:bg-slate-900"
|
className="mx-auto mt-2 flex size-11 shrink-0 items-center justify-center rounded-xl transition-colors hover:bg-slate-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/40 dark:hover:bg-slate-900"
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
src="/cm-assistant-logo.png"
|
src={brandLogoSrc}
|
||||||
alt="CM 助手"
|
alt="CM 助手"
|
||||||
className="size-10 object-contain"
|
className="size-10 object-contain"
|
||||||
/>
|
/>
|
||||||
@@ -105,9 +108,9 @@ export function CmChatSidebar({
|
|||||||
aria-label={item.label}
|
aria-label={item.label}
|
||||||
title={item.label}
|
title={item.label}
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex size-10 items-center justify-center rounded-xl transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500/40",
|
"flex size-10 items-center justify-center rounded-xl transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/40",
|
||||||
active
|
active
|
||||||
? "bg-[#edf4ff] text-[#165ee8] dark:bg-blue-500/15 dark:text-blue-300"
|
? "bg-primary/10 text-primary dark:bg-primary/15 dark:text-primary"
|
||||||
: "text-slate-600 hover:bg-slate-100 hover:text-slate-950 dark:text-slate-300 dark:hover:bg-slate-900 dark:hover:text-white",
|
: "text-slate-600 hover:bg-slate-100 hover:text-slate-950 dark:text-slate-300 dark:hover:bg-slate-900 dark:hover:text-white",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
@@ -127,7 +130,7 @@ export function CmChatSidebar({
|
|||||||
href="/page/workspace/settings"
|
href="/page/workspace/settings"
|
||||||
aria-label="设置和更多"
|
aria-label="设置和更多"
|
||||||
title="设置和更多"
|
title="设置和更多"
|
||||||
className="flex size-10 items-center justify-center rounded-xl text-slate-600 transition-colors hover:bg-slate-100 hover:text-slate-950 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500/40 dark:text-slate-300 dark:hover:bg-slate-900 dark:hover:text-white"
|
className="flex size-10 items-center justify-center rounded-xl text-slate-600 transition-colors hover:bg-slate-100 hover:text-slate-950 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/40 dark:text-slate-300 dark:hover:bg-slate-900 dark:hover:text-white"
|
||||||
>
|
>
|
||||||
<Settings className="size-[19px]" strokeWidth={1.8} />
|
<Settings className="size-[19px]" strokeWidth={1.8} />
|
||||||
</Link>
|
</Link>
|
||||||
@@ -138,27 +141,27 @@ export function CmChatSidebar({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex h-full min-h-0 flex-col overflow-hidden border-r border-slate-200/80 bg-white text-slate-900 dark:border-slate-800 dark:bg-slate-950 dark:text-slate-100">
|
<div className="flex h-full min-h-0 flex-col overflow-hidden border-r border-slate-200/80 bg-white text-slate-900 dark:border-slate-800 dark:bg-slate-950 dark:text-slate-100">
|
||||||
<div className="flex shrink-0 items-center gap-2 px-6 pt-4 pb-3">
|
<div className="flex shrink-0 items-center gap-1.5 px-4 pt-3.5 pb-2.5">
|
||||||
<Link href={NEW_CHAT_PATH} className="flex min-w-0 flex-1 items-center gap-3.5 outline-none focus-visible:ring-2 focus-visible:ring-blue-500/40">
|
<Link href={NEW_CHAT_PATH} className="flex min-w-0 flex-1 items-center gap-2.5 outline-none focus-visible:ring-2 focus-visible:ring-primary/40">
|
||||||
<img
|
<img
|
||||||
src="/cm-assistant-logo.png"
|
src={brandLogoSrc}
|
||||||
alt="CM 助手"
|
alt="CM 助手"
|
||||||
className="size-10 shrink-0 object-contain"
|
className="size-9 shrink-0 object-contain"
|
||||||
/>
|
/>
|
||||||
<span className="truncate text-[20px] font-semibold tracking-[-0.025em]">CM 助手</span>
|
<span className="truncate text-[19px] font-semibold tracking-[-0.025em]">CM 助手</span>
|
||||||
</Link>
|
</Link>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={onCollapse}
|
onClick={onCollapse}
|
||||||
aria-label="收起侧边栏"
|
aria-label="收起侧边栏"
|
||||||
title="收起侧边栏"
|
title="收起侧边栏"
|
||||||
className="flex size-8 shrink-0 items-center justify-center rounded-md text-slate-500 transition-colors hover:bg-slate-100 hover:text-slate-900 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500/40 dark:hover:bg-slate-900 dark:hover:text-white"
|
className="flex size-8 shrink-0 items-center justify-center rounded-md text-slate-500 transition-colors hover:bg-slate-100 hover:text-slate-900 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/40 dark:hover:bg-slate-900 dark:hover:text-white"
|
||||||
>
|
>
|
||||||
<PanelLeftClose className="size-[18px]" strokeWidth={1.8} />
|
<PanelLeftClose className="size-[18px]" strokeWidth={1.8} />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<nav className="shrink-0 px-4 pt-1" aria-label="工作台导航">
|
<nav className="shrink-0 px-3 pt-1" aria-label="工作台导航">
|
||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
{NAV_ITEMS.map((item) => {
|
{NAV_ITEMS.map((item) => {
|
||||||
const active = item.href === NEW_CHAT_PATH
|
const active = item.href === NEW_CHAT_PATH
|
||||||
@@ -174,9 +177,9 @@ export function CmChatSidebar({
|
|||||||
onClick={item.href === NEW_CHAT_PATH ? handleNewChat : undefined}
|
onClick={item.href === NEW_CHAT_PATH ? handleNewChat : undefined}
|
||||||
aria-current={active ? "page" : undefined}
|
aria-current={active ? "page" : undefined}
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex h-11 items-center gap-3 rounded-xl px-4 text-[14px] font-medium transition-colors",
|
"flex h-10 items-center gap-3 rounded-xl px-3 text-[14px] font-medium transition-colors",
|
||||||
active
|
active
|
||||||
? "bg-[#edf4ff] text-[#165ee8] dark:bg-blue-500/15 dark:text-blue-300"
|
? "bg-primary/10 text-primary dark:bg-primary/15 dark:text-primary"
|
||||||
: "text-slate-600 hover:bg-slate-100 hover:text-slate-950 dark:text-slate-300 dark:hover:bg-slate-900 dark:hover:text-white",
|
: "text-slate-600 hover:bg-slate-100 hover:text-slate-950 dark:text-slate-300 dark:hover:bg-slate-900 dark:hover:text-white",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ export function CustomPromptBar({
|
|||||||
title={prompt.content}
|
title={prompt.content}
|
||||||
className={cn(
|
className={cn(
|
||||||
"border-border/60 bg-muted/40 text-foreground/80 hover:bg-muted hover:text-foreground hover:border-border max-w-[200px] shrink-0 truncate rounded-full border px-3 py-1 text-xs font-medium shadow-sm transition-colors",
|
"border-border/60 bg-muted/40 text-foreground/80 hover:bg-muted hover:text-foreground hover:border-border max-w-[200px] shrink-0 truncate rounded-full border px-3 py-1 text-xs font-medium shadow-sm transition-colors",
|
||||||
compact && "border-slate-200 bg-white px-3.5 py-1.5 text-[12px] text-slate-600 shadow-none hover:border-blue-200 hover:bg-blue-50/60 hover:text-blue-700",
|
compact && "border-slate-200 bg-white px-3.5 py-1.5 text-[12px] text-slate-600 shadow-none hover:border-primary/25 hover:bg-primary/5 hover:text-primary",
|
||||||
"dark:border-slate-600/70 dark:bg-slate-700/40 dark:text-slate-200 dark:hover:bg-slate-700",
|
"dark:border-slate-600/70 dark:bg-slate-700/40 dark:text-slate-200 dark:hover:bg-slate-700",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
@@ -151,7 +151,7 @@ export function CustomPromptBar({
|
|||||||
className={cn(
|
className={cn(
|
||||||
"text-muted-foreground hover:text-foreground hover:bg-muted/70 h-7 w-7 shrink-0 rounded-full",
|
"text-muted-foreground hover:text-foreground hover:bg-muted/70 h-7 w-7 shrink-0 rounded-full",
|
||||||
compact &&
|
compact &&
|
||||||
"h-9 w-9 rounded-xl border border-slate-200 bg-white text-slate-600 shadow-[0_6px_18px_-14px_rgba(15,23,42,0.4)] hover:border-blue-200 hover:bg-blue-50 hover:text-blue-700 dark:border-slate-700 dark:bg-slate-900",
|
"h-9 w-9 rounded-xl border border-slate-200 bg-white text-slate-600 shadow-[0_6px_18px_-14px_rgba(15,23,42,0.4)] hover:border-primary/25 hover:bg-primary/5 hover:text-primary dark:border-slate-700 dark:bg-slate-900",
|
||||||
)}
|
)}
|
||||||
title="管理常用提示词"
|
title="管理常用提示词"
|
||||||
aria-label="管理常用提示词"
|
aria-label="管理常用提示词"
|
||||||
|
|||||||
@@ -637,7 +637,7 @@ export function InputBox({
|
|||||||
title="调整提示词顺序"
|
title="调整提示词顺序"
|
||||||
aria-label="调整提示词顺序"
|
aria-label="调整提示词顺序"
|
||||||
onClick={() => setCompactPromptOrder((current) => current + 1)}
|
onClick={() => setCompactPromptOrder((current) => current + 1)}
|
||||||
className="flex size-7 items-center justify-center rounded-full text-slate-400 transition-colors hover:bg-slate-100 hover:text-blue-600 focus-visible:outline-none focus-visible:ring-4 focus-visible:ring-blue-500/15 dark:hover:bg-slate-800 dark:hover:text-blue-300"
|
className="flex size-7 items-center justify-center rounded-full text-slate-400 transition-colors hover:bg-slate-100 hover:text-primary focus-visible:outline-none focus-visible:ring-4 focus-visible:ring-primary/15 dark:hover:bg-slate-800 dark:hover:text-primary"
|
||||||
>
|
>
|
||||||
<RefreshCwIcon className="size-3.5" strokeWidth={1.8} />
|
<RefreshCwIcon className="size-3.5" strokeWidth={1.8} />
|
||||||
</button>
|
</button>
|
||||||
@@ -650,7 +650,7 @@ export function InputBox({
|
|||||||
type="button"
|
type="button"
|
||||||
data-quick-prompt={item.id}
|
data-quick-prompt={item.id}
|
||||||
title={item.content}
|
title={item.content}
|
||||||
className="inline-flex min-h-11 max-w-full items-center justify-center rounded-xl border border-[#e5e7eb] bg-white px-4 py-2 text-center text-[14px] font-normal leading-5 text-slate-700 shadow-[0_2px_6px_rgba(15,23,42,0.025)] transition-[background-color,border-color,box-shadow] hover:border-slate-300 hover:bg-slate-50 hover:text-slate-900 hover:shadow-[0_4px_10px_rgba(15,23,42,0.04)] focus-visible:outline-none focus-visible:ring-4 focus-visible:ring-blue-500/15 dark:border-slate-700 dark:bg-slate-900 dark:text-slate-200 dark:hover:border-slate-600 dark:hover:bg-slate-800"
|
className="inline-flex min-h-11 max-w-full items-center justify-center rounded-xl border border-[#e5e7eb] bg-white px-4 py-2 text-center text-[14px] font-normal leading-5 text-slate-700 shadow-[0_2px_6px_rgba(15,23,42,0.025)] transition-[background-color,border-color,box-shadow] hover:border-primary/25 hover:bg-primary/5 hover:text-slate-900 hover:shadow-[0_4px_10px_rgba(15,23,42,0.04)] focus-visible:outline-none focus-visible:ring-4 focus-visible:ring-primary/15 dark:border-slate-700 dark:bg-slate-900 dark:text-slate-200 dark:hover:border-primary/35 dark:hover:bg-primary/10"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
textInput.setInput(item.content);
|
textInput.setInput(item.content);
|
||||||
requestAnimationFrame(() =>
|
requestAnimationFrame(() =>
|
||||||
@@ -748,7 +748,7 @@ export function InputBox({
|
|||||||
: "*:data-[slot='input-group']:rounded-3xl",
|
: "*:data-[slot='input-group']:rounded-3xl",
|
||||||
// 紧凑落地态(CM 参考图):白卡 + 细边 + 轻阴影 + 主色聚焦环(无旋转彩边)
|
// 紧凑落地态(CM 参考图):白卡 + 细边 + 轻阴影 + 主色聚焦环(无旋转彩边)
|
||||||
compact && isNewThread
|
compact && isNewThread
|
||||||
? "overflow-hidden rounded-[24px] border border-slate-200/90 bg-white shadow-[0_18px_50px_-32px_rgba(37,99,235,0.6),0_8px_24px_-20px_rgba(15,23,42,0.35)] transition-all duration-300 focus-within:border-blue-300 focus-within:ring-4 focus-within:ring-blue-500/10 dark:border-slate-700 dark:bg-slate-800"
|
? "overflow-hidden rounded-[24px] border border-slate-200/90 bg-white shadow-[0_18px_50px_-32px_rgba(15,23,42,0.22),0_8px_24px_-20px_rgba(15,23,42,0.35)] transition-all duration-300 focus-within:border-primary/35 focus-within:ring-4 focus-within:ring-primary/10 dark:border-slate-700 dark:bg-slate-800"
|
||||||
: // landing 态:透明,让外层 gemini-gradient-border 提供白卡 + 旋转描边
|
: // landing 态:透明,让外层 gemini-gradient-border 提供白卡 + 旋转描边
|
||||||
// 对话态:常规白卡 + 中性边框 + 轻阴影
|
// 对话态:常规白卡 + 中性边框 + 轻阴影
|
||||||
isNewThread
|
isNewThread
|
||||||
@@ -844,7 +844,7 @@ export function InputBox({
|
|||||||
"gap-1.5! rounded-full px-3! shadow-none",
|
"gap-1.5! rounded-full px-3! shadow-none",
|
||||||
compact && "rounded-lg px-2.5! py-1! text-[11px] font-medium",
|
compact && "rounded-lg px-2.5! py-1! text-[11px] font-medium",
|
||||||
memoryInjectionEnabled
|
memoryInjectionEnabled
|
||||||
? "border border-blue-300 bg-blue-50 text-blue-700 ring-1 ring-blue-300/35 hover:bg-blue-100 dark:border-cyan-300/70 dark:bg-cyan-400/20 dark:text-cyan-50 dark:ring-cyan-300/35 dark:shadow-[0_0_0_1px_rgba(34,211,238,0.18),0_0_18px_rgba(34,211,238,0.18)] dark:hover:bg-cyan-400/25"
|
? "border border-primary/35 bg-primary/5 text-primary ring-1 ring-primary/20 hover:bg-primary/10 dark:border-primary/45 dark:bg-primary/15 dark:text-primary dark:ring-primary/25 dark:hover:bg-primary/20"
|
||||||
: compact
|
: compact
|
||||||
? "border border-transparent bg-muted/40 text-muted-foreground hover:bg-muted hover:text-foreground"
|
? "border border-transparent bg-muted/40 text-muted-foreground hover:bg-muted hover:text-foreground"
|
||||||
: "border-0 bg-transparent text-muted-foreground hover:bg-muted/70 hover:text-foreground dark:text-slate-400 dark:hover:bg-slate-700/70 dark:hover:text-slate-100",
|
: "border-0 bg-transparent text-muted-foreground hover:bg-muted/70 hover:text-foreground dark:text-slate-400 dark:hover:bg-slate-700/70 dark:hover:text-slate-100",
|
||||||
@@ -852,7 +852,7 @@ export function InputBox({
|
|||||||
onClick={handleMemoryInjectionToggle}
|
onClick={handleMemoryInjectionToggle}
|
||||||
>
|
>
|
||||||
{memoryInjectionEnabled && (
|
{memoryInjectionEnabled && (
|
||||||
<CheckIcon className="size-3 text-blue-700 dark:text-cyan-50" />
|
<CheckIcon className="text-primary size-3" />
|
||||||
)}
|
)}
|
||||||
<BrainCircuitIcon className="size-3" />
|
<BrainCircuitIcon className="size-3" />
|
||||||
<span className="text-xs font-normal">记忆</span>
|
<span className="text-xs font-normal">记忆</span>
|
||||||
@@ -1303,9 +1303,9 @@ export function InputBox({
|
|||||||
</ModelSelector>
|
</ModelSelector>
|
||||||
<PromptInputSubmit
|
<PromptInputSubmit
|
||||||
className={cn(
|
className={cn(
|
||||||
"rounded-full border-border bg-background shadow-sm hover:bg-muted dark:bg-blue-500 dark:border-blue-500 dark:text-white dark:hover:bg-blue-400 dark:shadow-none",
|
"rounded-full border-border bg-background shadow-sm hover:bg-muted dark:bg-primary dark:border-primary dark:text-primary-foreground dark:hover:bg-primary/90 dark:shadow-none",
|
||||||
compact &&
|
compact &&
|
||||||
"size-10 rounded-full border-0 bg-blue-600 text-white shadow-[0_8px_18px_-10px_rgba(37,99,235,0.9)] hover:bg-blue-700 disabled:bg-muted disabled:text-muted-foreground/40 dark:border-0 dark:bg-blue-500 dark:text-white dark:hover:bg-blue-400 dark:disabled:bg-muted",
|
"bg-primary hover:bg-primary/90 size-10 rounded-full border-0 text-primary-foreground shadow-[0_8px_18px_-10px_rgba(15,23,42,0.34)] disabled:bg-muted disabled:text-muted-foreground/40 dark:border-0 dark:bg-primary dark:text-primary-foreground dark:hover:bg-primary/90 dark:disabled:bg-muted",
|
||||||
)}
|
)}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
variant="outline"
|
variant="outline"
|
||||||
|
|||||||
@@ -762,7 +762,7 @@ export function SkillRow({
|
|||||||
{isFromOthers && (
|
{isFromOthers && (
|
||||||
<Badge
|
<Badge
|
||||||
variant="outline"
|
variant="outline"
|
||||||
className="border-blue-500/30 text-blue-700 dark:text-blue-300 text-xs"
|
className="border-primary/30 text-primary text-xs dark:text-primary"
|
||||||
title={
|
title={
|
||||||
skill.owner_user_id
|
skill.owner_user_id
|
||||||
? t.settings.skills.badgeFromOthersTitle.replace(
|
? t.settings.skills.badgeFromOthersTitle.replace(
|
||||||
@@ -1027,7 +1027,7 @@ export function SkillRow({
|
|||||||
: skill.source === "agent"
|
: skill.source === "agent"
|
||||||
? {
|
? {
|
||||||
Icon: WorkflowIcon,
|
Icon: WorkflowIcon,
|
||||||
className: "bg-[#2166e8] text-white shadow-[0_6px_16px_rgba(37,99,235,0.22)]",
|
className: "bg-primary text-primary-foreground shadow-[0_6px_16px_rgba(15,23,42,0.18)]",
|
||||||
}
|
}
|
||||||
: {
|
: {
|
||||||
Icon: Upload,
|
Icon: Upload,
|
||||||
@@ -1044,7 +1044,7 @@ export function SkillRow({
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{isCard ? (
|
{isCard ? (
|
||||||
<div className="flex h-full min-w-0 flex-col rounded-xl border border-slate-200 bg-white p-5 shadow-[0_5px_18px_rgba(15,23,42,0.035)] transition-[border-color,box-shadow] hover:border-blue-200 hover:shadow-[0_10px_28px_rgba(37,99,235,0.07)] dark:border-slate-800 dark:bg-slate-900 dark:text-white">
|
<div className="flex h-full min-w-0 flex-col rounded-2xl border border-slate-200 bg-white p-5 shadow-[0_5px_18px_rgba(15,23,42,0.035)] transition-[background-color,border-color,box-shadow] hover:border-primary/25 hover:bg-primary/[0.025] hover:shadow-[0_10px_28px_rgba(15,23,42,0.07)] dark:border-slate-800 dark:bg-slate-900 dark:text-white">
|
||||||
<div
|
<div
|
||||||
className="min-w-0 flex-1 cursor-pointer"
|
className="min-w-0 flex-1 cursor-pointer"
|
||||||
onClick={() => setDetailOpen(true)}
|
onClick={() => setDetailOpen(true)}
|
||||||
@@ -1075,10 +1075,10 @@ export function SkillRow({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="group/skill-card w-full rounded-xl border border-slate-200 bg-white px-5 py-4 shadow-[0_5px_18px_rgba(15,23,42,0.03)] transition-[border-color,box-shadow] hover:border-blue-200 hover:shadow-[0_10px_28px_rgba(37,99,235,0.07)] dark:border-slate-800 dark:bg-slate-900 dark:text-white">
|
<div className="group/skill-card w-full rounded-2xl border border-slate-200 bg-white px-5 py-3.5 shadow-[0_5px_18px_rgba(15,23,42,0.03)] transition-[background-color,border-color,box-shadow] hover:border-primary/25 hover:bg-primary/[0.025] hover:shadow-[0_10px_28px_rgba(15,23,42,0.07)] dark:border-slate-800 dark:bg-slate-900 dark:text-white">
|
||||||
<div className="grid min-w-0 grid-cols-1 gap-4 xl:grid-cols-[minmax(0,1.65fr)_minmax(150px,0.72fr)_minmax(100px,0.42fr)_minmax(132px,0.58fr)_auto] xl:items-center xl:gap-x-6">
|
<div className="grid min-w-0 grid-cols-1 gap-4 xl:grid-cols-[minmax(0,1.55fr)_minmax(160px,0.78fr)_minmax(110px,0.42fr)_minmax(142px,0.56fr)_auto] xl:items-center xl:gap-x-5">
|
||||||
<div className="flex min-w-0 cursor-pointer items-start gap-4" onClick={() => setDetailOpen(true)}>
|
<div className="flex min-w-0 cursor-pointer items-start gap-3.5" onClick={() => setDetailOpen(true)}>
|
||||||
<div className={cn("flex size-[60px] shrink-0 items-center justify-center rounded-full", iconStyle.className)}>
|
<div className={cn("flex size-14 shrink-0 items-center justify-center rounded-2xl", iconStyle.className)}>
|
||||||
<SkillIcon className="size-7" />
|
<SkillIcon className="size-7" />
|
||||||
</div>
|
</div>
|
||||||
<div className="min-w-0 flex-1 pt-0.5">
|
<div className="min-w-0 flex-1 pt-0.5">
|
||||||
@@ -1097,7 +1097,7 @@ export function SkillRow({
|
|||||||
}}
|
}}
|
||||||
className={cn(
|
className={cn(
|
||||||
"mt-2 flex max-w-full items-center gap-1 text-xs text-slate-400",
|
"mt-2 flex max-w-full items-center gap-1 text-xs text-slate-400",
|
||||||
skill.owner_user_id && onPublisherClick && "cursor-pointer hover:text-blue-600 hover:underline",
|
skill.owner_user_id && onPublisherClick && "cursor-pointer hover:text-primary hover:underline",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<UserIcon className="size-3.5 shrink-0" />
|
<UserIcon className="size-3.5 shrink-0" />
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ export function UserIdentityBadge({
|
|||||||
className={cn(
|
className={cn(
|
||||||
"bg-muted text-muted-foreground relative flex size-7 shrink-0 items-center justify-center rounded-full",
|
"bg-muted text-muted-foreground relative flex size-7 shrink-0 items-center justify-center rounded-full",
|
||||||
variant === "topbar" &&
|
variant === "topbar" &&
|
||||||
"size-8 bg-gradient-to-br from-blue-500 to-indigo-600 text-white shadow-[0_4px_12px_-6px_rgba(37,99,235,0.8)] ring-1 ring-blue-500/10 dark:from-blue-400 dark:to-indigo-500",
|
"bg-primary text-primary-foreground size-8 shadow-[0_4px_12px_-6px_rgba(15,23,42,0.26)] ring-1 ring-primary/15",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<UserRound className={cn("size-3.5", variant === "topbar" && "size-4")} />
|
<UserRound className={cn("size-3.5", variant === "topbar" && "size-4")} />
|
||||||
|
|||||||
@@ -136,7 +136,9 @@ export function WorkspaceLayout({
|
|||||||
{
|
{
|
||||||
'--page-sidebar-width': pageSidebarWidth,
|
'--page-sidebar-width': pageSidebarWidth,
|
||||||
'--header-height': headerHidden ? '0rem' : '4rem',
|
'--header-height': headerHidden ? '0rem' : '4rem',
|
||||||
'--sidebar-width': '18.5rem',
|
// Shared by red, blue, and dark workbench themes. Keep this in sync
|
||||||
|
// with the Sidebar primitive instead of giving one route a wider rail.
|
||||||
|
'--sidebar-width': '14rem',
|
||||||
} as CSSProperties
|
} as CSSProperties
|
||||||
}
|
}
|
||||||
key={String(compactWorkspaceSidebar)}
|
key={String(compactWorkspaceSidebar)}
|
||||||
|
|||||||
@@ -1290,9 +1290,9 @@ html.lightblue .tiptap-writing-editor .ProseMirror ::selection {
|
|||||||
* agent surfaces on classic rgba()/hex colours instead.
|
* agent surfaces on classic rgba()/hex colours instead.
|
||||||
* -------------------------------------------------------------------------- */
|
* -------------------------------------------------------------------------- */
|
||||||
.agent-avatar {
|
.agent-avatar {
|
||||||
background-color: #edf4ff;
|
background-color: #fff1f0;
|
||||||
color: #1f5fdb;
|
color: #be2323;
|
||||||
box-shadow: inset 0 0 0 1px rgba(59, 130, 246, 0.16);
|
box-shadow: inset 0 0 0 1px rgba(190, 35, 35, 0.16);
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark .agent-avatar {
|
.dark .agent-avatar {
|
||||||
|
|||||||
Reference in new issue
Block a user