Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Define and Document a Standard Architecture for Components Creation #1430

Open
saadanzari opened this issue Jan 15, 2025 · 0 comments
Open
Labels
enhancement New feature or request

Comments

@saadanzari
Copy link
Contributor

saadanzari commented Jan 15, 2025

Description

Establish a standardized architecture for components in the project to ensure consistency, maintainability, and scalability. This standard will include guidelines for file structure, CSS styling using BEM methodology, and best practices for component development. The goal is to create a uniform approach that can be easily followed by all team members.

Acceptance Criteria

File Structure:

Define a standard folder/file structure for components (e.g., each component should have its own folder containing .tsx, .css/.scss, and any additional assets like .types.ts or .constants.ts).
Example:

/ComponentName
  ├── ComponentName.tsx
  ├── ComponentName.module.scss (following BEM)
  ├── ComponentName.types.ts
  ├── ComponentName.test.tsx
  ├── index.ts

Styling with BEM:

All CSS classes should follow the BEM methodology.

Example:

  • Block: component-name
  • Element: component-name__element
  • Modifier: component-name__element--modifier

Inline styles should be avoided. Use CSS modules or JSS where applicable.

Component Development Standards:

  • Components should follow the single-responsibility principle.
  • Each component should be reusable, modular, and focused on a specific task.
  • Use TypeScript for type safety with clearly defined props/interfaces.
  • Write unit tests for each component with at least 80% test coverage.

Documentation:

  • Document the architecture standards in the project’s README.md or a dedicated CONTRIBUTING.md file.
  • Include examples and best practices for file structure, BEM, and component design.
  • Provide a sample component implementation following the standards.

Implementation:

  • Audit the existing codebase to identify components not following the defined standards.
  • Refactor a selected set of components to serve as templates for others.

SAMPLE COMPONENT:

Button.tsx

A functional component written in TypeScript.

import React from 'react';
import styles from './Button.module.scss';
import { ButtonProps } from './Button.types';

const Button: React.FC<ButtonProps> = ({ label, onClick, variant = 'primary', disabled = false }) => {
  return (
    <button
      className={`${styles['button']} ${styles[`button--${variant}`]}`}
      onClick={onClick}
      disabled={disabled}
    >
      {label}
    </button>
  );
};
export default Button;

Button.module.scss

Styling using BEM methodology.

.button {
  padding: 10px 20px;
  font-size: 16px;
  border: none;
  cursor: pointer;
  transition: background-color 0.3s;

  &--primary {
    background-color: #007bff;
    color: #fff;
  }

  &--secondary {
    background-color: #6c757d;
    color: #fff;
  }

  &:disabled {
    background-color: #e0e0e0;
    cursor: not-allowed;
  }
}

Button.types.ts

Define TypeScript types and props for the Button component.

export interface ButtonProps {
  label: string;
  onClick: () => void;
  variant?: 'primary' | 'secondary';
  disabled?: boolean;
}

Button.constants.ts [OPTIONAL]

Define constants for reuse (e.g., default values, variants, or labels).

export const BUTTON_VARIANTS = ['primary', 'secondary'] as const;

Button.test.tsx

Unit tests for the Button component.

import { render, screen, fireEvent } from '@testing-library/react';
import Button from './Button';

test('renders the Button component with label', () => {
  render(<Button label="Click Me" onClick={() => {}} />);
  expect(screen.getByText('Click Me')).toBeInTheDocument();
});

test('calls onClick handler when clicked', () => {
  const handleClick = jest.fn();
  render(<Button label="Click Me" onClick={handleClick} />);
  fireEvent.click(screen.getByText('Click Me'));
  expect(handleClick).toHaveBeenCalledTimes(1);
});

test('disables the button when disabled prop is true', () => {
  render(<Button label="Click Me" onClick={() => {}} disabled />);
  expect(screen.getByText('Click Me')).toBeDisabled();
});

index.ts

Barrel file for easy imports.

export { default as Button } from './Button';
export * from './Button.types';

Why This Component?

  • Simplicity: Easy to understand and implement.
  • Versatility: Can demonstrate reusable props, styles, and structure.
  • Relevance: A common UI element that exists in almost every application.
  • Scalability: Can be extended with additional features like icons, loading states, or different sizes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
Status: NEW USER REQUEST
Development

No branches or pull requests

1 participant