diff --git a/PRD.md b/PRD.md index eb16c22..fe9c300 100644 --- a/PRD.md +++ b/PRD.md @@ -242,8 +242,12 @@ Animations should feel responsive and purposeful - quick panel transitions (200m - Section margins: mb-6 (24px) between major sections - **Mobile**: + - Burger menu navigation with grouped feature categories for cleaner mobile experience + - Page header displays current section with icon and description + - Responsive toolbar with icon-only buttons on mobile, full labels on desktop - Stack panels vertically instead of resizable horizontal splits - - Convert main tabs to a drawer menu on mobile - Full-screen editor mode as default on small screens - Collapse file tree into slide-out sheet - - Touch-friendly hit areas (min 44px) for all tree items and buttons + - Touch-friendly hit areas (min 44px) for all interactive elements + - Error badge overlays on navigation icon when errors present + - Search accessible via icon-only button on mobile diff --git a/src/App.tsx b/src/App.tsx index d0f9cc9..9a85749 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -34,6 +34,8 @@ import { PWAStatusBar } from '@/components/PWAStatusBar' import { PWASettings } from '@/components/PWASettings' import { FaviconDesigner } from '@/components/FaviconDesigner' import { GlobalSearch } from '@/components/GlobalSearch' +import { NavigationMenu } from '@/components/NavigationMenu' +import { PageHeader } from '@/components/PageHeader' import { useKeyboardShortcuts } from '@/hooks/use-keyboard-shortcuts' import { generateNextJSProject, generatePrismaSchema, generateMUITheme, generatePlaywrightTests, generateStorybookStories, generateUnitTests, generateFlaskApp } from '@/lib/generators' import { AIService } from '@/lib/ai-service' @@ -526,30 +528,34 @@ Navigate to the backend directory and follow the setup instructions. -
-
-
-
- +
+
+
+ +
+
-
-

CodeForge

-

+

+

CodeForge

+

Low-Code Next.js App Builder

-
+
0 && ( )} - - - + +
-
- - - - Dashboard - - {safeFeatureToggles.codeEditor && ( - - - Code Editor - - )} - {safeFeatureToggles.models && ( - - - Models - - )} - {safeFeatureToggles.components && ( - - - Components - - )} - {safeFeatureToggles.componentTrees && ( - - - Component Trees - - )} - {safeFeatureToggles.workflows && ( - - - Workflows - - )} - {safeFeatureToggles.lambdas && ( - - - Lambdas - - )} - {safeFeatureToggles.styling && ( - - - Styling - - )} - {safeFeatureToggles.flaskApi && ( - - - Flask API - - )} - - - Settings - - - - PWA - - {safeFeatureToggles.faviconDesigner && ( - - - Favicon - - )} - - - Features - - {safeFeatureToggles.playwright && ( - - - Playwright - - )} - {safeFeatureToggles.storybook && ( - - - Storybook - - )} - {safeFeatureToggles.unitTests && ( - - - Unit Tests - - )} - {safeFeatureToggles.errorRepair && ( - - - Error Repair - {autoDetectedErrors.length > 0 && ( - - {autoDetectedErrors.length} - - )} - - )} - {safeFeatureToggles.documentation && ( - - - Documentation - - )} - {safeFeatureToggles.sassStyles && ( - - - Sass Styles - - )} - -
- + +
+ + + +
@@ -63,18 +79,18 @@ export function KeyboardShortcutsDialog({ open, onOpenChange }: KeyboardShortcut

Actions

+ - void + featureToggles: FeatureToggles + errorCount?: number +} + +export function NavigationMenu({ + activeTab, + onTabChange, + featureToggles, + errorCount = 0, +}: NavigationMenuProps) { + const [open, setOpen] = useState(false) + + const navigationGroups: NavigationGroup[] = [ + { + id: 'overview', + label: 'Overview', + items: [ + { + id: 'dashboard', + label: 'Dashboard', + icon: , + value: 'dashboard', + }, + ], + }, + { + id: 'development', + label: 'Development', + items: [ + { + id: 'code', + label: 'Code Editor', + icon: , + value: 'code', + featureKey: 'codeEditor', + }, + { + id: 'models', + label: 'Models', + icon: , + value: 'models', + featureKey: 'models', + }, + { + id: 'components', + label: 'Components', + icon: , + value: 'components', + featureKey: 'components', + }, + { + id: 'component-trees', + label: 'Component Trees', + icon: , + value: 'component-trees', + featureKey: 'componentTrees', + }, + ], + }, + { + id: 'automation', + label: 'Automation', + items: [ + { + id: 'workflows', + label: 'Workflows', + icon: , + value: 'workflows', + featureKey: 'workflows', + }, + { + id: 'lambdas', + label: 'Lambdas', + icon: , + value: 'lambdas', + featureKey: 'lambdas', + }, + ], + }, + { + id: 'design', + label: 'Design & Styling', + items: [ + { + id: 'styling', + label: 'Styling', + icon: , + value: 'styling', + featureKey: 'styling', + }, + { + id: 'sass', + label: 'Sass Styles', + icon: , + value: 'sass', + featureKey: 'sassStyles', + }, + { + id: 'favicon', + label: 'Favicon Designer', + icon: , + value: 'favicon', + featureKey: 'faviconDesigner', + }, + ], + }, + { + id: 'backend', + label: 'Backend', + items: [ + { + id: 'flask', + label: 'Flask API', + icon: , + value: 'flask', + featureKey: 'flaskApi', + }, + ], + }, + { + id: 'testing', + label: 'Testing', + items: [ + { + id: 'playwright', + label: 'Playwright', + icon: , + value: 'playwright', + featureKey: 'playwright', + }, + { + id: 'storybook', + label: 'Storybook', + icon: , + value: 'storybook', + featureKey: 'storybook', + }, + { + id: 'unit-tests', + label: 'Unit Tests', + icon: , + value: 'unit-tests', + featureKey: 'unitTests', + }, + ], + }, + { + id: 'tools', + label: 'Tools & Configuration', + items: [ + { + id: 'errors', + label: 'Error Repair', + icon: , + value: 'errors', + badge: errorCount, + featureKey: 'errorRepair', + }, + { + id: 'docs', + label: 'Documentation', + icon: , + value: 'docs', + featureKey: 'documentation', + }, + { + id: 'settings', + label: 'Settings', + icon: , + value: 'settings', + }, + { + id: 'pwa', + label: 'PWA', + icon: , + value: 'pwa', + }, + { + id: 'features', + label: 'Features', + icon: , + value: 'features', + }, + ], + }, + ] + + const handleItemClick = (value: string) => { + onTabChange(value) + setOpen(false) + } + + const isItemVisible = (item: NavigationItem) => { + if (!item.featureKey) return true + return featureToggles[item.featureKey] + } + + const getVisibleItemsCount = (group: NavigationGroup) => { + return group.items.filter(isItemVisible).length + } + + return ( + + + + + + + Navigation + + +
+ {navigationGroups.map((group) => { + const visibleItemsCount = getVisibleItemsCount(group) + if (visibleItemsCount === 0) return null + + return ( +
+

+ {group.label} +

+
+ {group.items.map((item) => { + if (!isItemVisible(item)) return null + + const isActive = activeTab === item.value + + return ( + + ) + })} +
+
+ ) + })} +
+
+
+
+ ) +} diff --git a/src/components/PageHeader.tsx b/src/components/PageHeader.tsx new file mode 100644 index 0000000..934a927 --- /dev/null +++ b/src/components/PageHeader.tsx @@ -0,0 +1,145 @@ +import { + ChartBar, + Code, + Database, + Tree, + FlowArrow, + PaintBrush, + Flask, + Play, + BookOpen, + Cube, + Wrench, + FileText, + Gear, + DeviceMobile, + Image, + Faders, +} from '@phosphor-icons/react' + +interface PageHeaderProps { + activeTab: string +} + +const tabInfo: Record = { + dashboard: { + title: 'Dashboard', + icon: , + description: 'Project overview and statistics', + }, + code: { + title: 'Code Editor', + icon: , + description: 'Edit project files', + }, + models: { + title: 'Models', + icon: , + description: 'Define Prisma data models', + }, + components: { + title: 'Components', + icon: , + description: 'Create React components', + }, + 'component-trees': { + title: 'Component Trees', + icon: , + description: 'Manage component hierarchies', + }, + workflows: { + title: 'Workflows', + icon: , + description: 'Design automation workflows', + }, + lambdas: { + title: 'Lambdas', + icon: , + description: 'Serverless functions', + }, + styling: { + title: 'Styling', + icon: , + description: 'Theme and design tokens', + }, + sass: { + title: 'Sass Styles', + icon: , + description: 'Custom Sass stylesheets', + }, + favicon: { + title: 'Favicon Designer', + icon: , + description: 'Design app icons', + }, + flask: { + title: 'Flask API', + icon: , + description: 'Backend API configuration', + }, + playwright: { + title: 'Playwright', + icon: , + description: 'E2E test scenarios', + }, + storybook: { + title: 'Storybook', + icon: , + description: 'Component documentation', + }, + 'unit-tests': { + title: 'Unit Tests', + icon: , + description: 'Unit test suites', + }, + errors: { + title: 'Error Repair', + icon: , + description: 'Automated error detection and fixing', + }, + docs: { + title: 'Documentation', + icon: , + description: 'Project guides and references', + }, + settings: { + title: 'Settings', + icon: , + description: 'Project configuration', + }, + pwa: { + title: 'PWA', + icon: , + description: 'Progressive Web App settings', + }, + features: { + title: 'Features', + icon: , + description: 'Toggle feature modules', + }, +} + +export function PageHeader({ activeTab }: PageHeaderProps) { + const info = tabInfo[activeTab] || { + title: 'Unknown', + icon: , + } + + return ( +
+
+
+ {info.icon} +
+
+

{info.title}

+ {info.description && ( +

+ {info.description} +

+ )} +
+
+
+ ) +}