Unverified 提交 065bab97 authored 作者: Mohamed Aziz Mejri's avatar Mohamed Aziz Mejri 提交者: GitHub

Improving chat input aesthetics (#2561)

<!-- devin-review-badge-begin --> --- <a href="https://app.devin.ai/review/dyad-sh/dyad/pull/2561" target="_blank"> <picture> <source media="(prefers-color-scheme: dark)" srcset="https://static.devin.ai/assets/gh-open-in-devin-review-dark.svg?v=1"> <img src="https://static.devin.ai/assets/gh-open-in-devin-review-light.svg?v=1" alt="Open with Devin"> </picture> </a> <!-- devin-review-badge-end --> <!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Refreshes the chat input UI for a cleaner look and consistent controls. Adds per‑mode icons and clearer visual states across inputs, pickers, and actions. - **UI Improvements** - Unified control sizing (h-7, text-xs, rounded-lg); vertical align center; input row aligns to end; removed spacer divs. - Borderless triggers for Mode/Model/Tools/Pro with subtle hover; smaller icons; muted “Model:”; mode chips show icons for all modes; Ask/Plan get color accents. - Input boxes rounded-2xl with focus-within ring; home input gets hover border; context banner rounded-t-2xl. - Send/Cancel use text-color hovers with clearer disabled; Cancel turns destructive on hover; Auxiliary Actions is circular with gentle hover scale. - Increased input padding and 15px text with repositioned placeholder; trimmed outer and MessagesList padding for tighter alignment; home send icon switched to SendHorizontal. <sup>Written for commit 301875efc229e998e9ba52b2eeeac057bd017b16. Summary will update on new commits.</sup> <!-- End of auto-generated description by cubic. --> --------- Co-authored-by: 's avatarWill Chen <willchen90@gmail.com>
上级 fd27826e
...@@ -82,6 +82,7 @@ The stashed changes will be automatically merged back after the rebase completes ...@@ -82,6 +82,7 @@ The stashed changes will be automatically merged back after the rebase completes
- If both sides of a conflict have valid imports/hooks, keep both and remove any duplicate constant redefinitions - If both sides of a conflict have valid imports/hooks, keep both and remove any duplicate constant redefinitions
- When rebasing documentation/table conflicts (e.g., workflow README tables), prefer keeping **both** additions from HEAD and upstream - merge new rows/content from both branches rather than choosing one side - When rebasing documentation/table conflicts (e.g., workflow README tables), prefer keeping **both** additions from HEAD and upstream - merge new rows/content from both branches rather than choosing one side
- **Complementary additions**: When both sides added new sections at the end of a file (e.g., both added different documentation tips), keep both sections rather than choosing one — they're not truly conflicting, just different additions - **Complementary additions**: When both sides added new sections at the end of a file (e.g., both added different documentation tips), keep both sections rather than choosing one — they're not truly conflicting, just different additions
- **React component wrapper conflicts**: When rebasing UI changes that conflict on wrapper div classes (e.g., `flex items-start space-x-2` vs `flex items-end gap-1`), keep the newer styling from the incoming commit but preserve any functional components (like dialogs or modals) that exist in HEAD but not in the incoming change
## Rebasing with uncommitted changes ## Rebasing with uncommitted changes
......
...@@ -23,7 +23,7 @@ export function ChatInputControls({ ...@@ -23,7 +23,7 @@ export function ChatInputControls({
(settings?.selectedChatMode === "build" && enabledMcpServersCount > 0); (settings?.selectedChatMode === "build" && enabledMcpServersCount > 0);
return ( return (
<div className="flex"> <div className="flex items-center">
<ChatModeSelector /> <ChatModeSelector />
{showMcpToolsPicker && ( {showMcpToolsPicker && (
<> <>
...@@ -33,15 +33,8 @@ export function ChatInputControls({ ...@@ -33,15 +33,8 @@ export function ChatInputControls({
)} )}
<div className="w-1.5"></div> <div className="w-1.5"></div>
<ModelPicker /> <ModelPicker />
<div className="w-1.5"></div>
<ProModeSelector /> <ProModeSelector />
<div className="w-1"></div> {showContextFilesPicker && <ContextFilesPicker />}
{showContextFilesPicker && (
<>
<ContextFilesPicker />
<div className="w-0.5"></div>
</>
)}
</div> </div>
); );
} }
...@@ -22,6 +22,7 @@ import { toast } from "sonner"; ...@@ -22,6 +22,7 @@ import { toast } from "sonner";
import { LocalAgentNewChatToast } from "./LocalAgentNewChatToast"; import { LocalAgentNewChatToast } from "./LocalAgentNewChatToast";
import { useAtomValue } from "jotai"; import { useAtomValue } from "jotai";
import { chatMessagesByIdAtom } from "@/atoms/chatAtoms"; import { chatMessagesByIdAtom } from "@/atoms/chatAtoms";
import { Hammer, Bot, MessageCircle, Lightbulb } from "lucide-react";
function NewBadge() { function NewBadge() {
return ( return (
...@@ -95,6 +96,22 @@ export function ChatModeSelector() { ...@@ -95,6 +96,22 @@ export function ChatModeSelector() {
return "Build"; return "Build";
} }
}; };
const getModeIcon = (mode: ChatMode) => {
switch (mode) {
case "build":
case "agent":
return <Hammer size={14} />;
case "ask":
return <MessageCircle size={14} />;
case "local-agent":
return <Bot size={14} />;
case "plan":
return <Lightbulb size={14} />;
default:
return <Hammer size={14} />;
}
};
const isMac = detectIsMac(); const isMac = detectIsMac();
return ( return (
...@@ -109,18 +126,25 @@ export function ChatModeSelector() { ...@@ -109,18 +126,25 @@ export function ChatModeSelector() {
<MiniSelectTrigger <MiniSelectTrigger
data-testid="chat-mode-selector" data-testid="chat-mode-selector"
className={cn( className={cn(
"h-6 w-fit px-1.5 py-0 text-xs-sm font-medium shadow-none gap-0.5", "cursor-pointer w-fit px-2 py-0 text-xs font-medium border-none shadow-none gap-1 rounded-lg transition-colors",
selectedMode === "build" || selectedMode === "build" || selectedMode === "local-agent"
selectedMode === "local-agent" || ? "text-foreground/80 hover:text-foreground hover:bg-muted/60"
selectedMode === "plan" : selectedMode === "ask"
? "bg-background hover:bg-muted/50 focus:bg-muted/50" ? "bg-purple-500/10 text-purple-600 hover:bg-purple-500/15 dark:bg-purple-500/15 dark:text-purple-400 dark:hover:bg-purple-500/20"
: "bg-primary/10 hover:bg-primary/20 focus:bg-primary/20 text-primary border-primary/20 dark:bg-primary/20 dark:hover:bg-primary/30 dark:focus:bg-primary/30", : selectedMode === "plan"
? "bg-blue-500/10 text-blue-600 hover:bg-blue-500/15 dark:bg-blue-500/15 dark:text-blue-400 dark:hover:bg-blue-500/20"
: "text-foreground/80 hover:text-foreground hover:bg-muted/60",
)} )}
size="sm" size="sm"
/> />
} }
> >
<SelectValue>{getModeDisplayName(selectedMode)}</SelectValue> <SelectValue>
<span className="flex items-center gap-1.5">
{getModeIcon(selectedMode)}
{getModeDisplayName(selectedMode)}
</span>
</SelectValue>
</TooltipTrigger> </TooltipTrigger>
<TooltipContent> <TooltipContent>
{`Open mode menu (${isMac ? "\u2318 + ." : "Ctrl + ."} to toggle)`} {`Open mode menu (${isMac ? "\u2318 + ." : "Ctrl + ."} to toggle)`}
...@@ -131,10 +155,11 @@ export function ChatModeSelector() { ...@@ -131,10 +155,11 @@ export function ChatModeSelector() {
<SelectItem value="local-agent"> <SelectItem value="local-agent">
<div className="flex flex-col items-start"> <div className="flex flex-col items-start">
<div className="flex items-center gap-1.5"> <div className="flex items-center gap-1.5">
<Bot size={14} className="text-muted-foreground" />
<span className="font-medium">Agent v2</span> <span className="font-medium">Agent v2</span>
<NewBadge /> <NewBadge />
</div> </div>
<span className="text-xs text-muted-foreground"> <span className="text-xs text-muted-foreground ml-[22px]">
Better at bigger tasks and debugging Better at bigger tasks and debugging
</span> </span>
</div> </div>
...@@ -143,10 +168,11 @@ export function ChatModeSelector() { ...@@ -143,10 +168,11 @@ export function ChatModeSelector() {
<SelectItem value="plan"> <SelectItem value="plan">
<div className="flex flex-col items-start"> <div className="flex flex-col items-start">
<div className="flex items-center gap-1.5"> <div className="flex items-center gap-1.5">
<Lightbulb size={14} className="text-blue-500" />
<span className="font-medium">Plan</span> <span className="font-medium">Plan</span>
<NewBadge /> <NewBadge />
</div> </div>
<span className="text-xs text-muted-foreground"> <span className="text-xs text-muted-foreground ml-[22px]">
Design before you build Design before you build
</span> </span>
</div> </div>
...@@ -155,13 +181,14 @@ export function ChatModeSelector() { ...@@ -155,13 +181,14 @@ export function ChatModeSelector() {
<SelectItem value="local-agent" disabled={isQuotaExceeded}> <SelectItem value="local-agent" disabled={isQuotaExceeded}>
<div className="flex flex-col items-start"> <div className="flex flex-col items-start">
<div className="flex items-center gap-1.5"> <div className="flex items-center gap-1.5">
<Bot size={14} className="text-muted-foreground" />
<span className="font-medium">Basic Agent</span> <span className="font-medium">Basic Agent</span>
<span className="text-xs text-muted-foreground"> <span className="text-xs text-muted-foreground">
({isQuotaExceeded ? "0" : messagesRemaining}/5 remaining for ({isQuotaExceeded ? "0" : messagesRemaining}/5 remaining for
today) today)
</span> </span>
</div> </div>
<span className="text-xs text-muted-foreground"> <span className="text-xs text-muted-foreground ml-[22px]">
{isQuotaExceeded {isQuotaExceeded
? "Daily limit reached" ? "Daily limit reached"
: "Try our AI agent for free"} : "Try our AI agent for free"}
...@@ -171,16 +198,22 @@ export function ChatModeSelector() { ...@@ -171,16 +198,22 @@ export function ChatModeSelector() {
)} )}
<SelectItem value="build"> <SelectItem value="build">
<div className="flex flex-col items-start"> <div className="flex flex-col items-start">
<span className="font-medium">Build</span> <div className="flex items-center gap-1.5">
<span className="text-xs text-muted-foreground"> <Hammer size={14} className="text-muted-foreground" />
<span className="font-medium">Build</span>
</div>
<span className="text-xs text-muted-foreground ml-[22px]">
Generate and edit code Generate and edit code
</span> </span>
</div> </div>
</SelectItem> </SelectItem>
<SelectItem value="ask"> <SelectItem value="ask">
<div className="flex flex-col items-start"> <div className="flex flex-col items-start">
<span className="font-medium">Ask</span> <div className="flex items-center gap-1.5">
<span className="text-xs text-muted-foreground"> <MessageCircle size={14} className="text-purple-500" />
<span className="font-medium">Ask</span>
</div>
<span className="text-xs text-muted-foreground ml-[22px]">
Ask questions about the app Ask questions about the app
</span> </span>
</div> </div>
......
...@@ -25,11 +25,11 @@ export function McpToolsPicker() { ...@@ -25,11 +25,11 @@ export function McpToolsPicker() {
return ( return (
<Popover open={isOpen} onOpenChange={setIsOpen}> <Popover open={isOpen} onOpenChange={setIsOpen}>
<PopoverTrigger <PopoverTrigger
className="inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground h-8 px-2" className="inline-flex items-center justify-center whitespace-nowrap rounded-lg text-xs font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 border-none bg-transparent shadow-none text-muted-foreground hover:text-foreground hover:bg-muted/60 h-7 px-1.5 cursor-pointer"
data-testid="mcp-tools-button" data-testid="mcp-tools-button"
title="Tools" title="Tools"
> >
<Wrench className="size-4" /> <Wrench className="size-3.5" />
</PopoverTrigger> </PopoverTrigger>
<PopoverContent <PopoverContent
className="w-120 max-h-[80vh] overflow-y-auto" className="w-120 max-h-[80vh] overflow-y-auto"
......
...@@ -166,14 +166,16 @@ export function ModelPicker() { ...@@ -166,14 +166,16 @@ export function ModelPicker() {
return ( return (
<DropdownMenu open={open} onOpenChange={setOpen}> <DropdownMenu open={open} onOpenChange={setOpen}>
<DropdownMenuTrigger <DropdownMenuTrigger
className="inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground h-8 max-w-[130px] px-1.5 text-xs-sm gap-2" className="inline-flex items-center justify-center whitespace-nowrap rounded-lg text-xs font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 border-none bg-transparent shadow-none text-foreground/80 hover:text-foreground hover:bg-muted/60 h-7 max-w-[130px] px-2 gap-1.5 cursor-pointer"
data-testid="model-picker" data-testid="model-picker"
title={modelDisplayName} title={modelDisplayName}
> >
<span className="truncate"> <span className="truncate">
{modelDisplayName === "Auto" && ( {modelDisplayName === "Auto" && (
<> <>
<span className="text-xs text-muted-foreground">Model:</span>{" "} <span className="text-xs text-muted-foreground/70">
Model:
</span>{" "}
</> </>
)} )}
{modelDisplayName} {modelDisplayName}
......
...@@ -71,11 +71,11 @@ export function ProModeSelector() { ...@@ -71,11 +71,11 @@ export function ProModeSelector() {
<Tooltip> <Tooltip>
<TooltipTrigger <TooltipTrigger
render={ render={
<PopoverTrigger className="inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 border border-primary/50 bg-background shadow-sm hover:bg-primary/10 h-8 px-1.5 gap-1.5 shadow-primary/10 hover:shadow-md hover:shadow-primary/15" /> <PopoverTrigger className="inline-flex items-center justify-center whitespace-nowrap rounded-lg text-xs font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 border-none bg-transparent shadow-none text-primary/95 hover:text-primary hover:bg-primary/10 h-7 px-2 gap-1 cursor-pointer" />
} }
> >
<Sparkles className="h-4 w-4 text-primary" /> <Sparkles className="h-3.5 w-3.5" />
<span className="text-primary font-medium text-xs-sm">Pro</span> <span className="font-medium">Pro</span>
</TooltipTrigger> </TooltipTrigger>
<TooltipContent>Configure Dyad Pro settings</TooltipContent> <TooltipContent>Configure Dyad Pro settings</TooltipContent>
</Tooltip> </Tooltip>
......
...@@ -132,7 +132,7 @@ export function AuxiliaryActionsMenu({ ...@@ -132,7 +132,7 @@ export function AuxiliaryActionsMenu({
<> <>
<DropdownMenu open={isOpen} onOpenChange={setIsOpen}> <DropdownMenu open={isOpen} onOpenChange={setIsOpen}>
<DropdownMenuTrigger <DropdownMenuTrigger
className="inline-flex items-center justify-center whitespace-nowrap rounded-xl text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 hover:bg-muted bg-primary/10 text-primary cursor-pointer h-8 px-2" className="inline-flex items-center justify-center whitespace-nowrap rounded-full text-sm font-medium transition-all duration-200 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 hover:bg-primary/20 hover:scale-105 bg-primary/10 text-primary cursor-pointer h-8 w-8 mb-1"
data-testid="auxiliary-actions-menu" data-testid="auxiliary-actions-menu"
> >
<Plus <Plus
......
...@@ -92,6 +92,7 @@ import { useCountTokens } from "@/hooks/useCountTokens"; ...@@ -92,6 +92,7 @@ import { useCountTokens } from "@/hooks/useCountTokens";
import { useChats } from "@/hooks/useChats"; import { useChats } from "@/hooks/useChats";
import { useRouter } from "@tanstack/react-router"; import { useRouter } from "@tanstack/react-router";
import { showError as showErrorToast } from "@/lib/toast"; import { showError as showErrorToast } from "@/lib/toast";
import { cn } from "@/lib/utils";
const showTokenBarAtom = atom(false); const showTokenBarAtom = atom(false);
...@@ -424,7 +425,7 @@ export function ChatInput({ chatId }: { chatId?: number }) { ...@@ -424,7 +425,7 @@ export function ChatInput({ chatId }: { chatId?: number }) {
{t("errorLoadingProposal", { message: proposalError.message })} {t("errorLoadingProposal", { message: proposalError.message })}
</div> </div>
)} )}
<div className="p-4" data-testid="chat-input-container"> <div className="p-2 pt-0" data-testid="chat-input-container">
{/* Show context limit banner above chat input for visibility */} {/* Show context limit banner above chat input for visibility */}
{showBanner && tokenCountResult && ( {showBanner && tokenCountResult && (
<ContextLimitBanner <ContextLimitBanner
...@@ -433,9 +434,12 @@ export function ChatInput({ chatId }: { chatId?: number }) { ...@@ -433,9 +434,12 @@ export function ChatInput({ chatId }: { chatId?: number }) {
/> />
)} )}
<div <div
className={`relative flex flex-col border border-border rounded-lg bg-(--background-lighter) shadow-sm ${ className={cn(
isDraggingOver ? "ring-2 ring-blue-500 border-blue-500" : "" "relative flex flex-col border border-border rounded-2xl bg-(--background-lighter) transition-colors duration-200",
} ${showBanner ? "rounded-t-none border-t-0" : ""}`} "focus-within:border-primary/30 focus-within:ring-1 focus-within:ring-primary/20",
isDraggingOver && "ring-2 ring-blue-500 border-blue-500",
showBanner && "rounded-t-none border-t-0",
)}
onDragOver={handleDragOver} onDragOver={handleDragOver}
onDragLeave={handleDragLeave} onDragLeave={handleDragLeave}
onDrop={handleDrop} onDrop={handleDrop}
...@@ -566,7 +570,7 @@ export function ChatInput({ chatId }: { chatId?: number }) { ...@@ -566,7 +570,7 @@ export function ChatInput({ chatId }: { chatId?: number }) {
onCancel={cancelPendingFiles} onCancel={cancelPendingFiles}
/> />
<div className="flex items-start space-x-2 "> <div className="flex items-end gap-1">
<LexicalChatInput <LexicalChatInput
value={inputValue} value={inputValue}
onChange={setInputValue} onChange={setInputValue}
...@@ -585,7 +589,7 @@ export function ChatInput({ chatId }: { chatId?: number }) { ...@@ -585,7 +589,7 @@ export function ChatInput({ chatId }: { chatId?: number }) {
<button <button
onClick={handleCancel} onClick={handleCancel}
aria-label={t("cancelGeneration")} aria-label={t("cancelGeneration")}
className="px-2 py-2 mt-1 mr-1 hover:bg-(--background-darkest) text-(--sidebar-accent-fg) rounded-lg" className="px-2 py-2 mb-0.5 mr-1 text-muted-foreground hover:text-destructive rounded-lg transition-colors duration-150 cursor-pointer"
/> />
} }
> >
...@@ -604,7 +608,7 @@ export function ChatInput({ chatId }: { chatId?: number }) { ...@@ -604,7 +608,7 @@ export function ChatInput({ chatId }: { chatId?: number }) {
disableSendButton disableSendButton
} }
aria-label={t("sendMessage")} aria-label={t("sendMessage")}
className="px-2 py-2 mt-1 mr-1 hover:bg-(--background-darkest) text-(--sidebar-accent-fg) rounded-lg disabled:opacity-50" className="px-2 py-2 mb-0.5 mr-1 text-muted-foreground hover:text-primary rounded-lg transition-colors duration-150 disabled:opacity-30 disabled:hover:text-muted-foreground cursor-pointer disabled:cursor-default"
/> />
} }
> >
...@@ -614,7 +618,7 @@ export function ChatInput({ chatId }: { chatId?: number }) { ...@@ -614,7 +618,7 @@ export function ChatInput({ chatId }: { chatId?: number }) {
</Tooltip> </Tooltip>
)} )}
</div> </div>
<div className="pl-2 pr-1 flex items-center justify-between pb-2"> <div className="px-2 flex items-center justify-between pb-0.5 pt-0.5">
<div className="flex items-center"> <div className="flex items-center">
<ChatInputControls showContextFilesPicker={false} /> <ChatInputControls showContextFilesPicker={false} />
</div> </div>
......
...@@ -50,7 +50,7 @@ export function ContextLimitBanner({ ...@@ -50,7 +50,7 @@ export function ContextLimitBanner({
return ( return (
<div <div
className="mx-auto max-w-3xl px-3 py-1.5 rounded-t-md border-t border-l border-r border-amber-500/30 bg-amber-500/10 flex items-center justify-between gap-3 text-xs text-amber-600 dark:text-amber-500" className="mx-auto max-w-3xl px-3 py-1.5 rounded-t-2xl border-t border-l border-r border-amber-500/30 bg-amber-500/10 flex items-center justify-between gap-3 text-xs text-amber-600 dark:text-amber-500"
data-testid="context-limit-banner" data-testid="context-limit-banner"
> >
<span className="flex items-center gap-1.5"> <span className="flex items-center gap-1.5">
......
import { SendIcon, StopCircleIcon } from "lucide-react"; import { SendHorizontalIcon, StopCircleIcon } from "lucide-react";
import { import {
Tooltip, Tooltip,
TooltipTrigger, TooltipTrigger,
...@@ -20,6 +20,7 @@ import { LexicalChatInput } from "./LexicalChatInput"; ...@@ -20,6 +20,7 @@ import { LexicalChatInput } from "./LexicalChatInput";
import { useChatModeToggle } from "@/hooks/useChatModeToggle"; import { useChatModeToggle } from "@/hooks/useChatModeToggle";
import { useTypingPlaceholder } from "@/hooks/useTypingPlaceholder"; import { useTypingPlaceholder } from "@/hooks/useTypingPlaceholder";
import { AuxiliaryActionsMenu } from "./AuxiliaryActionsMenu"; import { AuxiliaryActionsMenu } from "./AuxiliaryActionsMenu";
import { cn } from "@/lib/utils";
export function HomeChatInput({ export function HomeChatInput({
onSubmit, onSubmit,
...@@ -85,9 +86,12 @@ export function HomeChatInput({ ...@@ -85,9 +86,12 @@ export function HomeChatInput({
<> <>
<div className="p-4" data-testid="home-chat-input-container"> <div className="p-4" data-testid="home-chat-input-container">
<div <div
className={`relative flex flex-col space-y-2 border border-border rounded-lg bg-(--background-lighter) shadow-sm ${ className={cn(
isDraggingOver ? "ring-2 ring-blue-500 border-blue-500" : "" "relative flex flex-col border border-border rounded-2xl bg-(--background-lighter) transition-colors duration-200",
}`} "hover:border-primary/30",
"focus-within:border-primary/30 focus-within:ring-1 focus-within:ring-primary/20",
isDraggingOver && "ring-2 ring-blue-500 border-blue-500",
)}
onDragOver={handleDragOver} onDragOver={handleDragOver}
onDragLeave={handleDragLeave} onDragLeave={handleDragLeave}
onDrop={handleDrop} onDrop={handleDrop}
...@@ -108,7 +112,7 @@ export function HomeChatInput({ ...@@ -108,7 +112,7 @@ export function HomeChatInput({
onCancel={cancelPendingFiles} onCancel={cancelPendingFiles}
/> />
<div className="flex items-start space-x-2 "> <div className="flex items-end gap-1">
<LexicalChatInput <LexicalChatInput
value={inputValue} value={inputValue}
onChange={setInputValue} onChange={setInputValue}
...@@ -127,7 +131,7 @@ export function HomeChatInput({ ...@@ -127,7 +131,7 @@ export function HomeChatInput({
render={ render={
<button <button
aria-label="Cancel generation (unavailable here)" aria-label="Cancel generation (unavailable here)"
className="px-2 py-2 mt-1 mr-1 text-(--sidebar-accent-fg) rounded-lg opacity-50 cursor-not-allowed" className="px-2 py-2 mb-0.5 mr-1 text-muted-foreground rounded-lg opacity-50 cursor-not-allowed transition-colors duration-150"
/> />
} }
> >
...@@ -145,17 +149,17 @@ export function HomeChatInput({ ...@@ -145,17 +149,17 @@ export function HomeChatInput({
onClick={handleCustomSubmit} onClick={handleCustomSubmit}
disabled={!inputValue.trim() && attachments.length === 0} disabled={!inputValue.trim() && attachments.length === 0}
aria-label="Send message" aria-label="Send message"
className="px-2 py-2 mt-1 mr-1 hover:bg-(--background-darkest) text-(--sidebar-accent-fg) rounded-lg disabled:opacity-50" className="px-2 py-2 mb-0.5 mr-1 text-muted-foreground hover:text-primary rounded-lg transition-colors duration-150 disabled:opacity-30 disabled:hover:text-muted-foreground cursor-pointer disabled:cursor-default"
/> />
} }
> >
<SendIcon size={20} /> <SendHorizontalIcon size={20} />
</TooltipTrigger> </TooltipTrigger>
<TooltipContent>Send message</TooltipContent> <TooltipContent>Send message</TooltipContent>
</Tooltip> </Tooltip>
)} )}
</div> </div>
<div className="pl-2 pr-1 flex items-center justify-between pb-2"> <div className="px-2 flex items-center justify-between pb-0.5 pt-0.5">
<div className="flex items-center"> <div className="flex items-center">
<ChatInputControls showContextFilesPicker={false} /> <ChatInputControls showContextFilesPicker={false} />
</div> </div>
......
...@@ -450,10 +450,10 @@ export function LexicalChatInput({ ...@@ -450,10 +450,10 @@ export function LexicalChatInput({
<PlainTextPlugin <PlainTextPlugin
contentEditable={ contentEditable={
<ContentEditable <ContentEditable
className="flex-1 p-2 focus:outline-none overflow-y-auto min-h-[40px] max-h-[200px] resize-none" className="flex-1 px-3 pt-3 pb-2 focus:outline-none overflow-y-auto min-h-[44px] max-h-[200px] resize-none text-[15px]"
aria-placeholder={placeholder} aria-placeholder={placeholder}
placeholder={ placeholder={
<div className="absolute top-2 left-2 text-muted-foreground pointer-events-none select-none"> <div className="absolute top-3 left-3 text-muted-foreground pointer-events-none select-none text-[15px]">
{placeholder} {placeholder}
</div> </div>
} }
......
...@@ -347,7 +347,7 @@ export const MessagesList = forwardRef<HTMLDivElement, MessagesListProps>( ...@@ -347,7 +347,7 @@ export const MessagesList = forwardRef<HTMLDivElement, MessagesListProps>(
if (setupBanner) { if (setupBanner) {
return ( return (
<div <div
className="absolute inset-0 overflow-y-auto p-4" className="absolute inset-0 overflow-y-auto p-4 pb-0 pr-0"
ref={ref} ref={ref}
data-testid="messages-list" data-testid="messages-list"
> >
...@@ -357,7 +357,7 @@ export const MessagesList = forwardRef<HTMLDivElement, MessagesListProps>( ...@@ -357,7 +357,7 @@ export const MessagesList = forwardRef<HTMLDivElement, MessagesListProps>(
} }
return ( return (
<div <div
className="absolute inset-0 overflow-y-auto p-4" className="absolute inset-0 overflow-y-auto p-4 pb-0 pr-0"
ref={ref} ref={ref}
data-testid="messages-list" data-testid="messages-list"
> >
...@@ -375,7 +375,7 @@ export const MessagesList = forwardRef<HTMLDivElement, MessagesListProps>( ...@@ -375,7 +375,7 @@ export const MessagesList = forwardRef<HTMLDivElement, MessagesListProps>(
if (isTestMode) { if (isTestMode) {
return ( return (
<div <div
className="absolute inset-0 p-4 overflow-y-auto" className="absolute inset-0 p-4 pb-0 pr-0 overflow-y-auto"
ref={ref} ref={ref}
data-testid="messages-list" data-testid="messages-list"
> >
...@@ -394,7 +394,7 @@ export const MessagesList = forwardRef<HTMLDivElement, MessagesListProps>( ...@@ -394,7 +394,7 @@ export const MessagesList = forwardRef<HTMLDivElement, MessagesListProps>(
return ( return (
<div <div
className="absolute inset-0 overflow-y-auto p-4" className="absolute inset-0 overflow-y-auto p-4 pb-0 mb-2 pr-0"
ref={ref} ref={ref}
data-testid="messages-list" data-testid="messages-list"
> >
......
...@@ -67,7 +67,7 @@ function MiniSelectTrigger({ ...@@ -67,7 +67,7 @@ function MiniSelectTrigger({
data-slot="select-trigger" data-slot="select-trigger"
data-size={size} data-size={size}
className={cn( className={cn(
"border-input data-[placeholder]:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 dark:hover:bg-input/50 flex w-fit items-center justify-between gap-2 rounded-md border bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", "border-input data-[placeholder]:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 dark:hover:bg-input/50 flex w-fit items-center justify-between gap-2 rounded-md border bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-9 data-[size=sm]:h-7 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
className, className,
)} )}
{...props} {...props}
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论