Files
Htmx/docs/Issues/Components/00-API-Limitations-and-Workarounds.md
T

3.3 KiB

Component API Limitations and Workarounds

This page documents known limitations in the current component API and practical ways to work effectively with them.

1) Magic String Parameters

Limitation:

  • Semantic options like variant, size, and similar values are frequently string-based.

What this means:

  • Typos may silently fall back to defaults.

Workaround:

  • Centralize repeated literals in local constants in your feature code.
  • Prefer named arguments for readability.

Example:

private const string VariantDestructive = "destructive";

var deleteButton = new Button(
    label: "Delete",
    variant: VariantDestructive,
    size: "sm");

2) Extra Styling Often Requires Wrappers

Limitation:

  • Not every component exposes a class extension parameter.

What this means:

  • You may need wrapper elements for layout spacing, sizing, or responsive behavior.

Workaround:

  • Use a minimal wrapper pattern and keep wrapper intent obvious.

Example:

<div class="md:max-w-sm w-full">$$SaveButton$$</div>

3) No Universal Attribute Bag

Limitation:

  • Some components expose hxAttrs, some do not, and no shared attributes model exists yet.

What this means:

  • Passing aria-*, data-*, or test selectors is inconsistent.

Workaround:

  • Prefer wrapper-level attributes where possible.
  • If using raw attr strings, keep them static and explicit.

4) No Direct "Props in .htmx Markup" Model

Limitation:

  • Component/page parameterization is constructor-driven in .htmx.cs, not inline-props driven in .htmx markup.

What this means:

  • Dynamic behavior is assembled in C# code-behind.

Workaround:

  • Treat .htmx as shape and slot layout.
  • Treat .htmx.cs as the single source of component input logic.

5) Raw HTML Output Requires Discipline

Limitation:

  • Several components render provided strings as HTML.

What this means:

  • User input must be encoded before rendering.

Workaround:

  • Always encode user-provided values before ToUtf8Bytes().

Example:

var safeName = System.Web.HttpUtility.HtmlEncode(userDisplayName);
_nameData = safeName.ToUtf8Bytes();

6) Interactive Components Depend on JS Contracts

Limitation:

  • Components like tabs, accordion, dialog, calendar, and toast depend on JavaScript hooks/selectors.

What this means:

  • Markup can render but behave incorrectly if expected JS wiring is missing.

Workaround:

  • Verify behavior after HTMX swaps.
  • Keep required data-role/class markers intact.

7) Tuple APIs for Complex Components

Limitation:

  • Some components expect tuple arrays for items/options.

What this means:

  • Call sites can become harder to read and evolve.

Workaround:

  • Build small local records/variables first, then map to tuples.

8) Form API Inconsistency

Limitation:

  • Form primitives do not all expose the same extension points.

What this means:

  • You need per-component familiarity.

Workaround:

  • Create feature-local helper methods to normalize usage patterns.

9) Recommendation for Teams

If multiple developers are contributing:

  1. Define local conventions for allowed variant strings.
  2. Standardize wrapper patterns (layout wrappers, a11y wrappers, test-id wrappers).
  3. Review for HTML encoding whenever user input is rendered.
  4. Track repeated pain points in docs/Issues for future API upgrades.