style(webui): clarify surface hierarchy (#5029)
This commit is contained in:
+1
-2
@@ -1936,7 +1936,7 @@ function Shell({
|
|||||||
"absolute inset-y-0 left-0 h-full w-full overflow-hidden",
|
"absolute inset-y-0 left-0 h-full w-full overflow-hidden",
|
||||||
showHostChrome
|
showHostChrome
|
||||||
? "host-sidebar-glass"
|
? "host-sidebar-glass"
|
||||||
: "bg-sidebar shadow-inner-right",
|
: "bg-sidebar",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Sidebar
|
<Sidebar
|
||||||
@@ -2004,7 +2004,6 @@ function Shell({
|
|||||||
<main
|
<main
|
||||||
className={cn(
|
className={cn(
|
||||||
"relative flex h-full min-w-0 flex-1 flex-col overflow-hidden bg-background",
|
"relative flex h-full min-w-0 flex-1 flex-col overflow-hidden bg-background",
|
||||||
showHostChrome && hostSidebarOpen && "border-l border-border/55",
|
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
|
|||||||
@@ -255,7 +255,7 @@ export const ChatList = memo(function ChatList({
|
|||||||
"group flex min-w-0 max-w-full items-center gap-2 rounded-xl px-2 text-[13px] transition-colors",
|
"group flex min-w-0 max-w-full items-center gap-2 rounded-xl px-2 text-[13px] transition-colors",
|
||||||
compact ? "min-h-7" : "min-h-8",
|
compact ? "min-h-7" : "min-h-8",
|
||||||
active
|
active
|
||||||
? "bg-sidebar-accent/70 text-sidebar-accent-foreground shadow-[inset_0_0_0_1px_hsl(var(--sidebar-border)/0.28)]"
|
? "bg-sidebar-accent/70 text-sidebar-accent-foreground shadow-[inset_0_0_0_1px_hsl(var(--sidebar-border)/0.16)]"
|
||||||
: "text-sidebar-foreground/82 hover:bg-sidebar-accent/50 hover:text-sidebar-foreground",
|
: "text-sidebar-foreground/82 hover:bg-sidebar-accent/50 hover:text-sidebar-foreground",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import { useTranslation } from "react-i18next";
|
|||||||
import { ChatList } from "@/components/ChatList";
|
import { ChatList } from "@/components/ChatList";
|
||||||
import { ConnectionBadge } from "@/components/ConnectionBadge";
|
import { ConnectionBadge } from "@/components/ConnectionBadge";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Separator } from "@/components/ui/separator";
|
|
||||||
import type {
|
import type {
|
||||||
ChatSummary,
|
ChatSummary,
|
||||||
SidebarViewState,
|
SidebarViewState,
|
||||||
@@ -90,7 +89,6 @@ export function Sidebar(props: SidebarProps) {
|
|||||||
className={cn(
|
className={cn(
|
||||||
"flex h-full w-full min-w-0 flex-col text-sidebar-foreground",
|
"flex h-full w-full min-w-0 flex-col text-sidebar-foreground",
|
||||||
props.hostChromeInset ? "bg-transparent" : "bg-sidebar",
|
props.hostChromeInset ? "bg-transparent" : "bg-sidebar",
|
||||||
!props.hostChromeInset && "border-r border-sidebar-border/60",
|
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
@@ -223,10 +221,9 @@ export function Sidebar(props: SidebarProps) {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<Separator className="bg-sidebar-border/50" />
|
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex items-center gap-1 px-2.5 py-2.5 text-xs",
|
"flex items-center gap-1 bg-sidebar/55 px-2.5 py-3 text-xs",
|
||||||
collapsed && "w-14 flex-col px-0",
|
collapsed && "w-14 flex-col px-0",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -1899,10 +1899,7 @@ export function SettingsView({
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex min-h-0 flex-1 flex-col overflow-hidden lg:flex-row",
|
"flex min-h-0 flex-1 flex-col overflow-hidden bg-background lg:flex-row",
|
||||||
showSidebar
|
|
||||||
? "bg-[radial-gradient(circle_at_50%_0%,hsl(var(--muted))_0%,hsl(var(--background))_42%)]"
|
|
||||||
: "bg-background",
|
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{showSidebar ? (
|
{showSidebar ? (
|
||||||
@@ -2058,7 +2055,7 @@ function SettingsSidebar({
|
|||||||
return (
|
return (
|
||||||
<aside
|
<aside
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex w-full shrink-0 flex-col border-b border-border/55 bg-card/62 px-3 pb-2 shadow-[inset_0_-1px_0_rgba(255,255,255,0.55)] backdrop-blur-xl dark:bg-card/45 dark:shadow-none lg:w-[17rem] lg:border-b-0 lg:border-r lg:px-3 lg:pb-4 lg:shadow-[inset_-1px_0_0_rgba(255,255,255,0.55)]",
|
"flex w-full shrink-0 flex-col bg-sidebar px-3 pb-2 lg:w-[17rem] lg:px-3 lg:pb-4",
|
||||||
hostChromeInset ? "pt-[4.25rem] lg:pt-[4.25rem]" : "pt-4 lg:pt-4",
|
hostChromeInset ? "pt-[4.25rem] lg:pt-[4.25rem]" : "pt-4 lg:pt-4",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
@@ -2091,7 +2088,7 @@ function SettingsSidebar({
|
|||||||
className={cn(
|
className={cn(
|
||||||
"flex h-9 w-auto shrink-0 snap-start items-center gap-2 rounded-full px-3 text-left text-[13px] font-medium transition-colors lg:w-full lg:rounded-[10px] lg:px-2.5",
|
"flex h-9 w-auto shrink-0 snap-start items-center gap-2 rounded-full px-3 text-left text-[13px] font-medium transition-colors lg:w-full lg:rounded-[10px] lg:px-2.5",
|
||||||
active
|
active
|
||||||
? "bg-muted/90 text-foreground shadow-[inset_0_0_0_1px_rgba(0,0,0,0.025)]"
|
? "bg-sidebar-accent text-foreground"
|
||||||
: "text-muted-foreground/78 hover:bg-muted/45 hover:text-foreground",
|
: "text-muted-foreground/78 hover:bg-muted/45 hover:text-foreground",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -170,8 +170,8 @@ export function PromptRail({
|
|||||||
aria-hidden
|
aria-hidden
|
||||||
className={cn(
|
className={cn(
|
||||||
"pointer-events-none absolute left-10 top-1/2 z-30 w-[34rem] max-w-[calc(100vw-4rem)] -translate-y-1/2 rounded-[20px] px-4 py-3 text-left",
|
"pointer-events-none absolute left-10 top-1/2 z-30 w-[34rem] max-w-[calc(100vw-4rem)] -translate-y-1/2 rounded-[20px] px-4 py-3 text-left",
|
||||||
"border border-border/70 bg-popover/95 text-popover-foreground shadow-[0_18px_45px_rgba(0,0,0,0.12)] backdrop-blur-xl",
|
"bg-popover/95 text-popover-foreground shadow-[0_18px_45px_rgba(0,0,0,0.12)] backdrop-blur-xl",
|
||||||
"dark:border-white/10 dark:bg-[#2f2f2f]/95 dark:text-white dark:shadow-[0_18px_45px_rgba(0,0,0,0.45)]",
|
"dark:bg-[#2f2f2f]/95 dark:text-white dark:shadow-[0_18px_45px_rgba(0,0,0,0.45)]",
|
||||||
"-translate-x-2 scale-[0.98] opacity-0 transition-[opacity,transform] duration-150",
|
"-translate-x-2 scale-[0.98] opacity-0 transition-[opacity,transform] duration-150",
|
||||||
"group-hover/marker:translate-x-0 group-hover/marker:scale-100 group-hover/marker:opacity-100",
|
"group-hover/marker:translate-x-0 group-hover/marker:scale-100 group-hover/marker:opacity-100",
|
||||||
"group-focus-visible/marker:translate-x-0 group-focus-visible/marker:scale-100 group-focus-visible/marker:opacity-100",
|
"group-focus-visible/marker:translate-x-0 group-focus-visible/marker:scale-100 group-focus-visible/marker:opacity-100",
|
||||||
|
|||||||
@@ -1822,11 +1822,9 @@ export function ThreadComposer({
|
|||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
"group/composer relative mx-auto flex w-full flex-col overflow-visible transition-all duration-200",
|
"group/composer relative mx-auto flex w-full flex-col overflow-visible transition-all duration-200",
|
||||||
"after:pointer-events-none after:absolute after:inset-[-1px] after:rounded-[inherit] after:border after:border-blue-300/75 after:opacity-0 after:transition-opacity after:duration-200 focus-within:after:opacity-100 dark:after:border-blue-400/55",
|
|
||||||
isHero
|
isHero
|
||||||
? "max-w-[58rem] rounded-[28px] border border-black/[0.035] bg-card shadow-[0_20px_55px_rgba(15,23,42,0.08)] dark:border-white/[0.06] dark:shadow-[0_24px_55px_rgba(0,0,0,0.34)]"
|
? "max-w-[58rem] rounded-[28px] bg-muted/30 focus-within:bg-muted/50 dark:bg-card dark:focus-within:bg-white/[0.06]"
|
||||||
: "max-w-[49.5rem] rounded-[22px] border border-black/[0.035] bg-card shadow-[0_12px_30px_rgba(15,23,42,0.07)] dark:border-white/[0.06] dark:shadow-[0_16px_34px_rgba(0,0,0,0.28)]",
|
: "max-w-[49.5rem] rounded-[22px] bg-muted/30 focus-within:bg-muted/50 dark:bg-card dark:focus-within:bg-white/[0.06]",
|
||||||
"focus-within:border-blue-300/75 dark:focus-within:border-blue-400/55",
|
|
||||||
disabled && "opacity-60",
|
disabled && "opacity-60",
|
||||||
isDragging && "ring-2 ring-primary/40 motion-reduce:ring-0 motion-reduce:border-primary",
|
isDragging && "ring-2 ring-primary/40 motion-reduce:ring-0 motion-reduce:border-primary",
|
||||||
goalState?.active &&
|
goalState?.active &&
|
||||||
|
|||||||
@@ -140,6 +140,7 @@ export const ThreadViewport = forwardRef<ThreadViewportHandle, ThreadViewportPro
|
|||||||
const [atBottom, setAtBottom] = useState(true);
|
const [atBottom, setAtBottom] = useState(true);
|
||||||
const [composerDockHeight, setComposerDockHeight] = useState(0);
|
const [composerDockHeight, setComposerDockHeight] = useState(0);
|
||||||
const [keyboardInsetBottom, setKeyboardInsetBottom] = useState(0);
|
const [keyboardInsetBottom, setKeyboardInsetBottom] = useState(0);
|
||||||
|
const [hasVerticalOverflow, setHasVerticalOverflow] = useState(false);
|
||||||
const [visibleMessageCount, setVisibleMessageCount] =
|
const [visibleMessageCount, setVisibleMessageCount] =
|
||||||
useState(INITIAL_HISTORY_WINDOW);
|
useState(INITIAL_HISTORY_WINDOW);
|
||||||
const hasMessages = messages.length > 0;
|
const hasMessages = messages.length > 0;
|
||||||
@@ -474,6 +475,29 @@ export const ThreadViewport = forwardRef<ThreadViewportHandle, ThreadViewportPro
|
|||||||
return () => observer.disconnect();
|
return () => observer.disconnect();
|
||||||
}, [hasMessages, measureComposerDock]);
|
}, [hasMessages, measureComposerDock]);
|
||||||
|
|
||||||
|
const measureVerticalOverflow = useCallback(() => {
|
||||||
|
const el = scrollRef.current;
|
||||||
|
if (!el) return;
|
||||||
|
const next = el.scrollHeight > el.clientHeight + 1;
|
||||||
|
setHasVerticalOverflow((current) => (current === next ? current : next));
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useLayoutEffect(() => {
|
||||||
|
const el = scrollRef.current;
|
||||||
|
const content = contentRef.current;
|
||||||
|
if (!el) return;
|
||||||
|
|
||||||
|
measureVerticalOverflow();
|
||||||
|
const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(measureVerticalOverflow);
|
||||||
|
observer?.observe(el);
|
||||||
|
if (content) observer?.observe(content);
|
||||||
|
window.addEventListener("resize", measureVerticalOverflow);
|
||||||
|
return () => {
|
||||||
|
observer?.disconnect();
|
||||||
|
window.removeEventListener("resize", measureVerticalOverflow);
|
||||||
|
};
|
||||||
|
}, [composerDockHeight, hasMessages, measureVerticalOverflow, visibleMessages.length]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const el = scrollRef.current;
|
const el = scrollRef.current;
|
||||||
if (!el) return;
|
if (!el) return;
|
||||||
@@ -507,7 +531,8 @@ export const ThreadViewport = forwardRef<ThreadViewportHandle, ThreadViewportPro
|
|||||||
<div
|
<div
|
||||||
ref={scrollRef}
|
ref={scrollRef}
|
||||||
className={cn(
|
className={cn(
|
||||||
"thread-viewport-scrollbar absolute inset-0 overflow-y-auto scroll-auto scrollbar-thin",
|
"thread-viewport-scrollbar absolute inset-0 scroll-auto scrollbar-thin",
|
||||||
|
hasMessages && hasVerticalOverflow ? "overflow-y-auto" : "overflow-hidden",
|
||||||
"[&::-webkit-scrollbar]:w-1.5",
|
"[&::-webkit-scrollbar]:w-1.5",
|
||||||
"[&::-webkit-scrollbar-thumb]:rounded-full",
|
"[&::-webkit-scrollbar-thumb]:rounded-full",
|
||||||
"[&::-webkit-scrollbar-thumb]:bg-muted-foreground/30",
|
"[&::-webkit-scrollbar-thumb]:bg-muted-foreground/30",
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ export function WorkspaceProjectPicker({
|
|||||||
|
|
||||||
if (nativeProjectPicker) {
|
if (nativeProjectPicker) {
|
||||||
return (
|
return (
|
||||||
<div className="flex min-w-0 items-center rounded-b-[28px] border-t border-border/25 bg-muted/60 px-3 py-1.5 dark:bg-white/[0.055] sm:px-4">
|
<div className="flex min-w-0 items-center rounded-b-[28px] bg-muted/45 px-3 py-1.5 dark:bg-white/[0.045] sm:px-4">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
disabled={disabled || pickingFolder}
|
disabled={disabled || pickingFolder}
|
||||||
@@ -133,7 +133,7 @@ export function WorkspaceProjectPicker({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex min-w-0 items-center rounded-b-[28px] border-t border-border/25 bg-muted/60 px-3 py-1.5 dark:bg-white/[0.055] sm:px-4">
|
<div className="flex min-w-0 items-center rounded-b-[28px] bg-muted/45 px-3 py-1.5 dark:bg-white/[0.045] sm:px-4">
|
||||||
<DropdownMenu open={open} onOpenChange={setOpen}>
|
<DropdownMenu open={open} onOpenChange={setOpen}>
|
||||||
<DropdownMenuTrigger asChild>
|
<DropdownMenuTrigger asChild>
|
||||||
<button
|
<button
|
||||||
|
|||||||
+19
-24
@@ -22,47 +22,47 @@
|
|||||||
--accent-foreground: 0 0% 9%;
|
--accent-foreground: 0 0% 9%;
|
||||||
--destructive: 0 84.2% 60.2%;
|
--destructive: 0 84.2% 60.2%;
|
||||||
--destructive-foreground: 0 0% 98%;
|
--destructive-foreground: 0 0% 98%;
|
||||||
--border: 0 0% 89.8%;
|
--border: 40 8% 90.5%;
|
||||||
--input: 0 0% 89.8%;
|
--input: 40 8% 90.5%;
|
||||||
--ring: 0 0% 3.9%;
|
--ring: 0 0% 3.9%;
|
||||||
--inline-token-highlight: 221 70% 50%;
|
--inline-token-highlight: 221 70% 50%;
|
||||||
--radius: 0.4375rem;
|
--radius: 0.4375rem;
|
||||||
--sidebar: 0 0% 98.5%;
|
--sidebar: 40 8% 96.8%;
|
||||||
--sidebar-foreground: 0 0% 3.9%;
|
--sidebar-foreground: 0 0% 3.9%;
|
||||||
--sidebar-accent: 0 0% 95.8%;
|
--sidebar-accent: 0 0% 95.8%;
|
||||||
--sidebar-accent-foreground: 0 0% 9%;
|
--sidebar-accent-foreground: 0 0% 9%;
|
||||||
--sidebar-border: 0 0% 89.8%;
|
--sidebar-border: 40 8% 90.5%;
|
||||||
--scrollbar-thumb: hsl(var(--muted-foreground) / 0.26);
|
--scrollbar-thumb: hsl(var(--muted-foreground) / 0.26);
|
||||||
--scrollbar-thumb-hover: hsl(var(--muted-foreground) / 0.42);
|
--scrollbar-thumb-hover: hsl(var(--muted-foreground) / 0.42);
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark {
|
.dark {
|
||||||
color-scheme: dark;
|
color-scheme: dark;
|
||||||
--background: 0 0% 10%;
|
--background: 0 0% 12%;
|
||||||
--foreground: 240 4% 96%;
|
--foreground: 240 4% 96%;
|
||||||
--card: 0 0% 12%;
|
--card: 0 0% 14%;
|
||||||
--card-foreground: 240 4% 96%;
|
--card-foreground: 240 4% 96%;
|
||||||
--popover: 0 0% 12%;
|
--popover: 0 0% 14%;
|
||||||
--popover-foreground: 240 4% 96%;
|
--popover-foreground: 240 4% 96%;
|
||||||
--primary: 240 5% 98%;
|
--primary: 240 5% 98%;
|
||||||
--primary-foreground: 0 0% 9%;
|
--primary-foreground: 0 0% 9%;
|
||||||
--secondary: 0 0% 12%;
|
--secondary: 0 0% 14%;
|
||||||
--secondary-foreground: 0 0% 98%;
|
--secondary-foreground: 0 0% 98%;
|
||||||
--muted: 0 0% 13%;
|
--muted: 0 0% 16%;
|
||||||
--muted-foreground: 0 0% 60%;
|
--muted-foreground: 0 0% 65%;
|
||||||
--accent: 0 0% 15%;
|
--accent: 0 0% 18%;
|
||||||
--accent-foreground: 0 0% 98%;
|
--accent-foreground: 0 0% 98%;
|
||||||
--destructive: 0 62.8% 30.6%;
|
--destructive: 0 62.8% 30.6%;
|
||||||
--destructive-foreground: 0 0% 98%;
|
--destructive-foreground: 0 0% 98%;
|
||||||
--border: 0 0% 18%;
|
--border: 0 0% 22%;
|
||||||
--input: 0 0% 18%;
|
--input: 0 0% 22%;
|
||||||
--ring: 0 0% 83.1%;
|
--ring: 0 0% 83.1%;
|
||||||
--inline-token-highlight: 217 92% 72%;
|
--inline-token-highlight: 217 92% 72%;
|
||||||
--sidebar: 0 0% 11.5%;
|
--sidebar: 0 0% 10.5%;
|
||||||
--sidebar-foreground: 0 0% 98%;
|
--sidebar-foreground: 0 0% 98%;
|
||||||
--sidebar-accent: 0 0% 15.5%;
|
--sidebar-accent: 0 0% 15%;
|
||||||
--sidebar-accent-foreground: 0 0% 98%;
|
--sidebar-accent-foreground: 0 0% 98%;
|
||||||
--sidebar-border: 0 0% 18%;
|
--sidebar-border: 0 0% 20%;
|
||||||
--scrollbar-thumb: hsl(var(--muted-foreground) / 0.28);
|
--scrollbar-thumb: hsl(var(--muted-foreground) / 0.28);
|
||||||
--scrollbar-thumb-hover: hsl(var(--muted-foreground) / 0.44);
|
--scrollbar-thumb-hover: hsl(var(--muted-foreground) / 0.44);
|
||||||
}
|
}
|
||||||
@@ -81,6 +81,7 @@
|
|||||||
|
|
||||||
body {
|
body {
|
||||||
@apply bg-background text-foreground font-sans antialiased;
|
@apply bg-background text-foreground font-sans antialiased;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
* {
|
* {
|
||||||
@@ -159,10 +160,7 @@
|
|||||||
background: hsl(var(--sidebar) / 0.94);
|
background: hsl(var(--sidebar) / 0.94);
|
||||||
-webkit-backdrop-filter: saturate(145%) blur(18px);
|
-webkit-backdrop-filter: saturate(145%) blur(18px);
|
||||||
backdrop-filter: saturate(145%) blur(18px);
|
backdrop-filter: saturate(145%) blur(18px);
|
||||||
box-shadow:
|
box-shadow: 14px 0 32px -30px rgb(0 0 0 / 0.12);
|
||||||
inset -1px 0 0 hsl(var(--border) / 0.32),
|
|
||||||
inset 1px 0 0 hsl(var(--background) / 0.52),
|
|
||||||
14px 0 32px -30px rgb(0 0 0 / 0.22);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark .host-window-shell,
|
.dark .host-window-shell,
|
||||||
@@ -174,10 +172,7 @@
|
|||||||
|
|
||||||
.dark .host-sidebar-glass {
|
.dark .host-sidebar-glass {
|
||||||
background: hsl(var(--sidebar) / 0.96);
|
background: hsl(var(--sidebar) / 0.96);
|
||||||
box-shadow:
|
box-shadow: 14px 0 34px -30px rgb(0 0 0 / 0.34);
|
||||||
inset -1px 0 0 hsl(var(--border) / 0.42),
|
|
||||||
inset 1px 0 0 hsl(var(--foreground) / 0.05),
|
|
||||||
14px 0 34px -30px rgb(0 0 0 / 0.62);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
|
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
|
||||||
|
|||||||
@@ -335,7 +335,7 @@ describe("ThreadComposer", () => {
|
|||||||
expect(input.className).toContain("text-[16px]");
|
expect(input.className).toContain("text-[16px]");
|
||||||
expect(input.parentElement?.parentElement?.className).toContain("max-w-[49.5rem]");
|
expect(input.parentElement?.parentElement?.className).toContain("max-w-[49.5rem]");
|
||||||
expect(input.parentElement?.parentElement?.className).toContain("rounded-[22px]");
|
expect(input.parentElement?.parentElement?.className).toContain("rounded-[22px]");
|
||||||
expect(input.parentElement?.parentElement?.className).toContain("shadow-[0_12px_30px_rgba(15,23,42,0.07)]");
|
expect(input.parentElement?.parentElement?.className).not.toContain("shadow-");
|
||||||
expect(screen.getByRole("button", { name: "Attach files" }).className).toContain("bg-card");
|
expect(screen.getByRole("button", { name: "Attach files" }).className).toContain("bg-card");
|
||||||
expect(screen.getByRole("button", { name: "Send message" }).className).toContain("bg-foreground");
|
expect(screen.getByRole("button", { name: "Send message" }).className).toContain("bg-foreground");
|
||||||
expect(screen.queryByText(/Enter to send/)).not.toBeInTheDocument();
|
expect(screen.queryByText(/Enter to send/)).not.toBeInTheDocument();
|
||||||
|
|||||||
Reference in New Issue
Block a user