Skip to content

Commit fd3bb4d

Browse files
JonSnow1807claude
andcommitted
Enhance UI/UX with comprehensive accessibility and responsiveness
- Add ARIA labels and semantic HTML for screen reader support - Implement responsive design patterns with Chakra UI breakpoints - Add toast notifications for better user feedback - Enhance progress indicators with detailed completion status - Improve keyboard navigation and form accessibility - Add role attributes and live regions for dynamic content 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 026c870 commit fd3bb4d

File tree

1 file changed

+107
-25
lines changed

1 file changed

+107
-25
lines changed

frontend/src/components/StreamingCodeGenerator.jsx

Lines changed: 107 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,12 @@ import {
3434
DocumentTextIcon,
3535
BeakerIcon
3636
} from '@heroicons/react/24/outline';
37+
import { useToast } from '@chakra-ui/react';
3738

3839
const StreamingCodeGenerator = () => {
3940
const { user } = useAuth();
4041
const { currentTheme } = useTheme();
42+
const toast = useToast();
4143
const wsRef = useRef(null);
4244
const [isConnected, setIsConnected] = useState(false);
4345

@@ -144,6 +146,13 @@ const StreamingCodeGenerator = () => {
144146
switch (message.type) {
145147
case 'connection_established':
146148
console.log('✅ Code generation WebSocket ready');
149+
toast({
150+
title: "Connected",
151+
description: "Ready to generate code",
152+
status: "success",
153+
duration: 3000,
154+
isClosable: true,
155+
});
147156
break;
148157

149158
case 'code_generation_started':
@@ -152,6 +161,13 @@ const StreamingCodeGenerator = () => {
152161
setCurrentStep('Starting code generation...');
153162
setError('');
154163
clearResults();
164+
toast({
165+
title: "Generation Started",
166+
description: "Your code is being generated",
167+
status: "info",
168+
duration: 3000,
169+
isClosable: true,
170+
});
155171
break;
156172

157173
case 'code_generation_progress':
@@ -236,14 +252,25 @@ const StreamingCodeGenerator = () => {
236252
minH="100vh"
237253
bg={currentTheme.colors.background}
238254
color={currentTheme.colors.text}
239-
p={6}
255+
p={{ base: 4, md: 6 }}
240256
>
241-
<VStack spacing={6} maxW="6xl" mx="auto">
257+
<VStack spacing={{ base: 4, md: 6 }} maxW="6xl" mx="auto" px={{ base: 2, sm: 4 }}>
242258
{/* Header */}
243-
<Flex align="center" gap={3}>
244-
<SparklesIcon className="w-8 h-8" />
245-
<Heading size="lg">Streaming Code Generator</Heading>
246-
<Badge colorScheme={isConnected ? 'green' : 'red'}>
259+
<Flex
260+
align="center"
261+
gap={3}
262+
role="banner"
263+
direction={{ base: "column", sm: "row" }}
264+
textAlign={{ base: "center", sm: "left" }}
265+
>
266+
<SparklesIcon className="w-8 h-8" aria-hidden="true" />
267+
<Heading size={{ base: "md", lg: "lg" }} as="h1">
268+
Streaming Code Generator
269+
</Heading>
270+
<Badge
271+
colorScheme={isConnected ? 'green' : 'red'}
272+
aria-label={`Connection status: ${isConnected ? 'Connected' : 'Disconnected'}`}
273+
>
247274
{isConnected ? 'Connected' : 'Disconnected'}
248275
</Badge>
249276
</Flex>
@@ -257,9 +284,9 @@ const StreamingCodeGenerator = () => {
257284
)}
258285

259286
{/* Input Form */}
260-
<Card w="full">
287+
<Card w="full" as="section" role="form" aria-labelledby="form-heading">
261288
<CardHeader>
262-
<Heading size="md">Code Generation Request</Heading>
289+
<Heading size="md" as="h2" id="form-heading">Code Generation Request</Heading>
263290
</CardHeader>
264291
<CardBody>
265292
<VStack spacing={4}>
@@ -270,12 +297,30 @@ const StreamingCodeGenerator = () => {
270297
size="lg"
271298
minH="120px"
272299
resize="vertical"
300+
aria-label="Code description"
301+
aria-describedby="description-help"
302+
required
273303
/>
274-
275-
<HStack w="full" spacing={4}>
276-
<Box flex={1}>
277-
<Text mb={2} fontWeight="semibold">Language</Text>
278-
<Select value={language} onChange={(e) => setLanguage(e.target.value)}>
304+
<Text id="description-help" fontSize="sm" color="gray.600" sr-only>
305+
Provide a detailed description of the code you want to generate
306+
</Text>
307+
308+
<VStack
309+
spacing={4}
310+
w="full"
311+
direction={{ base: "column", md: "row" }}
312+
as={HStack}
313+
>
314+
<Box flex={1} w="full">
315+
<Text mb={2} fontWeight="semibold" as="label" htmlFor="language-select">
316+
Language
317+
</Text>
318+
<Select
319+
id="language-select"
320+
value={language}
321+
onChange={(e) => setLanguage(e.target.value)}
322+
aria-label="Select programming language"
323+
>
279324
{languages.map(lang => (
280325
<option key={lang.value} value={lang.value}>
281326
{lang.label}
@@ -284,55 +329,92 @@ const StreamingCodeGenerator = () => {
284329
</Select>
285330
</Box>
286331

287-
<Box flex={1}>
288-
<Text mb={2} fontWeight="semibold">Code Type</Text>
289-
<Select value={codeType} onChange={(e) => setCodeType(e.target.value)}>
332+
<Box flex={1} w="full">
333+
<Text mb={2} fontWeight="semibold" as="label" htmlFor="code-type-select">
334+
Code Type
335+
</Text>
336+
<Select
337+
id="code-type-select"
338+
value={codeType}
339+
onChange={(e) => setCodeType(e.target.value)}
340+
aria-label="Select code type"
341+
>
290342
{codeTypes.map(type => (
291343
<option key={type.value} value={type.value}>
292344
{type.label}
293345
</option>
294346
))}
295347
</Select>
296348
</Box>
297-
</HStack>
349+
</VStack>
298350

299351
<HStack>
300352
<Button
301-
leftIcon={<PlayIcon className="w-4 h-4" />}
353+
leftIcon={<PlayIcon className="w-4 h-4" aria-hidden="true" />}
302354
colorScheme="blue"
303355
onClick={handleGenerateCode}
304356
disabled={!isConnected || isGenerating || !description.trim()}
305357
isLoading={isGenerating}
306358
loadingText="Generating..."
359+
aria-label="Generate code based on description"
360+
aria-describedby={!isConnected ? "connection-error" : undefined}
307361
>
308362
Generate Code
309363
</Button>
310364

311365
{isGenerating && (
312366
<Button
313-
leftIcon={<StopIcon className="w-4 h-4" />}
367+
leftIcon={<StopIcon className="w-4 h-4" aria-hidden="true" />}
314368
colorScheme="red"
315369
variant="outline"
316370
onClick={handleStopGeneration}
371+
aria-label="Stop code generation"
317372
>
318373
Stop
319374
</Button>
320375
)}
321376
</HStack>
377+
378+
{!isConnected && (
379+
<Text id="connection-error" fontSize="sm" color="red.500" sr-only>
380+
Connection required to generate code
381+
</Text>
382+
)}
322383
</VStack>
323384
</CardBody>
324385
</Card>
325386

326387
{/* Progress */}
327388
{isGenerating && (
328-
<Card w="full">
389+
<Card w="full" role="status" aria-live="polite" aria-label="Code generation progress">
329390
<CardBody>
330391
<VStack spacing={3}>
331-
<Text fontWeight="semibold">{currentStep}</Text>
332-
<Progress value={progress} w="full" colorScheme="blue" hasStripe isAnimated />
333-
<Text fontSize="sm" color={currentTheme.colors.textSecondary}>
334-
{progress}% complete
335-
</Text>
392+
<HStack w="full" justify="space-between" align="center">
393+
<Text fontWeight="semibold" aria-describedby="progress-bar">
394+
{currentStep}
395+
</Text>
396+
<Text fontSize="sm" fontWeight="medium" color="blue.500">
397+
{progress}%
398+
</Text>
399+
</HStack>
400+
<Progress
401+
id="progress-bar"
402+
value={progress}
403+
w="full"
404+
colorScheme="blue"
405+
hasStripe
406+
isAnimated
407+
size="lg"
408+
aria-label={`Code generation ${progress}% complete`}
409+
/>
410+
<HStack w="full" justify="space-between" align="center">
411+
<Text fontSize="sm" color={currentTheme.colors.textSecondary}>
412+
Generating your code...
413+
</Text>
414+
<Text fontSize="xs" color={currentTheme.colors.textSecondary}>
415+
{Math.ceil((100 - progress) / 20)} steps remaining
416+
</Text>
417+
</HStack>
336418
</VStack>
337419
</CardBody>
338420
</Card>

0 commit comments

Comments
 (0)