Skip to main content

Interactive

Interactive is a primitive for building clickable and focusable elements.

Import

import { Interactive } from '@vortexlabs/vortex';
import type { InteractiveProps } from '@vortexlabs/vortex';

Display

<Interactive type="button">Interactive</Interactive>

Allied components

Other links

<Interactive
  type="button"
  disabled={false}
  fullWidth={false}
  insetFocus={false}
  focusRingDisabled={false}
  touchHitbox={false}
>
  Interactive
</Interactive>

Features

  • Renders buttons, links, and custom elements.
  • Supports keyboard, mouse, and touch activation.
  • Supports disabled and fullWidth states.
  • Expands pointer targets with touchHitbox.
  • Supports inset focus rings and optional focus-ring suppression.

Role

Interactive renders an anchor (<a>) with a non-empty href, or a button (<button>) with onClick or type. With none of these props, it renders a passive <span> by default.

Interactive LinkPassive span
import { Interactive } from "@vortexlabs/vortex";

const Example = () => {
  return (
    <>
      <Interactive href="/docs/quick-start">Interactive Link</Interactive>
      <Interactive type="button">Interactive Button</Interactive>
      <Interactive>Passive span</Interactive>
    </>
  );
};

export default Example;

Use href to render a link. Add openInNewTab to open it in a new tab with rel="noopener noreferrer".

<Interactive href="/docs/quick-start">Quick Start</Interactive>
<Interactive href="https://vortex.design" openInNewTab>External link</Interactive>

Disabled State

Set disabled to block activation. Buttons selected by type or onClick receive the native disabled attribute; links lose their href.

Disabled link
<Interactive type="button" disabled>Disabled button</Interactive>
<Interactive href="https://vortex.design" disabled>Disabled link</Interactive>

Full Width

Interactive can be made full width by setting the fullWidth property to true.

<Interactive fullWidth href="/">
  Full Width Interactive
</Interactive>

Focus Ring

Interactive shows a focus ring during keyboard navigation when used within VortexProvider. Use Tab to focus the examples.

Inset Focus

Use insetFocus to place the focus ring inside the element bounds. The inset ring uses the element's text color.

<Interactive type="button" insetFocus>Inset focus ring</Interactive>

Disabled Focus Ring

Use focusRingDisabled only when another element provides a visible focus indicator. It also hides child rings created by borderRadius="inherit".

Inherited Border Radius

Use borderRadius="inherit" to draw the focus ring on direct children. Wrap the content in one rounded element for a single ring.

<Interactive type="button" borderRadius="inherit">
  <span style={{ display: 'block', borderRadius: '999px', padding: '8px 16px' }}>
    Rounded child
  </span>
</Interactive>

Touch Hitbox

Use touchHitbox to add an invisible target overlay without changing layout. Its minimum size comes from the theme, so leave enough space around small controls to avoid overlapping targets.

<Interactive type="button" touchHitbox>Small target</Interactive>

Custom Element

Use as to choose a different HTML element when there is no href. With onClick, a div receives role="button" and keyboard activation with Enter or Space. Prefer a native button when possible.

For a native button, pass type="button". Setting as="button" alone does not apply the default button type or native disabled behavior.

Activated 0 times
"use client";

import { useState } from "react";
import { Interactive } from "@vortexlabs/vortex";

const Example = () => {
  const [count, setCount] = useState(0);

  return (
    <Interactive as="div" onClick={() => setCount((value) => value + 1)}>
      Activated {count} times
    </Interactive>
  );
};

export default Example;

Render Slot

Use render in a client component to replace the root element. Spread the supplied attributes, including the ref, event handlers, and children, onto an element with matching semantics.

"use client";

import { Interactive } from "@vortexlabs/vortex";

const Example = () => {
  return (
    <Interactive
      href="https://vortex.design"
      render={(attributes) => (
        <a {...attributes} data-custom="value" />
      )}
    >
      Custom anchor
    </Interactive>
  );
};

export default Example;

Accessibility

Key
Description
EnterSpace
Pressing Enter or Space activates non-native buttons with role="button".
Enter
Pressing Enter activates links.
Disabled elements receive aria-disabled="true". Disabled buttons leave the tab order.
Disabled links remove the href attribute to prevent navigation.
The focus ring is only visible during keyboard navigation.
Provide a visible text label or pass an accessible name through attributes={{ "aria-label": "…" }}.