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