201 lines
16 KiB
JSON
201 lines
16 KiB
JSON
{
|
|
"name": "Frontend Component Development",
|
|
"description": "Standardized workflow for React/Vue component development with accessibility and testing",
|
|
"workflowType": "frontend-component",
|
|
"applicablePatterns": ["React", "Vue", "Angular", "Web Components"],
|
|
"phases": {
|
|
"design": {
|
|
"description": "Component design and specification phase",
|
|
"activities": [
|
|
"Define component API and props interface",
|
|
"Create component design system documentation",
|
|
"Plan responsive behavior and breakpoints",
|
|
"Design accessibility features and ARIA labels",
|
|
"Consider component composition and reusability"
|
|
]
|
|
},
|
|
"implementation": {
|
|
"description": "Core component implementation phase",
|
|
"activities": [
|
|
"Create component with TypeScript interfaces",
|
|
"Implement responsive styling with CSS/Tailwind",
|
|
"Add accessibility features (ARIA, keyboard navigation)",
|
|
"Implement component state management",
|
|
"Add proper error boundaries and loading states"
|
|
]
|
|
},
|
|
"testing": {
|
|
"description": "Comprehensive component testing phase",
|
|
"activities": [
|
|
"Write unit tests for component logic",
|
|
"Create integration tests with user interactions",
|
|
"Test accessibility with screen readers",
|
|
"Validate responsive behavior across devices",
|
|
"Test component with different prop combinations"
|
|
]
|
|
},
|
|
"documentation": {
|
|
"description": "Component documentation and examples",
|
|
"activities": [
|
|
"Create Storybook stories for all variants",
|
|
"Document component API and usage examples",
|
|
"Add accessibility guidelines and best practices",
|
|
"Create interactive documentation",
|
|
"Document component performance characteristics"
|
|
]
|
|
}
|
|
},
|
|
"implementationPatterns": {
|
|
"structure": {
|
|
"functional": "Use functional components with hooks",
|
|
"typescript": "Define proper TypeScript interfaces for props",
|
|
"composition": "Design for component composition and reusability",
|
|
"separation": "Separate logic, presentation, and styling concerns",
|
|
"naming": "Use descriptive and consistent naming conventions"
|
|
},
|
|
"styling": {
|
|
"responsive": "Mobile-first responsive design approach",
|
|
"design_tokens": "Use design tokens for consistency",
|
|
"css_modules": "Scoped styling to prevent conflicts",
|
|
"accessibility": "Ensure sufficient color contrast and focus indicators",
|
|
"dark_mode": "Support light and dark theme variations"
|
|
},
|
|
"accessibility": {
|
|
"semantic_html": "Use semantic HTML elements when possible",
|
|
"aria_labels": "Add appropriate ARIA labels and descriptions",
|
|
"keyboard_nav": "Implement full keyboard navigation support",
|
|
"screen_readers": "Ensure screen reader compatibility",
|
|
"focus_management": "Proper focus management and indicators"
|
|
},
|
|
"state_management": {
|
|
"local_state": "Use useState for component-local state",
|
|
"side_effects": "Use useEffect with proper cleanup",
|
|
"performance": "Use useMemo and useCallback for optimization",
|
|
"context": "Use React Context for component tree state",
|
|
"forms": "Controlled components with proper validation"
|
|
},
|
|
"error_handling": {
|
|
"boundaries": "Implement error boundaries for error containment",
|
|
"validation": "Input validation with user-friendly messages",
|
|
"loading_states": "Proper loading and skeleton states",
|
|
"fallbacks": "Graceful degradation for component failures",
|
|
"user_feedback": "Clear feedback for user actions"
|
|
}
|
|
},
|
|
"qualityGates": {
|
|
"design": [
|
|
"Component API designed with reusability in mind",
|
|
"Accessibility requirements identified and documented",
|
|
"Responsive behavior planned for all breakpoints",
|
|
"Design tokens and styling approach determined",
|
|
"Component composition strategy defined"
|
|
],
|
|
"implementation": [
|
|
"TypeScript interfaces defined for all props",
|
|
"Component implements planned accessibility features",
|
|
"Responsive behavior works across all target devices",
|
|
"Component follows established coding patterns",
|
|
"Error handling and edge cases addressed"
|
|
],
|
|
"testing": [
|
|
"Unit tests cover all component logic and edge cases",
|
|
"Accessibility tests pass with screen reader testing",
|
|
"Integration tests validate user interaction flows",
|
|
"Visual regression tests prevent styling issues",
|
|
"Performance tests meet established benchmarks"
|
|
],
|
|
"documentation": [
|
|
"Storybook stories demonstrate all component variants",
|
|
"API documentation is complete and accurate",
|
|
"Usage examples and best practices documented",
|
|
"Accessibility guidelines provided",
|
|
"Performance characteristics documented"
|
|
]
|
|
},
|
|
"testingStrategy": {
|
|
"unit_tests": {
|
|
"scope": "Component logic, prop handling, and state changes",
|
|
"tools": "React Testing Library, Jest",
|
|
"coverage": "Minimum 85% code coverage",
|
|
"focus": "User interactions and business logic"
|
|
},
|
|
"accessibility_tests": {
|
|
"scope": "ARIA labels, keyboard navigation, screen reader compatibility",
|
|
"tools": "axe-core, @testing-library/jest-dom",
|
|
"manual": "Manual testing with actual screen readers",
|
|
"standards": "WCAG 2.1 AA compliance"
|
|
},
|
|
"visual_tests": {
|
|
"scope": "Component appearance across different states",
|
|
"tools": "Chromatic, Percy, or similar visual testing",
|
|
"devices": "Test across multiple device sizes",
|
|
"themes": "Test light/dark theme variations"
|
|
},
|
|
"integration_tests": {
|
|
"scope": "Component behavior within larger application context",
|
|
"user_flows": "End-to-end user interaction scenarios",
|
|
"data_flow": "Test with real or realistic data",
|
|
"performance": "Component performance under load"
|
|
},
|
|
"responsive_tests": {
|
|
"scope": "Component behavior across different screen sizes",
|
|
"breakpoints": "Test all defined responsive breakpoints",
|
|
"orientation": "Portrait and landscape orientations",
|
|
"devices": "Physical device testing when possible"
|
|
}
|
|
},
|
|
"codeTemplates": {
|
|
"reactComponent": {
|
|
"framework": "React",
|
|
"template": "import React, { useState, useEffect, useCallback } from 'react';\nimport { cn } from '@/lib/utils';\n\ninterface ComponentNameProps {\n /** Primary content for the component */\n children?: React.ReactNode;\n /** Additional CSS class names */\n className?: string;\n /** Component variant */\n variant?: 'primary' | 'secondary' | 'outline';\n /** Component size */\n size?: 'sm' | 'md' | 'lg';\n /** Disabled state */\n disabled?: boolean;\n /** Click handler */\n onClick?: () => void;\n}\n\n/**\n * ComponentName - Brief description of what this component does\n * \n * @example\n * <ComponentName variant=\"primary\" size=\"md\">\n * Content goes here\n * </ComponentName>\n */\nexport const ComponentName: React.FC<ComponentNameProps> = ({\n children,\n className,\n variant = 'primary',\n size = 'md',\n disabled = false,\n onClick,\n ...props\n}) => {\n const [isActive, setIsActive] = useState(false);\n\n const handleClick = useCallback(() => {\n if (!disabled && onClick) {\n onClick();\n }\n }, [disabled, onClick]);\n\n const handleKeyDown = useCallback((event: React.KeyboardEvent) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n handleClick();\n }\n }, [handleClick]);\n\n return (\n <button\n className={cn(\n // Base styles\n 'inline-flex items-center justify-center rounded-md font-medium transition-colors',\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2',\n \n // Variant styles\n {\n 'bg-primary text-primary-foreground hover:bg-primary/90': variant === 'primary',\n 'bg-secondary text-secondary-foreground hover:bg-secondary/80': variant === 'secondary',\n 'border border-input hover:bg-accent hover:text-accent-foreground': variant === 'outline',\n },\n \n // Size styles\n {\n 'h-8 px-3 text-sm': size === 'sm',\n 'h-10 px-4 py-2': size === 'md',\n 'h-12 px-6 text-lg': size === 'lg',\n },\n \n // State styles\n {\n 'opacity-50 cursor-not-allowed': disabled,\n },\n \n className\n )}\n disabled={disabled}\n onClick={handleClick}\n onKeyDown={handleKeyDown}\n role=\"button\"\n tabIndex={disabled ? -1 : 0}\n aria-disabled={disabled}\n {...props}\n >\n {children}\n </button>\n );\n};\n\nComponentName.displayName = 'ComponentName';"
|
|
},
|
|
"componentTest": {
|
|
"framework": "React Testing Library",
|
|
"template": "import { render, screen, fireEvent, waitFor } from '@testing-library/react';\nimport userEvent from '@testing-library/user-event';\nimport { axe, toHaveNoViolations } from 'jest-axe';\nimport { ComponentName } from './ComponentName';\n\n// Extend Jest matchers\nexpect.extend(toHaveNoViolations);\n\ndescribe('ComponentName', () => {\n const user = userEvent.setup();\n\n it('renders with default props', () => {\n render(<ComponentName>Test Content</ComponentName>);\n \n const button = screen.getByRole('button', { name: 'Test Content' });\n expect(button).toBeInTheDocument();\n expect(button).toHaveClass('bg-primary'); // default variant\n });\n\n it('handles click events', async () => {\n const handleClick = jest.fn();\n render(\n <ComponentName onClick={handleClick}>\n Click me\n </ComponentName>\n );\n\n const button = screen.getByRole('button', { name: 'Click me' });\n await user.click(button);\n \n expect(handleClick).toHaveBeenCalledTimes(1);\n });\n\n it('supports keyboard navigation', async () => {\n const handleClick = jest.fn();\n render(\n <ComponentName onClick={handleClick}>\n Press Enter\n </ComponentName>\n );\n\n const button = screen.getByRole('button', { name: 'Press Enter' });\n button.focus();\n \n await user.keyboard('{Enter}');\n expect(handleClick).toHaveBeenCalledTimes(1);\n \n await user.keyboard(' ');\n expect(handleClick).toHaveBeenCalledTimes(2);\n });\n\n it('handles disabled state correctly', async () => {\n const handleClick = jest.fn();\n render(\n <ComponentName disabled onClick={handleClick}>\n Disabled\n </ComponentName>\n );\n\n const button = screen.getByRole('button', { name: 'Disabled' });\n expect(button).toBeDisabled();\n expect(button).toHaveAttribute('aria-disabled', 'true');\n \n await user.click(button);\n expect(handleClick).not.toHaveBeenCalled();\n });\n\n it('applies correct variant styles', () => {\n const { rerender } = render(\n <ComponentName variant=\"secondary\">\n Secondary\n </ComponentName>\n );\n \n let button = screen.getByRole('button');\n expect(button).toHaveClass('bg-secondary');\n \n rerender(\n <ComponentName variant=\"outline\">\n Outline\n </ComponentName>\n );\n \n button = screen.getByRole('button');\n expect(button).toHaveClass('border');\n });\n\n it('has no accessibility violations', async () => {\n const { container } = render(\n <ComponentName>\n Accessible Button\n </ComponentName>\n );\n \n const results = await axe(container);\n expect(results).toHaveNoViolations();\n });\n\n it('supports custom className', () => {\n render(\n <ComponentName className=\"custom-class\">\n Custom\n </ComponentName>\n );\n \n const button = screen.getByRole('button');\n expect(button).toHaveClass('custom-class');\n });\n});"
|
|
},
|
|
"storybookStory": {
|
|
"framework": "Storybook",
|
|
"template": "import type { Meta, StoryObj } from '@storybook/react';\nimport { ComponentName } from './ComponentName';\n\nconst meta: Meta<typeof ComponentName> = {\n title: 'Components/ComponentName',\n component: ComponentName,\n parameters: {\n layout: 'centered',\n docs: {\n description: {\n component: 'A versatile button component with multiple variants and sizes.',\n },\n },\n },\n argTypes: {\n variant: {\n control: 'select',\n options: ['primary', 'secondary', 'outline'],\n description: 'The visual variant of the button',\n },\n size: {\n control: 'select', \n options: ['sm', 'md', 'lg'],\n description: 'The size of the button',\n },\n disabled: {\n control: 'boolean',\n description: 'Whether the button is disabled',\n },\n onClick: {\n action: 'clicked',\n description: 'Function called when button is clicked',\n },\n },\n};\n\nexport default meta;\ntype Story = StoryObj<typeof meta>;\n\n// Default story\nexport const Default: Story = {\n args: {\n children: 'Button',\n variant: 'primary',\n size: 'md',\n disabled: false,\n },\n};\n\n// Variants showcase\nexport const Variants: Story = {\n render: () => (\n <div className=\"flex gap-4\">\n <ComponentName variant=\"primary\">Primary</ComponentName>\n <ComponentName variant=\"secondary\">Secondary</ComponentName>\n <ComponentName variant=\"outline\">Outline</ComponentName>\n </div>\n ),\n};\n\n// Sizes showcase\nexport const Sizes: Story = {\n render: () => (\n <div className=\"flex items-center gap-4\">\n <ComponentName size=\"sm\">Small</ComponentName>\n <ComponentName size=\"md\">Medium</ComponentName>\n <ComponentName size=\"lg\">Large</ComponentName>\n </div>\n ),\n};\n\n// Disabled state\nexport const Disabled: Story = {\n args: {\n children: 'Disabled Button',\n disabled: true,\n },\n};\n\n// Interactive example\nexport const Interactive: Story = {\n render: () => {\n const [count, setCount] = React.useState(0);\n return (\n <div className=\"text-center\">\n <p className=\"mb-4\">Count: {count}</p>\n <ComponentName onClick={() => setCount(count + 1)}>\n Increment\n </ComponentName>\n </div>\n );\n },\n};"
|
|
}
|
|
},
|
|
"accessibilityRequirements": [
|
|
"Use semantic HTML elements when possible (button, input, etc.)",
|
|
"Provide meaningful alt text for images",
|
|
"Ensure sufficient color contrast (4.5:1 for normal text)",
|
|
"Support keyboard navigation for all interactive elements",
|
|
"Use ARIA labels and descriptions where needed",
|
|
"Implement proper focus management and indicators",
|
|
"Support screen readers with appropriate ARIA attributes",
|
|
"Test with actual assistive technologies",
|
|
"Provide skip links for navigation",
|
|
"Use proper heading hierarchy",
|
|
"Ensure form labels are properly associated",
|
|
"Implement error states with clear messaging"
|
|
],
|
|
"performanceOptimizations": [
|
|
"Use React.memo for components that receive stable props",
|
|
"Implement useMemo for expensive calculations",
|
|
"Use useCallback for event handlers passed to child components",
|
|
"Optimize images with proper formats and lazy loading",
|
|
"Implement virtualization for large lists",
|
|
"Use code splitting for large components",
|
|
"Minimize bundle size by importing only needed modules",
|
|
"Use CSS-in-JS efficiently to avoid style recalculations",
|
|
"Implement proper error boundaries to prevent crashes",
|
|
"Monitor component re-render frequency and optimize"
|
|
],
|
|
"bestPractices": [
|
|
"Design components for reusability and composition",
|
|
"Use TypeScript for better development experience and catch errors",
|
|
"Follow accessibility guidelines from the start",
|
|
"Write comprehensive tests including accessibility tests",
|
|
"Document components with clear examples and usage",
|
|
"Use consistent naming conventions across components",
|
|
"Implement proper error handling and loading states",
|
|
"Consider mobile-first responsive design",
|
|
"Use design tokens for consistent styling",
|
|
"Optimize for performance without premature optimization",
|
|
"Follow the principle of least privilege for component APIs",
|
|
"Use proper semantic HTML for better accessibility"
|
|
]
|
|
} |