feat: redesign mobile Config Profiles detail, preview, and edit pages

- Rewrite ConfigProfilesMobileView to match desktop functionality:
  full detail view with all fields, preview action showing resolved
  profile, and edit view with project/tool selects, includes,
  environment variables, runtime hints, files, mounts with nested
  files, and git mounts.
- Update useConfigProfiles.handleSubmit to return boolean success.
- Update ConfigProfilesPage to pass required state and callbacks.
- Add mobile-specific CSS for config profile forms, includes,
  mount/file cards, and preview panels.
- Allow MobileDetailView to render extra children.

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

Refs: openspec/changes/mobile-config-profiles-ui
This commit is contained in:
Developer
2026-06-13 22:04:17 +00:00
parent 35f0a3ea2e
commit 98d4393387
29 changed files with 1135 additions and 337 deletions
+1 -1
View File
@@ -2,7 +2,7 @@
dir: apps/web/src/styles
## role
Provides the complete visual design system and styling foundation for the web application, encompassing global styles, theme tokens, syntax highlighting, and utility classes.
Houses the complete CSS styling system for the web application, providing design tokens, global styles, component-specific styles, syntax highlighting themes, and responsive utility classes.
## parent
index: apps/web/src/.pi-map.index.md
map: apps/web/src/.pi-map.md
+4 -4
View File
@@ -4,16 +4,16 @@ dir: apps/web/src/styles
index: apps/web/src/styles/.pi-map.index.md
## role
Provides the complete visual design system and styling foundation for the web application, encompassing global styles, theme tokens, syntax highlighting, and utility classes.
Houses the complete CSS styling system for the web application, providing design tokens, global styles, component-specific styles, syntax highlighting themes, and responsive utility classes.
## files
- global.css | Defines global CSS styles for a web application shell layout, navigation, cards, forms, dialogs, settings pages, and responsive design patterns. | dep: CSS custom properties (CSS variables: --border, --panel, --brand, --muted, --ink, --bg, --danger, --success, --warning, --font-size-xs, --font-size-sm, --space-2, --space-3, --space-4, --space-5)
- syntax-highlight.css | Stylesheet for a syntax highlighting component with toolbar, line numbers, code display, and Prism.js theme integration | dep: Prism.js
- tokens.css | Defines a comprehensive CSS design token system with light/dark themes, spacing scales, breakpoints, and fluid typography for a web application.
- utilities.css | Provides responsive CSS utility classes and component-specific styles for a web application featuring terminals, dialogs, tables, forms, and navigation. | dep: CSS custom properties (variables), xterm.js (terminal integration)
- utilities.css | Provides responsive CSS utility classes and component-specific styles for a web application featuring terminals, session management, dialogs, tables, and forms with mobile-first responsive design. | dep: CSS custom properties (variables like --space-*, --border, --bg, --brand, --muted, --success, --danger, --text-xs, --text-sm), xterm.js (terminal library)
## arch
CSS custom properties-based design token architecture with theme-aware variables, modular separation of concerns across global/base/syntax/utility layers, and responsive breakpoint system with fluid typography scaling.
Token-based CSS architecture using CSS custom properties for light/dark theming, mobile-first responsive design with breakpoint scaling, and modular separation of concerns across tokens, globals, utilities, and component-specific stylesheets.
## tags
space, global, css, web, application, syntax, defines, styles
space, global, css, web, application, responsive, design, syntax
## symbols
-
## workflows
+229
View File
@@ -2452,6 +2452,235 @@ a.nav-item,
width: 100% !important;
}
/* Mobile config profile form extras */
.mobile-form-group p {
margin: 0;
}
.mobile-form-row {
display: flex;
align-items: center;
}
.mobile-form-section {
padding: var(--space-3);
background: var(--panel);
border-radius: 8px;
border: 1px solid var(--border);
margin-bottom: var(--space-2);
}
.mobile-form-section-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: var(--space-3);
}
.mobile-form-section-header h4 {
margin: 0;
font-size: 1rem;
}
.mobile-add-button {
width: 100%;
justify-content: center;
margin-top: var(--space-2);
}
.mobile-form-success {
display: flex;
align-items: center;
gap: var(--space-2);
padding: var(--space-3);
background: var(--success-light);
color: var(--success);
border-radius: 10px;
font-size: 0.875rem;
margin: var(--space-2) 0;
}
.mobile-list-plain {
list-style: none;
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
gap: var(--space-1);
}
.mobile-list-plain li {
padding: var(--space-2);
background: var(--bg);
border-radius: 6px;
font-size: 0.875rem;
}
/* Mobile detail extra actions */
.mobile-detail-actions-extra {
padding: var(--space-3);
padding-top: 0;
margin-top: calc(var(--space-2) * -1);
}
.mobile-detail-actions-extra .secondary-button {
width: 100%;
justify-content: center;
}
/* Mobile includes */
.mobile-includes-list {
display: flex;
flex-direction: column;
gap: var(--space-2);
margin-bottom: var(--space-3);
}
.mobile-include-item {
display: flex;
align-items: center;
gap: var(--space-2);
padding: var(--space-2) var(--space-3);
background: var(--bg);
border: 1px solid var(--border);
border-radius: 8px;
}
.mobile-include-name {
flex: 1;
font-weight: 500;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.mobile-include-scope {
font-size: 0.75rem;
padding: 0.125rem 0.5rem;
background: var(--bg);
color: var(--muted);
border-radius: 999px;
text-transform: uppercase;
letter-spacing: 0.025em;
}
/* Mobile key/value rows */
.mobile-key-value-row {
display: flex;
gap: var(--space-2);
align-items: center;
margin-bottom: var(--space-2);
}
.mobile-key-value-row .mobile-form-input {
flex: 1;
}
/* Mobile file and mount cards */
.mobile-file-card,
.mobile-mount-card {
padding: var(--space-3);
background: var(--bg);
border: 1px solid var(--border);
border-radius: 8px;
margin-bottom: var(--space-2);
}
.mobile-file-header,
.mobile-mount-header {
display: flex;
gap: var(--space-2);
align-items: center;
margin-bottom: var(--space-2);
}
.mobile-file-header .mobile-form-input,
.mobile-mount-header .mobile-form-input {
flex: 1;
}
.mobile-mount-files {
padding-left: var(--space-3);
border-left: 2px solid var(--border);
display: flex;
flex-direction: column;
gap: var(--space-2);
}
.mobile-mount-file-row {
display: flex;
gap: var(--space-2);
align-items: flex-start;
}
.mobile-mount-file-row .mobile-form-input,
.mobile-mount-file-row .mobile-form-textarea {
flex: 1;
}
/* Mobile preview */
.mobile-preview-code {
background: var(--code-bg, #1e1e1e);
color: var(--code-fg, #d4d4d4);
padding: var(--space-3);
border-radius: 8px;
overflow-x: auto;
font-size: 0.8125rem;
font-family: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Monaco,
Consolas, monospace;
margin: var(--space-2) 0 0 0;
}
.mobile-preview-item {
padding: var(--space-3);
background: var(--bg);
border: 1px solid var(--border);
border-radius: 8px;
margin-bottom: var(--space-2);
font-size: 0.875rem;
}
.mobile-preview-item strong {
display: block;
margin-bottom: var(--space-2);
word-break: break-all;
}
.mobile-preview-mapping {
font-family: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Monaco,
Consolas, monospace;
font-size: 0.8125rem;
color: var(--muted);
margin-top: var(--space-1);
}
/* Mobile git mount editor overrides */
.mobile-form-section .git-mount-editor .card {
padding: var(--space-3);
margin-bottom: var(--space-2);
}
.mobile-form-section .git-mount-editor .form-row {
flex-direction: column;
align-items: stretch;
gap: var(--space-2);
}
.mobile-form-section .git-mount-editor input,
.mobile-form-section .git-mount-editor select,
.mobile-form-section .git-mount-editor textarea {
width: 100%;
}
.mobile-form-section .git-mount-editor .form-actions {
flex-direction: row;
}
.mobile-form-section .git-mount-editor button {
min-height: 44px;
}
/* Ensure minimum touch targets on mobile */
button,
a,