Install
pnpm add buy-me-a-coffee-cta
Quick start
import { createCoffeeCta } from "buy-me-a-coffee-cta";
import "buy-me-a-coffee-cta/style.css";
createCoffeeCta({
username: "yourname",
label: "Buy me a coffee",
emoji: "☕",
});
Use the playground to tune options visually and copy a ready-to-paste snippet for Vanilla JS, React, Vue, Solid, Angular, or Svelte.
CDN (no bundler)
<link rel="stylesheet" href="https://unpkg.com/buy-me-a-coffee-cta/dist/style.css" />
<script type="module">
import { createCoffeeCta } from "https://unpkg.com/buy-me-a-coffee-cta/dist/index.js";
createCoffeeCta({ username: "yourname" });
</script>
Configuration
| Option | Type | Default | Description |
|---|---|---|---|
username |
string |
— | BMC username (used if url is omitted) |
url |
string |
— | Full BMC profile URL |
label |
string |
"Buy me a coffee" |
Tooltip text |
emoji |
string |
"" |
Optional emoji prefix in tooltip |
size |
number |
40 |
Cup size in px (desktop) |
position |
preset or offsets | "bottom-right" |
Corner preset or custom offsets (fixed mode only) |
anchor |
Element | string | null |
null |
In-flow placement inside an element; ignores position |
tooltipPosition |
"auto" | … |
"auto" |
Tooltip side relative to the cup — same on desktop and mobile |
theme.* |
string |
BMC defaults | yellow, ink, chipBg, chipFg, … |
darkTheme.* |
string |
dark defaults | Overrides when dark mode is active |
darkMode |
"auto" | "class" | … |
"auto" |
auto = CSS; media / class = JS — see Dark theme |
scroll.* |
object | see README | target, reverse, fillDelay, … |
See the full option list on GitHub for every property and default.
API
const cta = createCoffeeCta({ username: "yourname" });
cta.updateConfig({ label: "Support my work" });
cta.destroy();
cta.element; // HTMLAnchorElement
Only one CTA per page is supported. Creating a second instance destroys the previous one.
The CTA stays hidden until scroll animation begins. Short pages that fit in the viewport stay visible when the cup would already be full.
Tooltip
Use tooltipPosition to pick a side: left, right,
top, bottom, or auto (default).
- Fixed mode —
autoplaces the tooltip on the left (or right when the CTA is left-aligned). - Flow mode (
anchorset) —autoplaces the tooltip on the right.
The tooltip uses the same side on desktop and mobile. Desktop shows it on hover;
mobile shows it on tap, then auto-hides after scroll.touchHideMs (default 2.2s).
Placement
Fixed to the viewport (default):
createCoffeeCta({ username: "yourname" });
Normal document flow inside an element:
createCoffeeCta({
username: "yourname",
anchor: "main",
});
When anchor is set, the host element controls layout and position is ignored.
Scroll target & reverse
Track a nested scroll container instead of the window:
createCoffeeCta({
username: "yourname",
scroll: { target: ".article-body" },
});
Reverse mode — full cup at the top, empties as you scroll down:
createCoffeeCta({
username: "yourname",
scroll: { reverse: true },
});
Dark theme
| Mode | Behavior |
|---|---|
"auto" |
Default. Light palette from JS; dark palette via CSS prefers-color-scheme using darkTheme. |
"media" |
JS follows system color scheme; updates when preference changes. |
"class" |
JS follows <html data-theme="dark"> or <html class="dark">. |
"off" |
Light theme always. |
createCoffeeCta({
username: "yourname",
darkMode: "auto",
darkTheme: {
ink: "#e8e8e8",
chipFg: "#ffffff",
},
});
For sites that toggle dark mode with a class or data attribute on
<html>, use darkMode: "class".
Utility exports
import {
computeScrollState,
getScrollMetrics,
isCtaVisible,
normalizeBmcUrl,
resolveScrollTarget,
resolveUrl,
} from "buy-me-a-coffee-cta";
Helpers for custom scroll integrations, URL normalization, or tests.
Size
Approximate gzipped size: ~7.5 KB JS + ~2.1 KB CSS. The JS bundle includes the inline SVG. Zero runtime dependencies.
Framework integration
Mount after your component loads, call destroy() on unmount, and use
updateConfig() when props change. Do not reimplement scroll logic in framework state.
Use the playground to tune options visually and copy a snippet with your custom configuration.
From the repo root, run a framework example locally (packs and installs the library like a consumer would):
pnpm example:react:setup
pnpm example:react:dev
Replace react with vue, solid, angular,
svelte, or vanilla for other frameworks.