Anti-Patterns
When to Use
Use this when code reviewing component implementations, debugging component issues, or establishing component development standards.
Decision
| Anti-Pattern | Why Wrong | Correct Approach |
|---|---|---|
| Over-componentizing | Each component has discovery/loading overhead | Create components at meaningful abstraction level |
| Logic in Twig | Business logic belongs in preprocessing | Templates should be presentation-only |
| Missing schema definitions | No validation, no IDE support | Always define complete props/slots schemas |
| Slots for simple data | Slots bypass validation | Use props for typed configuration data |
| Hardcoded child components | Reduces flexibility | Use slots for variable content areas |
Not using with_context = false |
Creates hidden dependencies | Isolate component context |
| Complex conditionals on slots | Slots contain arbitrary renderables | Only check if slot for existence |
Using @extend in SCSS |
Bloats compiled CSS | Use mixins or utility classes |
| Not checking slot existence | Creates empty wrapper elements | Wrap optional slots in conditionals |
| Global CSS selectors | Collides with other components | Use BEM with component-specific namespace |
| Module component overrides | Only themes can use replaces |
Override in theme, not module |
Changing schema in replaces |
Breaks API contract | Replacement must have identical schema |
Pattern
Anti-Pattern 1: Over-Componentizing
❌ WRONG: Atomic-level components
components/
├── heading/
├── paragraph/
├── link/
└── image/
✓ RIGHT: Meaningful abstraction
components/
└── article-card/ ← Combines elements
Anti-Pattern 3: Missing Schema
❌ WRONG: No schema
name: 'Button'
status: stable
✓ RIGHT: Complete schema
name: 'Button'
status: stable
props:
type: object
properties:
text:
type: string
title: 'Button Text'
Anti-Pattern 6: Variable Leakage
❌ WRONG: Leaking context
{{ include('my_theme:button', { text: 'Click' }) }}
✓ RIGHT: Isolated context
{{ include('my_theme:button', { text: 'Click' }, with_context = false) }}
Anti-Pattern 9: Empty Wrappers
❌ WRONG: Unconditional wrapper
<header class="component__header">
{{ header }}
</header>
✓ RIGHT: Conditional wrapper
{% if header %}
<header class="component__header">
{{ header }}
</header>
{% endif %}