refactor: organize frontend components into features/ directories
Moved 43 component files into 9 feature domains: - features/git/ — commit-dialog, commit-panel, file-editor, git-mount-editor, git-toolbar, merge-dialog - features/project/ — repositories-settings-tab, repository-create-dialog - features/terminal/ — special-keys-panel, special-keys-strip, terminal-session-tabs, terminal - features/workspace/ — workspace-card, workspace-create-form, workspace-header, workspace-instance-chips - features/session/ — create-session-form, session-card, session-list - features/tool/ — instance-list, manifest-editor, start-tool-fab, start-tool-modal, tool-starter, tools-bottom-sheet - features/notification/ — event-toast-bridge, notification-center, notification-item - features/settings/ — settings-tab-layout - features/mobile/ — mobile-action-sheet, mobile-detail-view, mobile-edit-view, mobile-fab, mobile-list-view, mobile-nav, mobile-page-header, mobile-terminal-header, mobile-terminal-wrapper Updated all imports across pages and components. Root components/ now only contains generic UI pieces: app-shell, code-editor, data-states, icon, protected-route, syntax-highlighter. Quality gates: verified no remaining old imports.
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
import { Icon } from "./icon";
|
||||
import type { IconName } from "../utils/icons";
|
||||
|
||||
interface MobileListItem {
|
||||
id: string;
|
||||
title: string;
|
||||
subtitle?: string;
|
||||
icon?: string;
|
||||
status?: string;
|
||||
}
|
||||
|
||||
interface MobileListViewProps {
|
||||
items: MobileListItem[];
|
||||
onItemClick: (id: string) => void;
|
||||
onItemDelete?: (id: string) => void;
|
||||
onItemDuplicate?: (id: string) => void;
|
||||
emptyMessage?: string;
|
||||
searchPlaceholder?: string;
|
||||
onSearch?: (query: string) => void;
|
||||
}
|
||||
|
||||
export const MobileListView: React.FC<MobileListViewProps> = ({
|
||||
items,
|
||||
onItemClick,
|
||||
emptyMessage = "No items found",
|
||||
searchPlaceholder = "Search...",
|
||||
onSearch,
|
||||
}) => {
|
||||
return (
|
||||
<div className="mobile-list-view">
|
||||
{onSearch && (
|
||||
<div className="mobile-list-search">
|
||||
<input
|
||||
type="search"
|
||||
placeholder={searchPlaceholder}
|
||||
onChange={(e) => onSearch(e.target.value)}
|
||||
className="mobile-list-search-input"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{items.length === 0 ? (
|
||||
<div className="mobile-list-empty">
|
||||
<Icon name="folder" size="lg" />
|
||||
<p>{emptyMessage}</p>
|
||||
</div>
|
||||
) : (
|
||||
<div className="mobile-list-items">
|
||||
{items.map((item) => (
|
||||
<button
|
||||
key={item.id}
|
||||
className="mobile-list-item"
|
||||
onClick={() => onItemClick(item.id)}
|
||||
type="button"
|
||||
>
|
||||
{item.icon && (
|
||||
<div className="mobile-list-item-icon">
|
||||
<Icon name={item.icon as IconName} size="md" />
|
||||
</div>
|
||||
)}
|
||||
<div className="mobile-list-item-content">
|
||||
<div className="mobile-list-item-title">{item.title}</div>
|
||||
{item.subtitle && (
|
||||
<div className="mobile-list-item-subtitle">{item.subtitle}</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="mobile-list-item-actions" style={{ transform: "rotate(180deg)" }}>
|
||||
<Icon name="arrow-left" size="sm" />
|
||||
</div>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user