diff --git a/packages/react/README.md b/packages/react/README.md index 7469794..19ab80a 100644 --- a/packages/react/README.md +++ b/packages/react/README.md @@ -295,6 +295,66 @@ function FeatureList() { } ``` +### SupaFeature Component + +A declarative component for rendering different UI based on boolean feature flag values. + +```tsx +} + variations={{ + true: , + false: , + }} +/> +``` + +**Props:** + +| Prop | Type | Required | Description | +| ------------- | --------------------------------------- | -------- | ---------------------------------------------------------------- | +| `feature` | `string` | Yes | The feature flag key to evaluate | +| `variations` | `{ true: ReactNode, false: ReactNode }` | Yes | Components to render for true/false values | +| `loading` | `ReactNode` | No | Component to render while loading | +| `fallback` | `ReactNode` | No | Component to render when feature value is neither true nor false | +| `context` | `Record` | No | Context override for this feature | +| `shouldFetch` | `boolean` | No | Whether to fetch the feature (default: true) | + +**Examples:** + +```tsx +// Simple boolean feature flag +function Header() { + return ( + } + variations={{ + true: , + false: , + }} + /> + ) +} + +// With context +function UserDashboard() { + const { user } = useAuth() + + return ( + , + false: , + }} + /> + ) +} +``` + ### useFeatureContext Hook Access and update the feature context within components. diff --git a/packages/react/src/components.tsx b/packages/react/src/components.tsx index 43382ba..de953f7 100644 --- a/packages/react/src/components.tsx +++ b/packages/react/src/components.tsx @@ -22,14 +22,17 @@ export interface SupaFeatureProps { shouldFetch?: boolean /** - * Variations object mapping feature values/keys to JSX elements + * Variations object mapping "true" or "false" to JSX elements */ - variations: Record + variations: { + true: ReactNode + false: ReactNode + } /** - * Key in variations object to use for loading state + * Component to render during loading state */ - loading?: string + loading?: ReactNode } /** @@ -40,10 +43,10 @@ export interface SupaFeatureProps { * ```tsx * } * variations={{ - * "true": , - * "false": , - * loading: + * true: , + * false: * }} * /> * ``` @@ -61,26 +64,20 @@ export function SupaFeature({ }) // Show loading state if provided and currently loading - if (isLoading && loading && variations[loading]) { - return <>{variations[loading]} - } - - // Don't render anything if still loading and no loader provided if (isLoading) { - return null + return loading ? <>{loading} : null } - // Don't render anything if no feature value (client config should provide defaults) - if (!hasValue(featureValue)) { - return null - } - - // Convert feature value to string for object key lookup + // Convert feature value to boolean string for lookup const valueKey = String(featureValue) - // Find matching variation by exact key match - if (variations[valueKey]) { - return <>{variations[valueKey]} + // Match "true" or "false" variations + if (variations.true && valueKey === 'true') { + return <>{variations.true} + } + + if (variations.false && (valueKey === 'false' || !hasValue(featureValue))) { + return <>{variations.false} } // Don't render anything if no variation matches