feat: mobile Spaces nav and list-based project/workspace views

- Combine Projects and Workspaces into a single 'Spaces' grouped mobile
  nav item that opens a bottom-sheet menu.
- Add SpacesBottomSheet component with Projects/Workspaces options.
- Extend MobileListView with optional renderItem prop for rich rows.
- Redesign mobile ProjectsPage rows to show project description and
  repository chips.
- Replace mobile WorkspacesPage list with compact WorkspaceCard grid,
  matching desktop card content.
- Add mobile-list-* CSS and mobile-workspaces-list spacing.

Quality gates: npm run typecheck, npm run lint clean,
npm test -- --run 87 passed.
This commit is contained in:
Developer
2026-06-13 19:32:16 +00:00
parent e6ab77d123
commit 530225d37c
27 changed files with 346 additions and 113 deletions
+1 -1
View File
@@ -16,7 +16,7 @@ dir: .
Trust boundary: index routes, map orients, source decides.
## role
Infrastructure and deployment configuration for a self-hosted project management platform with containerized services, SSO integration, and AI agent development workflows.
Infrastructure and deployment configuration for a self-hosted project management and git repository platform with OAuth2 authentication.
## parent
-
## children
+2 -2
View File
@@ -18,7 +18,7 @@ index: ./.pi-map.index.md
Trust boundary: index routes, map orients, source decides.
## role
Infrastructure and deployment configuration for a self-hosted project management platform with containerized services, SSO integration, and AI agent development workflows.
Infrastructure and deployment configuration for a self-hosted project management and git repository platform with OAuth2 authentication.
## files
- .env.example | Provides a template of environment variables for configuring a Headquarter application with PostgreSQL, Redis, Authentik SSO, and Docker/Traefik deployment
- .gitignore | Specifies files and directories for Git to ignore across a multi-language project with Python, Node, and custom tooling | dep: Git
@@ -31,7 +31,7 @@ Infrastructure and deployment configuration for a self-hosted project management
- progress.md | Tracks completed and remaining tasks for a backend-frontend code refactoring project organized in 7 phases
- swap-pane | Empty file with no functionality
## arch
Multi-service Docker Compose architecture with PostgreSQL/Redis data layer, Node/Python frontend/backend split, Traefik reverse proxy for TLS termination, and OpenSpec-driven AI agent orchestration with environment-based configuration management.
Containerized microservices architecture using Docker Compose with PostgreSQL/Redis persistence, Traefik reverse proxy for TLS termination, environment-driven configuration, and a decoupled frontend/API backend structure.
## tags
docker, redis, git, application, postgresql, compose, traefik, project
## symbols
+1 -1
View File
@@ -2,7 +2,7 @@
dir: apps
## role
Contains the main deployable application entry points and top-level configurations for the project.
Contains the main executable application modules that serve as entry points for the project.
## parent
index: ./.pi-map.index.md
map: ./.pi-map.md
+2 -2
View File
@@ -4,10 +4,10 @@ dir: apps
index: apps/.pi-map.index.md
## role
Contains the main deployable application entry points and top-level configurations for the project.
Contains the main executable application modules that serve as entry points for the project.
## files
## arch
Monorepo-style directory structure typically housing multiple independent applications that share common libraries or modules, each with its own configuration and dependencies.
Modular application structure with separate deployable units, likely following microservices or layered architecture patterns with domain-driven design boundaries.
## tags
-
## symbols
+1 -1
View File
@@ -2,7 +2,7 @@
dir: apps/web
## role
Frontend web application serving as the browser-based UI for the project, built with React/Vite/TypeScript and deployed via nginx.
Frontend web application for the headquarters system, providing a browser-based UI with code editing, terminal, and routing capabilities.
## parent
index: apps/.pi-map.index.md
map: apps/.pi-map.md
+2 -2
View File
@@ -4,7 +4,7 @@ dir: apps/web
index: apps/web/.pi-map.index.md
## role
Frontend web application serving as the browser-based UI for the project, built with React/Vite/TypeScript and deployed via nginx.
Frontend web application for the headquarters system, providing a browser-based UI with code editing, terminal, and routing capabilities.
## files
- .env.example | Template file defining example environment variables for frontend API and application URL configuration
- .eslintrc.cjs | Configures ESLint for a TypeScript browser project with modern ECMAScript module support | dep: @typescript-eslint/parser, @typescript-eslint/eslint-plugin, eslint
@@ -16,7 +16,7 @@ Frontend web application serving as the browser-based UI for the project, built
- tsconfig.json | TypeScript configuration file for a React project using Vite with modern ES2020 target and bundler module resolution | dep: typescript, react, vite
- vite.config.ts | Configures Vite build tool for a React project with custom dev server port and Vitest test settings. | dep: vite, @vitejs/plugin-react
## arch
Modern SPA architecture using Vite for bundling, React for UI, TypeScript for type safety, with containerized nginx deployment and environment-driven configuration.
Modern React SPA built with Vite and TypeScript, containerized with multi-stage Docker/nginx deployment, using ES modules with Vitest for testing.
## tags
react, eslint, vite, typescript, dom, application, nginx, web
## symbols
+1 -1
View File
@@ -2,7 +2,7 @@
dir: apps/web/src
## role
Provides the core web application entry point, routing infrastructure, and shared domain type definitions for a React-based frontend.
Frontend web application entry point and core infrastructure for a React-based collaborative development platform.
## parent
index: apps/web/.pi-map.index.md
map: apps/web/.pi-map.md
+2 -2
View File
@@ -4,13 +4,13 @@ dir: apps/web/src
index: apps/web/src/.pi-map.index.md
## role
Provides the core web application entry point, routing infrastructure, and shared domain type definitions for a React-based frontend.
Frontend web application entry point and core infrastructure for a React-based collaborative development platform.
## files
- main.tsx | Bootstraps a React application with routing, authentication, and session management providers. | dep: react, react-dom/client, react-router-dom, ./router, ./state/auth, ./state/sessions, ./styles/tokens.css, ./styles/global.css, ./styles/utilities.css, ./styles/syntax-highlight.css, ./styles/pages/git-history.css, ./styles/pages/projects.css, ./styles/pages/sessions.css, ./styles/pages/ssh-keys.css, ./styles/pages/workspace-detail.css, ./styles/pages/workspaces.css, react-dom
- router.tsx | Defines the React Router configuration for a web application with protected routes, nested layouts, and redirects. | exp: AppRouter | dep: react-router-dom, ./components/app-shell, ./components/protected-route, ./pages/DashboardPage, ./pages/PlaceholderPage, ./pages/ProfilePage, ./pages/ProjectsPage, ./pages/GitRepositoriesPage, ./pages/GitHistoryPage, ./pages/ProjectSettingsPage, ./pages/SettingsPage, ./pages/TerminalPage, ./pages/ToolWorkshopPage, ./pages/SshKeysPage, ./pages/ConfigProfilesPage, ./pages/SessionsPage, ./pages/WorkspacesPage, ./pages/WorkspaceDetailPage
- types.ts | Defines TypeScript type definitions for user sessions, projects, repositories, and workspaces in an application. | exp: SessionUser, SessionPayload, Project, WorkspaceSummary, RepositorySummary, ProjectWithRepos
## arch
Layered architecture with provider composition pattern for cross-cutting concerns (auth, routing, sessions), declarative route configuration with nested layouts and route guards, and centralized TypeScript domain modeling.
Provider-composition pattern with React Router v6 nested route declarations, centralized type definitions, and layered authentication/session management wrapping a protected route hierarchy.
## tags
pages, styles, css, router, react, session, dom, project
## symbols
+1 -1
View File
@@ -2,7 +2,7 @@
dir: apps/web/src/components
## role
Provides reusable, accessible React UI components and utilities for the web application including layout shells, data display states, icon system, code editing, routing guards, and toast notification infrastructure.
Provides foundational, reusable React UI components and utilities for rendering layouts, interactive elements, data states, icons, code editing, routing guards, and toast notifications across the web application.
## parent
index: apps/web/src/.pi-map.index.md
map: apps/web/src/.pi-map.md
+2 -2
View File
@@ -4,7 +4,7 @@ dir: apps/web/src/components
index: apps/web/src/components/.pi-map.index.md
## role
Provides reusable, accessible React UI components and utilities for the web application including layout shells, data display states, icon system, code editing, routing guards, and toast notification infrastructure.
Provides foundational, reusable React UI components and utilities for rendering layouts, interactive elements, data states, icons, code editing, routing guards, and toast notifications across the web application.
## files
- app-shell.tsx | Renders the main application shell layout with navigation, session management, and responsive mobile/desktop views for a React Router-based app. | exp: AppShell | dep: react-router-dom, ../api/sessions, ../hooks/use-theme, ../state/auth, ../state/sessions, ../hooks/use-mobile-viewport, ../state/events, ../state/toast, ../state/notifications, ./features/notification/event-toast-bridge, ./features/notification/notification-center, ./icon, ./features/mobile/mobile-nav, ./features/tool/start-tool-fab, ../utils/icons
- code-editor.tsx | A React component that renders a syntax-highlighted code editor with line numbers using react-simple-code-editor. | exp: CodeEditor | dep: react, react-simple-code-editor, ../utils/language
@@ -17,7 +17,7 @@ Provides reusable, accessible React UI components and utilities for the web appl
- toast-rules.test.ts | Unit tests for mapping instance events to toast notification categories and severities | dep: vitest, ./toast-rules, ../types/events
- toast-rules.ts | Maps instance events to toast notifications with deduplication logic to prevent spam | exp: func:mapEventToCategory(event: InstanceEventPayload) → string, call:event.event.startsWith, func:mapEventToSeverity(event: InstanceEventPayload) → "info" | "warning" | "error" | "success", func:handleEventToast(event: InstanceEventPayload) → void, call:shouldShowToast, call:toast.info, call:toast.success, call:toast.warning, call:toast.error, func:clearToastDedup() → void, call:lastToastTime.clear | dep: ../state/toast, ../types/events, toast state module, InstanceEventPayload type
## arch
Component-based architecture with functional React patterns, custom hooks for state management, utility modules for cross-cutting concerns (icons, toasts), and test co-location with implementation files.
Component-based architecture with functional React patterns, custom hooks for state management, centralized icon mapping with type safety, HOC-like route guards, and utility modules for cross-cutting concerns (toast rules, data states) with co-located test files.
## tags
toast, icon, react, state, code, loading, event, editor
## symbols
@@ -1,52 +1,52 @@
# features (index)
dir: features
# apps/web/src/components/features (index)
dir: apps/web/src/components/features
## role
Contains modular, feature-based components that encapsulate specific domain functionality or user-facing capabilities within the project.
Contains reusable UI components organized by feature domain for the web application.
## parent
index: ./.pi-map.index.md
map: ./.pi-map.md
index: apps/web/src/components/.pi-map.index.md
map: apps/web/src/components/.pi-map.md
## children
- features/config-profiles
index: features/config-profiles/.pi-map.index.md
map: features/config-profiles/.pi-map.md
- features/git
index: features/git/.pi-map.index.md
map: features/git/.pi-map.md
- features/mobile
index: features/mobile/.pi-map.index.md
map: features/mobile/.pi-map.md
- features/notification
index: features/notification/.pi-map.index.md
map: features/notification/.pi-map.md
- features/project
index: features/project/.pi-map.index.md
map: features/project/.pi-map.md
- features/session
index: features/session/.pi-map.index.md
map: features/session/.pi-map.md
- features/settings
index: features/settings/.pi-map.index.md
map: features/settings/.pi-map.md
- features/ssh-keys
index: features/ssh-keys/.pi-map.index.md
map: features/ssh-keys/.pi-map.md
- features/terminal
index: features/terminal/.pi-map.index.md
map: features/terminal/.pi-map.md
- features/tool
index: features/tool/.pi-map.index.md
map: features/tool/.pi-map.md
- features/tool-workshop
index: features/tool-workshop/.pi-map.index.md
map: features/tool-workshop/.pi-map.md
- features/workspace
index: features/workspace/.pi-map.index.md
map: features/workspace/.pi-map.md
- apps/web/src/components/features/config-profiles
index: apps/web/src/components/features/config-profiles/.pi-map.index.md
map: apps/web/src/components/features/config-profiles/.pi-map.md
- apps/web/src/components/features/git
index: apps/web/src/components/features/git/.pi-map.index.md
map: apps/web/src/components/features/git/.pi-map.md
- apps/web/src/components/features/mobile
index: apps/web/src/components/features/mobile/.pi-map.index.md
map: apps/web/src/components/features/mobile/.pi-map.md
- apps/web/src/components/features/notification
index: apps/web/src/components/features/notification/.pi-map.index.md
map: apps/web/src/components/features/notification/.pi-map.md
- apps/web/src/components/features/project
index: apps/web/src/components/features/project/.pi-map.index.md
map: apps/web/src/components/features/project/.pi-map.md
- apps/web/src/components/features/session
index: apps/web/src/components/features/session/.pi-map.index.md
map: apps/web/src/components/features/session/.pi-map.md
- apps/web/src/components/features/settings
index: apps/web/src/components/features/settings/.pi-map.index.md
map: apps/web/src/components/features/settings/.pi-map.md
- apps/web/src/components/features/ssh-keys
index: apps/web/src/components/features/ssh-keys/.pi-map.index.md
map: apps/web/src/components/features/ssh-keys/.pi-map.md
- apps/web/src/components/features/terminal
index: apps/web/src/components/features/terminal/.pi-map.index.md
map: apps/web/src/components/features/terminal/.pi-map.md
- apps/web/src/components/features/tool
index: apps/web/src/components/features/tool/.pi-map.index.md
map: apps/web/src/components/features/tool/.pi-map.md
- apps/web/src/components/features/tool-workshop
index: apps/web/src/components/features/tool-workshop/.pi-map.index.md
map: apps/web/src/components/features/tool-workshop/.pi-map.md
- apps/web/src/components/features/workspace
index: apps/web/src/components/features/workspace/.pi-map.index.md
map: apps/web/src/components/features/workspace/.pi-map.md
## files
## links
index: features/.pi-map.index.md
map: features/.pi-map.md
index: apps/web/src/components/features/.pi-map.index.md
map: apps/web/src/components/features/.pi-map.md
## workflows
-
## dirty
+5 -5
View File
@@ -1,13 +1,13 @@
# features
dir: features
# apps/web/src/components/features
dir: apps/web/src/components/features
index: features/.pi-map.index.md
index: apps/web/src/components/features/.pi-map.index.md
## role
Contains modular, feature-based components that encapsulate specific domain functionality or user-facing capabilities within the project.
Contains reusable UI components organized by feature domain for the web application.
## files
## arch
Feature-based modular architecture with self-contained, cohesive units that likely combine related components, logic, and assets to support vertical slicing of application functionality.
Feature-based colocation pattern with domain-specific subdirectories grouping related components, likely using composition patterns with shared UI primitives.
## tags
-
## symbols
@@ -2,7 +2,7 @@
dir: apps/web/src/components/features/mobile
## role
Provides mobile-optimized UI components for a responsive web application, covering navigation, lists, detail views, forms, modals, and specialized terminal interfaces.
Provides a complete set of mobile-optimized UI components for core application patterns including navigation, lists, detail views, editing, modals, and specialized terminal interfaces.
## parent
index: apps/web/src/components/features/.pi-map.index.md
map: apps/web/src/components/features/.pi-map.md
@@ -18,6 +18,7 @@ map: apps/web/src/components/features/.pi-map.md
- mobile-page-header.tsx
- mobile-terminal-header.tsx
- mobile-terminal-wrapper.tsx
- spaces-bottom-sheet.tsx
## links
index: apps/web/src/components/features/mobile/.pi-map.index.md
map: apps/web/src/components/features/mobile/.pi-map.md
@@ -4,21 +4,22 @@ dir: apps/web/src/components/features/mobile
index: apps/web/src/components/features/mobile/.pi-map.index.md
## role
Provides mobile-optimized UI components for a responsive web application, covering navigation, lists, detail views, forms, modals, and specialized terminal interfaces.
Provides a complete set of mobile-optimized UI components for core application patterns including navigation, lists, detail views, editing, modals, and specialized terminal interfaces.
## files
- mobile-action-sheet.tsx | Renders a mobile-optimized action sheet modal with title, configurable action buttons, and cancel option. | exp: MobileActionSheetItem, func:MobileActionSheet({ isOpen, onClose, title, actions, }: MobileActionSheetProps), call:useRef, call:useEffect, call:onClose, call:document.addEventListener, call:document.removeEventListener, call:e.stopPropagation, call:actions.map, call:action.onClick | dep: react, ../../icon, icon
- mobile-detail-view.tsx | A React component that renders a mobile-optimized detail view with a header (back button, title, edit/delete actions) and a field list supporting multiple value types (text, code, JSON, boolean). | exp: MobileDetailView | dep: ../../icon, react
- mobile-edit-view.tsx | A React component that renders a mobile-optimized form for editing data with configurable field types and save/cancel actions. | exp: MobileEditView | dep: react
- mobile-fab.tsx | Renders a floating action button component for mobile with an add icon and configurable click handler and label. | exp: MobileFAB | dep: ../../icon, react, icon
- mobile-list-view.tsx | Renders a searchable mobile-friendly list view with optional icons, subtitles, and click handling | exp: MobileListView | dep: ../../icon, ../../../utils/icons, react, icon, icons
- mobile-nav.tsx | Renders a mobile navigation bar with routing links, a tools group button that opens a bottom sheet, and session count badges | exp: MobileNav | dep: react, react-router-dom, ../../icon, ../tool/tools-bottom-sheet, ../../../utils/icons, icon, tools-bottom-sheet, icons utils
- mobile-list-view.tsx | Renders a mobile-optimized list view with optional search, custom item rendering, and empty state handling | exp: MobileListView | dep: react, ../../icon, ../../../utils/icons, icon
- mobile-nav.tsx | Renders a mobile navigation bar with route links and expandable bottom sheets for grouped navigation items. | exp: MobileNav | dep: react, react-router-dom, ../../icon, ../tool/tools-bottom-sheet, ./spaces-bottom-sheet, ../../../utils/icons
- mobile-page-header.tsx | Renders a mobile-only page header with optional back navigation and custom actions. | exp: func:MobilePageHeader({ title, showBack = true, actions }: MobilePageHeaderProps), call:useNavigate, call:useMobileViewport, call:navigate | dep: react-router-dom, ../../../hooks/use-mobile-viewport, ../../icon, use-mobile-viewport hook, Icon component
- mobile-terminal-header.tsx | Renders a mobile-responsive header for a terminal interface with navigation, title, connection status, font size controls, and close actions. | exp: MobileTerminalHeader | dep: react, ../../icon, icon
- mobile-terminal-wrapper.tsx | Wraps a terminal component with mobile-specific UI including auto-hiding header, virtual keyboard handling, and special keys interface. | exp: MobileTerminalWrapper | dep: react, ../terminal/terminal, ./mobile-terminal-header, ../terminal/special-keys-strip, ../terminal/special-keys-panel, ../../../hooks/use-mobile-viewport, ../../../hooks/use-virtual-keyboard, ../../../hooks/use-auto-hide, ../../../hooks/use-special-keys
- spaces-bottom-sheet.tsx | Renders a mobile bottom sheet navigation menu for switching between "Projects" and "Workspaces" spaces with active state highlighting | exp: SpacesBottomSheet | dep: react-router-dom, ../../icon
## arch
Feature-based component organization with compound mobile UI patterns (action sheets, FABs, bottom sheets, auto-hiding headers) that mirror native mobile app paradigms, using configurable props for customization and likely React Context or hooks for keyboard/virtual terminal state management.
Composable mobile-first component library using bottom sheets, action sheets, and floating action buttons as primary mobile interaction patterns, with feature-specific wrappers that handle mobile concerns like virtual keyboards and auto-hiding headers.
## tags
mobile, terminal, view, icon, header, react, sheet, action
mobile, terminal, sheet, view, react, icon, header, renders
## symbols
- MobileActionSheet
- MobilePageHeader
@@ -1,3 +1,4 @@
import type { ReactNode } from "react";
import { Icon } from "../../icon";
import type { IconName } from "../../../utils/icons";
@@ -17,6 +18,7 @@ interface MobileListViewProps {
emptyMessage?: string;
searchPlaceholder?: string;
onSearch?: (query: string) => void;
renderItem?: (item: MobileListItem) => ReactNode;
}
export const MobileListView: React.FC<MobileListViewProps> = ({
@@ -25,6 +27,7 @@ export const MobileListView: React.FC<MobileListViewProps> = ({
emptyMessage = "No items found",
searchPlaceholder = "Search...",
onSearch,
renderItem,
}) => {
return (
<div className="mobile-list-view">
@@ -58,12 +61,16 @@ export const MobileListView: React.FC<MobileListViewProps> = ({
<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>
{renderItem ? (
renderItem(item)
) : (
<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>
@@ -2,6 +2,7 @@ import { useState } from "react";
import { NavLink, useLocation } from "react-router-dom";
import { Icon } from "../../icon";
import { ToolsBottomSheet } from "../tool/tools-bottom-sheet";
import { SpacesBottomSheet } from "./spaces-bottom-sheet";
import type { IconName } from "../../../utils/icons";
interface MobileNavProps {
@@ -13,26 +14,35 @@ interface NavItem {
label: string;
icon: IconName;
isGroup?: boolean;
group?: "tools" | "spaces";
}
const MOBILE_NAV_ITEMS: NavItem[] = [
{ to: "/", label: "Home", icon: "dashboard" },
{ to: "/projects", label: "Projects", icon: "projects" },
{ to: "/sessions", label: "Sessions", icon: "terminal" },
{ to: "/tools", label: "Tools", icon: "settings", isGroup: true },
{ to: "/spaces", label: "Spaces", icon: "projects", isGroup: true, group: "spaces" },
{ to: "/tools", label: "Tools", icon: "settings", isGroup: true, group: "tools" },
{ to: "/settings", label: "Settings", icon: "settings" },
];
export const MobileNav: React.FC<MobileNavProps> = ({ sessionCount }) => {
const location = useLocation();
const [toolsSheetOpen, setToolsSheetOpen] = useState(false);
const [spacesSheetOpen, setSpacesSheetOpen] = useState(false);
const isToolsActive =
location.pathname === "/tool-workshop" ||
location.pathname === "/config-profiles";
const isSpacesActive =
location.pathname.startsWith("/projects") ||
location.pathname.startsWith("/workspaces");
const handleNavClick = (item: NavItem) => {
if (item.isGroup) {
if (!item.isGroup) return;
if (item.group === "spaces") {
setSpacesSheetOpen(true);
} else {
setToolsSheetOpen(true);
}
};
@@ -42,10 +52,11 @@ export const MobileNav: React.FC<MobileNavProps> = ({ sessionCount }) => {
<nav className="mobile-nav" role="navigation" aria-label="Mobile navigation">
{MOBILE_NAV_ITEMS.map((item) => {
if (item.isGroup) {
const isActive = item.group === "spaces" ? isSpacesActive : isToolsActive;
return (
<button
key={item.to}
className={`mobile-nav-item ${isToolsActive ? "active" : ""}`}
className={`mobile-nav-item ${isActive ? "active" : ""}`}
onClick={() => handleNavClick(item)}
type="button"
>
@@ -82,6 +93,10 @@ export const MobileNav: React.FC<MobileNavProps> = ({ sessionCount }) => {
isOpen={toolsSheetOpen}
onClose={() => setToolsSheetOpen(false)}
/>
<SpacesBottomSheet
isOpen={spacesSheetOpen}
onClose={() => setSpacesSheetOpen(false)}
/>
</>
);
};
@@ -0,0 +1,62 @@
import { useLocation, useNavigate } from "react-router-dom";
import { Icon } from "../../icon";
interface SpacesBottomSheetProps {
isOpen: boolean;
onClose: () => void;
}
const SPACES_ITEMS = [
{ to: "/projects", label: "Projects" },
{ to: "/workspaces", label: "Workspaces" },
];
export const SpacesBottomSheet: React.FC<SpacesBottomSheetProps> = ({
isOpen,
onClose,
}) => {
const location = useLocation();
const navigate = useNavigate();
if (!isOpen) return null;
const handleSelect = (to: string) => {
onClose();
navigate(to);
};
return (
<div
className="mobile-bottom-sheet-overlay"
onClick={onClose}
role="presentation"
>
<div
className="mobile-bottom-sheet"
onClick={(e) => e.stopPropagation()}
role="dialog"
aria-label="Spaces menu"
>
<div className="mobile-bottom-sheet-header">
<div className="mobile-bottom-sheet-handle" />
<h3 className="mobile-bottom-sheet-title">Spaces</h3>
</div>
<div className="mobile-bottom-sheet-content">
{SPACES_ITEMS.map((item) => (
<button
key={item.to}
className={`mobile-bottom-sheet-item ${
location.pathname === item.to ? "active" : ""
}`}
onClick={() => handleSelect(item.to)}
type="button"
>
<span className="mobile-bottom-sheet-item-label">{item.label}</span>
{location.pathname === item.to && <Icon name="success" size="sm" />}
</button>
))}
</div>
</div>
</div>
);
};
+1 -1
View File
@@ -2,7 +2,7 @@
dir: apps/web/src/pages
## role
Contains top-level page components that serve as route endpoints for the web application, each rendering distinct feature areas of the developer workspace platform.
Contains top-level page components that serve as route endpoints for the web application's primary UI surfaces, each handling a specific domain area (dashboard, projects, workspaces, git, settings, etc.) with responsive layouts and CRUD operations.
## parent
index: apps/web/src/.pi-map.index.md
map: apps/web/src/.pi-map.md
+5 -5
View File
@@ -4,10 +4,10 @@ dir: apps/web/src/pages
index: apps/web/src/pages/.pi-map.index.md
## role
Contains top-level page components that serve as route endpoints for the web application, each rendering distinct feature areas of the developer workspace platform.
Contains top-level page components that serve as route endpoints for the web application's primary UI surfaces, each handling a specific domain area (dashboard, projects, workspaces, git, settings, etc.) with responsive layouts and CRUD operations.
## files
- ConfigProfilesPage.tsx | Renders a responsive configuration profiles management page with sidebar list and editor panel for desktop, and a dedicated mobile view for creating, editing, and managing config profiles. | exp: ConfigProfilesPage | dep: react, ../components/data-states, ../hooks/use-mobile-viewport, ../hooks/use-config-profiles, ../components/features/config-profiles/ConfigProfileListSidebar, ../components/features/config-profiles/ConfigProfileEditorPanel, ../components/features/config-profiles/ConfigProfilesMobileView
- DashboardPage.test.tsx | Tests the DashboardPage (HomePage) component's rendering, loading states, and error handling with retry functionality | dep: @testing-library/jest-dom/vitest, @testing-library/react, react-router-dom, vitest, ./DashboardPage, ../state/sessions, ../state/session-operations, ../api/dashboard, ../api/sessions, ../api/projects, ../api/git-repositories, ../api/tool-types
- DashboardPage.test.tsx | Unit tests for the DashboardPage component verifying overview loading and error retry behavior | dep: @testing-library/jest-dom/vitest, @testing-library/react, react-router-dom, vitest, ./DashboardPage, ../state/sessions, DashboardPage, SessionsProvider
- DashboardPage.tsx | Renders a dashboard homepage that displays workspace overview, active/recent sessions, summary statistics, and polling health checks for running instances. | exp: HomePage | dep: react, react-router-dom, ../api/dashboard, ../api/sessions, ../components/data-states, ../components/features/session/session-list, ../hooks/use-instance-actions, ../state/sessions
- GitHistoryPage.tsx | Renders a Git commit history page with branch selection, commit list with graph visualization, and a detail panel showing commit metadata, stats, and diffs. | exp: GitHistoryPage | dep: react, react-router-dom, ../api/git-repositories, ../components/data-states, ../components/icon, ../hooks/use-async-data
- GitRepositoriesPage.tsx | Displays and manages a project's Git repositories with CRUD operations including listing, creating, navigating to history, and deleting with confirmation | exp: GitRepositoriesPage | dep: react, react-router-dom, ../api/git-repositories, ../components/data-states, ../components/icon, ../components/features/project/repository-create-dialog, ../hooks/use-async-data
@@ -15,7 +15,7 @@ Contains top-level page components that serve as route endpoints for the web app
- ProfilePage.tsx | A React component that displays and allows editing of a user profile, including name, email, and avatar upload with validation. | exp: ProfilePage | dep: react, ../api/profile, ../components/data-states, ../components/icon, ../state/auth, ../hooks/use-async-data
- ProjectSettingsPage.tsx | Renders a project settings page with tabbed navigation for general settings, repositories, and members, including project data fetching, editing, and deletion capabilities. | exp: ProjectSettingsPage | dep: react, react-router-dom, ../components/features/settings/settings-tab-layout, ../components/features/project/repositories-settings-tab, ../api/client, ../types
- ProjectsPage.test.tsx | Unit tests for the ProjectsPage component covering loading, empty, error, create, edit, and delete states with API mocking. | dep: @testing-library/react, react-router-dom, vitest, ./ProjectsPage, ../api/projects, ProjectsPage
- ProjectsPage.tsx | Renders a responsive projects management page with separate mobile and desktop layouts, supporting project CRUD operations, repository creation, and workspace management. | exp: ProjectsPage | dep: react, ../components/data-states, ../components/icon, ../hooks/use-mobile-viewport, ../components/features/project/ProjectCard, ../components/features/project/ProjectDialog, ../components/features/project/repository-create-dialog, ../components/features/mobile/mobile-list-view, ../components/features/mobile/mobile-fab, ../hooks/use-projects, ../types
- ProjectsPage.tsx | Renders a responsive projects management page with separate mobile and desktop layouts, supporting project CRUD operations, repository management, and workspace actions. | exp: ProjectsPage | dep: react, ../components/data-states, ../components/icon, ../hooks/use-mobile-viewport, ../components/features/project/ProjectCard, ../components/features/project/ProjectDialog, ../components/features/project/repository-create-dialog, ../components/features/mobile/mobile-list-view, ../components/features/mobile/mobile-fab, ../hooks/use-projects, ../types
- SessionsPage.tsx | Renders a sessions management page that displays, polls health for, and handles CRUD operations on development environment sessions with dirty delete confirmation. | exp: SessionsPage | dep: react, ../api/sessions, ../api/settings, ../components/data-states, ../components/features/session/session-list, ../components/features/session/session-card, ../hooks/use-instance-actions, ../state/sessions
- SettingsPage.tsx | A React settings page component that loads, displays, and manages user configuration with tabbed navigation and nested outlet for child routes. | exp: SettingsPage | dep: react, react-router-dom, ../api/settings, ../components/data-states, ../hooks/use-async-data, ../components/features/settings/GeneralSettingsTab
- SshKeysPage.tsx | React page component for managing SSH keys including generation, listing, signing, verification, and deletion | exp: SSHKeysPage | dep: react-router-dom, ../components/data-states, ../hooks/use-ssh-keys, ../components/features/ssh-keys/SSHKeyCreateForm, ../components/features/ssh-keys/SSHKeyList
@@ -23,9 +23,9 @@ Contains top-level page components that serve as route endpoints for the web app
- ToolWorkshopPage.tsx | Renders a responsive tool workshop page with sidebar/editor layout for desktop and tabbed mobile view for managing tool types | exp: ToolWorkshopPage | dep: ../components/data-states, ../hooks/use-mobile-viewport, ../hooks/use-tool-workshop, ../components/features/tool-workshop/ToolTypeListSidebar, ../components/features/tool-workshop/ToolTypeEditorPanel, ../components/features/tool-workshop/ToolWorkshopMobileView, react, use-mobile-viewport, use-tool-workshop, data-states, ToolTypeListSidebar, ToolTypeEditorPanel, ToolWorkshopMobileView
- WorkspaceDetailPage.test.tsx | Tests the WorkspaceDetailPage component rendering and tab switching behavior | dep: @testing-library/jest-dom/vitest, @testing-library/react, react-router-dom, vitest, ./WorkspaceDetailPage, @testing-library/jest-dom, WorkspaceDetailPage, use-workspaces, use-workspace-files, use-workspace-git, use-workspace-instances, use-mobile-viewport
- WorkspaceDetailPage.tsx | Renders a workspace detail page with tab-based navigation for files, git, tools, and settings panels, with mobile-responsive layout. | exp: func:WorkspaceDetailPage(), call:useParams, call:useState, call:useMobileViewport, call:useWorkspaces, call:workspaces.find | dep: react, react-router-dom, ../hooks/use-workspaces, ../hooks/use-mobile-viewport, ../components/features/workspace/workspace-detail-header, ../components/features/workspace/workspace-tab-bar, ../components/features/workspace/workspace-file-panel, ../components/features/workspace/workspace-git-panel, ../components/features/workspace/workspace-tools-panel, ../components/features/workspace/workspace-settings-panel, use-workspaces, use-mobile-viewport, workspace-detail-header, workspace-tab-bar, workspace-file-panel, workspace-git-panel, workspace-tools-panel, workspace-settings-panel
- WorkspacesPage.tsx | Renders a responsive workspaces management page with separate mobile (list/detail/create views) and desktop (grid with cards) layouts, supporting CRUD operations and tool launching. | exp: func:WorkspacesPage(), call:useMobileViewport, call:useState, call:useWorkspaces, call:useWorkspaceActions, call:actions.delete, call:actions.sync, call:setMobileView, call:refresh, call:setStartWorkspace, call:handleDelete, call:setSelectedWorkspace, call:workspaces.map, call:workspaces.find, call:e.stopPropagation, call:setShowCreate | dep: react, ../components/icon, ../hooks/use-mobile-viewport, ../hooks/use-workspaces, ../hooks/use-workspace-actions, ../components/features/workspace/workspace-card, ../components/features/workspace/workspace-create-form, ../components/features/mobile/mobile-list-view, ../components/features/mobile/mobile-detail-view, ../components/features/mobile/mobile-fab, ../components/features/tool/tool-starter, ../types/workspace
- WorkspacesPage.tsx | Renders a responsive workspaces management page with separate mobile and desktop layouts, supporting workspace listing, creation, deletion, sync, and tool launching. | exp: func:WorkspacesPage(), call:useMobileViewport, call:useState, call:useWorkspaces, call:useWorkspaceActions, call:actions.delete, call:actions.sync, call:setMobileView, call:refresh, call:setStartWorkspace, call:handleDelete, call:setSelectedWorkspace, call:workspaces.map, call:e.stopPropagation, call:setShowCreate | dep: react, ../components/icon, ../hooks/use-mobile-viewport, ../hooks/use-workspaces, ../hooks/use-workspace-actions, ../components/features/workspace/workspace-card, ../components/features/workspace/workspace-create-form, ../components/features/mobile/mobile-detail-view, ../components/features/mobile/mobile-fab, ../components/features/tool/tool-starter, ../types/workspace
## arch
Follows a React Router-based page-level architecture with responsive dual-layout patterns (mobile/desktop), tabbed navigation, CRUD operations with API integration, polling mechanisms, and nested outlet routing for complex settings/workspace detail views.
Follows a page-based routing architecture where each file maps to a URL route, using responsive design patterns with explicit mobile/desktop view branching, compound component layouts (sidebar/editor, tabbed panels), polling for real-time data, and direct API integration within page components rather than abstracted service layers.
## tags
page, components, workspace, features, react, mobile, settings, hooks
## symbols
+25 -1
View File
@@ -168,8 +168,32 @@ export const ProjectsPage = () => {
items={projects.map((p) => ({
id: p.id,
title: p.name,
subtitle: `${p.repositories?.length ?? 0} repo${(p.repositories?.length ?? 0) !== 1 ? "s" : ""}${p.description ? " · " + p.description : ""}`,
}))}
renderItem={(item) => {
const project = projects.find((p) => p.id === item.id);
if (!project) return null;
return (
<div className="mobile-list-item-content mobile-list-item-content-rich">
<div className="mobile-list-item-title">{project.name}</div>
{project.description && (
<p className="mobile-list-item-description">
{project.description}
</p>
)}
<div className="mobile-list-item-chips">
{(project.repositories?.length ?? 0) === 0 ? (
<span className="mobile-list-item-chip muted">No repositories</span>
) : (
project.repositories.map((repo) => (
<span key={repo.id} className="mobile-list-item-chip">
{repo.name}
</span>
))
)}
</div>
</div>
);
}}
onItemClick={(id) => {
const project = projects.find((p) => p.id === id);
if (project) {
+12 -17
View File
@@ -7,7 +7,6 @@ import { useWorkspaces } from "../hooks/use-workspaces";
import { useWorkspaceActions } from "../hooks/use-workspace-actions";
import { WorkspaceCard } from "../components/features/workspace/workspace-card";
import { WorkspaceCreateForm } from "../components/features/workspace/workspace-create-form";
import { MobileListView } from "../components/features/mobile/mobile-list-view";
import { MobileDetailView } from "../components/features/mobile/mobile-detail-view";
import { MobileFAB } from "../components/features/mobile/mobile-fab";
import { ToolStarter } from "../components/features/tool/tool-starter";
@@ -100,22 +99,18 @@ export function WorkspacesPage() {
{loading && workspaces.length === 0 ? (
<div className="loading-state">Loading workspaces...</div>
) : (
<MobileListView
items={workspaces.map((ws) => ({
id: ws.id,
title: ws.name,
subtitle: `${ws.project_name} · ${ws.name}`,
status: ws.status,
}))}
onItemClick={(id) => {
const ws = workspaces.find((w) => w.id === id);
if (ws) {
setSelectedWorkspace(ws);
setMobileView("detail");
}
}}
emptyMessage="No workspaces yet"
/>
<div className="workspaces-grid mobile-workspaces-list">
{workspaces.map((ws) => (
<WorkspaceCard
key={ws.id}
workspace={ws}
loading={actions.loadingId === ws.id}
onStartTool={setStartWorkspace}
onSync={handleSync}
onDelete={handleDelete}
/>
))}
</div>
)}
<MobileFAB
+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 a web application, including design tokens, global styles, syntax highlighting themes, and 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 a web application, including design tokens, global styles, syntax highlighting themes, and 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 a comprehensive responsive CSS utility system including layout primitives, mobile-first breakpoints, terminal styling, session management UI, and touch-target accessibility patterns for a web application. | dep: CSS custom properties (var(--space-*), var(--border), var(--bg), var(--primary), var(--danger), etc.), xterm.js (terminal rendering)
- utilities.css | Provides a comprehensive responsive CSS utility system with terminal-specific styling, mobile adaptations, and component patterns for a web application. | dep: CSS custom properties (var(--space-*), var(--border), var(--bg), var(--text), var(--brand), var(--muted), var(--success), var(--danger), var(--danger-light)), xterm.js (terminal integration)
## arch
CSS custom properties-based design token architecture with light/dark theme support, mobile-first responsive breakpoint system, utility-first CSS patterns, and modular separation of concerns across global, component-specific, token, and utility layers.
Token-driven CSS architecture using CSS custom properties for themeable light/dark modes, utility-first responsive patterns, and component-scoped stylesheets with Prism.js integration for syntax highlighting.
## tags
space, var(, global, css, web, application, syntax, defines
var(, space, global, css, web, application, syntax, defines
## symbols
-
## workflows
+1 -1
View File
@@ -2,7 +2,7 @@
dir: apps/web/src/styles/pages
## role
Contains page-specific CSS stylesheets for individual application views in the web frontend.
Package containing page-specific CSS stylesheets for individual web application views
## parent
index: apps/web/src/styles/.pi-map.index.md
map: apps/web/src/styles/.pi-map.md
+4 -4
View File
@@ -4,18 +4,18 @@ dir: apps/web/src/styles/pages
index: apps/web/src/styles/pages/.pi-map.index.md
## role
Contains page-specific CSS stylesheets for individual application views in the web frontend.
Package containing page-specific CSS stylesheets for individual web application views
## files
- git-history.css | Stylesheet for a Git history visualization page with commit list, branch selector, and detail panel layout | dep: CSS custom properties (var(--border), var(--panel), var(--ink), var(--brand), var(--muted))
- projects.css | Stylesheet for a projects page UI featuring expandable project toggles, repository listings, workspace grids, and repository creation radio controls. | dep: CSS custom properties (variables)
- sessions.css | Stylesheet for session management UI components including cards, dropdowns, forms, and responsive mobile layouts. | dep: CSS custom properties/variables (var(--border), var(--panel), var(--text), var(--space-*), var(--danger), var(--color-border))
- ssh-keys.css | Styles a responsive SSH key list component that stacks vertically on mobile and switches to horizontal layout on larger screens | dep: CSS custom properties (var(--space-3), var(--space-2), var(--space-4), var(--bg), var(--border))
- workspace-detail.css | Stylesheet for a workspace detail page with tabbed interface including files, git, tools, and settings views, plus a workspace creation form | dep: CSS custom properties (variables for colors, spacing, typography)
- workspaces.css | Stylesheet for a workspaces page featuring a responsive grid of workspace cards with status badges, hover effects, and mobile adaptations. | dep: CSS custom properties (var(--space-*), var(--border), var(--panel), var(--muted), var(--success), var(--warning), var(--danger))
- workspaces.css | Styles a workspaces page with responsive card grid layout, status badges, and instance chips | dep: CSS custom properties (var(--space-*), var(--border), var(--brand), var(--panel), var(--ink), var(--muted), var(--bg), var(--success), var(--warning), var(--danger), var(--font-size-*))
## arch
Modular page-scoped styling using dedicated CSS files per route/page, with responsive design patterns (mobile-first breakpoints, grid/flex layouts) and component-oriented class naming.
Modular CSS architecture with dedicated stylesheets per page domain, featuring responsive design patterns, component-based styling, and mobile-first breakpoint strategies
## tags
var(, workspace, stylesheet, space, git, page, detail, history
var(, workspace, space, stylesheet, git, page, detail, history
## symbols
-
## workflows
+5
View File
@@ -233,4 +233,9 @@
width: 100%;
justify-content: center;
}
.mobile-workspaces-list {
gap: var(--space-3);
margin-top: 0;
}
}
+123
View File
@@ -1957,6 +1957,129 @@ a.nav-item,
color: var(--brand);
}
/* Mobile List View */
.mobile-list-view {
display: flex;
flex-direction: column;
gap: var(--space-3);
}
.mobile-list-items {
display: flex;
flex-direction: column;
gap: var(--space-2);
}
.mobile-list-item {
display: flex;
align-items: center;
gap: var(--space-3);
width: 100%;
padding: var(--space-3);
background: var(--panel);
border: 1px solid var(--border);
border-radius: 10px;
color: var(--text);
text-align: left;
cursor: pointer;
min-height: 56px;
}
.mobile-list-item:active {
background: var(--bg);
}
.mobile-list-item-icon {
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
color: var(--muted);
}
.mobile-list-item-content {
flex: 1;
min-width: 0;
display: flex;
flex-direction: column;
gap: var(--space-1);
}
.mobile-list-item-title {
font-weight: 600;
font-size: var(--font-size-base);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.mobile-list-item-subtitle {
font-size: var(--font-size-sm);
color: var(--muted);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.mobile-list-item-actions {
display: flex;
align-items: center;
flex-shrink: 0;
color: var(--muted);
}
.mobile-list-empty {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: var(--space-3);
padding: var(--space-10) var(--space-4);
color: var(--muted);
text-align: center;
}
.mobile-list-empty p {
margin: 0;
}
/* Rich project rows */
.mobile-list-item-content-rich {
gap: var(--space-2);
}
.mobile-list-item-description {
margin: 0;
font-size: var(--font-size-sm);
color: var(--muted);
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
.mobile-list-item-chips {
display: flex;
flex-wrap: wrap;
gap: var(--space-1);
margin-top: var(--space-1);
}
.mobile-list-item-chip {
font-size: var(--font-size-xs);
padding: var(--space-1) var(--space-2);
background: var(--bg);
border: 1px solid var(--border);
border-radius: 999px;
color: var(--ink);
}
.mobile-list-item-chip.muted {
color: var(--muted);
font-style: italic;
background: transparent;
}
/* Mobile Page Header */
.mobile-page-header {
display: flex;