Skip to main content

Component Props Standards

๐Ÿ“‹ Overviewโ€‹

This document establishes standardized prop patterns for React components in the Uptime Watcher application to ensure consistency, maintainability, and improved developer experience.

๐ŸŽฏ Standardization Goalsโ€‹

  • Consistency: Uniform prop patterns across all components
  • Type Safety: Strong TypeScript typing with predictable interfaces
  • Accessibility: Built-in accessibility support through standardized props
  • Developer Experience: Predictable API patterns and clear documentation
  • Maintainability: Easier refactoring and component composition

๐Ÿ—๏ธ Core Prop Patternsโ€‹

1. Interface Naming Conventionโ€‹

Standard: Use Properties suffix for all component prop interfaces

// โœ… Correct
export interface ButtonProperties {
readonly onClick?: () => void;
}

// โŒ Avoid
export interface ButtonProps {
onClick?: () => void;
}

Rationale:

  • Consistency with existing codebase patterns
  • Clearer distinction from React's built-in Props types
  • Better alignment with TypeScript conventions

2. Property Mutabilityโ€‹

Standard: All props should be readonly to prevent accidental mutations

// โœ… Correct
export interface ComponentProperties {
readonly title: string;
readonly disabled?: boolean;
readonly onClick?: () => void;
}

// โŒ Avoid
export interface ComponentProperties {
title: string;
disabled?: boolean;
onClick?: () => void;
}

Rationale:

  • Prevents accidental mutations of props
  • Encourages immutable data patterns
  • Better TypeScript safety

3. Event Handler Patternsโ€‹

Click Eventsโ€‹

Standard: Use simple function signatures for click handlers unless event object is needed

// โœ… Preferred (simple actions)
export interface SimpleButtonProperties {
readonly onClick?: () => void;
}

// โœ… Acceptable (when event object is needed)
export interface EventButtonProperties {
readonly onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void;
}

// โŒ Avoid optional event parameters
export interface BadButtonProperties {
readonly onClick?: (event?: React.MouseEvent<HTMLButtonElement>) => void;
}

Change Eventsโ€‹

Standard: Use value-based handlers for form components, event-based for low-level components

// โœ… Form Components (high-level, value-focused)
export interface FormFieldBaseProperties {
readonly onChange: (value: string) => void;
}

// โœ… Themed Components (low-level, event-focused)
export interface ThemedInputProperties {
readonly onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
}

Submit Eventsโ€‹

Standard: Always include event object for form submissions

// โœ… Correct
export interface FormProperties {
readonly onSubmit: (event: React.FormEvent<HTMLFormElement>) => void;
}

4. Common Prop Categoriesโ€‹

Core Props (Present in most components)โ€‹

export interface CoreComponentProperties {
/** Additional CSS classes for styling customization */
readonly className?: string;
/** Whether the component is disabled */
readonly disabled?: boolean;
/** Component content */
readonly children?: React.ReactNode;
}

Accessibility Propsโ€‹

export interface AccessibilityProperties {
/** ARIA label for screen readers */
readonly "aria-label"?: string;
/** ARIA described-by reference */
readonly "aria-describedby"?: string;
/** ARIA labelledby reference */
readonly "aria-labelledby"?: string;
/** Role attribute for semantic meaning */
readonly role?: string;
}

Form Propsโ€‹

export interface FormFieldBaseProperties {
/** Unique identifier for the field */
readonly id: string;
/** Field label text */
readonly label: string;
/** Whether the field is required */
readonly required?: boolean;
/** Error message to display */
readonly error?: string;
/** Help text for guidance */
readonly helpText?: string;
}

Styling Propsโ€‹

export interface StylingProperties {
/** Size variant */
readonly size?: "xs" | "sm" | "md" | "lg" | "xl";
/** Visual variant */
readonly variant?:
| "primary"
| "secondary"
| "danger"
| "success"
| "warning";
/** Whether component takes full width */
readonly fullWidth?: boolean;
}

State Propsโ€‹

export interface StateProperties {
/** Loading state indicator */
readonly loading?: boolean;
/** Whether component is in an active state */
readonly active?: boolean;
/** Whether component is selected */
readonly selected?: boolean;
}

๐Ÿ“ Size and Variant Standardsโ€‹

Size Optionsโ€‹

Standard sizes: "xs" | "sm" | "md" | "lg" | "xl"

// โœ… Standard size variants
export interface SizedComponentProperties {
readonly size?: "xs" | "sm" | "md" | "lg" | "xl";
}

// Default: "md"

Visual Variantsโ€‹

Standard variants: "primary" | "secondary" | "danger" | "success" | "warning" | "ghost"

// โœ… Standard visual variants
export interface VariantComponentProperties {
readonly variant?:
| "primary"
| "secondary"
| "danger"
| "success"
| "warning"
| "ghost";
}

// Default: "primary"

๐Ÿงฉ Composition Patternsโ€‹

Prop Interface Compositionโ€‹

Standard: Compose interfaces using intersection types rather than extension

// โœ… Preferred (composition)
export interface ButtonProperties
extends CoreComponentProperties,
AccessibilityProperties,
StylingProperties,
StateProperties {
readonly onClick?: () => void;
readonly type?: "button" | "submit" | "reset";
}

// โœ… Also acceptable (intersection)
export type ButtonProperties = CoreComponentProperties &
AccessibilityProperties &
StylingProperties &
StateProperties & {
readonly onClick?: () => void;
readonly type?: "button" | "submit" | "reset";
};

Icon Integrationโ€‹

Standard: Consistent icon prop patterns across components

export interface IconComponentProperties {
/** Icon element to display */
readonly icon?: React.ReactNode;
/** Icon position relative to content */
readonly iconPosition?: "left" | "right";
/** Icon color theme */
readonly iconColor?: string;
}

๐Ÿ“ Documentation Standardsโ€‹

Property Documentationโ€‹

Standard: Use TSDoc comments with clear descriptions


export interface ComponentProperties {
/**
* Primary action handler for the component.
*
* @remarks
* Called when user interacts with the component. Should handle any
* necessary validation or state updates.
*
* @example
*
* ```tsx
* <Component onClick={() => console.log("Clicked!")} />;
* ```
*/
readonly onClick?: () => void;

/**
* Visual size variant for the component.
*
* @defaultValue "md"
*/
readonly size?: "xs" | "sm" | "md" | "lg" | "xl";
}

Component Documentationโ€‹

Standard: Include comprehensive examples and usage patterns


/**
* Button component with theming, states, and accessibility support.
*
* @remarks
* Provides a comprehensive button implementation with various visual variants,
* sizes, loading states, and full accessibility support.
*
* @example Basic usage:
*
* ```tsx
* <Button onClick={handleClick}>Click me</Button>;
* ```
*
* @example With loading state:
*
* ```tsx
* <Button
* onClick={handleSubmit}
* loading={isSubmitting}
* disabled={!isValid}
* >
* Submit Form
* </Button>;
* ```
*
* @public
*/

๐ŸŽจ Implementation Templatesโ€‹

Basic Component Templateโ€‹


/**
* [Component] - [brief description]
*
* @remarks
* [Detailed description of component purpose and features]
*
* @example
*
* ```tsx
* <ComponentName prop="value" />;
* ```
*/

import React from "react";

/**
* Properties for the [Component] component.
*/
export interface ComponentNameProperties
extends CoreComponentProperties,
AccessibilityProperties {
/** Component-specific props */
readonly specificProp?: string;
/** Event handlers */
readonly onClick?: () => void;
}

/**
* [Component description]
*
* @param props - Component properties
*
* @returns JSX element
*/
export const ComponentName: React.FC<ComponentNameProperties> = React.memo(
({
className,
disabled = false,
children,
specificProp,
onClick,
...accessibilityProps
}) => {
// Component implementation
return (
<div className={className} {...accessibilityProps}>
{children}
</div>
);
}
);

ComponentName.displayName = "ComponentName";

export default ComponentName;

Form Component Templateโ€‹

/**
* [FormComponent] - [description]
*/

import React, { useCallback } from "react";

export interface FormComponentProperties
extends FormFieldBaseProperties,
CoreComponentProperties {
/** Current value */
readonly value: string;
/** Change handler */
readonly onChange: (value: string) => void;
/** Component-specific props */
readonly placeholder?: string;
}

export const FormComponent: React.FC<FormComponentProperties> = React.memo(
({
id,
label,
value,
onChange,
required = false,
error,
helpText,
placeholder,
disabled = false,
className,
}) => {
const handleChange = useCallback(
(event: React.ChangeEvent<HTMLInputElement>) => {
onChange(event.target.value);
},
[onChange]
);

return (
<BaseFormField
id={id}
label={label}
required={required}
error={error}
helpText={helpText}
>
{(ariaProps) => (
<input
{...ariaProps}
type="text"
value={value}
onChange={handleChange}
placeholder={placeholder}
disabled={disabled}
className={className}
/>
)}
</BaseFormField>
);
}
);

FormComponent.displayName = "FormComponent";

export default FormComponent;

โœ… Compliance Checklistโ€‹

Interface Designโ€‹

  • [ ] Uses Properties suffix for prop interfaces
  • [ ] All props marked as readonly
  • [ ] Proper TSDoc documentation for all props
  • [ ] Consistent event handler signatures
  • [ ] Appropriate use of optional vs required props

Event Handlersโ€‹

  • [ ] Simple () => void for basic actions
  • [ ] Event object included when needed
  • [ ] Consistent naming (onClick, onChange, onSubmit)
  • [ ] Value-based handlers for form components

Accessibilityโ€‹

  • [ ] Appropriate ARIA props included
  • [ ] Screen reader considerations
  • [ ] Keyboard navigation support
  • [ ] Focus management

Documentationโ€‹

  • [ ] Component purpose clearly documented
  • [ ] Usage examples provided
  • [ ] Props documented with descriptions
  • [ ] Default values specified

Type Safetyโ€‹

  • [ ] Strong TypeScript typing
  • [ ] No any types used
  • [ ] Proper generic constraints
  • [ ] Interface composition over inheritance

๐Ÿ”ง Migration Guideโ€‹

Updating Existing Componentsโ€‹

  1. Interface Naming:

    // Before
    interface ButtonProps {
    onClick?: () => void;
    }

    // After
    interface ButtonProperties {
    readonly onClick?: () => void;
    }
  2. Event Handlers:

    // Before
    readonly onClick?: (e?: React.MouseEvent) => void;

    // After
    readonly onClick?: () => void;
    // OR (if event needed)
    readonly onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void;
  3. Property Mutability:

    // Before
    interface ComponentProps {
    title: string;
    disabled?: boolean;
    }

    // After
    interface ComponentProperties {
    readonly title: string;
    readonly disabled?: boolean;
    }


This document should be reviewed and updated as new patterns emerge or requirements change. All new components must follow these standards for consistency.