Interactable adds keyboard-accessible, clickable behavior to a child surface when a standard Button or Icon button is not the right visual wrapper. It bridges custom layout or third-party markup with expected focus, activation, and ARIA roles. The mental model is “make this region behave like a button—or merge props into a child element—without fighting the design.”
When to use
Custom hit areas: cards, rows, or composite tiles that must activate as one control.
Slot-based children where wrapping everything in a real button would break layout or semantics.
Drag-and-drop plus activation when the same surface needs both (with careful event handling).
Inject child (injectChild true): preserve the child element type while merging interactive props (for example a styled container that must stay a non-button element for CSS reasons).
When not to use
Standard actions: prefer Button or Icon button for conventional triggers.
Navigation to a URL: prefer the app’s link or router component so routing, middle-click, and assistive tech get correct semantics.
Not a substitute for semantic state; pair with design
active
Shows selection within a set
Don’t use alone for “pressed” without aria-pressed when it behaves as a toggle
disabled
Blocks interaction
Keep visible only when the user needs to know the action exists
Anatomy
Interactable wraps children (or injects into them) and centralizes onClick, keyboard handlers (Enter / Space), tabIndex, and disabled behavior. Nested interactive elements require explicit event handling so inner controls don’t fire the outer handler unintentionally.
Content guidelines
Naming: If there is no visible text, provide aria-label (or labelled-by) that states the action, not the visual style.
Toggle-like controls: Use aria-pressed or the appropriate role when state changes meaning, not only color.
Disclosure: If opening content, pair with aria-expanded and move focus sensibly.
i18n: Localize accessible names the same as visible labels.
Behavior and states
Focus: Focusable when enabled; removed or skipped when disabled per platform pattern.
Keyboard:Enter and Space activate; don’t swallow keys needed by nested inputs.
Hover and active: Visual feedback should match active and disabled props.
Nested interactivity: Stop propagation on inner buttons and links; verify tab order.
Best practices
Do
Choose injectChild only when you’ve verified the child can receive merged props and remains accessible.
Memoize handlers in long lists to avoid unnecessary re-renders.
Use CSS for hover where possible; reserve state for semantics and keyboard.
Don’t
Stack multiple nested Interactables without a clear focus path.
Use Interactable to avoid using a button when a button would simplify accessibility.
Rely on pointer-only interactions for essential tasks.
Accessibility
When behaving as a button, expose role="button" (or use real button) and support keyboard activation.
Provide visible focus; don’t outline: none without replacement.
For icon-only or ambiguous tiles, expose descriptive names and optional descriptions.
Test with screen readers: name, role, state, and whether double semantics confuse users.