V2 Restructure homepage (#4138)

Component Extraction & Context Refactor - Summary

  🔧 What We Did

- Extracted HomePage's 286-line monolithic component into focused parts
  - Created ToolPanel (105 lines) for tool selection UI
  - Created Workbench (203 lines) for view management
  - Created ToolWorkflowContext (220 lines) for centralized state
  - Reduced HomePage to 60 lines of provider setup
  - Eliminated all prop drilling - components use contexts directly

  🏆 Why This is Good

- Maintainability: Each component has single purpose, easy
debugging/development
- Architecture: Clean separation of concerns, future features easier to
add
- Code Quality: 105% more lines but organized/purposeful vs tangled
spaghetti code

---------

Co-authored-by: Connor Yoh <[email protected]>
Co-authored-by: James Brunton <[email protected]>
This commit is contained in:
ConnorYoh
2025-08-08 15:56:20 +01:00
committed by GitHub
co-authored by Connor Yoh James Brunton
parent 7735ea7f48
commit b45d3a43d4
7 changed files with 503 additions and 288 deletions
+7 -18
View File
@@ -1,32 +1,21 @@
import React, { useState } from "react";
import { Box, Text, Stack, Button, TextInput, Group } from "@mantine/core";
import React from "react";
import { Box, Text, Stack, Button } from "@mantine/core";
import { useTranslation } from "react-i18next";
import { ToolRegistry } from "../../types/tool";
interface ToolPickerProps {
selectedToolKey: string | null;
onSelect: (id: string) => void;
toolRegistry: ToolRegistry;
/** Pre-filtered tools to display */
filteredTools: [string, ToolRegistry[string]][];
}
const ToolPicker = ({ selectedToolKey, onSelect, toolRegistry }: ToolPickerProps) => {
const ToolPicker = ({ selectedToolKey, onSelect, filteredTools }: ToolPickerProps) => {
const { t } = useTranslation();
const [search, setSearch] = useState("");
const filteredTools = Object.entries(toolRegistry).filter(([_, { name }]) =>
name.toLowerCase().includes(search.toLowerCase())
);
return (
<Box >
<TextInput
placeholder={t("toolPicker.searchPlaceholder", "Search tools...")}
value={search}
onChange={(e) => setSearch(e.currentTarget.value)}
mb="md"
autoComplete="off"
/>
<Stack align="flex-start">
<Box>
<Stack align="flex-start">
{filteredTools.length === 0 ? (
<Text c="dimmed" size="sm">
{t("toolPicker.noToolsFound", "No tools found")}