SkillAgentSearch skills...

tsx

tsx Style Guide

Install / Use

npx skills add zenbase-ai/context42

Installs into whichever agent you are using.

About this skill
📐

Cursor Rules

Cursor IDE rules (v2)

Quality Score

57/100

Supported Platforms

Cursor

description: tsx Style Guide globs: "**/*.tsx" alwaysApply: false

Developer Style Guide: TypeScript React Components (.tsx)

This guide decodes the unique coding DNA of the developer, providing insights into their patterns, preferences, and the subtle decisions that make their code distinctively theirs. The goal is to enable an AI agent to seamlessly mimic this style, making contributions indistinguishable from the original author.

1. CORE PHILOSOPHY

The developer prioritizes readability, maintainability, and functional purity in UI components, with a keen eye on performance optimization for complex rendering scenarios. They believe in explicit data flow and clear separation of concerns, favoring composition over deep inheritance. The code "feels" clean, predictable, and robust, designed for long-term evolution.

Rationale: This approach minimizes cognitive load for future developers, reduces the likelihood of subtle bugs, and ensures a responsive user interface, especially in data-intensive components.

2. NAMING PATTERNS

2.1. Component Naming

  • Convention: PascalCase for component files and component exports.
  • Rationale: Standard React convention, clearly distinguishes components from other modules.
  • Examples:
    // File: ExplorerStatus.tsx
    export const ExplorerStatus: React.FC<ExplorerStatusProps> = ({ ... }) => { ... }
    
    // File: ProgressBar.tsx
    export const ProgressBar: React.FC<ProgressBarProps> = ({ ... }) => { ... }
    
    // File: Index.tsx
    export const Index: React.FC<IndexProps> = ({ ... }) => { ... }
    
  • Anti-Example (Avoid): explorerStatus.tsx (camelCase file name), export const explorerStatus = ... (camelCase component name).

2.2. Prop Type Naming

  • Convention: PascalCase followed by Props suffix.
  • Rationale: Clearly identifies the interface as defining component properties.
  • Examples:
    export type ExplorerStatusProps = {
      readonly fileGroups: Map<Language, FileGroup[]>
      readonly isLoading: boolean
    }
    
    export type ProgressBarProps = {
      readonly value: number
      readonly max: number
      readonly label?: string
      readonly terminalWidth?: number
    }
    
    export type IndexProps = {
      fileGroups: Map<Language, FileGroup[]>
      inputDir: string
      outputDir: string
      model: string
      concurrency: number
      total: number
      database: DB
      debug?: boolean
    }
    
  • Anti-Example (Avoid): ExplorerStatusP, IExplorerStatusProps.

2.3. Variable and Function Naming

  • Convention: camelCase for local variables, function names, and object keys. Descriptive and avoids excessive abbreviations unless contextually clear (e.g., colI for column index in a loop).
  • Rationale: Standard JavaScript/TypeScript convention, promotes readability.
  • Examples:
    const foundLanguages = Array.from(fileGroups.keys())
    let fileCount = 0
    const languageCounts: Record<string, number> = {}
    
    const truncateText = (text: string, maxWidth: number, padding: number): string => { ... }
    const intersperse = <T, I>(intersperser: (index: number) => I, elements: T[]): (T | I)[] => { ... }
    
    const outputPath = (inputDir: string, outputDir: string, lang: Language) =>
      path.relative(inputDir, path.join(outputDir, `${lang}.md`))
    
  • Anti-Example (Avoid): fL, fCnt, langCnts (over-abbreviation).

2.4. Readonly Modifier

  • Convention: Use readonly for props and type properties that are not intended to be modified after creation.
  • Rationale: Enforces immutability, improves predictability, and leverages TypeScript's type safety.
  • Examples:
    export type ExplorerStatusProps = {
      readonly fileGroups: Map<Language, FileGroup[]>
      readonly isLoading: boolean
    }
    
    export type ProgressBarProps = {
      readonly value: number
      readonly max: number
      readonly label?: string
      readonly terminalWidth?: number
    }
    
    export type WorkersStatusProps = {
      inputDir: string
      readonly workers: readonly Worker[]
      readonly queuedTasks?: readonly QueuedTask[]
    }
    
  • Anti-Example (Avoid): Omitting readonly when the property is not meant to be mutated.

3. CODE ORGANIZATION

3.1. File Structure and Component Cohesion

  • Convention: Each major UI component resides in its own .tsx file. Related helper components or utility functions that are highly specific to a single component are co-located within that component's file. Generic utilities are moved to a lib directory. Top-level application components (like Index) reside directly in src/.
  • Rationale: Promotes high cohesion and low coupling. Components are self-contained units. Clear separation between application entry points, core UI components, and reusable utilities.
  • Examples:
    • Table.tsx contains Table component, Header, Cell, Skeleton (helper components specific to Table), and row, truncateText, intersperse (utility functions specific to Table's rendering logic).
    • ExplorerStatus.tsx, ProgressBar.tsx, WorkerStatus.tsx are single-component files in src/components/.
    • index.tsx (the main application component) and main.tsx (the CLI entry point) are in src/.
  • Anti-Example (Avoid): Placing Header or Cell in a separate components/table/ subdirectory if they are not reusable outside Table. Mixing CLI setup logic directly within a React component.

3.2. Import Statement Organization

  • Convention: Imports are grouped and ordered:
    1. Node.js built-in modules (e.g., node:path).
    2. External libraries (e.g., ink, react).
    3. Local relative imports (e.g., ../lib/types.js, ./Table.js). Type-only imports (import type ...) are often grouped separately or at the top of their respective sections.
  • Rationale: Consistency, readability, and easy identification of dependencies.
  • Examples:
    // WorkerStatus.tsx
    import path from "node:path" // Node.js built-in
    import { Box, Text } from "ink" // External
    import type React from "react" // External type
    import { useMemo } from "react" // External
    import type { QueuedTask, Worker } from "../lib/types.js" // Local type
    import Table from "./Table.js" // Local component
    
    // Index.tsx
    import path from "node:path" // Node.js built-in
    import { Box, Text, useApp } from "ink" // External
    import BigText from "ink-big-text" // External
    import Gradient from "ink-gradient" // External
    import { useEffect, useMemo } from "react" // External
    import { ExplorerStatus } from "./components/ExplorerStatus.js" // Local component
    import { ProgressBar } from "./components/ProgressBar.js" // Local component
    import Table from "./components/Table.js" // Local component
    import { WorkersStatus } from "./components/WorkerStatus.js" // Local component
    import { useProcessor } from "./hooks/use-processor.js" // Local hook
    import type { DB } from "./lib/database.js" // Local type
    import type { FileGroup, Language } from "./lib/types.js" // Local type
    
  • Anti-Example (Avoid): Mixed import order, e.g., import Table from "./Table.js" followed by import { Box } from "ink".

3.3. Functional Component Structure

  • Convention: Functional components are defined as React.FC<PropsType> and use destructuring for props. useMemo and useCallback are used extensively for memoization of derived values and functions, respectively. useEffect is used for side effects, including component lifecycle management (e.g., running a process on mount, exiting on completion/error).
  • Rationale: Standard React functional component pattern, leverages memoization for performance, especially in components that re-render frequently or perform complex calculations. useEffect ensures proper handling of side effects and integration with the Ink application lifecycle.
  • Examples:
    export const ExplorerStatus: React.FC<ExplorerStatusProps> = ({ fileGroups, isLoading }) => {
      // ... logic ...
      return (
        <Box>...</Box>
      )
    }
    
    export const WorkersStatus: React.FC<WorkersStatusProps> = ({ workers, inputDir, queuedTasks = [] }) => {
      const workersViewModel = useMemo(
        () =>
          workers
            .map(agent => ({ ... })),
        [workers, inputDir],
      )
      // ...
    }
    
    // Index.tsx
    export const Index: React.FC<IndexProps> = ({ ... }) => {
      const { exit } = useApp()
      const { run, workers, queuedTasks, progress, results, error, reset } = useProcessor({ ... })
    
      useEffect(() => {
        run()
      }, [run])
    
      useEffect(() => {
        if (results != null || error != null) {
          database.close()
          reset()
          exit()
        }
      }, [results, error, exit, reset, database])
      // ...
    }
    
  • Anti-Example (Avoid): Defining components as function MyComponent(props: MyProps) { ... } without React.FC or not using useMemo/useCallback for potentially expensive computations or stable function references. Performing side effects directly in the render function.

4. ERROR HANDLING

  • Convention: Error handling in UI components is primarily focused on displaying errors passed down via props rather than internal try/catch blocks for rendering logic. Data validation and error generation are assumed to happen upstream (e.g., in data fetching layers or business logic, or custom hooks like useProcessor). Components react to an error prop to display appropriate messages.
  • Rationale: UI components are responsible for presentation. Separating error generation from error presentation simplifies component logic and allows for centralized error management and consistent UI feedback.
  • Examples:
    // WorkerStatus.tsx
    // The 'error' property is part of the Worker type, passed down.
    status:
      agent.status === "idle"
        ? "Waiting..."
        : agent.status === "working"
          ? agent.progress || "Working..."
          : agent.status === "success"
            ? "Success"
            : agent.error, // Displaying the error if agent.status is an error state
    
    // Index.tsx
    ) : error != null ? (
      <>
        <ExplorerStatus fileGroups={fileGroups} isLoading={false} />
        <Box marginTop={1}>
          <Text color="red">✗ Error: {error}</Text>
          {debug && <Text dimColor>Run ID: {database.runId}</Text>}
        </Box>
      </>
    ) : (
    
  • Anti-Example (Avoid): try/catch blocks directly within render methods or useMemo hooks for data that is expected to be valid. UI components performing complex error validation that should be handled by business logic.

5. STATE MANAGEMENT

  • Convention: Local component state is managed using React's built-in hooks (useState, useMemo, useCallback, useEffect). There is no evidence of a global state management library (e.g., Redux, Zustand). Derived state is heavily memoized using useMemo. Complex, shared logic and state are encapsulated within custom hooks (e.g., useProcessor), which then expose their state and methods via a structured return object.
  • Rationale: For the current scope of UI components, local state and prop drilling are sufficient. useMemo ensures performance by preventing unnecessary re-calculations of derive

Truncated for display — read the full file on GitHub.

Related Skills

View on GitHub
GitHub Stars0
CategoryDevelopment
Updated7mo ago
Forks0

Security Score

69/100

Audited on Feb 14, 2026

1 medium3 low