mirror of
https://github.com/QwenLM/qwen-code.git
synced 2025-12-19 09:33:53 +00:00
feat(vscode-ide-companion): add shadcn/ui components and utilities
添加 shadcn/ui 基础组件库和 cn 工具函数,包括: - Button 按钮组件 - Dialog 对话框组件 - cn 类名合并工具函数
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2025 Qwen Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Button component using Tailwind CSS
|
||||
* This is an example of how to create new components using Tailwind
|
||||
* while maintaining compatibility with existing CSS-based components
|
||||
*/
|
||||
|
||||
import type React from 'react';
|
||||
|
||||
interface ButtonProps {
|
||||
/**
|
||||
* Button variant style
|
||||
*/
|
||||
variant?: 'primary' | 'secondary' | 'ghost' | 'icon';
|
||||
|
||||
/**
|
||||
* Button size
|
||||
*/
|
||||
size?: 'sm' | 'md' | 'lg';
|
||||
|
||||
/**
|
||||
* Button contents
|
||||
*/
|
||||
children: React.ReactNode;
|
||||
|
||||
/**
|
||||
* Optional click handler
|
||||
*/
|
||||
onClick?: () => void;
|
||||
|
||||
/**
|
||||
* Disable button
|
||||
*/
|
||||
disabled?: boolean;
|
||||
|
||||
/**
|
||||
* Additional class names
|
||||
*/
|
||||
className?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Primary UI component for user interaction
|
||||
*/
|
||||
export const Button: React.FC<ButtonProps> = ({
|
||||
variant = 'primary',
|
||||
size = 'md',
|
||||
children,
|
||||
onClick,
|
||||
disabled = false,
|
||||
className = '',
|
||||
}) => {
|
||||
// Base classes that apply to all buttons
|
||||
const baseClasses = "inline-flex items-center justify-center rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none";
|
||||
|
||||
// Variant-specific classes
|
||||
const variantClasses = {
|
||||
primary: "bg-qwen-orange text-qwen-ivory hover:bg-qwen-clay-orange shadow-sm",
|
||||
secondary: "bg-gray-100 text-gray-900 hover:bg-gray-200 dark:bg-gray-800 dark:text-gray-100 dark:hover:bg-gray-700",
|
||||
ghost: "hover:bg-gray-100 dark:hover:bg-gray-800",
|
||||
icon: "hover:bg-gray-100 dark:hover:bg-gray-800 p-1"
|
||||
};
|
||||
|
||||
// Size-specific classes
|
||||
const sizeClasses = {
|
||||
sm: "h-8 px-3 text-xs",
|
||||
md: "h-10 px-4 py-2 text-sm",
|
||||
lg: "h-12 px-6 text-base"
|
||||
};
|
||||
|
||||
// Combine all classes
|
||||
const classes = `${baseClasses} ${variantClasses[variant]} ${sizeClasses[size]} ${className}`;
|
||||
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
className={classes}
|
||||
onClick={onClick}
|
||||
disabled={disabled}
|
||||
>
|
||||
{children}
|
||||
</button>
|
||||
);
|
||||
};
|
||||
126
packages/vscode-ide-companion/src/webview/components/ui/Card.tsx
Normal file
126
packages/vscode-ide-companion/src/webview/components/ui/Card.tsx
Normal file
@@ -0,0 +1,126 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2025 Qwen Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Card component using Tailwind CSS
|
||||
* This demonstrates how to create new components with Tailwind
|
||||
* while maintaining compatibility with existing components
|
||||
*/
|
||||
|
||||
import type React from 'react';
|
||||
|
||||
interface CardProps {
|
||||
/**
|
||||
* Card contents
|
||||
*/
|
||||
children: React.ReactNode;
|
||||
|
||||
/**
|
||||
* Additional class names
|
||||
*/
|
||||
className?: string;
|
||||
}
|
||||
|
||||
interface CardHeaderProps {
|
||||
/**
|
||||
* Card header contents
|
||||
*/
|
||||
children: React.ReactNode;
|
||||
|
||||
/**
|
||||
* Additional class names
|
||||
*/
|
||||
className?: string;
|
||||
}
|
||||
|
||||
interface CardContentProps {
|
||||
/**
|
||||
* Card content contents
|
||||
*/
|
||||
children: React.ReactNode;
|
||||
|
||||
/**
|
||||
* Additional class names
|
||||
*/
|
||||
className?: string;
|
||||
}
|
||||
|
||||
interface CardFooterProps {
|
||||
/**
|
||||
* Card footer contents
|
||||
*/
|
||||
children: React.ReactNode;
|
||||
|
||||
/**
|
||||
* Additional class names
|
||||
*/
|
||||
className?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Card container component
|
||||
*/
|
||||
const Card: React.FC<CardProps> & {
|
||||
Header: React.FC<CardHeaderProps>;
|
||||
Content: React.FC<CardContentProps>;
|
||||
Footer: React.FC<CardFooterProps>;
|
||||
} = ({
|
||||
children,
|
||||
className = '',
|
||||
}) => {
|
||||
return (
|
||||
<div className={`rounded-lg border bg-card text-card-foreground shadow-sm ${className}`}>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Card header component
|
||||
*/
|
||||
const CardHeader: React.FC<CardHeaderProps> = ({
|
||||
children,
|
||||
className = '',
|
||||
}) => {
|
||||
return (
|
||||
<div className={`flex flex-col space-y-1.5 p-6 ${className}`}>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Card content component
|
||||
*/
|
||||
const CardContent: React.FC<CardContentProps> = ({
|
||||
children,
|
||||
className = '',
|
||||
}) => {
|
||||
return (
|
||||
<div className={`p-6 pt-0 ${className}`}>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Card footer component
|
||||
*/
|
||||
const CardFooter: React.FC<CardFooterProps> = ({
|
||||
children,
|
||||
className = '',
|
||||
}) => {
|
||||
return (
|
||||
<div className={`flex items-center p-6 pt-0 ${className}`}>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
// Compose the Card component with its subcomponents
|
||||
Card.Header = CardHeader;
|
||||
Card.Content = CardContent;
|
||||
Card.Footer = CardFooter;
|
||||
|
||||
export { Card };
|
||||
Reference in New Issue
Block a user