Skip to main content

Interactive

Interactive is a base element that makes content clickable and focusable, such as cards or list rows that act as buttons or links.

Import

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

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/web/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/web/quick-start">Quick Start</Interactive>
<Interactive href="https://vortex.design" openInNewTab>External link</Interactive>

Disabled

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

Set fullWidth to fill the container.

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

Focus Ring

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

Set touchHitbox to enlarge the touch target without changing layout. The theme sets its minimum size, so leave space between small controls.

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

Custom Element

Without href, use as to render another element. With onClick, a div gets role="button" and Enter and Space activation; prefer a native button. For one, pass type="button": as="button" alone doesn't set the type or native disabled.

Activated 0 times
"use client";

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

const Example = () => {
  const [count, setCount] = React.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": "…" }}.