Skip to main content Home About the Design SystemRoadmap OverviewDesignersDevelopers OverviewColorGridIconographyInteractionsSpacingTypography Overview Global colorBox shadowTypographyBorderOpacitySpaceLengthIconBreakpointsMedia queries All elements Accordion Alert Announcement Audio player Avatar Back to top Badge Blockquote Breadcrumb Button group Button Card Chip Code block Call to action Dialog Disclosure Footer Health index Icon Jump links Menu dropdown Navigation link Navigation (primary) Navigation (secondary) Navigation (vertical) Pagination PopoverPlanned Progress stepper Readtime Scheme toggle Select Site status Skeleton Skip link Spinner Statistic Subnavigation Surface Switch Table Tabs Tag Tile Timestamp Tooltip Video embed OverviewColor PalettesCustomizingDevelopers All PatternsAccordionAlertCall to ActionCardFilterFormLink with iconLogo wallSearch barSticky bannerSticky cardTabsTagTile All Personalization PatternsAnnouncement FundamentalsAccessibility toolsAssistive technologiesCI/CDContentContributorsDesignDevelopmentManual testingResourcesScreen readers Design/code status Release notes Get support

Call to action

OverviewStyleGuidelinesCodeAccessibilityDemos
Call to actionAnalyticsArrow Follows TextBrickButtonColor Context With Lightdom CssColor ContextNo Cta JavascriptResizingRight To LeftSlotted LinksVariantsCall to actionAnalyticsArrow Follows TextBrickButtonColor Context With Lightdom CssColor ContextNo Cta JavascriptResizingRight To LeftSlotted LinksVariants

Call to action

Default call-to-action demo with inline link and trailing arrow.

import '@rhds/elements/rh-cta/rh-cta.js';
<rh-cta href="#">Call to Action</rh-cta>
import { Cta } from "@rhds/elements/react/rh-cta/rh-cta.js";

// NOTE: React 19+ does not require these wrapper imports.
// You can use the custom elements directly as-is.

export const Demo = () => (
  <Cta href="#">Call to Action</Cta>
);

Analytics

CTA with analytics event tracking integration.

rh-cta[variant="brick"] {
  /* for demo reviewer ergonomics, even though this is against style guidelines */
  width: auto;
}
json-viewer {
  --json-viewer-background: white;
  --json-viewer-boolean-color: #f76707;
  --json-viewer-color: black;
  --json-viewer-key-color: #f76707;
  --json-viewer-null-color: Light #e03131;
  --json-viewer-number-color: #0ca678;
  --json-viewer-string-color: #0c8599;
}
import '@rhds/elements/rh-cta/rh-cta.js';
import 'https://ga.jspm.io/npm:@power-elements/json-viewer@2.1.1/json-viewer.js';

customElements.define('slotted-link', class SlottedLinkElement extends HTMLElement {
  constructor() {
    super();
    this.attachShadow({ mode: 'open' }).innerHTML = /* html */`
      <rh-cta><slot name="default"></slot></rh-cta>
      <rh-cta variant="primary"><slot name="primary"></slot></rh-cta>
      <rh-cta variant="secondary"><slot name="secondary"></slot></rh-cta>
      <rh-cta variant="brick" style="width:auto;"><slot name="brick"></slot></rh-cta>
    `;
  }
});

document.addEventListener('click', function(event) {
  const data = event.composedPath().reduceRight((acc, node) => {
    if (node instanceof HTMLElement) {
      for (const [datakey, value] of Object.entries(node.dataset)) {
        if (datakey.startsWith('analytics')) {
const key = datakey.replace(/^analytics(.)/, (_, m) => m.toLowerCase());
acc[key] = `${acc[key] ?? ''}|${value}`.replace(/^\|/,'');
        }
      }
    }
    return acc;
  }, {});
  if (data.linktype === 'cta') {
    document.querySelector('json-viewer').object = data;
  }
});
<p>In this demo, analytics events involving <code>&lt;rh-cta&gt;</code> elements are parsed by a
  document-level analytics event listener. Unlike <code>&lt;pfe-cta&gt;</code>, which implemented
  support for analytics internally, <code>&lt;rh-cta&gt;</code> users must implement their own
  analytics code, taking this demo as an example.</p>

<section data-analytics-category="simple">
  <h2>Simple Case: Light DOM</h2>
  <rh-cta data-analytics-linktype="cta" data-analytics-text="Default">
    <a href="#default">Default</a>
  </rh-cta>
  <rh-cta variant="primary" data-analytics-linktype="cta" data-analytics-text="Primary">
    <a href="#primary">Primary</a>
  </rh-cta>
  <rh-cta variant="secondary" data-analytics-linktype="cta" data-analytics-text="Secondary">
    <a href="#secondary">Secondary</a>
  </rh-cta>
  <rh-cta variant="brick" data-analytics-linktype="cta" data-analytics-text="Brick">
    <a href="#brick">Brick</a>
  </rh-cta>

  <section data-analytics-category="href-attr">
    <h3>Using <code>href</code> attribute</h3>
    <rh-cta href="#default" data-analytics-linktype="cta" data-analytics-text="Default">Default</rh-cta>
    <rh-cta href="#primary" variant="primary" data-analytics-linktype="cta" data-analytics-text="Primary">Primary</rh-cta>
    <rh-cta href="#secondary" variant="secondary" data-analytics-linktype="cta" data-analytics-text="Secondary">Secondary</rh-cta>
    <rh-cta href="#brick" variant="brick" data-analytics-linktype="cta" data-analytics-text="Brick">Brick</rh-cta>
  </section>
</section>

<section data-analytics-category="shadow">
  <h2>Advanced Case: Deep Shadow</h2>
  <shadow-root>
    <template shadowrootmode="open">
      <rh-cta data-analytics-linktype="cta" data-analytics-text="Default">
        <a href="#default">Default</a>
      </rh-cta>
      <rh-cta variant="primary" data-analytics-linktype="cta" data-analytics-text="Primary">
        <a href="#primary">Primary</a>
      </rh-cta>
      <rh-cta variant="secondary" data-analytics-linktype="cta" data-analytics-text="Secondary">
        <a href="#secondary">Secondary</a>
      </rh-cta>
      <rh-cta variant="brick" style="width:auto;" data-analytics-linktype="cta" data-analytics-text="Brick">
        <a href="#brick">Brick</a>
      </rh-cta>
    </template>
  </shadow-root>
  <h3>Using <code>href</code> attribute</h3>
  <shadow-root data-analytics-category="href-attr">
    <template shadowrootmode="open">
      <rh-cta href="#default" data-analytics-linktype="cta" data-analytics-text="Default">Default</rh-cta>
      <rh-cta href="#primary" data-analytics-linktype="cta" data-analytics-text="Primary" variant="primary">Primary</rh-cta>
      <rh-cta href="#secondary" data-analytics-linktype="cta" data-analytics-text="Secondary" variant="secondary">Secondary</rh-cta>
      <rh-cta href="#brick" style="width:auto;" variant="brick" data-analytics-linktype="cta" data-analytics-text="Brick">Brick</rh-cta>
    </template>
  </shadow-root>
</section>

<section data-analytics-category="slotted">
  <h2>Complex Case: Slotted Link, Deep CTA</h2>
  <slotted-link>
    <a slot="default" data-analytics-linktype="cta" data-analytics-text="Default" href="#default">Default</a>
    <a slot="primary" data-analytics-linktype="cta" data-analytics-text="Primary" href="#primary">Primary</a>
    <a slot="secondary" data-analytics-linktype="cta" data-analytics-text="Secondary" href="#secondary">Secondary</a>
    <a slot="brick" data-analytics-linktype="cta" data-analytics-text="Brick" href="#brick">Brick</a>
  </slotted-link>
</section>

<h2>Last CTA Analytics Event</h2>
<json-viewer>{}</json-viewer>
import { Cta } from "@rhds/elements/react/rh-cta/rh-cta.js";

// NOTE: React 19+ does not require these wrapper imports.
// You can use the custom elements directly as-is.

export const Demo = () => (
  <p>
    In this demo, analytics events involving
    <code><rh-cta></code>
    elements are parsed by a
    document-level analytics event listener. Unlike
    <code><pfe-cta></code>
    , which implemented
    support for analytics internally,
    <code><rh-cta></code>
    users must implement their own
    analytics code, taking this demo as an example.
  </p>
  <section data-analytics-category="simple">
    <h2>Simple Case: Light DOM</h2>
    <Cta data-analytics-linktype="cta" data-analytics-text="Default"><a href="#default">Default</a></Cta>
    <Cta variant="primary" data-analytics-linktype="cta" data-analytics-text="Primary"><a href="#primary">Primary</a></Cta>
    <Cta variant="secondary" data-analytics-linktype="cta" data-analytics-text="Secondary"><a href="#secondary">Secondary</a></Cta>
    <Cta variant="brick" data-analytics-linktype="cta" data-analytics-text="Brick"><a href="#brick">Brick</a></Cta>
    <section data-analytics-category="href-attr">
      <h3>
        Using
        <code>href</code>
        attribute
      </h3>
      <Cta href="#default" data-analytics-linktype="cta" data-analytics-text="Default">Default</Cta>
      <Cta href="#primary" variant="primary" data-analytics-linktype="cta" data-analytics-text="Primary">Primary</Cta>
      <Cta href="#secondary" variant="secondary" data-analytics-linktype="cta" data-analytics-text="Secondary">Secondary</Cta>
      <Cta href="#brick" variant="brick" data-analytics-linktype="cta" data-analytics-text="Brick">Brick</Cta>
    </section>
  </section>
  <section data-analytics-category="shadow">
    <h2>Advanced Case: Deep Shadow</h2>
    <shadow-root>
      <template shadowrootmode="open" />
    </shadow-root>
    <h3>
      Using
      <code>href</code>
      attribute
    </h3>
    <shadow-root data-analytics-category="href-attr">
      <template shadowrootmode="open" />
    </shadow-root>
  </section>
  <section data-analytics-category="slotted">
    <h2>Complex Case: Slotted Link, Deep CTA</h2>
    <slotted-link>
      <a slot="default" data-analytics-linktype="cta" data-analytics-text="Default" href="#default">Default</a>
      <a slot="primary" data-analytics-linktype="cta" data-analytics-text="Primary" href="#primary">Primary</a>
      <a slot="secondary" data-analytics-linktype="cta" data-analytics-text="Secondary" href="#secondary">Secondary</a>
      <a slot="brick" data-analytics-linktype="cta" data-analytics-text="Brick" href="#brick">Brick</a>
    </slotted-link>
  </section>
  <h2>Last CTA Analytics Event</h2>
  <json-viewer>{}</json-viewer>
);

Arrow Follows Text

CTA arrow icon following text wrap behavior in a narrow resizable container with long words.

#container {
  width: 230px;
  resize: horizontal;
  overflow: hidden;
}
import "@rhds/elements/rh-cta/rh-cta.js";
<div id="container">
  <rh-cta href="#">
    Register for the webinar
  </rh-cta>
  <rh-cta>
    <a href="#">Register for the webinar</a>
  </rh-cta>
  <rh-cta href="#">
    Lebensabschnitts<wbr>gefährtenverlustangst
  </rh-cta>
  <rh-cta>
    <a href="#">Lebensabschnitts<wbr>gefährtenverlustangst</a>
  </rh-cta>
</div>
import { Cta } from "@rhds/elements/react/rh-cta/rh-cta.js";

// NOTE: React 19+ does not require these wrapper imports.
// You can use the custom elements directly as-is.

export const Demo = () => (
  <div id="container">
    <Cta href="#">Register for the webinar</Cta>
    <Cta><a href="#">Register for the webinar</a></Cta>
    <Cta href="#">
      Lebensabschnitts
      <wbr />
      gefährtenverlustangst
    </Cta>
    <Cta>
      <a href="#">
        Lebensabschnitts
        <wbr />
        gefährtenverlustangst
      </a>
    </Cta>
  </div>
);

Brick

Brick variant CTA that stretches to fill container width in a grid.

import '@rhds/elements/rh-cta/rh-cta.js';
#grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1rem;
}
<div id="grid">
  <rh-cta variant="brick" href="#">Link #1</rh-cta>
  <rh-cta variant="brick" href="#">Link #2</rh-cta>
  <rh-cta variant="brick" href="#">Link #3</rh-cta>
  <rh-cta variant="brick" href="#default">Supercalifragilisticexpialidocious</rh-cta>
</div>
import { Cta } from "@rhds/elements/react/rh-cta/rh-cta.js";

// NOTE: React 19+ does not require these wrapper imports.
// You can use the custom elements directly as-is.

export const Demo = () => (
  <div id="grid">
    <Cta variant="brick" href="#">Link #1</Cta>
    <Cta variant="brick" href="#">Link #2</Cta>
    <Cta variant="brick" href="#">Link #3</Cta>
    <Cta variant="brick" href="#default">Supercalifragilisticexpialidocious</Cta>
  </div>
);

Button

CTA with a slotted button element instead of an anchor.

import '@rhds/elements/rh-cta/rh-cta.js';
<rh-cta>
  <button>Button</button>
</rh-cta>

<rh-cta variant="primary">
  <button>Button</button>
</rh-cta>

<rh-cta variant="secondary">
  <button>Button</button>
</rh-cta>
import { Cta } from "@rhds/elements/react/rh-cta/rh-cta.js";

// NOTE: React 19+ does not require these wrapper imports.
// You can use the custom elements directly as-is.

export const Demo = () => (
  <Cta>
    <button>Button</button>
  </Cta>
  <Cta variant="primary">
    <button>Button</button>
  </Cta>
  <Cta variant="secondary">
    <button>Button</button>
  </Cta>
);

Color Context With Lightdom Css

CTA color context demo using lightdom CSS shim for pre-upgrade styling.

import '@rhds/elements/rh-cta/rh-cta.js';
import '@rhds/elements/lib/elements/rh-context-demo/rh-context-demo.js';
<rh-context-demo>
  <rh-cta href="#default">Default</rh-cta>
  <rh-cta icon="play-circle" href="#default-video">Default Video</rh-cta>
  <rh-cta variant="primary" href="#primary">Primary</rh-cta>
  <rh-cta variant="primary" icon="play-circle" href="#primary-video">Video</rh-cta>
  <rh-cta variant="secondary" href="#secondary">Secondary</rh-cta>
  <rh-cta variant="brick" href="#brick">Brick</rh-cta>
  <rh-cta variant="brick" icon="play-circle" href="#brick-video">Brick Video</rh-cta>
</rh-context-demo>

<link rel="stylesheet" href="../rh-cta-lightdom-shim.css">
import { ContextDemo } from "@rhds/elements/react/rh-context-demo/rh-context-demo.js";
import { Cta } from "@rhds/elements/react/rh-cta/rh-cta.js";

// NOTE: React 19+ does not require these wrapper imports.
// You can use the custom elements directly as-is.

export const Demo = () => (
  <ContextDemo>
    <Cta href="#default">Default</Cta>
    <Cta icon="play-circle" href="#default-video">Default Video</Cta>
    <Cta variant="primary" href="#primary">Primary</Cta>
    <Cta variant="primary" icon="play-circle" href="#primary-video">Video</Cta>
    <Cta variant="secondary" href="#secondary">Secondary</Cta>
    <Cta variant="brick" href="#brick">Brick</Cta>
    <Cta variant="brick" icon="play-circle" href="#brick-video">Brick Video</Cta>
  </ContextDemo>
  <link rel="stylesheet" href="../rh-cta-lightdom-shim.css" />
);

Color Context

CTA variants on light and dark color contexts.

import '@rhds/elements/rh-cta/rh-cta.js';
import '@rhds/elements/lib/elements/rh-context-demo/rh-context-demo.js';
<rh-context-demo>
  <rh-cta href="#default">Default</rh-cta>
  <rh-cta icon="play-circle" href="#default-video">Default Video</rh-cta>
  <rh-cta variant="primary" href="#primary">Primary</rh-cta>
  <rh-cta variant="primary" icon="play-circle" href="#primary-video">Video</rh-cta>
  <rh-cta variant="secondary" href="#secondary">Secondary</rh-cta>
  <rh-cta variant="brick" href="#brick">Brick</rh-cta>
  <rh-cta variant="brick" icon="play-circle" href="#brick-video">Brick Video</rh-cta>
</rh-context-demo>
import { ContextDemo } from "@rhds/elements/react/rh-context-demo/rh-context-demo.js";
import { Cta } from "@rhds/elements/react/rh-cta/rh-cta.js";

// NOTE: React 19+ does not require these wrapper imports.
// You can use the custom elements directly as-is.

export const Demo = () => (
  <ContextDemo>
    <Cta href="#default">Default</Cta>
    <Cta icon="play-circle" href="#default-video">Default Video</Cta>
    <Cta variant="primary" href="#primary">Primary</Cta>
    <Cta variant="primary" icon="play-circle" href="#primary-video">Video</Cta>
    <Cta variant="secondary" href="#secondary">Secondary</Cta>
    <Cta variant="brick" href="#brick">Brick</Cta>
    <Cta variant="brick" icon="play-circle" href="#brick-video">Brick Video</Cta>
  </ContextDemo>
);

No Cta Javascript

CTA rendering without JavaScript using lightdom CSS shim.

shadow-root:not(:defined) {
  display: block;
  opacity: 1;
}

header[lang="en"] {
  width: 100%;
}
import '@rhds/elements/rh-surface/rh-surface.js';

// import('/assets/dsd-polyfill.js');
// TODO: DSD poly wont load in local dev dynamically
// imported from /assets path loading inline here:
if (!('shadowRootMode' in HTMLTemplateElement.prototype)) {
  (function attachShadowRoots(root) {
    // find all templates with a shadowrootmode attribute
    root.querySelectorAll('template[shadowrootmode]').forEach(template => {
      // get the mode: open or closed
      const mode = template.getAttribute('shadowrootmode');
      // attach a shadow to the component
      const shadowRoot = template.parentNode.attachShadow({ mode });
      // append the content in the template
      shadowRoot.appendChild(template.content);
      // remove the template
      template.remove();
      attachShadowRoots(shadowRoot);
    });
  })(document);
}
document.body.removeAttribute('dsd-pending');

customElements.define('shadow-root', class ShadowRootElement extends HTMLElement { });
<link rel="stylesheet" href="../rh-cta-lightdom-shim.css">
<p>&lt;rh-cta&gt; where JavaScript is not loaded, while loading a `lightdom-shim.css`.</p>

<section id="variants">
  <h2>Variants</h2>
  <rh-cta><a href="#default">Default</a></rh-cta>
  <rh-cta icon="play-circle"><a href="#default-video">Default Video</a></rh-cta>
  <rh-cta variant="primary"><a href="#primary">Primary</a></rh-cta>
  <rh-cta variant="primary" icon="play-circle"><a href="#primary-video">Video</a></rh-cta>
  <rh-cta variant="secondary"><a href="#secondary">Secondary</a></rh-cta>
  <rh-cta variant="brick"><a href="#brick">Brick</a></rh-cta>
  <rh-cta variant="brick" icon="play-circle"><a href="#brick-video">Brick Video</a></rh-cta>
</section>

<rh-surface color-palette="darkest">
  <h2>Dark Color Context</h2>
  <rh-cta><a href="#default">Default</a></rh-cta>
  <rh-cta icon="play-circle"><a href="#default-video">Default Video</a></rh-cta>
  <rh-cta variant="primary"><a href="#primary">Primary</a></rh-cta>
  <rh-cta variant="primary" icon="play-circle"><a href="#primary-video">Video</a></rh-cta>
  <rh-cta variant="secondary"><a href="#secondary">Secondary</a></rh-cta>
  <rh-cta variant="brick"><a href="#brick">Brick</a></rh-cta>
  <rh-cta variant="brick" icon="play-circle"><a href="#brick-video">Brick Video</a></rh-cta>
</rh-surface>

<section dir="rtl" lang="he">
  <header lang="en" dir="ltr">
    <h2>Right-to-Left Languages</h2>
  </header>

  <div>
    <rh-cta>
      <a href="#default">ברירת מחדל</a>
    </rh-cta>

    <rh-cta icon="play-circle">
      <a href="#default-video">ברירת מחדל - וידאו</a>
    </rh-cta>

    <rh-cta variant="primary">
      <a href="#primary">ראשי</a>
    </rh-cta>

    <rh-cta variant="primary" icon="play-circle">
      <a href="#primary-video">ראשי - וידאו</a>
    </rh-cta>

    <rh-cta variant="secondary">
      <a href="#secondary">משני</a>
    </rh-cta>

    <rh-cta variant="brick">
      <a href="#brick">לבנה</a>
    </rh-cta>

    <rh-cta variant="brick" icon="user">
      <a href="#brick-icon">לבנה עם אייקון</a>
    </rh-cta>
  </div>
</section>

<section dir="rtl" lang="he">
  <header dir="ltr" lang="en">
    <h2>Deep Shadow RTL</h2>
    <p>
      When the CTA is found within the shadow root of an element which is itself within a RTL context,
      it's own contents should also be displayed right-to-left, including the various box models, the placement
      of the icon, and the direction of the arrow. Authors should not need to specify the direction with the
      <code>dir="rtl"</code> attribute if it is added to a containing element.
      In this demo, the shadow root's host element has a light blue background color, in order distinguish it from the document content.
    </p>
  </header>
  <shadow-root>
    <template shadowrootmode="open">
      <link rel="stylesheet" href="../rh-cta-lightdom-shim.css">
      <style>
        :host {
width: 100%;
padding: var(--rh-space-xl, 24px);
background-color: var(--rh-color-blue-50, #e7f1fa);
display: flex;
flex-flow: row wrap;
gap: 16px;
align-items: center;
        }
      </style>

      <rh-cta id="deep">
        <a href="#default">ברירת מחדל</a>
      </rh-cta>

      <rh-cta icon="play-circle">
        <a href="#default-video">ברירת מחדל - וידאו</a>
      </rh-cta>

      <rh-cta variant="primary">
        <a href="#primary">ראשי</a>
      </rh-cta>

      <rh-cta variant="primary" icon="play-circle">
        <a href="#primary-video">ראשי - וידאו</a>
      </rh-cta>

      <rh-cta variant="secondary">
        <a href="#secondary">משני</a>
      </rh-cta>

      <rh-cta variant="brick">
        <a href="#brick">לבנה</a>
      </rh-cta>

      <rh-cta variant="brick" icon="user">
        <a href="#brick-icon">לבנה עם אייקון</a>
      </rh-cta>
    </template>
  </shadow-root>
</section>
import { Cta } from "@rhds/elements/react/rh-cta/rh-cta.js";
import { Surface } from "@rhds/elements/react/rh-surface/rh-surface.js";

// NOTE: React 19+ does not require these wrapper imports.
// You can use the custom elements directly as-is.

export const Demo = () => (
  <link rel="stylesheet" href="../rh-cta-lightdom-shim.css" />
  <p><rh-cta> where JavaScript is not loaded, while loading a `lightdom-shim.css`.</p>
  <section id="variants">
    <h2>Variants</h2>
    <Cta><a href="#default">Default</a></Cta>
    <Cta icon="play-circle"><a href="#default-video">Default Video</a></Cta>
    <Cta variant="primary"><a href="#primary">Primary</a></Cta>
    <Cta variant="primary" icon="play-circle"><a href="#primary-video">Video</a></Cta>
    <Cta variant="secondary"><a href="#secondary">Secondary</a></Cta>
    <Cta variant="brick"><a href="#brick">Brick</a></Cta>
    <Cta variant="brick" icon="play-circle"><a href="#brick-video">Brick Video</a></Cta>
  </section>
  <Surface color-palette="darkest">
    <h2>Dark Color Context</h2>
    <Cta><a href="#default">Default</a></Cta>
    <Cta icon="play-circle"><a href="#default-video">Default Video</a></Cta>
    <Cta variant="primary"><a href="#primary">Primary</a></Cta>
    <Cta variant="primary" icon="play-circle"><a href="#primary-video">Video</a></Cta>
    <Cta variant="secondary"><a href="#secondary">Secondary</a></Cta>
    <Cta variant="brick"><a href="#brick">Brick</a></Cta>
    <Cta variant="brick" icon="play-circle"><a href="#brick-video">Brick Video</a></Cta>
  </Surface>
  <section dir="rtl" lang="he">
    <header lang="en" dir="ltr">
      <h2>Right-to-Left Languages</h2>
    </header>
    <div>
      <Cta><a href="#default">ברירת מחדל</a></Cta>
      <Cta icon="play-circle"><a href="#default-video">ברירת מחדל - וידאו</a></Cta>
      <Cta variant="primary"><a href="#primary">ראשי</a></Cta>
      <Cta variant="primary" icon="play-circle"><a href="#primary-video">ראשי - וידאו</a></Cta>
      <Cta variant="secondary"><a href="#secondary">משני</a></Cta>
      <Cta variant="brick"><a href="#brick">לבנה</a></Cta>
      <Cta variant="brick" icon="user"><a href="#brick-icon">לבנה עם אייקון</a></Cta>
    </div>
  </section>
  <section dir="rtl" lang="he">
    <header dir="ltr" lang="en">
      <h2>Deep Shadow RTL</h2>
      <p>
        When the CTA is found within the shadow root of an element which is itself within a RTL context,
        it's own contents should also be displayed right-to-left, including the various box models, the placement
        of the icon, and the direction of the arrow. Authors should not need to specify the direction with the
        <code>dir="rtl"</code>
        attribute if it is added to a containing element.
        In this demo, the shadow root's host element has a light blue background color, in order distinguish it from the document content.
      </p>
    </header>
    <shadow-root>
      <template shadowrootmode="open" />
    </shadow-root>
  </section>
);

Resizing

CTA behavior when resizing the container.

import '@rhds/elements/rh-cta/rh-cta.js';
#resize {
  display: flex;
  flex-flow: row wrap;
  gap: var(--rh-space-lg, 16px);
}

#resize > p {
  width: 100%;
}

#resize > div {
  resize: horizontal;
  overflow: auto;
  display: flex;
  width: 180px;
  flex-flow: row nowrap;
  border: 1px solid #dddddd;
  padding: 10px;
}
<section id="resize">
  <div>
    <rh-cta>
      <a href="#default">Get product details</a>
    </rh-cta>
  </div>

  <div>
    <rh-cta icon="play-circle">
      <a href="#default-video">Get product details</a>
    </rh-cta>
  </div>

  <div>
    <rh-cta variant="primary">
      <a href="#primary">Get product details</a>
    </rh-cta>
  </div>

  <div>
    <rh-cta variant="primary" icon="play-circle">
      <a href="#primary-video">Get product details</a>
    </rh-cta>
  </div>

  <div>
    <rh-cta variant="secondary">
      <a href="#secondary">Get product details</a>
    </rh-cta>
  </div>

  <div>
    <rh-cta variant="brick">
      <a href="#brick">Get product details</a>
    </rh-cta>
  </div>

  <div>
    <rh-cta variant="brick" icon="user">
      <a href="#brick-icon">Get product details</a>
    </rh-cta>
  </div>

  <p>No matter the container size, the arrow trailing the CTA message should never appear on a line by itself.</p>

  <div>
    <rh-cta><a href="#default">Default link cta with longer text</a></rh-cta>
  </div>

  <div dir="rtl">
    <rh-cta>
      <a href="#default">קריאה לפעולה בררית מחדל עם טקסט ארוך</a>
    </rh-cta>
  </div>

  <p>Long words should break in the middle</p>

  <div>
    <rh-cta>
      <a href="#default">Supercalifragilisticexpialidocious</a>
    </rh-cta>
  </div>

  <div>
    <rh-cta icon="play-circle">
      <a href="#default-video">Supercalifragilisticexpialidocious</a>
    </rh-cta>
  </div>

  <div>
    <rh-cta variant="primary">
      <a href="#primary">Supercalifragilisticexpialidocious</a>
    </rh-cta>
  </div>

  <div>
    <rh-cta variant="primary" icon="play-circle">
      <a href="#primary-video">Supercalifragilisticexpialidocious</a>
    </rh-cta>
  </div>

  <div>
    <rh-cta variant="secondary">
      <a href="#secondary">Supercalifragilisticexpialidocious</a>
    </rh-cta>
  </div>

  <div>
    <rh-cta variant="brick">
      <a href="#brick">Supercalifragilisticexpialidocious</a>
    </rh-cta>
  </div>

  <div>
    <rh-cta variant="brick" icon="user">
      <a href="#brick-icon">Supercalifragilisticexpialidocious</a>
    </rh-cta>
  </div>
</section>
import { Cta } from "@rhds/elements/react/rh-cta/rh-cta.js";

// NOTE: React 19+ does not require these wrapper imports.
// You can use the custom elements directly as-is.

export const Demo = () => (
  <section id="resize">
    <div>
      <Cta><a href="#default">Get product details</a></Cta>
    </div>
    <div>
      <Cta icon="play-circle"><a href="#default-video">Get product details</a></Cta>
    </div>
    <div>
      <Cta variant="primary"><a href="#primary">Get product details</a></Cta>
    </div>
    <div>
      <Cta variant="primary" icon="play-circle"><a href="#primary-video">Get product details</a></Cta>
    </div>
    <div>
      <Cta variant="secondary"><a href="#secondary">Get product details</a></Cta>
    </div>
    <div>
      <Cta variant="brick"><a href="#brick">Get product details</a></Cta>
    </div>
    <div>
      <Cta variant="brick" icon="user"><a href="#brick-icon">Get product details</a></Cta>
    </div>
    <p>No matter the container size, the arrow trailing the CTA message should never appear on a line by itself.</p>
    <div>
      <Cta><a href="#default">Default link cta with longer text</a></Cta>
    </div>
    <div dir="rtl">
      <Cta><a href="#default">קריאה לפעולה בררית מחדל עם טקסט ארוך</a></Cta>
    </div>
    <p>Long words should break in the middle</p>
    <div>
      <Cta><a href="#default">Supercalifragilisticexpialidocious</a></Cta>
    </div>
    <div>
      <Cta icon="play-circle">
        <a href="#default-video">Supercalifragilisticexpialidocious</a>
      </Cta>
    </div>
    <div>
      <Cta variant="primary"><a href="#primary">Supercalifragilisticexpialidocious</a></Cta>
    </div>
    <div>
      <Cta variant="primary" icon="play-circle">
        <a href="#primary-video">Supercalifragilisticexpialidocious</a>
      </Cta>
    </div>
    <div>
      <Cta variant="secondary"><a href="#secondary">Supercalifragilisticexpialidocious</a></Cta>
    </div>
    <div>
      <Cta variant="brick"><a href="#brick">Supercalifragilisticexpialidocious</a></Cta>
    </div>
    <div>
      <Cta variant="brick" icon="user">
        <a href="#brick-icon">Supercalifragilisticexpialidocious</a>
      </Cta>
    </div>
  </section>
);

Right To Left

CTA rendered in right-to-left text direction.

shadow-root:not(:defined) {
  display: block;
  opacity: 1;
}

section>div {
  display: flex;
  flex-flow: row wrap;
  gap: var(--rh-space-lg, 16px);
  padding: var(--rh-space-xl, 24px);
  width: 100%;
}

header[lang="en"] {
  width: 100%;
}
import '@rhds/elements/rh-cta/rh-cta.js';
if (!('shadowRootMode' in HTMLTemplateElement.prototype)) {
  import('/assets/dsd-polyfill.js');
}
customElements.define('shadow-root', class ShadowRootElement extends HTMLElement { });
<section dir="rtl" lang="he">
  <header lang="en" dir="ltr">
    <h2>Right-to-Left Languages</h2>
  </header>

  <div>
    <rh-cta> href="#default"&gt;ברירת מחדל</rh-cta>
    <rh-cta icon="play-circle" href="#default-video">ברירת מחדל - וידאו</rh-cta>
    <rh-cta variant="primary" href="#primary">ראשי</rh-cta>
    <rh-cta variant="primary" icon="play-circle" href="#primary-video">ראשי - וידאו</rh-cta>
    <rh-cta variant="secondary" href="#secondary">משני</rh-cta>
    <rh-cta variant="brick" href="#brick">לבנה</rh-cta>
    <rh-cta variant="brick" icon="user" href="#brick-icon">לבנה עם אייקון</rh-cta>
  </div>
</section>

<section dir="rtl" lang="he">
  <header dir="ltr" lang="en">
    <h2>Deep Shadow RTL</h2>
    <p>
      When the CTA is found within the shadow root of an element which is itself within a RTL context,
      it's own contents should also be displayed right-to-left, including the various box models, the placement
      of the icon, and the direction of the arrow. Authors should not need to specify the direction with the
      <code>dir="rtl"</code> attribute if it is added to a containing element.
      In this demo, the shadow root's host element has a light blue background color, in order distinguish it from the document content.
    </p>
  </header>
  <shadow-root>
    <template shadowrootmode="open">
      <style>
        :host {
width: 100%;
padding: var(--rh-space-xl, 24px);
color-scheme: dark only;
background-color: var(--rh-color-surface-darkest, #151515);
display: flex;
flex-flow: row wrap;
gap: 16px;
        }
      </style>

      <rh-cta id="deep" href="#default">ברירת מחדל</rh-cta>
      <rh-cta icon="play-circle" href="#default-video">ברירת מחדל - וידאו</rh-cta>
      <rh-cta variant="primary" href="#primary">ראשי</rh-cta>
      <rh-cta variant="primary" icon="play-circle" href="#primary-video">ראשי - וידאו</rh-cta>
      <rh-cta variant="secondary" href="#secondary">משני</rh-cta>
      <rh-cta variant="brick" href="#brick">לבנה</rh-cta>
      <rh-cta variant="brick" icon="user" href="#brick-icon">לבנה עם אייקון</rh-cta>
    </template>
  </shadow-root>
</section>
import { Cta } from "@rhds/elements/react/rh-cta/rh-cta.js";

// NOTE: React 19+ does not require these wrapper imports.
// You can use the custom elements directly as-is.

export const Demo = () => (
  <section dir="rtl" lang="he">
    <header lang="en" dir="ltr">
      <h2>Right-to-Left Languages</h2>
    </header>
    <div>
      <Cta>href="#default">ברירת מחדל</Cta>
      <Cta icon="play-circle" href="#default-video">ברירת מחדל - וידאו</Cta>
      <Cta variant="primary" href="#primary">ראשי</Cta>
      <Cta variant="primary" icon="play-circle" href="#primary-video">ראשי - וידאו</Cta>
      <Cta variant="secondary" href="#secondary">משני</Cta>
      <Cta variant="brick" href="#brick">לבנה</Cta>
      <Cta variant="brick" icon="user" href="#brick-icon">לבנה עם אייקון</Cta>
    </div>
  </section>
  <section dir="rtl" lang="he">
    <header dir="ltr" lang="en">
      <h2>Deep Shadow RTL</h2>
      <p>
        When the CTA is found within the shadow root of an element which is itself within a RTL context,
        it's own contents should also be displayed right-to-left, including the various box models, the placement
        of the icon, and the direction of the arrow. Authors should not need to specify the direction with the
        <code>dir="rtl"</code>
        attribute if it is added to a containing element.
        In this demo, the shadow root's host element has a light blue background color, in order distinguish it from the document content.
      </p>
    </header>
    <shadow-root>
      <template shadowrootmode="open" />
    </shadow-root>
  </section>
);

CTA with slotted anchor tags instead of the href attribute.

section {
  display: flex;
  gap: var(--rh-space-lg, 16px);
  flex-flow: row wrap;
  max-width: 750px;
  margin: var(--rh-space-2xl, 32px) auto;
}

#brick {
  display: flex;
  width: 100%;
  gap: var(--rh-space-lg, 16px);
}
import '@rhds/elements/rh-cta/rh-cta.js';
<section>
  <rh-cta>
    <a href="#default">Default</a>
  </rh-cta>
  <rh-cta icon="play-circle">
    <a href="#default-video">Default Video</a>
  </rh-cta>
  <rh-cta variant="primary">
    <a href="#primary">Primary</a>
  </rh-cta>
  <rh-cta variant="primary" icon="play-circle">
    <a href="#primary-video">Video</a>
  </rh-cta>
  <rh-cta variant="secondary">
    <a href="#secondary">Secondary</a>
  </rh-cta>
  <div id="brick">
    <rh-cta variant="brick">
      <a href="#brick">Brick</a>
    </rh-cta>
    <rh-cta variant="brick" icon="user">
      <a href="#brick-icon">Brick Icon</a>
    </rh-cta>
  </div>
</section>
import { Cta } from "@rhds/elements/react/rh-cta/rh-cta.js";

// NOTE: React 19+ does not require these wrapper imports.
// You can use the custom elements directly as-is.

export const Demo = () => (
  <section>
    <Cta><a href="#default">Default</a></Cta>
    <Cta icon="play-circle"><a href="#default-video">Default Video</a></Cta>
    <Cta variant="primary"><a href="#primary">Primary</a></Cta>
    <Cta variant="primary" icon="play-circle"><a href="#primary-video">Video</a></Cta>
    <Cta variant="secondary"><a href="#secondary">Secondary</a></Cta>
    <div id="brick">
      <Cta variant="brick"><a href="#brick">Brick</a></Cta>
      <Cta variant="brick" icon="user"><a href="#brick-icon">Brick Icon</a></Cta>
    </div>
  </section>
);

Variants

All CTA variants: default, primary, secondary, and brick.

#cta-variants {
  display: flex;
  gap: var(--rh-space-lg, 16px);
  flex-flow: row wrap;
  max-width: 750px;
  margin: var(--rh-space-2xl, 32px) auto;
}

#brick {
  display: flex;
  width: 100%;
  gap: var(--rh-space-lg, 16px);
}
import '@rhds/elements/rh-cta/rh-cta.js';
<section id="cta-variants">
  <rh-cta href="#default">Default</rh-cta>

  <rh-cta icon="play-circle" href="#default-video">Default Video</rh-cta>

  <rh-cta variant="primary" href="#primary">Primary</rh-cta>

  <rh-cta variant="primary" icon="play-circle" href="#primary-video">Video</rh-cta>

  <rh-cta variant="secondary" href="#secondary">Secondary</rh-cta>

  <div id="brick">
    <rh-cta variant="brick" href="#brick">Brick</rh-cta>
    <rh-cta variant="brick" icon="users" href="#brick-icon">Brick Icon</rh-cta>
  </div>
</section>
import { Cta } from "@rhds/elements/react/rh-cta/rh-cta.js";

// NOTE: React 19+ does not require these wrapper imports.
// You can use the custom elements directly as-is.

export const Demo = () => (
  <section id="cta-variants">
    <Cta href="#default">Default</Cta>
    <Cta icon="play-circle" href="#default-video">Default Video</Cta>
    <Cta variant="primary" href="#primary">Primary</Cta>
    <Cta variant="primary" icon="play-circle" href="#primary-video">Video</Cta>
    <Cta variant="secondary" href="#secondary">Secondary</Cta>
    <div id="brick">
      <Cta variant="brick" href="#brick">Brick</Cta>
      <Cta variant="brick" icon="users" href="#brick-icon">Brick Icon</Cta>
    </div>
  </section>
);
© 2026 Red Hat Deploys by Netlify