Composition pitfalls

Review the most common Salt composition mistakes, including nested interactive primitives, pass-through wrappers, and rebuilding standard primitives.

Compose Salt components to simplify implementation and make behavior more predictable. If composition is making the hierarchy harder to understand or is recreating an existing Salt primitive, the structure is probably doing too much.

Good composition should:

  • make intent clearer
  • reduce repeated code
  • preserve the semantics of the underlying Salt primitives
  • keep structure shallow unless deeper nesting is necessary for the interaction

Do not nest interactive components such as Button and Link inside each other. Choose one interactive owner for the action or navigation.

Treat wrappers that only forward props to a Salt primitive as suspicious. If a wrapper does not add behavior, semantics, or a stable domain API, prefer using the Salt primitive directly.

Avoid rebuilding Salt buttons, links, navigation items, or other common components from raw HTML, custom roles, and ad hoc styling when Salt already provides the correct primitive.

Avoid stacking multiple layout containers when one Salt layout component can express the structure more clearly. Each wrapper should have a clear job such as controlling spacing, flow, split regions, or parent-child arrangement.

Avoid raw spacing, sizing, and color values that override Salt foundations and token usage without a strong reason. Prefer Salt layouts, foundations, and tokens before introducing custom styling.

If a wrapper remains, it should add more than prop forwarding. Give it a clear reason such as shared behavior, domain semantics, or a stable public API.

A wrapper can be the right choice when it:

  • establishes a stable domain-specific API
  • adds shared behavior such as analytics, permissions, or data wiring
  • adds semantics that the base primitive does not carry on its own
  • coordinates multiple Salt primitives into a reusable higher-level unit

If the wrapper is justified, keep the responsibilities explicit and avoid hiding the underlying interaction model.

This wrapper adds a domain-specific API and shared behavior rather than only renaming Button.

Before shipping or reviewing composed UI, check:

  1. Is the interaction owned by the right Salt primitive?
  2. Are there nested interactive Salt primitives that should be flattened?
  3. Is there a pass-through wrapper over a Salt primitive that should be removed?
  4. Could a Salt layout or pattern replace some of the custom structure?
  5. Does the styling still follow Salt foundations and token guidance?