Rules Hub

Coding Rules Library

← Back to all rules
frontend ruleStack: react
reactcomponentsreusabilityclean-codeui-patterns

Extract generic UI patterns into reusable components

Avoid implementing generic UI behaviors (like Modals, Drawers, or Tooltips) inline within feature components; extract them into reusable components.

PR: Feat/FCK-1561 - Adding Invoice Table to Minside #3570Created: Dec 8, 2025

Bad example

Old codetsx
1const InvoiceTable = ({ invoices, isOpen, onClose }) => {
2 if (!isOpen) return null;
3
4 // BAD: Generic Modal logic (overlay, click propagation, scroll lock)
5 // is mixed directly with domain-specific invoice logic.
6 return (
7 <div
8 className="modal-overlay"
9 onClick={onClose}
10 style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.5)' }}
11 >
12 <div
13 className="modal-content"
14 onClick={(e) => e.stopPropagation()}
15 >
16 <h2>Invoice History</h2>
17 {invoices.map(inv => <div key={inv.id}>{inv.amount}</div>)}
18 <button onClick={onClose}>Close</button>
19 </div>
20 </div>
21 );
22};

Explanation (EN)

The component mixes domain logic (displaying invoices) with generic UI mechanics (handling overlay clicks, stopping propagation, positioning). This makes the code repetitive if you need another modal elsewhere and clutters the component.

Objašnjenje (HR)

Komponenta miješa domensku logiku (prikaz faktura) s generičkom UI mehanikom (klikanje na overlay, zaustavljanje propagacije, pozicioniranje). To čini kod repetitivnim ako je potreban drugi modal negdje drugdje i zatrpava komponentu.

Good example

New codetsx
1// 1. Extract generic logic to a reusable component
2const Modal = ({ isOpen, onClose, children }: ModalProps) => {
3 if (!isOpen) return null;
4
5 return (
6 <div className="modal-overlay" onClick={onClose}>
7 <div className="modal-content" onClick={(e) => e.stopPropagation()}>
8 {children}
9 </div>
10 </div>
11 );
12};
13
14// 2. Consume it in the feature component
15const InvoiceTable = ({ invoices, isOpen, onClose }) => {
16 return (
17 <Modal isOpen={isOpen} onClose={onClose}>
18 <h2>Invoice History</h2>
19 {invoices.map(inv => <div key={inv.id}>{inv.amount}</div>)}
20 <button onClick={onClose}>Close</button>
21 </Modal>
22 );
23};

Explanation (EN)

The generic modal behavior is extracted into a dedicated `Modal` component that handles visibility, overlay clicks, and event propagation. The `InvoiceTable` component now focuses purely on rendering invoice data.

Objašnjenje (HR)

Generičko ponašanje modala izdvojeno je u zasebnu `Modal` komponentu koja upravlja vidljivošću, klikovima na pozadinu i propagacijom događaja. Komponenta `InvoiceTable` sada se fokusira isključivo na prikazivanje podataka o fakturama.