Analytics
The design system does not ship an analytics SDK, provider or analytics-specific props. Instead,
every interactive component forwards the attributes and handlers you pass to the real
interactive DOM element: the button, link or input the user actually clicks. Your analytics
library finds them there, typically with a document-level click listener and
event.target.closest('[data-analytics-id]').
The canonical attributes are data-analytics-id and data-analytics-props, but the rule covers
any data-*, aria-*, id, ref and event handler.
Attributes land on the click target
data-analytics-props is forwarded byte-for-byte: the design system never parses, normalizes or
reserializes it. Its format is up to you and your analytics library.
Attributes survive rerenders, open and close transitions, variant changes and controlled or uncontrolled state changes. Your own event handlers run alongside the component's internal ones; they are never silently replaced.
asChild
With asChild, the attributes reach the element you render:
Components with several click targets
When a component has more than one interactive part, each part is an exported sub-component, and you put the attributes on the part itself, not on a wrapper around the whole component:
Don't wrap a component in <div data-analytics-id> when the click target is inside it: the
attribute ends up on an element nobody clicks.
A few internal targets cannot be reached this way yet, such as parts of the table. Their component
folder documents the gap and the callback to track instead (for example
Table/ANALYTICS_GAPS.md).
Interactions without a DOM click, such as sorting or resizing, are reported through typed
callbacks (onSortingChange on Table, onResizeEnd on DrawerResizeHandle, …) that you track from your
own code.
Clickable containers
Some components delegate clicks from a container: a Card with onClick is clickable on its whole
surface. Native interactive descendants (<button>, <a href>, <input>, …) don't trigger the
card's click. A descendant that handles its own click but is not a native interactive element opts
out with the data-ds-suppress-parent-click attribute on its own DOM node. InlineCodeSnippet
(click to copy, rendered as <code>) already does this, so copying the address below does not
open the card:
Give your own non-native clickable elements inside such a container the same attribute.
Don't use event.stopPropagation() for this: a blanket stop in a click handler also blocks the
document-level listener your analytics library relies on.
Coexistence with data-slot and data-testid
data-slot (CSS hooks), data-testid (test ids) and your data-* attributes
live side by side on the same element without colliding.