mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-08-28 05:27:24 +00:00
Update icons in chattextarea (#5520)
* Update icons in chattextarea * fix: update icons in ChatTextArea and IndexingStatusBadge components * fix: update Camera icon to Image and fix alignment - Changed Camera icon to Image icon from lucide-react - Fixed alignment issue by adjusting gap and removing extra margin - Updated tests to work with new Lucide icon structure * fix: revert alignment changes for Image icon - Keep original alignment with gap-0.5 and mr-1 to match send and enhance buttons --------- Co-authored-by: Daniel Riccio <ricciodaniel98@gmail.com>
This commit is contained in:
parent
fed603a927
commit
2b7c266546
4 changed files with 81 additions and 36 deletions
|
|
@ -25,9 +25,8 @@ import Thumbnails from "../common/Thumbnails"
|
|||
import ModeSelector from "./ModeSelector"
|
||||
import { MAX_IMAGES_PER_MESSAGE } from "./ChatView"
|
||||
import ContextMenu from "./ContextMenu"
|
||||
import { VolumeX, Pin, Check } from "lucide-react"
|
||||
import { IconButton } from "./IconButton"
|
||||
import { IndexingStatusDot } from "./IndexingStatusBadge"
|
||||
import { VolumeX, Pin, Check, Image, WandSparkles, SendHorizontal } from "lucide-react"
|
||||
import { IndexingStatusBadge } from "./IndexingStatusBadge"
|
||||
import { cn } from "@/lib/utils"
|
||||
import { usePromptHistory } from "./hooks/usePromptHistory"
|
||||
|
||||
|
|
@ -962,24 +961,49 @@ const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
|
|||
)}
|
||||
|
||||
<div className="absolute top-1 right-1 z-30">
|
||||
<IconButton
|
||||
iconClass={isEnhancingPrompt ? "codicon-loading" : "codicon-sparkle"}
|
||||
<button
|
||||
aria-label={t("chat:enhancePrompt")}
|
||||
title={t("chat:enhancePrompt")}
|
||||
disabled={sendingDisabled}
|
||||
isLoading={isEnhancingPrompt}
|
||||
onClick={handleEnhancePrompt}
|
||||
className="opacity-60 hover:opacity-100 text-vscode-descriptionForeground hover:text-vscode-foreground"
|
||||
/>
|
||||
onClick={!sendingDisabled ? handleEnhancePrompt : undefined}
|
||||
className={cn(
|
||||
"relative inline-flex items-center justify-center",
|
||||
"bg-transparent border-none p-1.5",
|
||||
"rounded-md min-w-[28px] min-h-[28px]",
|
||||
"opacity-60 hover:opacity-100 text-vscode-descriptionForeground hover:text-vscode-foreground",
|
||||
"transition-all duration-150",
|
||||
"hover:bg-[rgba(255,255,255,0.03)] hover:border-[rgba(255,255,255,0.15)]",
|
||||
"focus:outline-none focus-visible:ring-1 focus-visible:ring-vscode-focusBorder",
|
||||
"active:bg-[rgba(255,255,255,0.1)]",
|
||||
!sendingDisabled && "cursor-pointer",
|
||||
sendingDisabled &&
|
||||
"opacity-40 cursor-not-allowed grayscale-[30%] hover:bg-transparent hover:border-[rgba(255,255,255,0.08)] active:bg-transparent",
|
||||
)}>
|
||||
<WandSparkles className={cn("w-4 h-4", isEnhancingPrompt && "animate-spin")} />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="absolute bottom-1 right-1 z-30">
|
||||
<IconButton
|
||||
iconClass="codicon-send"
|
||||
<button
|
||||
aria-label={t("chat:sendMessage")}
|
||||
title={t("chat:sendMessage")}
|
||||
disabled={sendingDisabled}
|
||||
onClick={onSend}
|
||||
className="opacity-60 hover:opacity-100 text-vscode-descriptionForeground hover:text-vscode-foreground"
|
||||
/>
|
||||
onClick={!sendingDisabled ? onSend : undefined}
|
||||
className={cn(
|
||||
"relative inline-flex items-center justify-center",
|
||||
"bg-transparent border-none p-1.5",
|
||||
"rounded-md min-w-[28px] min-h-[28px]",
|
||||
"opacity-60 hover:opacity-100 text-vscode-descriptionForeground hover:text-vscode-foreground",
|
||||
"transition-all duration-150",
|
||||
"hover:bg-[rgba(255,255,255,0.03)] hover:border-[rgba(255,255,255,0.15)]",
|
||||
"focus:outline-none focus-visible:ring-1 focus-visible:ring-vscode-focusBorder",
|
||||
"active:bg-[rgba(255,255,255,0.1)]",
|
||||
!sendingDisabled && "cursor-pointer",
|
||||
sendingDisabled &&
|
||||
"opacity-40 cursor-not-allowed grayscale-[30%] hover:bg-transparent hover:border-[rgba(255,255,255,0.08)] active:bg-transparent",
|
||||
)}>
|
||||
<SendHorizontal className="w-4 h-4" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{!inputValue && (
|
||||
|
|
@ -1145,14 +1169,28 @@ const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
|
|||
</div>
|
||||
|
||||
<div className={cn("flex", "items-center", "gap-0.5", "shrink-0")}>
|
||||
<IndexingStatusDot />
|
||||
<IconButton
|
||||
iconClass="codicon-device-camera"
|
||||
<IndexingStatusBadge />
|
||||
<button
|
||||
aria-label={t("chat:addImages")}
|
||||
title={t("chat:addImages")}
|
||||
disabled={shouldDisableImages}
|
||||
onClick={onSelectImages}
|
||||
className="mr-1"
|
||||
/>
|
||||
onClick={!shouldDisableImages ? onSelectImages : undefined}
|
||||
className={cn(
|
||||
"relative inline-flex items-center justify-center",
|
||||
"bg-transparent border-none p-1.5",
|
||||
"rounded-md min-w-[28px] min-h-[28px]",
|
||||
"text-vscode-foreground opacity-85",
|
||||
"transition-all duration-150",
|
||||
"hover:opacity-100 hover:bg-[rgba(255,255,255,0.03)] hover:border-[rgba(255,255,255,0.15)]",
|
||||
"focus:outline-none focus-visible:ring-1 focus-visible:ring-vscode-focusBorder",
|
||||
"active:bg-[rgba(255,255,255,0.1)]",
|
||||
!shouldDisableImages && "cursor-pointer",
|
||||
shouldDisableImages &&
|
||||
"opacity-40 cursor-not-allowed grayscale-[30%] hover:bg-transparent hover:border-[rgba(255,255,255,0.08)] active:bg-transparent",
|
||||
"mr-1",
|
||||
)}>
|
||||
<Image className="w-4 h-4" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import React, { useState, useEffect, useMemo } from "react"
|
||||
import { Database } from "lucide-react"
|
||||
import { cn } from "@src/lib/utils"
|
||||
import { vscode } from "@src/utils/vscode"
|
||||
import { useAppTranslation } from "@/i18n/TranslationContext"
|
||||
|
|
@ -6,11 +7,11 @@ import { useTooltip } from "@/hooks/useTooltip"
|
|||
import { CodeIndexPopover } from "./CodeIndexPopover"
|
||||
import type { IndexingStatus, IndexingStatusUpdateMessage } from "@roo/ExtensionMessage"
|
||||
|
||||
interface IndexingStatusDotProps {
|
||||
interface IndexingStatusBadgeProps {
|
||||
className?: string
|
||||
}
|
||||
|
||||
export const IndexingStatusDot: React.FC<IndexingStatusDotProps> = ({ className }) => {
|
||||
export const IndexingStatusBadge: React.FC<IndexingStatusBadgeProps> = ({ className }) => {
|
||||
const { t } = useAppTranslation()
|
||||
const { showTooltip, handleMouseEnter, handleMouseLeave, cleanup } = useTooltip({ delay: 300 })
|
||||
const [isHovered, setIsHovered] = useState(false)
|
||||
|
|
@ -77,23 +78,23 @@ export const IndexingStatusDot: React.FC<IndexingStatusDotProps> = ({ className
|
|||
handleMouseLeave()
|
||||
}
|
||||
|
||||
// Get status color classes based on status and hover state
|
||||
// Get status color classes for the badge dot
|
||||
const getStatusColorClass = () => {
|
||||
const statusColors = {
|
||||
Standby: {
|
||||
default: "bg-vscode-descriptionForeground/40",
|
||||
hover: "bg-vscode-descriptionForeground/60",
|
||||
default: "bg-vscode-descriptionForeground/60",
|
||||
hover: "bg-vscode-descriptionForeground/80",
|
||||
},
|
||||
Indexing: {
|
||||
default: "bg-yellow-500/40 animate-pulse",
|
||||
default: "bg-yellow-500 animate-pulse",
|
||||
hover: "bg-yellow-500 animate-pulse",
|
||||
},
|
||||
Indexed: {
|
||||
default: "bg-green-500/40",
|
||||
default: "bg-green-500",
|
||||
hover: "bg-green-500",
|
||||
},
|
||||
Error: {
|
||||
default: "bg-red-500/40",
|
||||
default: "bg-red-500",
|
||||
hover: "bg-red-500",
|
||||
},
|
||||
}
|
||||
|
|
@ -117,12 +118,17 @@ export const IndexingStatusDot: React.FC<IndexingStatusDotProps> = ({ className
|
|||
"hover:opacity-100 hover:bg-[rgba(255,255,255,0.03)] hover:border-[rgba(255,255,255,0.15)]",
|
||||
"focus:outline-none focus-visible:ring-1 focus-visible:ring-vscode-focusBorder",
|
||||
"active:bg-[rgba(255,255,255,0.1)]",
|
||||
"cursor-pointer",
|
||||
className,
|
||||
)}
|
||||
aria-label={getTooltipText()}>
|
||||
{/* File search icon */}
|
||||
<Database className="w-4 h-4 text-vscode-foreground" />
|
||||
|
||||
{/* Status dot badge */}
|
||||
<span
|
||||
className={cn(
|
||||
"inline-block w-2 h-2 rounded-full relative z-10 transition-colors duration-200",
|
||||
"absolute top-0.5 right-0.5 w-1.5 h-1.5 rounded-full transition-colors duration-200",
|
||||
getStatusColorClass(),
|
||||
)}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -38,8 +38,8 @@ vi.mock("@src/context/ExtensionStateContext")
|
|||
const getEnhancePromptButton = () => {
|
||||
return screen.getByRole("button", {
|
||||
name: (_, element) => {
|
||||
// Find the button with the sparkle icon
|
||||
return element.querySelector(".codicon-sparkle") !== null
|
||||
// Find the button with the wand sparkles icon (Lucide React)
|
||||
return element.querySelector(".lucide-wand-sparkles") !== null
|
||||
},
|
||||
})
|
||||
}
|
||||
|
|
@ -154,8 +154,9 @@ describe("ChatTextArea", () => {
|
|||
const enhanceButton = getEnhancePromptButton()
|
||||
fireEvent.click(enhanceButton)
|
||||
|
||||
const loadingSpinner = screen.getByText("", { selector: ".codicon-loading" })
|
||||
expect(loadingSpinner).toBeInTheDocument()
|
||||
// Check if the WandSparkles icon has the animate-spin class
|
||||
const animatingIcon = enhanceButton.querySelector(".animate-spin")
|
||||
expect(animatingIcon).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { render, screen, fireEvent, waitFor, act } from "@/utils/test-utils"
|
|||
|
||||
import { vscode } from "@src/utils/vscode"
|
||||
|
||||
import { IndexingStatusDot } from "../IndexingStatusBadge"
|
||||
import { IndexingStatusBadge } from "../IndexingStatusBadge"
|
||||
|
||||
vi.mock("@/i18n/setup", () => ({
|
||||
__esModule: true,
|
||||
|
|
@ -104,9 +104,9 @@ vi.mock("@/i18n/TranslationContext", () => ({
|
|||
}),
|
||||
}))
|
||||
|
||||
describe("IndexingStatusDot", () => {
|
||||
describe("IndexingStatusBadge", () => {
|
||||
const renderComponent = (props = {}) => {
|
||||
return render(<IndexingStatusDot {...props} />)
|
||||
return render(<IndexingStatusBadge {...props} />)
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue