Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x | "use client";
/**
* A/B Test Component
*
* Renders different content based on A/B test variant assignment.
*/
import { type ReactNode } from "react";
import { useABTest } from "@/hooks/useABTest";
/**
* Props for ABTest component
*/
interface ABTestProps {
/** The name of the experiment */
experimentName: string;
/** Variant components to render */
variants: {
[key: string]: ReactNode;
};
/** Fallback component while loading */
fallback?: ReactNode;
/** Component to show when experiment not running or user not in test */
defaultVariant?: string;
}
/**
* A/B Test Component
*
* Renders different content based on the visitor's assigned variant.
*
* @example
* ```tsx
* <ABTest
* experimentName="checkout-button-color"
* variants={{
* control: <Button variant="primary">Checkout</Button>,
* variant_a: <Button variant="success">Complete Order</Button>,
* variant_b: <Button variant="warning">Buy Now</Button>,
* }}
* fallback={<Skeleton className="h-10 w-24" />}
* />
* ```
*/
export function ABTest({
experimentName,
variants,
fallback,
defaultVariant = "control"}: ABTestProps) {
const { variant, isLoading } = useABTest(experimentName);
// Show fallback while loading
if (isLoading) {
return <>{fallback || variants[defaultVariant] || null}</>;
}
// If no variant assigned (experiment not running or user excluded),
// show default variant
if (!variant) {
return <>{variants[defaultVariant] || fallback || null}</>;
}
// Show assigned variant or fall back to default
return <>{variants[variant] || variants[defaultVariant] || fallback || null}</>;
}
/**
* Hook version of ABTest for more control
*
* @example
* ```tsx
* const { renderVariant, variant, isLoading, trackConversion } = useABTestRender("checkout-cta");
*
* return (
* <Button onClick={() => { trackConversion(); handleCheckout(); }}>
* {renderVariant({
* control: "Checkout",
* variant_a: "Complete Order",
* variant_b: "Buy Now",
* })}
* </Button>
* );
* ```
*/
export function useABTestRender(experimentName: string) {
const { variant, isLoading, trackConversion } = useABTest(experimentName);
const renderVariant = <T,>(
variants: Record<string, T>,
defaultVariant: string = "control"
): T | undefined => {
if (isLoading || !variant) {
return variants[defaultVariant];
}
return variants[variant] || variants[defaultVariant];
};
return {
renderVariant,
variant,
isLoading,
trackConversion};
}
|