# email-button _(no submodules)_ ## Purpose `EmailButton` is the canonical call-to-action surface in an email body — a table-wrapped `` 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 `` containing a centred `
` containing the styled ``. 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 `` and the `` 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 ```ts 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: ```ts 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.