mirror of
https://github.com/HKUDS/nanobot.git
synced 2026-08-11 14:58:39 +03:00
fix(webui): soften form control focus rings
This commit is contained in:
+1
-1
@@ -362,7 +362,7 @@ function AuthForm({
|
||||
disabled={submitting}
|
||||
aria-invalid={validationError ? true : undefined}
|
||||
aria-describedby={validationError ? "webui-auth-error" : undefined}
|
||||
className="pr-10 focus-visible:ring-1 focus-visible:ring-ring/30 focus-visible:ring-offset-0"
|
||||
className="pr-10"
|
||||
autoFocus
|
||||
/>
|
||||
<Button
|
||||
|
||||
@@ -19,7 +19,6 @@ import { cn } from "@/lib/utils";
|
||||
export const SETTINGS_SEARCH_INPUT_CLASS = cn(
|
||||
"border-border/45 bg-settings-surface transition-colors hover:border-border/70",
|
||||
"focus-visible:border-border/70 focus-visible:bg-background",
|
||||
"focus-visible:ring-0 focus-visible:ring-offset-0",
|
||||
);
|
||||
|
||||
export function CapabilityInstallNotice({
|
||||
|
||||
@@ -35,6 +35,7 @@ import {
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
import { formControlFocusClassName } from "@/components/ui/form-control";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { SegmentedControl } from "@/components/ui/segmented-control";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
@@ -835,7 +836,10 @@ export function AutomationEditDialog({
|
||||
everyUnit: event.target.value as AutomationEveryUnit,
|
||||
}))
|
||||
}
|
||||
className="h-10 w-full rounded-[12px] border border-input bg-background px-3 text-[13px] text-foreground outline-none transition-colors focus-visible:ring-2 focus-visible:ring-ring"
|
||||
className={cn(
|
||||
"h-10 w-full rounded-[12px] border border-input bg-background px-3 text-[13px] text-foreground transition-colors",
|
||||
formControlFocusClassName,
|
||||
)}
|
||||
>
|
||||
{AUTOMATION_EVERY_UNITS.map((unit) => (
|
||||
<option key={unit.value} value={unit.value}>
|
||||
|
||||
@@ -3,6 +3,7 @@ import { ListTree, Search } from "lucide-react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { formControlFocusClassName } from "@/components/ui/form-control";
|
||||
import {
|
||||
Sheet,
|
||||
SheetContent,
|
||||
@@ -83,7 +84,8 @@ export function PromptNavigator({
|
||||
placeholder={t("thread.promptNavigator.search")}
|
||||
className={cn(
|
||||
"h-10 w-full rounded-full border border-border bg-background pl-9 pr-3 text-sm",
|
||||
"outline-none transition focus:border-ring focus:ring-2 focus:ring-ring/20",
|
||||
"transition-colors",
|
||||
formControlFocusClassName,
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -256,10 +256,7 @@ export function WorkspaceProjectPicker({
|
||||
aria-label={t("workspace.dialog.manual")}
|
||||
aria-invalid={pathError || error ? true : undefined}
|
||||
aria-describedby={pathError || error ? pathErrorId : undefined}
|
||||
className={cn(
|
||||
"h-9 rounded-full border-border/55 bg-background/80 px-3 text-[12.5px]",
|
||||
"focus-visible:ring-1 focus-visible:ring-foreground/10 focus-visible:ring-offset-0",
|
||||
)}
|
||||
className="h-9 rounded-full border-border/55 bg-background/80 px-3 text-[12.5px]"
|
||||
/>
|
||||
<Button
|
||||
type="submit"
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
export const formControlFocusClassName =
|
||||
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring/50";
|
||||
@@ -1,5 +1,6 @@
|
||||
import * as React from "react";
|
||||
|
||||
import { formControlFocusClassName } from "@/components/ui/form-control";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
export type InputProps = React.InputHTMLAttributes<HTMLInputElement>;
|
||||
@@ -10,7 +11,8 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
||||
<input
|
||||
type={type}
|
||||
className={cn(
|
||||
"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
||||
"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50",
|
||||
formControlFocusClassName,
|
||||
className,
|
||||
)}
|
||||
ref={ref}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import * as React from "react";
|
||||
|
||||
import { formControlFocusClassName } from "@/components/ui/form-control";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
export type TextareaProps = React.TextareaHTMLAttributes<HTMLTextAreaElement>;
|
||||
@@ -9,7 +10,8 @@ const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
|
||||
return (
|
||||
<textarea
|
||||
className={cn(
|
||||
"flex min-h-[60px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
||||
"flex min-h-[60px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50",
|
||||
formControlFocusClassName,
|
||||
className,
|
||||
)}
|
||||
ref={ref}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
import { render, screen } from "@testing-library/react";
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
|
||||
describe("form control focus styles", () => {
|
||||
it.each([
|
||||
["input", <Input aria-label="input" />],
|
||||
["textarea", <Textarea aria-label="textarea" />],
|
||||
])("uses a subdued inset focus ring for the %s", (label, control) => {
|
||||
render(control);
|
||||
|
||||
const element = screen.getByLabelText(label);
|
||||
expect(element).toHaveClass(
|
||||
"focus-visible:ring-2",
|
||||
"focus-visible:ring-inset",
|
||||
"focus-visible:ring-ring/50",
|
||||
);
|
||||
expect(element).not.toHaveClass(
|
||||
"ring-offset-background",
|
||||
"focus-visible:ring-ring",
|
||||
"focus-visible:ring-offset-2",
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -834,8 +834,9 @@ describe("Settings channels", () => {
|
||||
|
||||
const emailRow = await screen.findByRole("button", { name: "View Email settings" });
|
||||
expect(screen.getByPlaceholderText("Search channels")).toHaveClass(
|
||||
"focus-visible:ring-0",
|
||||
"focus-visible:ring-offset-0",
|
||||
"focus-visible:ring-2",
|
||||
"focus-visible:ring-inset",
|
||||
"focus-visible:ring-ring/50",
|
||||
);
|
||||
expect(screen.queryByRole("switch", { name: "Email channel" })).not.toBeInTheDocument();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user