All components · Category: Banners and notices
Promo countdown
An offer strip that counts down to a real date you pass.
Give it the end as a date, time and zone and it counts down with digits that flip. It is honest by design: the end is printed in words, nothing ever restarts the clock, and when the date passes the strip says the offer ended.
01
Try it
Props
Generated from the component's manifest and the values above.
index.html
<promo-countdown
ends="2035-12-31T15:25:40Z"
href="https://example.com/sale"
locale="en"
></promo-countdown>
<script>
const element = document.querySelector("promo-countdown");
element.addEventListener("promo-countdown:ended", (event) => {
console.log(event.detail);
});
</script>
- Add the site's Taggor script once; the component appears when it loads.
taggor-component.js
const element = document.createElement("promo-countdown");
element.setAttribute("ends", "2035-12-31T15:25:40Z");
element.setAttribute("href", "https://example.com/sale");
element.setAttribute("locale", "en");
element.addEventListener("promo-countdown:ended", (event) => {
console.log(event.detail);
});
document.body.append(element);
- Add the site's Taggor script once; the component appears when it loads.
PromoCountdown.tsx
import { useEffect, useRef } from "react";
export function PromoCountdown() {
const ref = useRef<HTMLElement>(null);
useEffect(() => {
const element = ref.current;
if (!element) return;
const onEnded = (event: Event) => {
console.log((event as CustomEvent).detail);
};
element.addEventListener("promo-countdown:ended", onEnded);
return () => {
element.removeEventListener("promo-countdown:ended", onEnded);
};
}, []);
return <promo-countdown
ref={ref}
ends="2035-12-31T15:25:40Z"
href="https://example.com/sale"
locale="en"
/>;
}
- Add the site's Taggor script once; the component appears when it loads.
- React 18 sends every prop of a custom element as a text attribute.
- The event is heard with addEventListener, inside an effect.
PromoCountdown.tsx
import { useEffect, useRef } from "react";
export function PromoCountdown() {
const ref = useRef<HTMLElement>(null);
useEffect(() => {
const element = ref.current;
if (!element) return;
const onEnded = (event: Event) => {
console.log((event as CustomEvent).detail);
};
element.addEventListener("promo-countdown:ended", onEnded);
return () => {
element.removeEventListener("promo-countdown:ended", onEnded);
};
}, []);
return <promo-countdown
ref={ref}
ends="2035-12-31T15:25:40Z"
href="https://example.com/sale"
locale="en"
/>;
}
- Add the site's Taggor script once; the component appears when it loads.
- React 19 sets a property when the element already has it, an attribute otherwise.
- The event is heard with addEventListener, inside an effect.
src/PromoCountdown.vue
<script setup lang="ts">
function onEnded(event: Event) {
console.log((event as CustomEvent).detail);
}
</script>
<template>
<promo-countdown
ends="2035-12-31T15:25:40Z"
href="https://example.com/sale"
locale="en"
@promo-countdown:ended="onEnded"
/>
</template>
vite.config.ts
import vue from "@vitejs/plugin-vue";
import { defineConfig } from "vite";
export default defineConfig({
plugins: [
vue({
template: {
compilerOptions: {
isCustomElement: (tag) => tag === "promo-countdown",
},
},
}),
],
});
- Add the site's Taggor script once; the component appears when it loads.
- vite.config.ts tells Vue that this tag is not a Vue component.
src/app/promo-countdown.component.ts
import { afterNextRender, Component, CUSTOM_ELEMENTS_SCHEMA, DestroyRef, ElementRef, inject } from "@angular/core";
@Component({
selector: "app-promo-countdown",
schemas: [CUSTOM_ELEMENTS_SCHEMA],
template: `
<promo-countdown
ends="2035-12-31T15:25:40Z"
href="https://example.com/sale"
locale="en"
></promo-countdown>
`,
})
export class PromoCountdownComponent {
constructor() {
const host = inject<ElementRef<HTMLElement>>(ElementRef);
const element = () => host.nativeElement.querySelector("promo-countdown");
const onEnded = (event: Event) => {
console.log((event as CustomEvent).detail);
};
afterNextRender(() => element()?.addEventListener("promo-countdown:ended", onEnded));
inject(DestroyRef).onDestroy(() => element()?.removeEventListener("promo-countdown:ended", onEnded));
}
}
- Add the site's Taggor script once; the component appears when it loads.
- The component declares CUSTOM_ELEMENTS_SCHEMA.
- The event is heard with addEventListener, inside an effect.
src/TaggorComponent.svelte
<script>
function onEnded(event) {
console.log(event.detail);
}
</script>
<promo-countdown
ends="2035-12-31T15:25:40Z"
href="https://example.com/sale"
locale="en"
onpromo-countdown:ended={onEnded}
></promo-countdown>
- Add the site's Taggor script once; the component appears when it loads.
How an agent gets a component like this onto a site:
taggor checktaggor publishThe CSS variables the component exposes, set the way a customer's page would.
styles.css
promo-countdown {
--pc-radius: 20px;
}02
Props
| Prop | Type | Default | What it does |
|---|---|---|---|
| ends | string | none | When the promotion ends: an ISO date-time with a zone, like 2030-05-01T23:59:00-03:00. |
| headline | string | none | Replaces the promotion headline. |
| cta | string | none | Replaces the button text. |
| href | url | none | Where the button goes; without it there is no button. |
| hideSample | boolean | false | Hides the Sample content mark. |
| locale | pt-BR | en | en | – |
Prop names and descriptions are the component's own, in English, as its author wrote them.
03
Events
| Event | When it fires |
|---|---|
| ended | The end date passed while the page was open. |
04
Build one with your agent
Paste this into your agent. It asks you before it signs in, pays or goes further than checking and publishing.
Build me a Taggor component like "Promo countdown" (promo-countdown): An offer strip that counts down to a real date you pass.
Fetch https://taggor.dev/agent-setup/prompt.md and follow its instructions to set me up for Taggor. Ask me before you sign in, create an account, accept terms, pay for anything or type a secret.
Check it with `taggor check` and publish it with `taggor publish`, and stop there.
Do not promote it to production, attach it to a site, roll back anything or use --yes, --force or --force-drop-invalid unless I ask for exactly that in this conversation.
05
Related components
- Announcement bar<announcement-bar>
- Launch countdown<launch-countdown>
- Booking picker<booking-picker>