diff --git a/autogpt_platform/frontend/src/app/error.tsx b/autogpt_platform/frontend/src/app/error.tsx index f6ce27a767..ce4db030c6 100644 --- a/autogpt_platform/frontend/src/app/error.tsx +++ b/autogpt_platform/frontend/src/app/error.tsx @@ -30,7 +30,7 @@ export default function Error({ again later or contact support if the issue persists.

-
diff --git a/autogpt_platform/frontend/src/components/PrimaryActionButton.tsx b/autogpt_platform/frontend/src/components/PrimaryActionButton.tsx index 19d36e29f8..bec81fc267 100644 --- a/autogpt_platform/frontend/src/components/PrimaryActionButton.tsx +++ b/autogpt_platform/frontend/src/components/PrimaryActionButton.tsx @@ -1,5 +1,6 @@ -import React from "react"; -import { Clock, LogOut } from "lucide-react"; +import React, { useState } from "react"; +import { Button } from "./ui/button"; +import { Clock, LogOut, ChevronLeft } from "lucide-react"; import { IconPlay, IconSquare } from "@/components/ui/icons"; import { Tooltip, @@ -7,7 +8,6 @@ import { TooltipTrigger, } from "@/components/ui/tooltip"; import { FaSpinner } from "react-icons/fa"; -import { Button } from "@/components/ui/button"; interface PrimaryActionBarProps { onClickAgentOutputs: () => void; @@ -41,7 +41,12 @@ const PrimaryActionBar: React.FC = ({
- } + {show_tutorial && ( + + )}
diff --git a/autogpt_platform/frontend/src/components/agptui/BecomeACreator.tsx b/autogpt_platform/frontend/src/components/agptui/BecomeACreator.tsx index 2dfff0b64b..c30c3df915 100644 --- a/autogpt_platform/frontend/src/components/agptui/BecomeACreator.tsx +++ b/autogpt_platform/frontend/src/components/agptui/BecomeACreator.tsx @@ -2,7 +2,6 @@ import * as React from "react"; import { PublishAgentPopout } from "./composite/PublishAgentPopout"; -import { Button } from "@/components/ui/button"; interface BecomeACreatorProps { title?: string; description?: string; @@ -47,7 +46,16 @@ export const BecomeACreator: React.FC = ({

{buttonText}} + trigger={ + + } /> diff --git a/autogpt_platform/frontend/src/components/agptui/ProfileInfoForm.tsx b/autogpt_platform/frontend/src/components/agptui/ProfileInfoForm.tsx index 88dbd6e185..302287788e 100644 --- a/autogpt_platform/frontend/src/components/agptui/ProfileInfoForm.tsx +++ b/autogpt_platform/frontend/src/components/agptui/ProfileInfoForm.tsx @@ -5,12 +5,12 @@ import { useState } from "react"; import Image from "next/image"; +import { Button } from "./Button"; import { IconPersonFill } from "@/components/ui/icons"; import { CreatorDetails, ProfileDetails } from "@/lib/autogpt-server-api/types"; import { Separator } from "@/components/ui/separator"; import useSupabase from "@/hooks/useSupabase"; import { useBackendAPI } from "@/lib/autogpt-server-api/context"; -import { Button } from "@/components/ui/button"; export const ProfileInfoForm = ({ profile }: { profile: CreatorDetails }) => { const [isSubmitting, setIsSubmitting] = useState(false); @@ -245,14 +245,21 @@ export const ProfileInfoForm = ({ profile }: { profile: CreatorDetails }) => {
-
diff --git a/autogpt_platform/frontend/src/components/auth/AuthButton.tsx b/autogpt_platform/frontend/src/components/auth/AuthButton.tsx index 36796857c5..be8c86f981 100644 --- a/autogpt_platform/frontend/src/components/auth/AuthButton.tsx +++ b/autogpt_platform/frontend/src/components/auth/AuthButton.tsx @@ -19,7 +19,7 @@ export default function AuthButton({ }: Props) { return ( diff --git a/autogpt_platform/frontend/src/components/edit/control/ControlPanel.tsx b/autogpt_platform/frontend/src/components/edit/control/ControlPanel.tsx index 736159ffae..870d345822 100644 --- a/autogpt_platform/frontend/src/components/edit/control/ControlPanel.tsx +++ b/autogpt_platform/frontend/src/components/edit/control/ControlPanel.tsx @@ -61,6 +61,7 @@ export const ControlPanel = ({ data-id={`control-button-${index}`} data-testid={`blocks-control-${control.label.toLowerCase()}-button`} disabled={control.disabled || false} + className="dark:bg-slate-900 dark:text-slate-100 dark:hover:bg-slate-800" > {control.icon} {control.label} diff --git a/autogpt_platform/frontend/src/components/edit/control/SaveControl.tsx b/autogpt_platform/frontend/src/components/edit/control/SaveControl.tsx index 4c589c635f..bfa0408dba 100644 --- a/autogpt_platform/frontend/src/components/edit/control/SaveControl.tsx +++ b/autogpt_platform/frontend/src/components/edit/control/SaveControl.tsx @@ -93,7 +93,7 @@ export const SaveControl = ({ data-testid="blocks-control-save-button" name="Save" > - + @@ -153,6 +153,7 @@ export const SaveControl = ({ @@ -135,8 +89,6 @@ export const Variants: Story = { const canvas = within(canvasElement); const buttons = canvas.getAllByRole("button"); await expect(buttons).toHaveLength(6); - - // Test hover states for (const button of buttons) { await userEvent.hover(button); await expect(button).toHaveAttribute( @@ -144,81 +96,47 @@ export const Variants: Story = { expect.stringContaining("hover:"), ); } - - // Test rounded-full styling on appropriate variants - const roundedVariants = [ - "default", - "destructive", - "outline", - "secondary", - "ghost", - ]; - for (let i = 0; i < 5; i++) { - await expect(buttons[i]).toHaveAttribute( - "class", - expect.stringContaining("rounded-full"), - ); - } - - // Link variant should not have rounded-full - await expect(buttons[5]).not.toHaveAttribute( - "class", - expect.stringContaining("rounded-full"), - ); }, }; export const Sizes: Story = { render: (args) => ( -
- +
- + -
-

Deprecated Size:

- -
+ +
), play: async ({ canvasElement }) => { const canvas = within(canvasElement); const buttons = canvas.getAllByRole("button"); await expect(buttons).toHaveLength(5); - - // Test icon size - const iconButton = canvas.getByRole("button", { name: /🚀/i }); - await expect(iconButton).toHaveAttribute( - "class", - expect.stringContaining("h-9 w-9"), - ); - - // Test specific size classes - const smallButton = canvas.getByRole("button", { name: /Small/i }); - await expect(smallButton).toHaveAttribute( - "class", - expect.stringContaining("h-8"), - ); - - const defaultButton = canvas.getByRole("button", { name: /Default/i }); - await expect(defaultButton).toHaveAttribute( - "class", - expect.stringContaining("h-9"), - ); - - const largeButton = canvas.getByRole("button", { name: /Large/i }); - await expect(largeButton).toHaveAttribute( - "class", - expect.stringContaining("h-10"), - ); + const sizes = ["sm", "default", "lg", "primary", "icon"]; + const sizeClasses = [ + "h-8 rounded-md px-3 text-xs", + "h-9 px-4 py-2", + "h-10 rounded-md px-8", + "md:h-14 md:w-44 rounded-2xl h-10 w-28", + "h-9 w-9", + ]; + buttons.forEach(async (button, index) => { + await expect(button).toHaveAttribute( + "class", + expect.stringContaining(sizeClasses[index]), + ); + }); }, }; @@ -231,101 +149,39 @@ export const Disabled: Story = { const canvas = within(canvasElement); const button = canvas.getByRole("button", { name: /Disabled Button/i }); await expect(button).toBeDisabled(); - await expect(button).toHaveAttribute( - "class", - expect.stringContaining("disabled:pointer-events-none"), - ); - await expect(button).toHaveAttribute( - "class", - expect.stringContaining("disabled:opacity-50"), - ); + await expect(button).toHaveStyle("pointer-events: none"); await expect(button).not.toHaveFocus(); }, }; export const WithIcon: Story = { - render: () => ( -
-
- - -
-
-

- Icon with automatic gap spacing: -

- -
-
- ), + args: { + children: ( + <> + + + + Button with Icon + + ), + }, play: async ({ canvasElement }) => { const canvas = within(canvasElement); - const buttons = canvas.getAllByRole("button"); - const icons = canvasElement.querySelectorAll("svg"); - - // Test that SVGs are present - await expect(icons.length).toBeGreaterThan(0); - - // Test for gap-2 class for spacing - await expect(buttons[0]).toHaveAttribute( - "class", - expect.stringContaining("gap-2"), - ); - - // Test SVG styling from buttonVariants - await expect(buttons[0]).toHaveAttribute( - "class", - expect.stringContaining("[&_svg]:size-4"), - ); - - await expect(buttons[0]).toHaveAttribute( - "class", - expect.stringContaining("[&_svg]:shrink-0"), - ); - - await expect(buttons[0]).toHaveAttribute( - "class", - expect.stringContaining("[&_svg]:pointer-events-none"), - ); + const button = canvas.getByRole("button", { name: /Button with Icon/i }); + const icon = button.querySelector("svg"); + await expect(icon).toBeInTheDocument(); + await expect(button).toHaveTextContent("Button with Icon"); }, }; @@ -337,8 +193,10 @@ export const LoadingState: Story = { render: (args) => ( - - - - -
- -
-

- Link variant maintains its original style: -

-
- -
-
- - ), - play: async ({ canvasElement }) => { - const canvas = within(canvasElement); - const buttons = canvas.getAllByRole("button"); - - // Test rounded-full on first 5 buttons - for (let i = 0; i < 5; i++) { - await expect(buttons[i]).toHaveAttribute( - "class", - expect.stringContaining("rounded-full"), - ); - } - - // Test that link variant doesn't have rounded-full - await expect(buttons[5]).not.toHaveAttribute( - "class", - expect.stringContaining("rounded-full"), - ); }, }; diff --git a/autogpt_platform/frontend/src/components/ui/button.tsx b/autogpt_platform/frontend/src/components/ui/button.tsx index 2422982d8d..2239996ac8 100644 --- a/autogpt_platform/frontend/src/components/ui/button.tsx +++ b/autogpt_platform/frontend/src/components/ui/button.tsx @@ -5,28 +5,28 @@ import { cva, type VariantProps } from "class-variance-authority"; import { cn } from "@/lib/utils"; const buttonVariants = cva( - "inline-flex items-center justify-center gap-2 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 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", + "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-neutral-950 disabled:pointer-events-none disabled:opacity-50 dark:focus-visible:ring-neutral-300", { variants: { variant: { default: - "bg-primary/90 text-primary-foreground shadow hover:bg-primary rounded-full", + "bg-neutral-900 text-neutral-50 shadow hover:bg-neutral-900/90 dark:bg-neutral-50 dark:text-neutral-900 dark:hover:bg-neutral-50/90", destructive: - "bg-destructive/90 text-destructive-foreground shadow-sm hover:bg-destructive rounded-full", + "bg-red-500 text-neutral-50 shadow-sm hover:bg-red-500/90 dark:bg-red-900 dark:text-neutral-50 dark:hover:bg-red-900/90", outline: - "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground rounded-full", + "border border-neutral-200 bg-white shadow-sm hover:bg-neutral-100 hover:text-neutral-900 dark:border-neutral-800 dark:bg-neutral-950 dark:hover:bg-neutral-800 dark:hover:text-neutral-50", secondary: - "bg-secondary/90 text-secondary-foreground shadow-sm hover:bg-secondary rounded-full", - ghost: "hover:bg-accent hover:text-accent-foreground rounded-full", - link: "text-primary underline-offset-4 hover:underline", + "bg-neutral-100 text-neutral-900 shadow-sm hover:bg-neutral-100/80 dark:bg-neutral-800 dark:text-neutral-50 dark:hover:bg-neutral-800/80", + ghost: + "hover:bg-neutral-100 hover:text-neutral-900 dark:hover:bg-neutral-800 dark:hover:text-neutral-50", + link: "text-neutral-900 underline-offset-4 hover:underline dark:text-neutral-50", }, size: { default: "h-9 px-4 py-2", sm: "h-8 rounded-md px-3 text-xs", lg: "h-10 rounded-md px-8", - icon: "h-9 w-9", - /** @deprecated Use default size with custom classes instead */ primary: "md:h-14 md:w-44 rounded-2xl h-10 w-28", + icon: "h-9 w-9", }, }, defaultVariants: {