Files
bootstrap/profiles/workflows/frontend-component.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"
]
}