Three patterns, each appropriate for different relationships.
1. Parent-to-Child via @api properties. Parent passes data via attributes; child receives via @api decorated properties.
javascript // child.js export default class Child extends LightningElement { @api recordName; } html <!-- parent.html --> <c-child record-name={accountName}></c-child>
2. Child-to-Parent via Custom Events. Child dispatches CustomEvent; parent listens.
javascript // child.js this.dispatchEvent(new CustomEvent('userselected', { detail: { id: '001xxx' } })); html <!-- parent.html --> <c-child onuserselected={handleUserSelected}></c-child>
3. Sibling-to-Sibling via Lightning Message Service (LMS). Components in different DOM trees use a Message Channel for pub-sub.
`javascript import { publish, subscribe, MessageContext } from 'lightning/messageService'; import RECORD_SELECTED_CHANNEL from '@salesforce/messageChannel/RecordSelected__c';
@wire(MessageContext) messageContext; publish(this.messageContext, RECORD_SELECTED_CHANNEL, { recordId: id }); `
LMS works across Aura/LWC/Visualforce on the same page, making it the universal sibling-communication channel.
Decision tree: parent->child = @api; child->parent = CustomEvent; siblings = LMS.
Avoid: directly manipulating sibling components (anti-pattern); using DOM events for cross-tree communication (won't propagate).
