Explorar o código

Merge branch 'RooVetGit:main' into mistral

Dominik Oswald hai 10 meses
pai
achega
5bb1692374

+ 1 - 1
webview-ui/.storybook/main.ts

@@ -2,7 +2,7 @@ import type { StorybookConfig } from "@storybook/react-vite"
 
 
 const config: StorybookConfig = {
 const config: StorybookConfig = {
 	stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"],
 	stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"],
-	addons: ["@storybook/addon-essentials", "@storybook/addon-interactions"],
+	addons: ["@storybook/addon-essentials", "storybook-dark-mode"],
 	framework: {
 	framework: {
 		name: "@storybook/react-vite",
 		name: "@storybook/react-vite",
 		options: {},
 		options: {},

+ 1 - 1
webview-ui/.storybook/preview.ts

@@ -1,7 +1,7 @@
 import type { Preview } from "@storybook/react"
 import type { Preview } from "@storybook/react"
 
 
-import "../src/index.css"
 import "./vscode.css"
 import "./vscode.css"
+import "../src/index.css"
 
 
 const preview: Preview = {
 const preview: Preview = {
 	parameters: {
 	parameters: {

+ 47 - 23
webview-ui/.storybook/vscode.css

@@ -6,27 +6,51 @@
  */
  */
 
 
 :root {
 :root {
-	--vscode-editor-background: #1f1f1f; /* "editor.background" */
-	--vscode-editor-foreground: #cccccc; /* "editor.foreground" */
-	--vscode-menu-background: #1f1f1f; /* "menu.background" */
-	--vscode-menu-foreground: #cccccc; /* "menu.foreground" */
-	--vscode-button-background: #0078d4; /* "button.background" */
-	--vscode-button-foreground: #ffffff; /* "button.foreground" */
-	--vscode-button-secondaryBackground: #313131; /* "button.secondaryBackground" */
-	--vscode-button-secondaryForeground: #cccccc; /* "button.secondaryForeground" */
-	--vscode-disabledForeground: #313131; /* "disabledForeground" */
-	--vscode-descriptionForeground: #9d9d9d; /* "descriptionForeground" */
-	--vscode-focusBorder: #0078d4; /* "focusBorder" */
-	--vscode-errorForeground: #f85149; /* "errorForeground" */
-	--vscode-widget-border: #313131; /* "widget.border" */
-	--vscode-input-background: #313131; /* "input.background" */
-	--vscode-input-foreground: #cccccc; /* "input.foreground" */
-	--vscode-input-border: #3c3c3c; /* "input.border" */
-
-	/* I can't find these in the output of `Developer: Generate Color Theme From Current Settings` */
-	--vscode-charts-red: red;
-	--vscode-charts-blue: blue;
-	--vscode-charts-yellow: yellow;
-	--vscode-charts-orange: orange;
-	--vscode-charts-green: green;
+	/**
+	 * The styles below have been defined for Tailwind.
+	 */
+
+	--vscode-foreground: #d1d5da; /* "foreground" */
+
+	--vscode-editor-foreground: #e1e4e8; /* "editor.foreground" */
+	--vscode-editor-background: #24292e; /* "editor.background" */
+
+	--vscode-button-foreground: #dcffe4; /* "button.foreground" */
+	--vscode-button-background: #176f2c; /* "button.background" */
+	--vscode-button-secondaryForeground: #ffffff; /* "button.secondaryForeground" */
+	--vscode-button-secondaryBackground: #444d56; /* "button.secondaryBackground" */
+
+	--vscode-dropdown-foreground: #e1e4e8; /* "dropdown.foreground" */
+	--vscode-dropdown-background: #2f363d; /* "dropdown.background" */
+	--vscode-dropdown-border: #1b1f23; /* "dropdown.border" */
+
+	--vscode-input-foreground: #e1e4e8; /* "input.foreground" */
+	--vscode-input-background: #2f363d; /* "input.background" */
+	--vscode-input-border: #1b1f23; /* "input.border" */
+
+	--vscode-focusBorder: #005cc5; /* "focusBorder" */
+
+	--vscode-badge-foreground: #c8e1ff; /* "badge.foreground" */
+	--vscode-badge-background: #044289; /* "badge.background" */
+
+	--vscode-notifications-foreground: #e1e4e8; /* "notifications.foreground" */
+	--vscode-notifications-background: #2f363d; /* "notifications.background" */
+	--vscode-notifications-border: #1b1f23; /* "notifications.border" */
+
+	--vscode-descriptionForeground: #959da5; /* "descriptionForeground" */
+	--vscode-errorForeground: #f97583; /* "errorForeground" */
+
+	--vscode-list-hoverForeground: #e1e4e8; /* "list.hoverForeground" */
+	--vscode-list-hoverBackground: #282e34; /* "list.hoverBackground" */
+	--vscode-list-focusBackground: #044289; /* "list.focusBackground" */
+
+	/**
+	 * The styles below are used in the @shadcn/ui + Tailwind theme but are
+	 * not exposed as `--color-vscode-*` variables.
+	 */
+
+	--vscode-menu-background: #2f363d; /* "menu.background" [MISSING] */
+	--vscode-menu-foreground: #e1e4e8; /* "menu.foreground" [MISSING] */
+
+	--vscode-disabledForeground: #cccccc; /* "disabledForeground" [MISSING] */
 }
 }

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 613 - 133
webview-ui/package-lock.json


+ 11 - 7
webview-ui/package.json

@@ -15,10 +15,14 @@
 		"build-storybook": "storybook build"
 		"build-storybook": "storybook build"
 	},
 	},
 	"dependencies": {
 	"dependencies": {
+		"@radix-ui/react-collapsible": "^1.1.3",
 		"@radix-ui/react-dialog": "^1.1.6",
 		"@radix-ui/react-dialog": "^1.1.6",
 		"@radix-ui/react-dropdown-menu": "^2.1.5",
 		"@radix-ui/react-dropdown-menu": "^2.1.5",
 		"@radix-ui/react-icons": "^1.3.2",
 		"@radix-ui/react-icons": "^1.3.2",
 		"@radix-ui/react-popover": "^1.1.6",
 		"@radix-ui/react-popover": "^1.1.6",
+		"@radix-ui/react-progress": "^1.1.2",
+		"@radix-ui/react-separator": "^1.1.2",
+		"@radix-ui/react-slider": "^1.2.3",
 		"@radix-ui/react-slot": "^1.1.1",
 		"@radix-ui/react-slot": "^1.1.1",
 		"@radix-ui/react-tooltip": "^1.1.8",
 		"@radix-ui/react-tooltip": "^1.1.8",
 		"@tailwindcss/vite": "^4.0.0",
 		"@tailwindcss/vite": "^4.0.0",
@@ -29,6 +33,7 @@
 		"debounce": "^2.1.1",
 		"debounce": "^2.1.1",
 		"fast-deep-equal": "^3.1.3",
 		"fast-deep-equal": "^3.1.3",
 		"fzf": "^0.5.2",
 		"fzf": "^0.5.2",
+		"lucide-react": "^0.475.0",
 		"react": "^18.3.1",
 		"react": "^18.3.1",
 		"react-dom": "^18.3.1",
 		"react-dom": "^18.3.1",
 		"react-remark": "^2.1.0",
 		"react-remark": "^2.1.0",
@@ -44,12 +49,10 @@
 		"vscrui": "^0.2.0"
 		"vscrui": "^0.2.0"
 	},
 	},
 	"devDependencies": {
 	"devDependencies": {
-		"@storybook/addon-essentials": "^8.5.2",
-		"@storybook/addon-interactions": "^8.5.2",
-		"@storybook/blocks": "^8.5.2",
-		"@storybook/react": "^8.5.2",
-		"@storybook/react-vite": "^8.5.2",
-		"@storybook/test": "^8.5.2",
+		"@storybook/addon-essentials": "^8.5.6",
+		"@storybook/blocks": "^8.5.6",
+		"@storybook/react": "^8.5.6",
+		"@storybook/react-vite": "^8.5.6",
 		"@testing-library/jest-dom": "^6.6.3",
 		"@testing-library/jest-dom": "^6.6.3",
 		"@testing-library/react": "^16.2.0",
 		"@testing-library/react": "^16.2.0",
 		"@testing-library/user-event": "^14.6.1",
 		"@testing-library/user-event": "^14.6.1",
@@ -72,7 +75,8 @@
 		"jest": "^27.5.1",
 		"jest": "^27.5.1",
 		"jest-environment-jsdom": "^27.5.1",
 		"jest-environment-jsdom": "^27.5.1",
 		"jest-simple-dot-reporter": "^1.0.5",
 		"jest-simple-dot-reporter": "^1.0.5",
-		"storybook": "^8.5.2",
+		"storybook": "^8.5.6",
+		"storybook-dark-mode": "^4.0.2",
 		"ts-jest": "^27.1.5",
 		"ts-jest": "^27.1.5",
 		"typescript": "^4.9.5",
 		"typescript": "^4.9.5",
 		"vite": "6.0.11"
 		"vite": "6.0.11"

+ 105 - 0
webview-ui/src/components/ui/autosize-textarea.tsx

@@ -0,0 +1,105 @@
+import * as React from "react"
+
+import { cn } from "@/lib/utils"
+
+interface UseAutosizeTextAreaProps {
+	textAreaRef: React.MutableRefObject<HTMLTextAreaElement | null>
+	minHeight?: number
+	maxHeight?: number
+	triggerAutoSize: string
+}
+
+export const useAutosizeTextArea = ({
+	textAreaRef,
+	triggerAutoSize,
+	maxHeight = Number.MAX_SAFE_INTEGER,
+	minHeight = 0,
+}: UseAutosizeTextAreaProps) => {
+	const [init, setInit] = React.useState(true)
+
+	React.useEffect(() => {
+		// We need to reset the height momentarily to get the correct scrollHeight
+		// for the textarea.
+		const offsetBorder = 6
+		const textAreaElement = textAreaRef.current
+
+		if (textAreaElement) {
+			if (init) {
+				textAreaElement.style.minHeight = `${minHeight + offsetBorder}px`
+
+				if (maxHeight > minHeight) {
+					textAreaElement.style.maxHeight = `${maxHeight}px`
+				}
+
+				setInit(false)
+			}
+
+			textAreaElement.style.height = `${minHeight + offsetBorder}px`
+			const scrollHeight = textAreaElement.scrollHeight
+
+			// We then set the height directly, outside of the render loop
+			// Trying to set this with state or a ref will product an incorrect value.
+			if (scrollHeight > maxHeight) {
+				textAreaElement.style.height = `${maxHeight}px`
+			} else {
+				textAreaElement.style.height = `${scrollHeight + offsetBorder}px`
+			}
+		}
+	}, [init, minHeight, maxHeight, textAreaRef, triggerAutoSize])
+}
+
+export type AutosizeTextAreaRef = {
+	textArea: HTMLTextAreaElement
+	minHeight: number
+	maxHeight: number
+}
+
+type AutosizeTextAreaProps = {
+	minHeight: number
+	maxHeight: number
+} & React.TextareaHTMLAttributes<HTMLTextAreaElement>
+
+export const AutosizeTextarea = React.forwardRef<AutosizeTextAreaRef, AutosizeTextAreaProps>(
+	(
+		{ minHeight, maxHeight, className, onChange, value, ...props }: AutosizeTextAreaProps,
+		ref: React.Ref<AutosizeTextAreaRef>,
+	) => {
+		const textAreaRef = React.useRef<HTMLTextAreaElement | null>(null)
+		const [triggerAutoSize, setTriggerAutoSize] = React.useState("")
+
+		useAutosizeTextArea({
+			textAreaRef,
+			triggerAutoSize: triggerAutoSize,
+			maxHeight,
+			minHeight,
+		})
+
+		React.useImperativeHandle(ref, () => ({
+			textArea: textAreaRef.current as HTMLTextAreaElement,
+			focus: () => textAreaRef?.current?.focus(),
+			maxHeight,
+			minHeight,
+		}))
+
+		React.useEffect(() => {
+			setTriggerAutoSize(value as string)
+		}, [props?.defaultValue, value])
+
+		return (
+			<textarea
+				{...props}
+				value={value}
+				ref={textAreaRef}
+				className={cn(
+					"flex w-full text-vscode-input-foreground border border-vscode-input-border bg-vscode-input-background rounded-xs ring-offset-background placeholder:text-muted-foreground focus:outline-0 focus-visible:outline-none focus-visible:border-vscode-focusBorder disabled:cursor-not-allowed disabled:opacity-50 scrollbar-hide",
+					className,
+				)}
+				onChange={(e) => {
+					setTriggerAutoSize(e.target.value)
+					onChange?.(e)
+				}}
+			/>
+		)
+	},
+)
+AutosizeTextarea.displayName = "AutosizeTextarea"

+ 29 - 0
webview-ui/src/components/ui/badge.tsx

@@ -0,0 +1,29 @@
+import * as React from "react"
+import { cva, type VariantProps } from "class-variance-authority"
+
+import { cn } from "@/lib/utils"
+
+const badgeVariants = cva(
+	"inline-flex items-center rounded-xs border border-transparent shadow px-2 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
+	{
+		variants: {
+			variant: {
+				default: "bg-primary text-primary-foreground hover:bg-primary/80",
+				secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
+				destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/80",
+				outline: "text-muted-foreground border-vscode-input-border",
+			},
+		},
+		defaultVariants: {
+			variant: "default",
+		},
+	},
+)
+
+export interface BadgeProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof badgeVariants> {}
+
+function Badge({ className, variant, ...props }: BadgeProps) {
+	return <div className={cn(badgeVariants({ variant }), className)} {...props} />
+}
+
+export { Badge, badgeVariants }

+ 6 - 6
webview-ui/src/components/ui/button.tsx

@@ -9,15 +9,15 @@ const buttonVariants = cva(
 	{
 	{
 		variants: {
 		variants: {
 			variant: {
 			variant: {
-				default: "bg-primary text-primary-foreground shadow hover:bg-primary/90",
-				secondary: "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
+				default: "text-primary-foreground bg-primary shadow hover:bg-primary/90",
+				secondary: "text-secondary-foreground bg-secondary shadow-sm hover:bg-secondary/80",
 				outline:
 				outline:
-					"border border-vscode-dropdown-border bg-vscode-background shadow-sm hover:border-vscode-dropdown-border/80",
-				ghost: "hover:bg-accent hover:text-accent-foreground",
+					"text-secondary-foreground bg-vscode-editor-background border border-vscode-dropdown-border shadow-sm hover:bg-vscode-editor-background/50",
+				ghost: "text-secondary-foreground hover:bg-accent hover:text-accent-foreground",
 				link: "text-primary underline-offset-4 hover:underline",
 				link: "text-primary underline-offset-4 hover:underline",
-				destructive: "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
+				destructive: "text-destructive-foreground bg-destructive shadow-sm hover:bg-destructive/90",
 				combobox:
 				combobox:
-					"bg-vscode-dropdown-background text-vscode-dropdown-foreground border border-vscode-dropdown-border",
+					"text-secondary-foreground bg-vscode-input-background border border-vscode-input-border hover:bg-vscode-input-background/80",
 			},
 			},
 			size: {
 			size: {
 				default: "h-7 px-3",
 				default: "h-7 px-3",

+ 9 - 0
webview-ui/src/components/ui/collapsible.tsx

@@ -0,0 +1,9 @@
+import * as CollapsiblePrimitive from "@radix-ui/react-collapsible"
+
+const Collapsible = CollapsiblePrimitive.Root
+
+const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger
+
+const CollapsibleContent = CollapsiblePrimitive.CollapsibleContent
+
+export { Collapsible, CollapsibleTrigger, CollapsibleContent }

+ 5 - 1
webview-ui/src/components/ui/dropdown-menu.tsx

@@ -151,7 +151,11 @@ const DropdownMenuSeparator = React.forwardRef<
 	React.ElementRef<typeof DropdownMenuPrimitive.Separator>,
 	React.ElementRef<typeof DropdownMenuPrimitive.Separator>,
 	React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>
 	React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>
 >(({ className, ...props }, ref) => (
 >(({ className, ...props }, ref) => (
-	<DropdownMenuPrimitive.Separator ref={ref} className={cn("-mx-1 my-1 h-px bg-muted", className)} {...props} />
+	<DropdownMenuPrimitive.Separator
+		ref={ref}
+		className={cn("-mx-1 my-1 h-px bg-vscode-input-border", className)}
+		{...props}
+	/>
 ))
 ))
 DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName
 DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName
 
 

+ 8 - 0
webview-ui/src/components/ui/index.ts

@@ -1,6 +1,14 @@
+export * from "./autosize-textarea"
+export * from "./badge"
 export * from "./button"
 export * from "./button"
+export * from "./collapsible"
 export * from "./command"
 export * from "./command"
 export * from "./dialog"
 export * from "./dialog"
 export * from "./dropdown-menu"
 export * from "./dropdown-menu"
+export * from "./input"
 export * from "./popover"
 export * from "./popover"
+export * from "./progress"
+export * from "./separator"
+export * from "./slider"
+export * from "./textarea"
 export * from "./tooltip"
 export * from "./tooltip"

+ 22 - 0
webview-ui/src/components/ui/input.tsx

@@ -0,0 +1,22 @@
+import * as React from "react"
+
+import { cn } from "@/lib/utils"
+
+const Input = React.forwardRef<HTMLInputElement, React.ComponentProps<"input">>(
+	({ className, type, ...props }, ref) => {
+		return (
+			<input
+				type={type}
+				className={cn(
+					"flex w-full text-vscode-input-foreground border border-vscode-input-border bg-vscode-input-background rounded-xs px-3 py-1 text-base transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus:outline-0 focus-visible:outline-none focus-visible:border-vscode-focusBorder disabled:cursor-not-allowed disabled:opacity-50",
+					className,
+				)}
+				ref={ref}
+				{...props}
+			/>
+		)
+	},
+)
+Input.displayName = "Input"
+
+export { Input }

+ 22 - 0
webview-ui/src/components/ui/progress.tsx

@@ -0,0 +1,22 @@
+import * as React from "react"
+import * as ProgressPrimitive from "@radix-ui/react-progress"
+
+import { cn } from "@/lib/utils"
+
+const Progress = React.forwardRef<
+	React.ElementRef<typeof ProgressPrimitive.Root>,
+	React.ComponentPropsWithoutRef<typeof ProgressPrimitive.Root>
+>(({ className, value, ...props }, ref) => (
+	<ProgressPrimitive.Root
+		ref={ref}
+		className={cn("relative h-2 w-full overflow-hidden rounded-full bg-vscode-editor-background", className)}
+		{...props}>
+		<ProgressPrimitive.Indicator
+			className="h-full w-full flex-1 bg-vscode-badge-background transition-all"
+			style={{ transform: `translateX(-${100 - (value || 0)}%)` }}
+		/>
+	</ProgressPrimitive.Root>
+))
+Progress.displayName = ProgressPrimitive.Root.displayName
+
+export { Progress }

+ 24 - 0
webview-ui/src/components/ui/separator.tsx

@@ -0,0 +1,24 @@
+import * as React from "react"
+import * as SeparatorPrimitive from "@radix-ui/react-separator"
+
+import { cn } from "@/lib/utils"
+
+const Separator = React.forwardRef<
+	React.ElementRef<typeof SeparatorPrimitive.Root>,
+	React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>
+>(({ className, orientation = "horizontal", decorative = true, ...props }, ref) => (
+	<SeparatorPrimitive.Root
+		ref={ref}
+		decorative={decorative}
+		orientation={orientation}
+		className={cn(
+			"shrink-0 bg-vscode-editor-background my-5",
+			orientation === "horizontal" ? "h-[1px] w-full" : "h-full w-[1px]",
+			className,
+		)}
+		{...props}
+	/>
+))
+Separator.displayName = SeparatorPrimitive.Root.displayName
+
+export { Separator }

+ 22 - 0
webview-ui/src/components/ui/slider.tsx

@@ -0,0 +1,22 @@
+import * as React from "react"
+import * as SliderPrimitive from "@radix-ui/react-slider"
+
+import { cn } from "@/lib/utils"
+
+const Slider = React.forwardRef<
+	React.ElementRef<typeof SliderPrimitive.Root>,
+	React.ComponentPropsWithoutRef<typeof SliderPrimitive.Root>
+>(({ className, ...props }, ref) => (
+	<SliderPrimitive.Root
+		ref={ref}
+		className={cn("relative flex w-full touch-none select-none items-center", className)}
+		{...props}>
+		<SliderPrimitive.Track className="relative h-1 w-full grow overflow-hidden bg-primary/20">
+			<SliderPrimitive.Range className="absolute h-full bg-primary" />
+		</SliderPrimitive.Track>
+		<SliderPrimitive.Thumb className="block h-3 w-3 rounded-full border border-primary/50 bg-primary shadow transition-colors cursor-pointer focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50" />
+	</SliderPrimitive.Root>
+))
+Slider.displayName = SliderPrimitive.Root.displayName
+
+export { Slider }

+ 21 - 0
webview-ui/src/components/ui/textarea.tsx

@@ -0,0 +1,21 @@
+import * as React from "react"
+
+import { cn } from "@/lib/utils"
+
+const Textarea = React.forwardRef<HTMLTextAreaElement, React.ComponentProps<"textarea">>(
+	({ className, ...props }, ref) => {
+		return (
+			<textarea
+				className={cn(
+					"flex min-h-[60px] w-full text-vscode-input-foreground border border-vscode-input-border bg-vscode-input-background rounded-xs px-3 py-2 text-base shadow-sm placeholder:text-muted-foreground focus:outline-0 focus-visible:outline-none focus-visible:border-vscode-focusBorder disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
+					className,
+				)}
+				ref={ref}
+				{...props}
+			/>
+		)
+	},
+)
+Textarea.displayName = "Textarea"
+
+export { Textarea }

+ 33 - 8
webview-ui/src/index.css

@@ -60,7 +60,6 @@
 	 */
 	 */
 
 
 	--color-vscode-foreground: var(--vscode-foreground);
 	--color-vscode-foreground: var(--vscode-foreground);
-	--color-vscode-background: var(--vscode-background);
 
 
 	--color-vscode-editor-foreground: var(--vscode-editor-foreground);
 	--color-vscode-editor-foreground: var(--vscode-editor-foreground);
 	--color-vscode-editor-background: var(--vscode-editor-background);
 	--color-vscode-editor-background: var(--vscode-editor-background);
@@ -74,17 +73,25 @@
 	--color-vscode-dropdown-background: var(--vscode-dropdown-background);
 	--color-vscode-dropdown-background: var(--vscode-dropdown-background);
 	--color-vscode-dropdown-border: var(--vscode-dropdown-border);
 	--color-vscode-dropdown-border: var(--vscode-dropdown-border);
 
 
+	--color-vscode-input-foreground: var(--vscode-input-foreground);
 	--color-vscode-input-background: var(--vscode-input-background);
 	--color-vscode-input-background: var(--vscode-input-background);
 	--color-vscode-input-border: var(--vscode-input-border);
 	--color-vscode-input-border: var(--vscode-input-border);
 
 
+	--color-vscode-focusBorder: var(--vscode-focusBorder);
+
 	--color-vscode-badge-foreground: var(--vscode-badge-foreground);
 	--color-vscode-badge-foreground: var(--vscode-badge-foreground);
 	--color-vscode-badge-background: var(--vscode-badge-background);
 	--color-vscode-badge-background: var(--vscode-badge-background);
 
 
 	--color-vscode-notifications-foreground: var(--vscode-notifications-foreground);
 	--color-vscode-notifications-foreground: var(--vscode-notifications-foreground);
 	--color-vscode-notifications-background: var(--vscode-notifications-background);
 	--color-vscode-notifications-background: var(--vscode-notifications-background);
 	--color-vscode-notifications-border: var(--vscode-notifications-border);
 	--color-vscode-notifications-border: var(--vscode-notifications-border);
+
 	--color-vscode-descriptionForeground: var(--vscode-descriptionForeground);
 	--color-vscode-descriptionForeground: var(--vscode-descriptionForeground);
 	--color-vscode-errorForeground: var(--vscode-errorForeground);
 	--color-vscode-errorForeground: var(--vscode-errorForeground);
+
+	--color-vscode-list-hoverForeground: var(--vscode-list-hoverForeground);
+	--color-vscode-list-hoverBackground: var(--vscode-list-hoverBackground);
+	--color-vscode-list-focusBackground: var(--vscode-list-focusBackground);
 }
 }
 
 
 @layer base {
 @layer base {
@@ -137,10 +144,15 @@
 }
 }
 
 
 /* Form Element Focus States */
 /* Form Element Focus States */
+
 textarea:focus {
 textarea:focus {
 	outline: 1.5px solid var(--vscode-focusBorder, #007fd4);
 	outline: 1.5px solid var(--vscode-focusBorder, #007fd4);
 }
 }
 
 
+.focus\:outline-0 {
+	outline: 0 !important; /* Allow tailwind to override the `textarea:focus` rule */
+}
+
 vscode-button::part(control):focus {
 vscode-button::part(control):focus {
 	outline: none;
 	outline: none;
 }
 }
@@ -201,19 +213,19 @@ body:focus-within .code-block-scrollable {
 	border-color: var(--vscode-scrollbarSlider-activeBackground);
 	border-color: var(--vscode-scrollbarSlider-activeBackground);
 }
 }
 
 
-/*
-Fix VSCode ignoring webkit scrollbar modifiers
-https://github.com/microsoft/vscode/issues/213045
-*/
+/**
+ * Fix VSCode ignoring webkit scrollbar modifiers
+ * https://github.com/microsoft/vscode/issues/213045
+ */
 @supports selector(::-webkit-scrollbar) {
 @supports selector(::-webkit-scrollbar) {
 	html {
 	html {
 		scrollbar-color: unset;
 		scrollbar-color: unset;
 	}
 	}
 }
 }
 
 
-/*
-The above scrollbar styling uses some transparent background color magic to accomplish its animation. However this doesn't play nicely with SyntaxHighlighter, so we need to set a background color for the code blocks' horizontal scrollbar. This actually has the unintended consequence of always showing the scrollbar which I prefer since it makes it more obvious that there is more content to scroll to.
-*/
+/**
+ * The above scrollbar styling uses some transparent background color magic to accomplish its animation. However this doesn't play nicely with SyntaxHighlighter, so we need to set a background color for the code blocks' horizontal scrollbar. This actually has the unintended consequence of always showing the scrollbar which I prefer since it makes it more obvious that there is more content to scroll to.
+ */
 
 
 .code-block-scrollable::-webkit-scrollbar-track {
 .code-block-scrollable::-webkit-scrollbar-track {
 	background: transparent;
 	background: transparent;
@@ -238,6 +250,19 @@ The above scrollbar styling uses some transparent background color magic to acco
 	background-color: transparent;
 	background-color: transparent;
 }
 }
 
 
+/**
+ * Add a way to hide scrollbars.
+ */
+
+.scrollbar-hide {
+	-ms-overflow-style: none; /* IE and Edge */
+	scrollbar-width: none; /* Firefox */
+}
+
+.scrollbar-hide::-webkit-scrollbar {
+	display: none; /* Chrome, Safari and Opera */
+}
+
 /**
 /**
  * Dropdown label
  * Dropdown label
  * https://github.com/microsoft/vscode-webview-ui-toolkit/tree/main/src/dropdown#with-label
  * https://github.com/microsoft/vscode-webview-ui-toolkit/tree/main/src/dropdown#with-label

+ 22 - 0
webview-ui/src/stories/AutosizeTextarea.stories.tsx

@@ -0,0 +1,22 @@
+import type { Meta, StoryObj } from "@storybook/react"
+import { AutosizeTextarea } from "../components/ui/autosize-textarea"
+
+const meta: Meta<typeof AutosizeTextarea> = {
+	title: "Primitives/AutosizeTextarea",
+	component: AutosizeTextarea,
+	tags: ["autodocs"],
+	args: {
+		minHeight: 40,
+		maxHeight: 400,
+		placeholder: "This textarea will expand as you type.",
+		className: "p-2",
+	},
+}
+
+export default meta
+
+type Story = StoryObj<typeof AutosizeTextarea>
+
+export const Default: Story = {
+	args: {},
+}

+ 43 - 0
webview-ui/src/stories/Badge.stories.tsx

@@ -0,0 +1,43 @@
+import type { Meta, StoryObj } from "@storybook/react"
+
+import { Badge } from "@/components/ui"
+
+const meta: Meta<typeof Badge> = {
+	title: "Primitives/Badge",
+	component: Badge,
+	tags: ["autodocs"],
+	args: {
+		children: "Badge",
+	},
+}
+
+export default meta
+
+type Story = StoryObj<typeof Badge>
+
+export const Default: Story = {
+	args: {
+		children: "Default",
+	},
+}
+
+export const Secondary: Story = {
+	args: {
+		variant: "secondary",
+		children: "Secondary",
+	},
+}
+
+export const Destructive: Story = {
+	args: {
+		variant: "destructive",
+		children: "Destructive",
+	},
+}
+
+export const Outline: Story = {
+	args: {
+		variant: "outline",
+		children: "Outline",
+	},
+}

+ 44 - 2
webview-ui/src/stories/Button.stories.ts

@@ -3,7 +3,7 @@ import type { Meta, StoryObj } from "@storybook/react"
 import { Button } from "@/components/ui"
 import { Button } from "@/components/ui"
 
 
 const meta = {
 const meta = {
-	title: "@shadcn/Button",
+	title: "primitives/Button",
 	component: Button,
 	component: Button,
 	parameters: { layout: "centered" },
 	parameters: { layout: "centered" },
 	tags: ["autodocs"],
 	tags: ["autodocs"],
@@ -49,5 +49,47 @@ export default meta
 type Story = StoryObj<typeof meta>
 type Story = StoryObj<typeof meta>
 
 
 export const Default: Story = {
 export const Default: Story = {
-	name: "Button",
+	name: "Default",
+}
+
+export const Secondary: Story = {
+	name: "Secondary",
+	args: {
+		variant: "secondary",
+	},
+}
+
+export const Destructive: Story = {
+	name: "Destructive",
+	args: {
+		variant: "destructive",
+	},
+}
+
+export const Outline: Story = {
+	name: "Outline",
+	args: {
+		variant: "outline",
+	},
+}
+
+export const Ghost: Story = {
+	name: "Ghost",
+	args: {
+		variant: "ghost",
+	},
+}
+
+export const Link: Story = {
+	name: "Link",
+	args: {
+		variant: "link",
+	},
+}
+
+export const Combobox: Story = {
+	name: "Combobox",
+	args: {
+		variant: "combobox",
+	},
 }
 }

+ 36 - 0
webview-ui/src/stories/Collapsible.stories.tsx

@@ -0,0 +1,36 @@
+import type { Meta, StoryObj } from "@storybook/react"
+import { useState } from "react"
+
+import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "../components/ui/collapsible"
+import { Button } from "../components/ui/button"
+import { ChevronsUpDown } from "lucide-react"
+
+const meta: Meta<typeof Collapsible> = {
+	title: "Primitives/Collapsible",
+	component: Collapsible,
+	tags: ["autodocs"],
+}
+
+export default meta
+
+type Story = StoryObj<typeof Collapsible>
+
+export const Default: Story = {
+	render: () => <CollapsibleDemo />,
+}
+
+const CollapsibleDemo = () => {
+	const [isOpen, setIsOpen] = useState(false)
+
+	return (
+		<Collapsible open={isOpen} onOpenChange={setIsOpen}>
+			<CollapsibleTrigger asChild>
+				<Button variant="ghost">
+					Hello
+					<ChevronsUpDown className="size-4" />
+				</Button>
+			</CollapsibleTrigger>
+			<CollapsibleContent className="p-2">👋</CollapsibleContent>
+		</Collapsible>
+	)
+}

+ 2 - 2
webview-ui/src/stories/Combobox.stories.tsx

@@ -17,7 +17,7 @@ import {
 } from "@/components/ui"
 } from "@/components/ui"
 
 
 const meta = {
 const meta = {
-	title: "@shadcn/Combobox",
+	title: "primitives/Combobox",
 	component: Combobox,
 	component: Combobox,
 	parameters: { layout: "centered" },
 	parameters: { layout: "centered" },
 	tags: ["autodocs"],
 	tags: ["autodocs"],
@@ -62,7 +62,7 @@ function Combobox() {
 	return (
 	return (
 		<Popover open={open} onOpenChange={setOpen}>
 		<Popover open={open} onOpenChange={setOpen}>
 			<PopoverTrigger asChild>
 			<PopoverTrigger asChild>
-				<Button variant="secondary" role="combobox" aria-expanded={open} className="w-[200px] justify-between">
+				<Button variant="combobox" role="combobox" aria-expanded={open} className="w-[200px] justify-between">
 					{value ? frameworks.find((framework) => framework.value === value)?.label : "Select framework..."}
 					{value ? frameworks.find((framework) => framework.value === value)?.label : "Select framework..."}
 					<CaretSortIcon className="opacity-50" />
 					<CaretSortIcon className="opacity-50" />
 				</Button>
 				</Button>

+ 1 - 1
webview-ui/src/stories/DropdownMenu.stories.tsx

@@ -27,7 +27,7 @@ import {
 } from "@/components/ui"
 } from "@/components/ui"
 
 
 const meta = {
 const meta = {
-	title: "@shadcn/DropdownMenu",
+	title: "primitives/DropdownMenu",
 	component: DropdownMenu,
 	component: DropdownMenu,
 	parameters: { layout: "centered" },
 	parameters: { layout: "centered" },
 	tags: ["autodocs"],
 	tags: ["autodocs"],

+ 25 - 0
webview-ui/src/stories/Progress.stories.tsx

@@ -0,0 +1,25 @@
+import type { Meta, StoryObj } from "@storybook/react"
+
+import { Progress } from "@/components/ui"
+
+const meta: Meta<typeof Progress> = {
+	title: "Primitives/Progress",
+	component: Progress,
+	parameters: {
+		layout: "centered",
+	},
+	args: {
+		className: "w-[300px]",
+	},
+	tags: ["autodocs"],
+}
+
+export default meta
+
+type Story = StoryObj<typeof Progress>
+
+export const Default: Story = {
+	args: {
+		value: 50,
+	},
+}

+ 32 - 0
webview-ui/src/stories/Slider.stories.tsx

@@ -0,0 +1,32 @@
+import type { Meta, StoryObj } from "@storybook/react"
+
+import { Slider } from "@/components/ui"
+
+const meta: Meta<typeof Slider> = {
+	title: "Primitives/Slider",
+	component: Slider,
+	parameters: {
+		layout: "centered",
+	},
+	args: {
+		defaultValue: [50],
+		max: 100,
+		min: 0,
+		step: 1,
+		className: "w-[300px]",
+	},
+	tags: ["autodocs"],
+}
+
+export default meta
+
+type Story = StoryObj<typeof Slider>
+
+export const Default: Story = {
+	args: {
+		defaultValue: [50],
+		max: 100,
+		min: 0,
+		step: 1,
+	},
+}

+ 0 - 47
webview-ui/src/stories/vscrui/Dropdown.stories.tsx

@@ -1,47 +0,0 @@
-import type { Meta, StoryObj } from "@storybook/react"
-
-import { Dropdown } from "vscrui"
-
-const meta = {
-	title: "@vscrui/Dropdown",
-	component: () => (
-		<Dropdown
-			value="foo"
-			role="combobox"
-			options={[
-				{ value: "foo", label: "Foo" },
-				{ value: "bar", label: "Bar" },
-				{ value: "baz", label: "Baz" },
-			]}
-		/>
-	),
-	parameters: { layout: "centered" },
-	tags: ["autodocs"],
-	argTypes: {},
-	args: {},
-} satisfies Meta<typeof Dropdown>
-
-export default meta
-
-type Story = StoryObj<typeof meta>
-
-export const Default: Story = {
-	args: {},
-	parameters: {
-		docs: {
-			source: {
-				code: `
-<Dropdown
-    value="foo"
-    role="combobox"
-    options={[
-        { value: "foo", label: "Foo" },
-        { value: "bar", label: "Bar" },
-        { value: "baz", label: "Baz" }
-    ]}
-/>`,
-				language: "tsx",
-			},
-		},
-	},
-}

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio