refactor: move components in src/components/ui to src/shared/view/ui

This commit is contained in:
Haileyesus
2026-02-27 22:49:18 +03:00
parent 040c300c29
commit f2e195bd08
30 changed files with 51 additions and 60 deletions

View File

@@ -1,7 +1,6 @@
import React, { useState, useEffect } from 'react';
import { X, FolderPlus, GitBranch, Key, ChevronRight, ChevronLeft, Check, Loader2, AlertCircle, FolderOpen, Eye, EyeOff, Plus } from 'lucide-react';
import { Button } from './ui/button';
import { Input } from './ui/input';
import { Button, Input } from '../shared/view/ui';
import { api } from '../utils/api';
import { useTranslation } from 'react-i18next';

View File

@@ -1,6 +1,6 @@
import { memo, useMemo } from 'react';
import { CheckCircle2, Circle, Clock, type LucideIcon } from 'lucide-react';
import { Badge } from '../../../../ui/badge';
import { Badge } from '../../../../../shared/view/ui';
type TodoStatus = 'completed' | 'in_progress' | 'pending';
type TodoPriority = 'high' | 'medium' | 'low';

View File

@@ -1,6 +1,7 @@
import type { ReactNode, RefObject } from 'react';
import { Folder, Search } from 'lucide-react';
import { useTranslation } from 'react-i18next';
import { ScrollArea } from '../../../shared/view/ui';
import type { FileTreeNode, FileTreeViewMode } from '../types/types';
import FileTreeEmptyState from './FileTreeEmptyState';
import FileTreeList from './FileTreeList';

View File

@@ -1,7 +1,6 @@
import { ChevronDown, Eye, FileText, FolderPlus, List, RefreshCw, Search, TableProperties, X } from 'lucide-react';
import { useTranslation } from 'react-i18next';
import { Button } from '../../ui/button';
import { Input } from '../../ui/input';
import { Button, Input } from '../../../shared/view/ui';
import { cn } from '../../../lib/utils';
import type { FileTreeViewMode } from '../types/types';

View File

@@ -1,6 +1,6 @@
import { useEffect, useState } from 'react';
import { X } from 'lucide-react';
import { Button } from '../../ui/button';
import { Button } from '../../../shared/view/ui';
import { authenticatedFetch } from '../../../utils/api';
import type { FileTreeImageSelection } from '../types/types';

View File

@@ -1,7 +1,7 @@
import { Settings as SettingsIcon, X } from 'lucide-react';
import { useTranslation } from 'react-i18next';
import LoginModal from '../../LoginModal';
import { Button } from '../../ui/button';
import { Button } from '../../../shared/view/ui';
import ClaudeMcpFormModal from '../view/modals/ClaudeMcpFormModal';
import CodexMcpFormModal from '../view/modals/CodexMcpFormModal';
import SettingsMainTabs from '../view/SettingsMainTabs';

View File

@@ -2,8 +2,7 @@ import { FolderOpen, Globe, X } from 'lucide-react';
import { useEffect, useMemo, useState } from 'react';
import type { FormEvent } from 'react';
import { useTranslation } from 'react-i18next';
import { Input } from '../../../ui/input';
import { Button } from '../../../ui/button';
import { Button, Input } from '../../../../shared/view/ui';
import { DEFAULT_CLAUDE_MCP_FORM } from '../../constants/constants';
import type { ClaudeMcpFormState, McpServer, McpScope, McpTransportType, SettingsProject } from '../../types/types';

View File

@@ -2,8 +2,7 @@ import { useEffect, useState } from 'react';
import type { FormEvent } from 'react';
import { X } from 'lucide-react';
import { useTranslation } from 'react-i18next';
import { Button } from '../../../ui/button';
import { Input } from '../../../ui/input';
import { Button, Input } from '../../../../shared/view/ui';
import { DEFAULT_CODEX_MCP_FORM } from '../../constants/constants';
import type { CodexMcpFormState, McpServer } from '../../types/types';

View File

@@ -1,7 +1,6 @@
import { LogIn } from 'lucide-react';
import { useTranslation } from 'react-i18next';
import { Badge } from '../../../../../../ui/badge';
import { Button } from '../../../../../../ui/button';
import { Badge, Button } from '../../../../../../../shared/view/ui';
import SessionProviderLogo from '../../../../../../llm-logo-provider/SessionProviderLogo';
import type { AgentProvider, AuthStatus } from '../../../../../types/types';

View File

@@ -1,7 +1,6 @@
import { Edit3, Globe, Plus, Server, Terminal, Trash2, Zap } from 'lucide-react';
import { useTranslation } from 'react-i18next';
import { Badge } from '../../../../../../ui/badge';
import { Button } from '../../../../../../ui/button';
import { Badge, Button } from '../../../../../../../shared/view/ui';
import type { McpServer, McpToolsResult, McpTestResult } from '../../../../../types/types';
const getTransportIcon = (type: string | undefined) => {

View File

@@ -1,8 +1,7 @@
import { useState } from 'react';
import { AlertTriangle, Plus, Shield, X } from 'lucide-react';
import { useTranslation } from 'react-i18next';
import { Button } from '../../../../../../ui/button';
import { Input } from '../../../../../../ui/input';
import { Button, Input } from '../../../../../../../shared/view/ui';
import type { CodexPermissionMode, GeminiPermissionMode } from '../../../../../types/types';
const COMMON_CLAUDE_TOOLS = [

View File

@@ -1,7 +1,6 @@
import { ExternalLink, Key, Plus, Trash2 } from 'lucide-react';
import { useTranslation } from 'react-i18next';
import { Button } from '../../../../../ui/button';
import { Input } from '../../../../../ui/input';
import { Button, Input } from '../../../../../../shared/view/ui';
import type { ApiKeyItem } from '../types';
type ApiKeysSectionProps = {

View File

@@ -1,7 +1,6 @@
import { Eye, EyeOff, Github, Plus, Trash2 } from 'lucide-react';
import { useTranslation } from 'react-i18next';
import { Button } from '../../../../../ui/button';
import { Input } from '../../../../../ui/input';
import { Button, Input } from '../../../../../../shared/view/ui';
import type { GithubCredentialItem } from '../types';
type GithubCredentialsSectionProps = {

View File

@@ -1,6 +1,6 @@
import { Check, Copy } from 'lucide-react';
import { useTranslation } from 'react-i18next';
import { Button } from '../../../../../ui/button';
import { Button } from '../../../../../../shared/view/ui';
import type { CreatedApiKey } from '../types';
type NewApiKeyAlertProps = {

View File

@@ -1,8 +1,7 @@
import { Check, GitBranch } from 'lucide-react';
import { useTranslation } from 'react-i18next';
import { useGitSettings } from '../../../hooks/useGitSettings';
import { Button } from '../../../../ui/button';
import { Input } from '../../../../ui/input';
import { Button, Input } from '../../../../../shared/view/ui';
export default function GitSettingsTab() {
const { t } = useTranslation('settings');

View File

@@ -1,4 +1,4 @@
import { ScrollArea } from '../../../ui/scroll-area';
import { ScrollArea } from '../../../../shared/view/ui';
import type { TFunction } from 'i18next';
import type { Project } from '../../../../types/app';
import type { ReleaseInfo } from '../../../../types/sharedTypes';

View File

@@ -1,7 +1,6 @@
import { FolderPlus, Plus, RefreshCw, Search, X, PanelLeftClose } from 'lucide-react';
import type { TFunction } from 'i18next';
import { Button } from '../../../ui/button';
import { Input } from '../../../ui/input';
import { Button, Input } from '../../../../shared/view/ui';
import { IS_PLATFORM } from '../../../../constants/config';
type SidebarHeaderProps = {

View File

@@ -2,7 +2,7 @@ import { useMemo } from 'react';
import ReactDOM from 'react-dom';
import { AlertTriangle, Trash2 } from 'lucide-react';
import type { TFunction } from 'i18next';
import { Button } from '../../../ui/button';
import { Button } from '../../../../shared/view/ui';
import ProjectCreationWizard from '../../../ProjectCreationWizard';
import Settings from '../../../settings/view/Settings';
import VersionUpgradeModal from '../modals/VersionUpgradeModal';

View File

@@ -1,4 +1,4 @@
import { Button } from '../../../ui/button';
import { Button } from '../../../../shared/view/ui';
import { Check, ChevronDown, ChevronRight, Edit3, Folder, FolderOpen, Star, Trash2, X } from 'lucide-react';
import type { TFunction } from 'i18next';
import { cn } from '../../../../lib/utils';

View File

@@ -1,6 +1,6 @@
import { ChevronDown, Plus } from 'lucide-react';
import type { TFunction } from 'i18next';
import { Button } from '../../../ui/button';
import { Button } from '../../../../shared/view/ui';
import type { Project, ProjectSession, SessionProvider } from '../../../../types/app';
import type { SessionWithProvider, TouchHandlerFactory } from '../../types/types';
import SidebarSessionItem from './SidebarSessionItem';

View File

@@ -1,5 +1,4 @@
import { Badge } from '../../../ui/badge';
import { Button } from '../../../ui/button';
import { Badge, Button } from '../../../../shared/view/ui';
import { Check, Clock, Edit2, Trash2, X } from 'lucide-react';
import type { TFunction } from 'i18next';
import { cn } from '../../../../lib/utils';

View File

@@ -1,6 +1,6 @@
import * as React from 'react';
import { cva, type VariantProps } from 'class-variance-authority';
import { cn } from '../../lib/utils';
import { cn } from '../../../../lib/utils';
const badgeVariants = cva(
'inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2',
@@ -17,12 +17,10 @@ const badgeVariants = cva(
defaultVariants: {
variant: 'default',
},
},
}
);
export interface BadgeProps
extends React.HTMLAttributes<HTMLDivElement>,
VariantProps<typeof badgeVariants> {}
type BadgeProps = React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof badgeVariants>;
function Badge({ className, variant, ...props }: BadgeProps) {
return <div className={cn(badgeVariants({ variant }), className)} {...props} />;

View File

@@ -0,0 +1 @@
export { Badge, badgeVariants } from './Badge';

View File

@@ -1,7 +1,8 @@
import * as React from 'react';
import { cva, type VariantProps } from 'class-variance-authority';
import { cn } from '../../lib/utils';
import { cn } from '../../../../lib/utils';
// Keep visual variants centralized so all button usages stay consistent.
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',
{
@@ -27,24 +28,20 @@ const buttonVariants = cva(
variant: 'default',
size: 'default',
},
},
}
);
export interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {}
type ButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement> &
VariantProps<typeof buttonVariants>;
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
({ className, variant, size, ...props }, ref) => {
return (
<button
className={cn(buttonVariants({ variant, size, className }))}
ref={ref}
{...props}
/>
<button className={cn(buttonVariants({ variant, size, className }))} ref={ref} {...props} />
);
},
}
);
Button.displayName = 'Button';
export { Button, buttonVariants };

View File

@@ -0,0 +1 @@
export { Button, buttonVariants } from './Button';

View File

@@ -1,2 +1,6 @@
export { Badge, badgeVariants } from './badge';
export { Button, buttonVariants } from './button';
export { DarkModeToggle } from './dark-mode-toggle';
export { Input } from './input';
export { ScrollArea } from './scroll-area';
export { Tooltip } from './tooltip';

View File

@@ -1,8 +1,7 @@
import * as React from 'react';
import { cn } from '../../lib/utils';
import { cn } from '../../../../lib/utils';
export interface InputProps
extends React.InputHTMLAttributes<HTMLInputElement> {}
type InputProps = React.InputHTMLAttributes<HTMLInputElement>;
const Input = React.forwardRef<HTMLInputElement, InputProps>(
({ className, type, ...props }, ref) => {
@@ -11,14 +10,15 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
type={type}
className={cn(
'flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50',
className,
className
)}
ref={ref}
{...props}
/>
);
},
}
);
Input.displayName = 'Input';
export { Input };

View File

@@ -0,0 +1 @@
export { Input } from './Input';

View File

@@ -1,14 +1,12 @@
import * as React from 'react';
import { cn } from '../../lib/utils';
import { cn } from '../../../../lib/utils';
export interface ScrollAreaProps extends React.HTMLAttributes<HTMLDivElement> {}
type ScrollAreaProps = React.HTMLAttributes<HTMLDivElement>;
const ScrollArea = React.forwardRef<HTMLDivElement, ScrollAreaProps>(
({ className, children, ...props }, ref) => (
<div
className={cn(className, 'relative overflow-hidden')}
{...props}
>
<div className={cn(className, 'relative overflow-hidden')} {...props}>
{/* Inner container keeps border radius while allowing momentum scrolling on touch devices. */}
<div
ref={ref}
className="h-full w-full rounded-[inherit] overflow-auto"
@@ -20,8 +18,9 @@ const ScrollArea = React.forwardRef<HTMLDivElement, ScrollAreaProps>(
{children}
</div>
</div>
),
)
);
ScrollArea.displayName = 'ScrollArea';
export { ScrollArea };

View File

@@ -0,0 +1 @@
export { ScrollArea } from './ScrollArea';