feat(ui): 宋对ui和输入框placeholder更改

This commit is contained in:
肖应宇 2026-04-15 17:37:20 +08:00
parent ac01d08eb5
commit c4fe34ed23
11 changed files with 117 additions and 35 deletions

View File

@ -472,8 +472,22 @@ export default function ChatPage() {
/>
) : (
<div className="relative flex size-full justify-center px-[20px]">
<div className="absolute top-2 right-2 z-30">
<Button
<div className="z-30">
</div>
{thread.values.artifacts?.length === 0 ? (
<ConversationEmptyState
icon={<FilesIcon />}
title="No artifact selected"
description="Select an artifact to view its details"
/>
) : (
<div className="flex size-full max-w-(--container-width-sm) flex-col justify-center">
<header className="shrink-0 flex justify-between items-center border-b ">
<h2 className="text-[14px] h-[58px] leading-[58px] font-bold text-[#333333]">
<span>{t.common.artifacts}</span>
</h2>
<Button
data-testid="artifacts-panel-close"
size="icon-sm"
variant="ghost"
@ -483,23 +497,10 @@ export default function ChatPage() {
>
<XIcon />
</Button>
</div>
{thread.values.artifacts?.length === 0 ? (
<ConversationEmptyState
icon={<FilesIcon />}
title="No artifact selected"
description="Select an artifact to view its details"
/>
) : (
<div className="flex size-full max-w-(--container-width-sm) flex-col justify-center p-4">
<header className="shrink-0">
<h2 className="text-[14px] font-bold text-[#333333]">
{t.common.artifacts}
</h2>
</header>
<main className="min-h-0 grow overflow-auto">
<ArtifactFileList
className="mb-[207px] max-w-(--container-width-sm) p-4 pt-12"
className="mb-[207px] max-w-(--container-width-sm) pt-[20px]"
files={thread.values.artifacts ?? []}
threadId={threadId}
/>
@ -656,7 +657,7 @@ export default function ChatPage() {
</DevDialog>
{/* MARK: 开发测试iframe 通信功能测试面板 */}
{process.env.NODE_ENV !== "production" && <IframeTestPanel />}
{/* {process.env.NODE_ENV !== "production" && <IframeTestPanel />} */}
</div>
</ThreadContext.Provider>
);

View File

@ -207,7 +207,7 @@ export const ChainOfThoughtContent = memo(
<Collapsible open={isOpen}>
<CollapsibleContent
className={cn(
"mt-2 space-y-3",
"mt-4 space-y-3",
"data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2 text-popover-foreground data-[state=closed]:animate-out data-[state=open]:animate-in outline-none",
className,
)}

View File

@ -22,15 +22,21 @@ import { Streamdown } from "streamdown";
export type MessageProps = HTMLAttributes<HTMLDivElement> & {
from: UIMessage["role"];
isFirstInSession?: boolean;
};
export const Message = ({ className, from, ...props }: MessageProps) => (
export const Message = ({
className,
from,
isFirstInSession = false,
...props
}: MessageProps) => (
<div
className={cn(
"group flex w-full flex-col gap-2",
from === "user"
? "is-user ml-auto justify-end"
: "is-assistant bg-white p-[20px]",
? cn("is-user ml-auto justify-end", !isFirstInSession && "mt-6")
: "is-assistant bg-white rounded-[10px] p-4",
className,
)}
{...props}

View File

@ -61,7 +61,7 @@ export const Suggestion = ({
return (
<Button
className={cn(
"cursor-pointer rounded-full px-[20px] py-[15px] text-xs font-normal",
"cursor-pointer rounded-full px-[20px] py-[15px] text-[14px] font-normal",
"border-none bg-[#F9F8FA] text-[#666666]",
"hover:bg-[#EAE9EB] hover:text-[#150033]",
className,

View File

@ -80,12 +80,12 @@ export function ArtifactFileList({
{files.map((file) => (
<Card
key={file}
className="relative cursor-pointer p-3"
className="relative cursor-pointer p-4"
data-testid="artifact-file-card"
onClick={() => handleClick(file)}
>
<CardHeader className="pr-2 pl-1">
<CardTitle className="relative overflow-hidden pl-8">
<CardTitle className="relative overflow-hidden pl-10">
<div
className="text-sm font-normal text-ellipsis whitespace-nowrap"
title={getFileName(file)}
@ -93,10 +93,10 @@ export function ArtifactFileList({
{truncateMiddle(getFileName(file), 50)}
</div>
</CardTitle>
<div className="absolute top-5 left-3">
{getFileIcon(file, "size-6 stroke-[1.5px] stroke-[#333333]")}
<div className="absolute top-5 left-4">
{getFileIcon(file, "size-9 stroke-[1px] stroke-[#333333]")}
</div>
<CardDescription className="pl-8 text-xs">
<CardDescription className="pl-10 text-xs">
{getFileExtensionDisplayName(file)} file
</CardDescription>
<CardAction>
@ -124,7 +124,10 @@ export function ArtifactFileList({
target="_blank"
onClick={(e) => e.stopPropagation()}
>
<Button variant="ghost">
<Button variant="ghost"
className="h-full! text-[var(--muted-foreground)]! hover:bg-transparent! hover:text-[#333333]!"
>
<DownloadIcon className="size-4" />
{t.common.download}
</Button>

View File

@ -741,7 +741,7 @@ export function InputBox({
"pointer-events-none invisible h-[0px] translate-y-2 p-[0px] opacity-0",
)}
>
<PromptInputTools className="min-w-0 flex-1">
<PromptInputTools className="min-w-0 flex-1 gap-[20px]">
{/* TODO: Add more connectors here
<PromptInputActionMenu>
<PromptInputActionMenuTrigger className="px-2!" />

View File

@ -125,7 +125,8 @@ export function MessageGroup({
{aboveLastToolCallSteps.length > 0 && (
<Button
key="above"
className="w-full items-start justify-start text-left"
// 等宋
className="w-full items-start justify-start text-left h-auto! py-4"
variant="ghost"
onClick={(event) => {
event.stopPropagation();
@ -152,7 +153,7 @@ export function MessageGroup({
</Button>
)}
{shouldShowToolSteps && (
<ChainOfThoughtContent className="px-4 pb-2">
<ChainOfThoughtContent className="px-4 pb-4">
{showAbove &&
aboveLastToolCallSteps.map((step) =>
step.type === "reasoning" ? (

View File

@ -41,11 +41,13 @@ export function MessageListItem({
message,
isLoading,
threadId,
isFirstInSession = false,
}: {
className?: string;
message: Message;
isLoading?: boolean;
threadId: string;
isFirstInSession?: boolean;
}) {
const isHuman = message.type === "human";
return (
@ -55,6 +57,7 @@ export function MessageListItem({
className,
)}
from={isHuman ? "user" : "assistant"}
isFirstInSession={isFirstInSession}
>
<MessageContent
className={isHuman ? "w-fit" : "w-full"}
@ -223,7 +226,7 @@ function MessageContent_({
content={contentToDisplay}
isLoading={isLoading}
rehypePlugins={[...rehypePlugins, [rehypeKatex, { output: "html" }]]}
className="my-3"
// className="my-3"
components={components}
/>
</AIElementMessageContent>

View File

@ -55,6 +55,9 @@ export function MessageList({
const rehypePlugins = useRehypeSplitWordsIntoSpans(thread.isLoading);
const updateSubtask = useUpdateSubtask();
const messages = messagesOverride ?? thread.messages;
const firstConversationMessageId = messages.find(
(message) => message.name !== "todo_reminder",
)?.id;
if (thread.isThreadLoading && !suppressThreadLoading) {
return <MessageListSkeleton />;
}
@ -71,6 +74,9 @@ export function MessageList({
message={group.messages[0]!}
isLoading={thread.isLoading}
threadId={threadId}
isFirstInSession={
group.messages[0]?.id === firstConversationMessageId
}
/>
);
} else if (group.type === "assistant:clarification") {

View File

@ -77,7 +77,7 @@ export const zhCN: Translations = {
// Input Box
inputBox: {
placeholder: "先输入说明需求选择Skill开始使用吧",
placeholder: "可直接聊天或者输入需求并选择skill完成更专业的任务",
createSkillPrompt:
"我们一起用 skill-creator 技能来创建一个技能吧。先问问我希望这个技能能做什么。",
sendMessagePrice:

View File

@ -247,7 +247,9 @@
--accent: #1500331a;
--accent-foreground: oklch(0.205 0 0);
--destructive: oklch(0.577 0.245 27.325);
--border: oklch(0.922 0.0098 87.47);
--border: #00000015;
/* --border: oklch(92.23% 0.00983 87.442 / 0.09); */
--input: oklch(0.88 0.0098 87.47);
--ring: transparent;
--chart-1: oklch(0.646 0.222 41.116);
@ -282,7 +284,7 @@
--accent: oklch(0.32 0.0036 106.64);
--accent-foreground: oklch(0.985 0 0);
--destructive: oklch(0.704 0.191 22.216);
--border: oklch(1 0.191 22.216 / 10%);
--border: oklch(87.64% 0.06554 21.887 / 0.038);
--input: oklch(1 0 0 / 15%);
--ring: transparent;
--chart-1: oklch(0.488 0.243 264.376);
@ -441,6 +443,10 @@ pre {
font-family:
"Microsoft YaHei", "微软雅黑", "PingFang SC", sans-serif !important;
}
pre{
border-radius: 5px;
padding: 12px 16px;
}
/* 列表项 - 14px */
[data-streamdown="list-item"] {
@ -465,6 +471,62 @@ pre {
font-size: calc(14px * var(--zoom-scale));
}
/* 代码块 - 14px */
[data-streamdown="table"] {
border: none;
border-collapse: separate;
border-spacing: 0;
}
[data-streamdown="table-cell"] {
background-color: transparent;
}
[data-streamdown="table-header"] {
background: #9c9b9b26;
height: 50px;
}
[data-streamdown="table-header"] th {
text-align: center;
}
/* 表格四角圆角:由四个角单元格承担视觉圆角 */
[data-streamdown="table-header"] tr:first-child > [data-streamdown="table-header-cell"]:first-child {
border-top-left-radius: 5px;
}
[data-streamdown="table-header"] tr:first-child > [data-streamdown="table-header-cell"]:last-child {
border-top-right-radius: 5px;
}
[data-streamdown="table-body"] tr:first-child td{
padding-top: 20px;
}
/* 行分隔线 */
[data-streamdown="table-body"] tr{
border-bottom: 1px solid var(--border);
}
[data-streamdown="table-body"] tr:last-child > [data-streamdown="table-cell"]:first-child {
border-bottom-left-radius: 5px;
}
[data-streamdown="table-body"] tr:last-child > [data-streamdown="table-cell"]:last-child {
border-bottom-right-radius: 5px;
}
[data-streamdown="table-body"] tr:last-child {
height: 50px;
}
[data-streamdown="table-row"] >[data-streamdown="table-cell"]{
line-height: 14px;
vertical-align: top;
text-align: center;
}
.cm-line {
font-size: calc(14px * var(--zoom-scale));
white-space: pre-wrap;