@olwiba/ui 0.2.8 → 0.2.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@olwiba/ui",
3
- "version": "0.2.8",
3
+ "version": "0.2.10",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -131,6 +131,15 @@ export interface PricingSectionProps {
131
131
  cadences?: PricingCadence[];
132
132
  /** Which cadence opens selected. Defaults to the first in `cadences`. */
133
133
  defaultCadence?: string;
134
+ /**
135
+ * Called when a plan's CTA is pressed, with the cadence currently selected —
136
+ * which is the half the caller can't otherwise know, since the toggle's state
137
+ * lives in here. Without it the CTA is inert: `PricingCard` takes an
138
+ * `onSelect` and this section had never passed one.
139
+ */
140
+ onSelectPlan?: (plan: PricingPlan, cadence?: string) => void;
141
+ /** Marks one plan as busy (e.g. its checkout is being created). */
142
+ pendingPlanName?: string;
134
143
  }
135
144
 
136
145
  const defaultRenderLink: AppShellRenderLink = ({ href, children, className }) => (
@@ -153,6 +162,8 @@ export function PricingSection({
153
162
  renderPlanFooter,
154
163
  cadences,
155
164
  defaultCadence,
165
+ onSelectPlan,
166
+ pendingPlanName,
156
167
  }: PricingSectionProps) {
157
168
  const [annual, setAnnual] = React.useState(false);
158
169
  const isOneTime = mode === 'one-time';
@@ -218,7 +229,12 @@ export function PricingSection({
218
229
  >
219
230
  {entry.label}
220
231
  {saveBadges[entry.key] && (
221
- <Badge variant="secondary" className="text-xs">
232
+ // `default` (primary), not `secondary`: the toggle is
233
+ // `bg-muted` with a `bg-background` active tab, and a
234
+ // secondary badge is the same grey as both — the
235
+ // saving is the incentive, so it has to carry brand
236
+ // colour to read at all.
237
+ <Badge variant="default" className="text-xs">
222
238
  {saveBadges[entry.key]}
223
239
  </Badge>
224
240
  )}
@@ -248,7 +264,7 @@ export function PricingSection({
248
264
  >
249
265
  Annual
250
266
  {saveBadge && (
251
- <Badge variant="secondary" className="text-xs">{saveBadge}</Badge>
267
+ <Badge variant="default" className="text-xs">{saveBadge}</Badge>
252
268
  )}
253
269
  </Button>
254
270
  </>
@@ -290,12 +306,19 @@ export function PricingSection({
290
306
  period={period}
291
307
  description={plan.description}
292
308
  features={plan.features}
293
- cta={plan.cta}
309
+ cta={pendingPlanName === plan.name ? 'Redirecting…' : plan.cta}
294
310
  highlighted={plan.highlighted}
295
311
  disabled={plan.disabled}
296
- ctaDisabled={plan.ctaDisabled}
312
+ // A plan mid-checkout is disabled too, so a second click
313
+ // can't open a second session.
314
+ ctaDisabled={plan.ctaDisabled || pendingPlanName === plan.name}
297
315
  badge={badge}
298
316
  footer={renderPlanFooter?.(plan)}
317
+ onSelect={
318
+ onSelectPlan
319
+ ? () => onSelectPlan(plan, useCadences ? activeCadence : undefined)
320
+ : undefined
321
+ }
299
322
  />
300
323
  );
301
324
  })}