Campaign Detail Widget – React SDK

Render the full campaign detail experience (hero, tasks, rewards, requirements, claim flow) for a single campaign — embedded as an iframe that you can drop inside your own modal, drawer, or full-page layout.

This widget is designed for partners who maintain their own campaign listing UI but want to delegate the campaign detail / claim flow to Legion.

Installation

npm install @legionhandtech/lht-react-widgets

React 17+ is a peer dependency.

Quick Start

1import { LegionCampaignDetail } from "@legionhandtech/lht-react-widgets"; 2 3function App() { 4 return ( 5 <LegionCampaignDetail 6 baseUrl="https://your-legion-domain.com" 7 id="00000000-0000-0000-0000-000000000001" 8 theme="light" 9 /> 10 ); 11}

You can also import from the dedicated sub-path:

import { LegionCampaignDetail } from "@legionhandtech/lht-react-widgets/campaign-detail";

Recipe: Embed inside your own modal

The canonical PMCAV pattern — keep your campaign listing UI, open your own modal, embed the widget inside it:

1import { useState } from "react"; 2import { Modal } from "@mantine/core"; 3import { LegionCampaignDetail } from "@legionhandtech/lht-react-widgets"; 4 5function CampaignList({ campaigns, token }) { 6 const [activeId, setActiveId] = useState<string | null>(null); 7 8 return ( 9 <> 10 {campaigns.map((c) => ( 11 <button key={c.id} onClick={() => setActiveId(c.id)}> 12 {c.title} — View details 13 </button> 14 ))} 15 16 <Modal opened={!!activeId} onClose={() => setActiveId(null)} size="lg"> 17 {activeId && ( 18 <LegionCampaignDetail 19 id={activeId} 20 apiKey={token} 21 baseUrl="https://your-legion-domain.com" 22 onClose={() => setActiveId(null)} 23 onClaim={({ id }) => { 24 console.log("Claimed campaign", id); 25 setActiveId(null); 26 }} 27 /> 28 )} 29 </Modal> 30 </> 31 ); 32}

Props Reference

Core Props

PropTypeDefaultDescription
idstringrequiredCampaign UUID
baseUrlstringrequiredBase URL of your Legion deployment
apiKeystringBearer token / API key for authenticated mode
theme"light" | "dark""light"Theme preset
widthstring"100%"Container width (CSS value)
heightstring | number"auto"Container height (CSS value or px number)
classNamestringCSS class applied to the outer container
styleReact.CSSPropertiesInline styles merged into the container
onLoad(detail) => voidCalled when the widget iframe finishes loading
onError(message: string) => voidCalled if the widget iframe fails to load
onClose() => voidCalled when the embedded view requests dismissal (use this to close your modal)
onClaim({ id }) => voidCalled after a successful claim / begin event

Theming Props

All theming props are optional and forwarded to the iframe as kebab-case query parameters. See the TypeScript CampaignDetailThemingProps interface for the complete list.

PropQuery ParamExample
detailBackgroundColordetail-background-color"#ffffff"
detailTextColordetail-text-color"#1a1b1e"
detailPrimaryColordetail-primary-color"#228be6"
detailBorderRadiusdetail-border-radius"12px"
detailShadowdetail-shadow"0 2px 8px rgba(0,0,0,0.08)"
detailTitleSizedetail-title-size"1.5rem"
detailFontFamilydetail-font-family"Inter, system-ui, sans-serif"

Imperative Ref API

1import { useRef } from "react"; 2import { 3 LegionCampaignDetail, 4 LegionCampaignDetailHandle, 5} from "@legionhandtech/lht-react-widgets"; 6 7function App() { 8 const widgetRef = useRef<LegionCampaignDetailHandle>(null); 9 10 return ( 11 <> 12 <button onClick={() => widgetRef.current?.refresh()}>Reload</button> 13 <LegionCampaignDetail 14 ref={widgetRef} 15 baseUrl="https://your-legion-domain.com" 16 id="…uuid…" 17 /> 18 </> 19 ); 20}
MethodDescription
refresh()Reloads the widget iframe (e.g. after the host context changes)

Web Component (from NPM)

import "@legionhandtech/lht-react-widgets/campaign-detail-web-component";
1<legion-campaign-detail 2 id="00000000-0000-0000-0000-000000000001" 3 base-url="https://your-legion-domain.com" 4 auth-token="" 5 theme="light" 6> 7</legion-campaign-detail>

The element dispatches close and claim CustomEvents that mirror the React component's onClose / onClaim callbacks.

TypeScript

1import type { 2 CampaignDetailWidgetProps, 3 CampaignDetailThemingProps, 4 LegionCampaignDetailHandle, 5} from "@legionhandtech/lht-react-widgets";
Documentation | Legion Hand Technologies