# 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.
|