feat: mobile edit-as-default with sticky save/delete actions

- Update MobileEditView to render Save and optional Delete in a
  sticky bottom action bar; header now shows Cancel + title only.
- Make ConfigProfilesMobileView open edit view on profile tap.
- Make ToolWorkshopMobileView open edit view on tool type tap.
- Wire delete into MobileEditView for existing profiles and tool
  types.
- Stay on edit view after saving an existing item; create flow
  returns to list as before.
- Update ToolWorkshopPage cancel to return to list.
- Add mobile-edit-actions and mobile-edit-delete CSS.

Quality gates: npm run typecheck, npm run lint, npm test -- --run (87 passed)

Refs: openspec/changes/mobile-edit-default-bottom-actions
This commit is contained in:
Developer
2026-06-13 22:29:15 +00:00
parent 8b15689fb3
commit 23fc0a6b82
29 changed files with 164 additions and 59 deletions
@@ -2,7 +2,7 @@
dir: apps/web/src/components/features/config-profiles
## role
Provides a complete UI subsystem for managing container configuration profiles across desktop and mobile form factors.
Provides UI components for managing Docker configuration profiles including creation, editing, listing, and mobile-responsive views.
## parent
index: apps/web/src/components/features/.pi-map.index.md
map: apps/web/src/components/features/.pi-map.md
@@ -4,13 +4,13 @@ dir: apps/web/src/components/features/config-profiles
index: apps/web/src/components/features/config-profiles/.pi-map.index.md
## role
Provides a complete UI subsystem for managing container configuration profiles across desktop and mobile form factors.
Provides UI components for managing Docker configuration profiles including creation, editing, listing, and mobile-responsive views.
## files
- ConfigProfileEditorPanel.tsx | React component that renders a form-based editor panel for creating and editing configuration profiles with support for includes, environment variables, runtime hints, files, and mounts. | exp: ConfigProfileEditorPanel | dep: ../../icon, ../git/git-mount-editor, ../../../api/config-profiles, ../../../types, ../../../api/tool-types, React, Icon, GitMountEditor, ConfigProfile, CreateConfigProfileRequest, ResolvedProfile, ProjectWithRepos, ToolType
- ConfigProfileListSidebar.tsx | Renders a sidebar component for listing, selecting, creating, and deleting configuration profiles with visual indicators for default status, scope, and includes. | exp: ConfigProfileListSidebar | dep: ../../icon, ../../../api/config-profiles, Icon, ConfigProfile
- ConfigProfilesMobileView.tsx | Renders a mobile-optimized view for managing configuration profiles with list, detail, edit, and preview states. | exp: ConfigProfilesMobileView | dep: react, ../mobile/mobile-list-view, ../mobile/mobile-detail-view, ../mobile/mobile-edit-view, ../mobile/mobile-fab, ../git/git-mount-editor, ../../icon, ../../../api/config-profiles, ../../../types, ../../../api/tool-types, mobile-list-view, mobile-detail-view, mobile-edit-view, mobile-fab, git-mount-editor, icon, config-profiles API types, project types, tool-types API
- ConfigProfilesMobileView.tsx | Renders a mobile-responsive view for managing configuration profiles with list, detail, edit, and preview states. | exp: ConfigProfilesMobileView | dep: react, ../mobile/mobile-list-view, ../mobile/mobile-detail-view, ../mobile/mobile-edit-view, ../mobile/mobile-fab, ../git/git-mount-editor, ../../icon, ../../../api/config-profiles, ../../../types, ../../../api/tool-types, mobile-list-view, mobile-detail-view, mobile-edit-view, mobile-fab, git-mount-editor, icon, config-profiles API types, types
## arch
Compound component architecture with state-driven mobile adaptation, separating list navigation from editing concerns with explicit responsive breakpoint handling.
Feature-based component composition with state-driven panels (list/detail/edit/preview), form-based editing, and responsive layout adaptation for mobile/desktop.
## tags
mobile, config, view, profiles, editor, profile, list, icon
## symbols
@@ -113,7 +113,7 @@ export const ConfigProfilesMobileView = ({
try {
const ok = await onSubmit();
if (ok) {
onViewChange(isCreating ? "list" : "detail");
onViewChange(isCreating ? "list" : "edit");
}
} finally {
setIsSaving(false);
@@ -150,7 +150,7 @@ export const ConfigProfilesMobileView = ({
const profile = profiles.find((p) => p.id === id);
if (profile) {
onSelect(profile);
onViewChange("detail");
onViewChange("edit");
}
}}
onItemDelete={(id: string) => onDelete(id)}
@@ -395,9 +395,11 @@ export const ConfigProfilesMobileView = ({
<MobileEditView
title={isCreating ? "Create Profile" : "Edit Profile"}
onCancel={() => {
onViewChange(isCreating ? "list" : "detail");
onViewChange("list");
}}
onSave={handleSave}
onDelete={isCreating ? undefined : handleDeleteClick}
deleteLabel="Delete Profile"
isSaving={isSaving || saveStatus === "saving"}
>
<div className="mobile-form-group">
@@ -793,7 +795,7 @@ export const ConfigProfilesMobileView = ({
const profile = profiles.find((p) => p.id === id);
if (profile) {
onSelect(profile);
onViewChange("detail");
onViewChange("edit");
}
}}
onItemDelete={(id: string) => onDelete(id)}