Install the Opportunities Widget as an NPM package for first-class React (and TypeScript) support.
npm install @legionhandtech/lht-react-widgetsReact 17+ is a peer dependency. If your project already has React installed you're good to go.
1import { LegionOpportunities } from '@legionhandtech/lht-react-widgets';
2
3function App() {
4 return (
5 <LegionOpportunities
6 baseUrl="https://your-legion-domain.com"
7 count={5}
8 layout="horizontal"
9 theme="light"
10 tags="retail,food"
11 />
12 );
13}| Prop | Type | Default | Description |
|---|---|---|---|
baseUrl | string | required | Base URL of your Legion deployment |
count | number | 5 | Number of opportunities to display (1–20) |
layout | "horizontal" | "vertical" | "horizontal" | Layout direction |
tags | string | — | Comma-separated list of tags to filter by |
theme | "light" | "dark" | "minimal" | "bold" | "corporate" | "vibrant" | "light" | Preset theme |
height | string | "auto" | Widget height — "auto", "100%", or a CSS value like "400px" |
apiKey | string | — | Optional API key for authenticated content |
className | string | — | CSS class applied to the outer container |
style | React.CSSProperties | — | Inline styles merged into the container |
onLoad | (detail) => void | — | Called when the widget iframe finishes loading |
onError | (message: string) => void | — | Called if the widget iframe fails to load |
All theming props are optional. When omitted the widget uses its built-in defaults.
| Prop | CSS Variable | Example |
|---|---|---|
oppPanelStart | --opp-panel-start | "0.6" |
oppPanelMid | --opp-panel-mid | "0.45" |
oppPanelEnd | --opp-panel-end | "0.25" |
oppPanelColor | --opp-panel-color | "0, 0, 0" (RGB) |
oppPanelShadow | --opp-panel-shadow | "0 8px 28px rgba(0,0,0,.45)" |
oppPanelBlur | --opp-panel-blur | "2px" |
oppPanelRadius | --opp-panel-radius | "10px" |
oppPanelPadding | --opp-panel-padding | "12px" |
oppPanelMaxWidth | --opp-panel-max-width | "600px" |
| Prop | CSS Variable | Example |
|---|---|---|
oppCardRadius | --opp-card-radius | "12px" |
oppCardShadow | --opp-card-shadow | "0 4px 12px rgba(0,0,0,.2)" |
oppCardBorder | --opp-card-border | "1px solid #333" |
oppCardMinHeight | --opp-card-min-height | "240px" |
| Prop | CSS Variable | Example |
|---|---|---|
oppTitleSize | --opp-title-size | "clamp(18px, 2.6vmin, 36px)" |
oppTitleColor | --opp-title-color | "#ffffff" |
oppTitleWeight | --opp-title-weight | "700" |
oppTitleShadow | --opp-title-shadow | "0 1px 3px rgba(0,0,0,.3)" |
oppTitleFontFamily | --opp-title-font-family | "Inter, sans-serif" |
oppTitleLetterSpacing | --opp-title-letter-spacing | "-0.02em" |
| Prop | CSS Variable | Example |
|---|---|---|
oppDescriptionSize | --opp-description-size | "14px" |
oppDescriptionColor | --opp-description-color | "#ccc" |
oppDescriptionShadow | --opp-description-shadow | "none" |
oppDescriptionFontFamily | --opp-description-font-family | "Inter, sans-serif" |
oppDescriptionLineHeight | --opp-description-line-height | "1.5" |
| Prop | CSS Variable | Example |
|---|---|---|
oppExpiresSize | --opp-expires-size | "12px" |
oppExpiresColor | --opp-expires-color | "#aaa" |
oppExpiresShadow | --opp-expires-shadow | "none" |
| Prop | CSS Variable | Example |
|---|---|---|
oppButtonBg | --opp-button-bg | "#3b82f6" |
oppButtonColor | --opp-button-color | "#fff" |
oppButtonRadius | --opp-button-radius | "8px" |
oppButtonShadow | --opp-button-shadow | "0 2px 6px rgba(0,0,0,.2)" |
| Prop | CSS Variable | Example |
|---|---|---|
oppTransitionDuration | --opp-transition-duration | "0.3s" |
oppAnimationScale | --opp-animation-scale | "1.02" |
Use the theme prop for quick preset styling instead of individual theming props:
| Theme | Description |
|---|---|
light | Default light theme |
dark | Higher contrast dark overlay |
minimal | Subtle overlay, no shadows |
bold | High contrast, larger typography |
corporate | Professional, minimal animations |
vibrant | Colored overlay with glow effects |
1<LegionOpportunities
2 baseUrl="https://your-legion-domain.com"
3 theme="dark"
4 count={5}
5/>Use a React ref to call methods on the widget:
1import { useRef } from 'react';
2import { LegionOpportunities, LegionOpportunitiesHandle } from '@legionhandtech/lht-react-widgets';
3
4function App() {
5 const widgetRef = useRef<LegionOpportunitiesHandle>(null);
6
7 return (
8 <>
9 <button onClick={() => widgetRef.current?.refresh()}>
10 Refresh Widget
11 </button>
12 <LegionOpportunities
13 ref={widgetRef}
14 baseUrl="https://your-legion-domain.com"
15 />
16 </>
17 );
18}| Method | Description |
|---|---|
refresh() | Reloads the widget iframe |
If you prefer the <legion-opportunities> custom element but want to install via NPM instead of a script tag:
import '@legionhandtech/lht-react-widgets/web-component';Then use it in your HTML or JSX:
1<legion-opportunities
2 base-url="https://your-legion-domain.com"
3 count="5"
4 layout="horizontal"
5 theme="light">
6</legion-opportunities>The package ships with full TypeScript declarations. All prop interfaces are exported:
1import type {
2 OpportunitiesWidgetProps,
3 OpportunitiesThemingProps,
4 LegionOpportunitiesHandle,
5} from '@legionhandtech/lht-react-widgets';Fired when the widget iframe has loaded. Receives a detail object:
1<LegionOpportunities
2 baseUrl="https://your-legion-domain.com"
3 onLoad={(detail) => {
4 console.log(detail.widget); // "opportunities"
5 console.log(detail.count); // number
6 console.log(detail.layout); // "horizontal" | "vertical"
7 console.log(detail.tags); // string
8 }}
9/>Fired if the widget iframe fails to load:
1<LegionOpportunities
2 baseUrl="https://your-legion-domain.com"
3 onError={(message) => console.error(message)}
4/>