feat: update UI components for improved responsiveness and accessibility

This commit is contained in:
Xi Zhang
2026-06-03 02:47:32 +01:00
parent bbb5c888f2
commit 58e2634108
5 changed files with 43 additions and 28 deletions
+1 -1
View File
@@ -9,7 +9,7 @@
*/
export function BetaBadge() {
return (
<span className="rounded-lg border border-teal-300/50 bg-teal-100/60 px-1.5 py-0.5 text-[10px] font-semibold tracking-wide text-teal-800 shadow-sm backdrop-blur-sm dark:border-teal-700/40 dark:bg-teal-900/30 dark:text-teal-300">
<span className="hidden rounded-lg border border-teal-300/50 bg-teal-100/60 px-1.5 py-0.5 text-[10px] font-semibold tracking-wide text-teal-800 shadow-sm backdrop-blur-sm dark:border-teal-700/40 dark:bg-teal-900/30 dark:text-teal-300 min-[420px]:inline-flex">
BETA
</span>
);
+25 -18
View File
@@ -60,9 +60,9 @@ interface ChatInterfaceProps {
}
const SUGGESTED_PROMPTS = [
"Find papers for a research topic",
"Plan an experiment pipeline",
"Brainstorm research directions",
"Survey recent papers on a topic",
"Design an experiment plan",
"Analyze workspace files",
];
interface UploadedWorkspaceFile {
@@ -583,11 +583,11 @@ export const ChatInterface = React.memo<ChatInterfaceProps>(({ assistant }) => {
{processedMessages.length === 0 && !isLoading && !threadId && (
<div className="flex min-h-[50vh] flex-col items-center justify-center px-4 text-center">
<h2 className="text-pretty text-xl font-semibold">
Start a Research Conversation
Start Research
</h2>
<p className="mt-2 max-w-lg text-sm text-muted-foreground">
Ask EvoScientist to explore literature, shape an experiment,
or develop a research direction.
Ask EvoScientist to review literature, inspect workspace
files, or plan the next experiment.
</p>
<div className="mt-5 flex max-w-2xl flex-wrap justify-center gap-2">
{SUGGESTED_PROMPTS.map((prompt) => (
@@ -595,7 +595,7 @@ export const ChatInterface = React.memo<ChatInterfaceProps>(({ assistant }) => {
key={prompt}
type="button"
onClick={() => handleSuggestedPrompt(prompt)}
className="rounded-full border border-border bg-background px-3 py-2 text-sm text-foreground transition-colors hover:bg-accent focus-visible:ring-2 focus-visible:ring-ring"
className="hover:border-primary/40 max-w-full rounded-full border border-border bg-card px-3 py-2 text-sm text-foreground shadow-sm transition-colors hover:bg-accent focus-visible:ring-2 focus-visible:ring-ring"
>
{prompt}
</button>
@@ -648,8 +648,8 @@ export const ChatInterface = React.memo<ChatInterfaceProps>(({ assistant }) => {
<div className="flex-shrink-0 bg-background">
<div
className={cn(
"mx-4 mb-6 flex flex-shrink-0 flex-col overflow-hidden rounded-xl border border-border bg-background",
"mx-auto w-[calc(100%-32px)] max-w-[1024px] transition-colors duration-200 ease-in-out",
"mb-3 flex flex-shrink-0 flex-col overflow-hidden rounded-xl border border-border bg-background sm:mb-6",
"mx-auto w-[calc(100%-24px)] max-w-[1024px] transition-colors duration-200 ease-in-out sm:w-[calc(100%-32px)]",
"focus-within:ring-2 focus-within:ring-ring"
)}
>
@@ -770,11 +770,15 @@ export const ChatInterface = React.memo<ChatInterfaceProps>(({ assistant }) => {
prev === "workspace" ? null : "workspace"
)
}
className="flex flex-shrink-0 cursor-pointer items-center gap-2 px-[18px] py-3 text-left text-sm"
className="flex flex-shrink-0 cursor-pointer items-center gap-2 px-3 py-3 text-left text-sm sm:px-[18px]"
aria-expanded={metaOpen === "workspace"}
aria-label="Open workspace"
>
<FolderOpen size={16} />
Workspace
<FolderOpen
size={16}
aria-hidden="true"
/>
<span>Workspace</span>
</button>
);
@@ -982,12 +986,12 @@ export const ChatInterface = React.memo<ChatInterfaceProps>(({ assistant }) => {
? "Respond to the request above to continue…"
: isLoading
? "Researching…"
: "Ask your research buddy anything…"
: "Ask EvoScientist anything…"
}
className="font-inherit field-sizing-content flex-1 resize-none border-0 bg-transparent px-[18px] pb-[13px] pt-[14px] text-sm leading-7 text-primary outline-none placeholder:text-tertiary disabled:cursor-not-allowed"
className="font-inherit field-sizing-content flex-1 resize-none border-0 bg-transparent px-4 pb-3 pt-[14px] text-sm leading-7 text-primary outline-none placeholder:text-tertiary disabled:cursor-not-allowed sm:px-[18px]"
rows={1}
/>
<div className="flex items-center justify-between gap-2 p-3">
<div className="flex items-center justify-between gap-2 p-2.5 sm:p-3">
<div className="flex items-center gap-1">
<input
ref={uploadInputRef}
@@ -1030,7 +1034,9 @@ export const ChatInterface = React.memo<ChatInterfaceProps>(({ assistant }) => {
className="size-3.5"
aria-hidden="true"
/>
{autoApprove ? "Auto-approve On" : "Auto-approve"}
<span className="hidden min-[360px]:inline">
{autoApprove ? "Auto-approve On" : "Auto-approve"}
</span>
</button>
</div>
<div className="flex justify-end gap-2">
@@ -1042,16 +1048,17 @@ export const ChatInterface = React.memo<ChatInterfaceProps>(({ assistant }) => {
!isLoading &&
(submitDisabled || isUploadingFiles || !input.trim())
}
aria-label={isLoading ? "Stop generating" : "Send message"}
>
{isLoading ? (
<>
<Square size={14} />
<span>Stop</span>
<span className="hidden sm:inline">Stop</span>
</>
) : (
<>
<ArrowUp size={18} />
<span>Send</span>
<span className="hidden sm:inline">Send</span>
</>
)}
</Button>
+1
View File
@@ -23,6 +23,7 @@ export function ThemeToggle() {
<Button
variant="ghost"
size="icon"
className="size-8 sm:size-9"
onClick={() => setTheme(isDark ? "light" : "dark")}
aria-label={isDark ? "Switch to light mode" : "Switch to dark mode"}
title={isDark ? "Switch to light mode" : "Switch to dark mode"}
+1 -1
View File
@@ -403,7 +403,7 @@ export function ThreadList({
<SelectValue />
</SelectTrigger>
<SelectContent align="end">
<SelectItem value="all">All statuses</SelectItem>
<SelectItem value="all">All</SelectItem>
<SelectSeparator />
<SelectGroup>
<SelectLabel>Active</SelectLabel>
+15 -8
View File
@@ -142,17 +142,20 @@ function HomePageInner({
initialConfig={config}
/>
<div className="flex h-screen flex-col">
<header className="flex h-16 items-center justify-between border-b border-border px-6">
<div className="flex items-center gap-3">
<div className="flex items-center gap-2">
<header className="flex h-16 items-center justify-between gap-2 border-b border-border px-3 sm:px-6">
<div className="flex min-w-0 items-center gap-2 sm:gap-3">
<div className="flex min-w-0 items-center gap-2">
<Image
src="/evoscientist-logo.png"
alt="EvoScientist"
width={28}
height={28}
className="size-6 shrink-0 min-[360px]:size-7"
priority
/>
<h1 className="text-xl font-semibold">EvoScientist</h1>
<h1 className="truncate text-base font-semibold min-[360px]:text-lg sm:text-xl">
EvoScientist
</h1>
<BetaBadge />
</div>
<div className="flex items-center gap-0.5">
@@ -161,7 +164,7 @@ function HomePageInner({
size="icon"
onClick={() => setSidebar(sidebar ? null : "1")}
aria-label={sidebar ? "Hide research" : "Show research"}
className="relative"
className="relative size-8 sm:size-9"
>
{sidebar ? (
<PanelLeftClose
@@ -186,6 +189,7 @@ function HomePageInner({
size="icon"
onClick={startNewChat}
aria-label="New chat"
className="size-8 sm:size-9"
>
<SquarePen
className="size-5"
@@ -195,18 +199,21 @@ function HomePageInner({
)}
</div>
</div>
<div className="flex items-center gap-2">
<div className="flex shrink-0 items-center gap-1 sm:gap-2">
<ThemeToggle />
<Button
variant="outline"
size="sm"
onClick={() => setConfigDialogOpen(true)}
aria-label="Settings"
title="Settings"
className="h-8 px-2 sm:h-8 sm:px-3"
>
<Settings
className="mr-2 h-4 w-4"
className="h-4 w-4 sm:mr-2"
aria-hidden="true"
/>
Settings
<span className="hidden sm:inline">Settings</span>
</Button>
</div>
</header>