Skip to content
This repository was archived by the owner on Oct 10, 2025. It is now read-only.

Commit cb1ac6a

Browse files
committed
feat: add new top level tabs
1 parent 7318bfa commit cb1ac6a

File tree

2 files changed

+116
-142
lines changed

2 files changed

+116
-142
lines changed

examples/context-editor/src/App.tsx

Lines changed: 104 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -1,154 +1,144 @@
1-
import React, { useState } from 'react';
2-
import { Container, Paper, Box, Button, Typography, Link as MuiLink, Snackbar, IconButton, Accordion, AccordionSummary, AccordionDetails, Divider, Select, MenuItem, FormControl, InputLabel, SelectChangeEvent } from '@mui/material';
1+
import React, { useState, useCallback } from 'react';
2+
import { Container, Paper, Box, Typography, Link as MuiLink, Snackbar, IconButton, Accordion, AccordionSummary, AccordionDetails, Divider, Button } from '@mui/material';
33
import { ThemeProvider } from '@mui/material/styles';
44
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
55
import CloseIcon from '@mui/icons-material/Close';
66
import GitHubIcon from '@mui/icons-material/GitHub';
7-
import { BrowserRouter as Router } from 'react-router-dom';
87
import theme from './theme';
98
import PromptViewer from './components/PromptViewer';
109
import SpecificationModal from './components/SpecificationModal';
10+
import NavTabs from './components/NavTabs';
11+
import ContextForm from './components/ContextForm';
1112
import { handleCopyToClipboard } from './utils/helpers';
1213
import usePrompts from './hooks/usePrompts';
1314
import useSnackbar from './hooks/useSnackbar';
1415
import './App.css';
1516

16-
const BASE_PATH = process.env.NODE_ENV === 'production' ? '/codebase-context-spec' : '';
17-
1817
const App: React.FC = () => {
1918
const [specModalOpen, setSpecModalOpen] = useState(false);
20-
const [selectedTool, setSelectedTool] = useState('');
21-
const [loadedPrompt, setLoadedPrompt] = useState<string | null>(null);
19+
const [selectedTab, setSelectedTab] = useState(0);
2220

2321
const { snackbarOpen, snackbarMessage, showSnackbar, closeSnackbar } = useSnackbar();
2422
const { codebaseContext, generateContextPrompt, codingAssistantPrompts } = usePrompts(
2523
showSnackbar,
2624
(open: boolean) => open ? showSnackbar('') : closeSnackbar()
2725
);
2826

29-
const handleToolChange = (event: SelectChangeEvent<string>) => {
30-
setSelectedTool(event.target.value as string);
31-
setLoadedPrompt(null);
27+
const handleTabChange = (event: React.SyntheticEvent, newValue: number) => {
28+
setSelectedTab(newValue);
3229
};
3330

34-
const handleLoadPrompt = () => {
35-
if (selectedTool && codingAssistantPrompts[selectedTool]) {
36-
setLoadedPrompt(selectedTool);
37-
showSnackbar(`Loaded ${selectedTool} prompt`);
38-
} else {
39-
showSnackbar('Please select a valid tool first');
40-
}
31+
const handleContextFormSubmit = (content: string) => {
32+
console.log('Generated .context.md content:', content);
33+
showSnackbar('Context form submitted successfully');
34+
// Here you can add logic to save or process the generated content
4135
};
4236

37+
const handleCopy = useCallback((content: string) => {
38+
handleCopyToClipboard(
39+
content,
40+
(message: string) => showSnackbar(message),
41+
(open: boolean) => open ? showSnackbar('') : closeSnackbar()
42+
);
43+
}, [showSnackbar, closeSnackbar]);
44+
4345
return (
4446
<ThemeProvider theme={theme}>
45-
<Router basename={BASE_PATH}>
46-
<Container className="container" maxWidth="lg">
47-
<Paper className="paper" elevation={3}>
48-
<Box className="header" display="flex" justifyContent="space-between" alignItems="center">
49-
<Typography className="title" variant="h4" component="h1">
50-
Codebase Context Editor
51-
</Typography>
52-
<Box display="flex" alignItems="center">
53-
<Button
54-
className="viewLatestSpec"
55-
onClick={() => setSpecModalOpen(true)}
56-
variant="contained"
57-
color="primary"
58-
sx={{ mr: 2 }}
59-
>
60-
View Latest Specification v1.0.0-RFC
61-
</Button>
62-
<MuiLink href="https://github.com/Agentic-Insights/codebase-context-spec" target="_blank" rel="noopener noreferrer">
63-
<GitHubIcon fontSize="large" />
64-
</MuiLink>
65-
</Box>
47+
<Container className="container" maxWidth="lg">
48+
<Paper className="paper" elevation={3}>
49+
<Box className="header" display="flex" justifyContent="space-between" alignItems="center">
50+
<Typography className="title" variant="h4" component="h1">
51+
Codebase Context Editor
52+
</Typography>
53+
<Box display="flex" alignItems="center">
54+
<Button
55+
onClick={() => setSpecModalOpen(true)}
56+
variant="contained"
57+
color="primary"
58+
sx={{ mr: 2 }}
59+
>
60+
View Specification
61+
</Button>
62+
<MuiLink href="https://github.com/Agentic-Insights/codebase-context-spec" target="_blank" rel="noopener noreferrer">
63+
<GitHubIcon fontSize="large" />
64+
</MuiLink>
6665
</Box>
66+
</Box>
6767

68-
<Divider sx={{ my: 3 }} />
68+
<Divider sx={{ my: 3 }} />
6969

70-
<Box sx={{ display: 'flex', alignItems: 'center', mb: 2 }}>
71-
<FormControl sx={{ minWidth: 200, mr: 2 }}>
72-
<InputLabel id="coding-tool-select-label">Select Coding Tool</InputLabel>
73-
<Select
74-
labelId="coding-tool-select-label"
75-
value={selectedTool}
76-
onChange={handleToolChange}
77-
label="Select Coding Tool"
78-
>
79-
<MenuItem value="claude-dev">Claude-dev</MenuItem>
80-
<MenuItem value="aider">Aider</MenuItem>
81-
<MenuItem value="cody">Cody</MenuItem>
82-
{/* Add more tools as needed */}
83-
</Select>
84-
</FormControl>
85-
<Button variant="contained" color="secondary" onClick={handleLoadPrompt}>
86-
Load Prompt
87-
</Button>
70+
<NavTabs value={selectedTab} onChange={handleTabChange} />
71+
72+
{selectedTab === 0 && (
73+
<Box>
74+
<Typography variant="h5" sx={{ mb: 2 }}>Coding Assistant Prompts</Typography>
75+
<Accordion defaultExpanded>
76+
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
77+
<Typography>Claude-dev Prompt</Typography>
78+
</AccordionSummary>
79+
<AccordionDetails>
80+
<PromptViewer
81+
title="CLAUDE-DEV Prompt"
82+
subtitle="CLAUDE-DEV-PROMPT.md"
83+
explanation={codingAssistantPrompts['claude-dev']?.explanation || ''}
84+
content={codingAssistantPrompts['claude-dev']?.content || ''}
85+
onCopy={() => handleCopy(codingAssistantPrompts['claude-dev']?.content || '')}
86+
/>
87+
</AccordionDetails>
88+
</Accordion>
89+
{/* Add other coding assistant prompts here if needed */}
8890
</Box>
91+
)}
8992

90-
<Typography variant="h5" sx={{ mb: 2 }}>Coding Assistant Prompts</Typography>
91-
92-
{loadedPrompt && codingAssistantPrompts[loadedPrompt] && (
93+
{selectedTab === 1 && (
94+
<Box>
95+
<Typography variant="h5" sx={{ mb: 2 }}>Generate Context Files</Typography>
9396
<PromptViewer
94-
title={`${loadedPrompt.toUpperCase()} Prompt`}
95-
subtitle={`${loadedPrompt.toUpperCase()}-PROMPT.md`}
96-
explanation={codingAssistantPrompts[loadedPrompt].explanation}
97-
content={codingAssistantPrompts[loadedPrompt].content}
98-
onCopy={() => handleCopyToClipboard(codingAssistantPrompts[loadedPrompt].content, showSnackbar, () => showSnackbar(''))}
97+
title="Generate Context Prompt"
98+
subtitle="GENERATE-CONTEXT-PROMPT.md"
99+
explanation={generateContextPrompt.explanation}
100+
content={generateContextPrompt.content}
101+
onCopy={() => handleCopy(generateContextPrompt.content)}
99102
/>
100-
)}
101-
102-
<Divider sx={{ my: 3 }} />
103+
</Box>
104+
)}
103105

104-
<Accordion>
105-
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
106-
<Typography variant="h6">Generate Context Files</Typography>
107-
</AccordionSummary>
108-
<AccordionDetails>
109-
<Typography variant="body2" paragraph>
110-
Use the 'Generate Context Prompt' to get an AI agent to draft your context files.
111-
</Typography>
112-
<PromptViewer
113-
title="Generate Context Prompt"
114-
subtitle="GENERATE-CONTEXT-PROMPT.md"
115-
explanation={generateContextPrompt.explanation}
116-
content={generateContextPrompt.content}
117-
onCopy={() => handleCopyToClipboard(generateContextPrompt.content, showSnackbar, () => showSnackbar(''))}
118-
/>
119-
</AccordionDetails>
120-
</Accordion>
121-
</Paper>
106+
{selectedTab === 2 && (
107+
<Box>
108+
<Typography variant="h5" sx={{ mb: 2 }}>Manual Context Form</Typography>
109+
<ContextForm onSubmit={handleContextFormSubmit} />
110+
</Box>
111+
)}
112+
</Paper>
122113

123-
<SpecificationModal
124-
open={specModalOpen}
125-
onClose={() => setSpecModalOpen(false)}
126-
content={codebaseContext.content}
127-
onCopy={() => handleCopyToClipboard(codebaseContext.content, showSnackbar, () => showSnackbar(''))}
128-
/>
114+
<SpecificationModal
115+
open={specModalOpen}
116+
onClose={() => setSpecModalOpen(false)}
117+
content={codebaseContext.content}
118+
onCopy={() => handleCopy(codebaseContext.content)}
119+
/>
129120

130-
<Snackbar
131-
anchorOrigin={{
132-
vertical: 'bottom',
133-
horizontal: 'center',
134-
}}
135-
open={snackbarOpen}
136-
autoHideDuration={2000}
137-
onClose={closeSnackbar}
138-
message={snackbarMessage}
139-
action={
140-
<IconButton
141-
size="small"
142-
aria-label="close"
143-
color="inherit"
144-
onClick={closeSnackbar}
145-
>
146-
<CloseIcon fontSize="small" />
147-
</IconButton>
148-
}
149-
/>
150-
</Container>
151-
</Router>
121+
<Snackbar
122+
anchorOrigin={{
123+
vertical: 'bottom',
124+
horizontal: 'center',
125+
}}
126+
open={snackbarOpen}
127+
autoHideDuration={2000}
128+
onClose={closeSnackbar}
129+
message={snackbarMessage}
130+
action={
131+
<IconButton
132+
size="small"
133+
aria-label="close"
134+
color="inherit"
135+
onClick={closeSnackbar}
136+
>
137+
<CloseIcon fontSize="small" />
138+
</IconButton>
139+
}
140+
/>
141+
</Container>
152142
</ThemeProvider>
153143
);
154144
};
Lines changed: 12 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,34 @@
11
import React from 'react';
22
import { Tabs, Tab } from '@mui/material';
3-
import { Link, useLocation } from 'react-router-dom';
43
import DescriptionIcon from '@mui/icons-material/Description';
54
import LibraryBooksIcon from '@mui/icons-material/LibraryBooks';
65
import BlockIcon from '@mui/icons-material/Block';
76

8-
const NavTabs: React.FC = () => {
9-
const location = useLocation();
10-
const currentForm = getCurrentForm(location.pathname);
7+
interface NavTabsProps {
8+
value: number;
9+
onChange: (event: React.SyntheticEvent, newValue: number) => void;
10+
}
1111

12+
const NavTabs: React.FC<NavTabsProps> = ({ value, onChange }) => {
1213
return (
13-
<Tabs value={currentForm} aria-label="file type tabs" variant="fullWidth">
14+
<Tabs value={value} onChange={onChange} aria-label="file type tabs" variant="fullWidth">
1415
<Tab
1516
icon={<DescriptionIcon />}
16-
label=".context.md"
17-
component={Link}
18-
to="/"
19-
sx={{ textTransform: 'lowercase' }}
17+
label="Coding Assistant Prompts"
18+
sx={{ textTransform: 'none' }}
2019
/>
2120
<Tab
2221
icon={<LibraryBooksIcon />}
23-
label=".contextdocs.md"
24-
component={Link}
25-
to="/contextdocs"
26-
sx={{ textTransform: 'lowercase' }}
22+
label="Generate Context Files"
23+
sx={{ textTransform: 'none' }}
2724
/>
2825
<Tab
2926
icon={<BlockIcon />}
30-
label=".contextignore"
31-
component={Link}
32-
to="/contextignore"
33-
sx={{ textTransform: 'lowercase' }}
27+
label="Manual Context Form"
28+
sx={{ textTransform: 'none' }}
3429
/>
3530
</Tabs>
3631
);
3732
};
3833

39-
const getCurrentForm = (pathname: string) => {
40-
switch (pathname) {
41-
case '/contextdocs':
42-
return 1;
43-
case '/contextignore':
44-
return 2;
45-
default:
46-
return 0;
47-
}
48-
};
49-
5034
export default NavTabs;

0 commit comments

Comments
 (0)