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:
2026-06-04 12:37:24 +02:00
parent 7224afafd1
commit 1021d61be3
54 changed files with 31 additions and 31 deletions
@@ -0,0 +1,95 @@
import { Icon } from "./icon";
interface Field {
label: string;
value: string | number | boolean | null;
type?: "text" | "code" | "json" | "boolean";
}
interface MobileDetailViewProps {
title: string;
subtitle?: string;
fields: Field[];
onEdit: () => void;
onDelete: () => void;
onBack: () => void;
}
export const MobileDetailView: React.FC<MobileDetailViewProps> = ({
title,
subtitle,
fields,
onEdit,
onDelete,
onBack,
}) => {
const renderValue = (field: Field) => {
if (field.value === null || field.value === undefined) {
return <span className="text-muted">Not set</span>;
}
if (field.type === "boolean") {
return field.value ? (
<span className="badge badge-success">Yes</span>
) : (
<span className="badge badge-secondary">No</span>
);
}
if (field.type === "code" || field.type === "json") {
return (
<pre className="mobile-detail-code">
{typeof field.value === "string" ? field.value : JSON.stringify(field.value, null, 2)}
</pre>
);
}
return <span>{String(field.value)}</span>;
};
return (
<div className="mobile-detail-view">
<header className="mobile-detail-header">
<button
className="mobile-detail-back"
onClick={onBack}
type="button"
aria-label="Go back"
>
<Icon name="arrow-left" size="md" />
</button>
<div className="mobile-detail-header-content">
<h1 className="mobile-detail-title">{title}</h1>
{subtitle && <p className="mobile-detail-subtitle">{subtitle}</p>}
</div>
<div className="mobile-detail-actions">
<button
className="mobile-detail-action"
onClick={onEdit}
type="button"
aria-label="Edit"
>
<Icon name="edit" size="sm" />
</button>
<button
className="mobile-detail-action mobile-detail-action-danger"
onClick={onDelete}
type="button"
aria-label="Delete"
>
<Icon name="delete" size="sm" />
</button>
</div>
</header>
<div className="mobile-detail-fields">
{fields.map((field, index) => (
<div key={index} className="mobile-detail-field">
<label className="mobile-detail-field-label">{field.label}</label>
<div className="mobile-detail-field-value">{renderValue(field)}</div>
</div>
))}
</div>
</div>
);
};