Skip to content

Allow arbitrary data-* attributes on DOM elements in JSX #152

@Maltaesh

Description

@Maltaesh

Problem

Currently data-* attributes cannot be used directly on HTML elements in ReScript JSX.

Example:

<input data-component="true" />

This produces the compiler error:

The field data-component does not belong to type JsxDOM.domProps

To use data-* attributes developers currently need to:

  • extend JsxDOM.domProps
  • implement a custom JSX module
  • bypass JSX with React.createElement

This introduces unnecessary complexity for a very common HTML pattern and reduces JSX ergonomics.

Context

data-* attributes are part of the HTML standard and are widely used across the React ecosystem for:

  • CSS state selectors
  • design-system variants
  • testing hooks (data-testid)
  • UI libraries such as Radix UI, Headless UI, and similar component systems

Example commonly used in modern component libraries:

<button data-state="open" data-variant="primary" />

CSS:

button[data-state="open"] {
  background: green;
}

This pattern is heavily used in modern design systems and utility-CSS ecosystems because it allows component state to be expressed declaratively and consumed by CSS.

Proposal

Allow arbitrary attributes matching the pattern:

data-*

on lowercase DOM elements in JSX without requiring them to be explicitly declared in JsxDOM.domProps.

This could be implemented as a special case in JSX attribute validation.

Benefits

  • better interoperability with the React ecosystem
  • easier migration of existing React / TypeScript codebases
  • simpler implementation of design systems
  • avoids the need for custom JSX infrastructure for a standard HTML feature

Expected developer experience

Developers should be able to write JSX like this without additional configuration:

<button data-state="open" data-variant="primary" />

In real-world usage these attributes often contain values coming from ReScript variables, component props, or state:

@react.component
let make = (~variant: string, ~isOpen: bool, ~count: int) => {
  <button
    data-state={isOpen ? "open" : "closed"}
    data-variant={variant}
    data-count={count}
  >
    {React.string("Click")}
  </button>
}

This pattern is widely used in React codebases and design systems, where data-* attributes act as a bridge between component state and CSS.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions