Files
skills/docs/communication/emails/email-templates/src/components/email-button/email-button.md
2026-05-29 08:20:56 +01:00

3.8 KiB

email-button

(no submodules)

Purpose

EmailButton is the canonical call-to-action surface in an email body — a table-wrapped <a> with variant-driven theme colours and three preset sizes. The table wrapper is non-optional: Outlook on Windows uses a Word-derived rendering engine that historically ignores padding on inline anchors, so the only reliable way to ship a visually-correct CTA into Outlook desktop is a <table> containing a centred <td> containing the styled <a>.

The component centralises the variant + size recipe so callers don't duplicate it at every CTA site, and validates variant/size against the published enums at call time — typos turn into a typed EmailTemplatesError(INVALID_OPTIONS) instead of a silently-malformed button.

Features

  • Three variants — primary, secondary, outline — each pulling colours from the active theme.
  • Three sizes — sm, md, lg — each driving distinct padding + font-size.
  • fullWidth toggle emits width: 100% on both the wrapping <table> and the <a> so the CTA spans its container.
  • align prop emitted as the table's align attribute.
  • Validation: unknown variant or size raises EmailTemplatesError(INVALID_OPTIONS) and bumps an OTel counter tagged reason="invalid_button_variant" or "invalid_button_size".
  • Safe link defaults (target="_blank", rel="noopener noreferrer").

Usage: Basic

import { EmailButton } from "@suaveplan/email-templates/components";
import { renderVNode } from "@suaveplan/email-templates/vnode";

renderVNode(EmailButton({
  href: "https://app.example.test/get-started",
  children: "Get Started",
}));

Usage: Advanced

A full-width secondary CTA with custom letter-spacing:

import { EmailButton } from "@suaveplan/email-templates/components";
import { renderVNode } from "@suaveplan/email-templates/vnode";

renderVNode(EmailButton({
  href: "https://app.example.test/upgrade",
  children: "Upgrade Now",
  variant: "secondary",
  size: "lg",
  fullWidth: true,
  style: { "letter-spacing": "0.5px" },
}));

API Reference

Prop Type Description
href string CTA target URL.
children string Button label (string only — keeps the table cell-tight).
theme EmailTheme? Theme override.
variant "primary" | "secondary" | "outline" Defaults to primary.
size "sm" | "md" | "lg" Defaults to md.
fullWidth boolean? Defaults to false.
align "left" | "center" | "right" Outer table align; defaults to "center".
style StyleObject? Additional anchor-level inline styles.

Implementation Notes

The variant style returns three keys (background-color, color, border) plus the size returns two (padding, font-size); a switch on the variant tag emits the right triple. Validation uses a Set lookup — branch coverage is satisfied by one true-case test plus one false-case test per validator.

The box-sizing: border-box declaration on the anchor ensures the 2 px border doesn't push the button over its intended outside width when fullWidth: true. Without that declaration Outlook would render the button slightly wider than its container in the outline variant where the border weight matters most.