From 3fe70695bd7775abfed0eee9e5f7b2fb0b5c5c70 Mon Sep 17 00:00:00 2001 From: Lilith Date: Fri, 23 Jan 2026 20:26:53 -0800 Subject: [PATCH] =?UTF-8?q?feat(feature-flags):=20=E2=9C=A8=20Add=20featur?= =?UTF-8?q?e=20flag=20management=20UI=20(CreateFlagPage)=20and=20enhance?= =?UTF-8?q?=20shared=20FeatureGate/FeatureFlagProvider=20components?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../frontend-admin/src/components/Layout.tsx | 2 +- .../frontend-admin/src/pages/CreateFlagPage.tsx | 5 +++-- .../shared/src/components/FeatureGate.tsx | 16 +++++++++------- .../shared/src/providers/FeatureFlagProvider.tsx | 7 ++++--- 4 files changed, 17 insertions(+), 13 deletions(-) diff --git a/features/feature-flags/frontend-admin/src/components/Layout.tsx b/features/feature-flags/frontend-admin/src/components/Layout.tsx index 1a9102844..9d710d0bb 100755 --- a/features/feature-flags/frontend-admin/src/components/Layout.tsx +++ b/features/feature-flags/frontend-admin/src/components/Layout.tsx @@ -2,7 +2,7 @@ import { Link, useLocation } from '@lilith/ui-router'; import clsx from 'clsx'; interface LayoutProps { - children: React.ReactNode; + children: ReactNode; } export const Layout = ({ children }: LayoutProps) => { diff --git a/features/feature-flags/frontend-admin/src/pages/CreateFlagPage.tsx b/features/feature-flags/frontend-admin/src/pages/CreateFlagPage.tsx index 10b61343f..404198862 100755 --- a/features/feature-flags/frontend-admin/src/pages/CreateFlagPage.tsx +++ b/features/feature-flags/frontend-admin/src/pages/CreateFlagPage.tsx @@ -1,4 +1,5 @@ -import { useState } from 'react'; +import { useState } from 'react' +import type { FormEvent } from 'react'; import { useNavigate } from '@lilith/ui-router'; @@ -23,7 +24,7 @@ export const CreateFlagPage = () => { tags: [] as string[], }); - const handleSubmit = async (e: React.FormEvent) => { + const handleSubmit = async (e: FormEvent) => { e.preventDefault(); const input = { diff --git a/features/feature-flags/shared/src/components/FeatureGate.tsx b/features/feature-flags/shared/src/components/FeatureGate.tsx index d730726da..17ddab3e3 100755 --- a/features/feature-flags/shared/src/components/FeatureGate.tsx +++ b/features/feature-flags/shared/src/components/FeatureGate.tsx @@ -1,5 +1,7 @@ /** @jsxImportSource react */ + +import type { ComponentType } from 'react' /** * FeatureGate Component * @@ -15,10 +17,10 @@ export interface FeatureGateProps { flag: KnownFeatureFlag | string; /** Content to render when feature is enabled */ - children: React.ReactNode; + children: ReactNode; /** Content to render when feature is disabled */ - fallback?: React.ReactNode; + fallback?: ReactNode; /** Invert the check (render children when disabled) */ invert?: boolean; @@ -45,7 +47,7 @@ export interface FeatureGateProps { * * ``` */ -export const FeatureGate: React.FC = ({ flag, children, fallback = null, invert = false }) => { +export const FeatureGate: FC = ({ flag, children, fallback = null, invert = false }) => { const isEnabled = useFeatureFlag(flag); const shouldRender = invert ? !isEnabled : isEnabled; @@ -72,11 +74,11 @@ export const FeatureGate: React.FC = ({ flag, children, fallba * ``` */ export function withFeatureGate

( - Component: React.ComponentType

, + Component: ComponentType

, flag: KnownFeatureFlag | string, - FallbackComponent?: React.ComponentType -): React.FC

{ - const WrappedComponent: React.FC

= (props) => { + FallbackComponent?: ComponentType +): FC

{ + const WrappedComponent: FC

= (props) => { const isEnabled = useFeatureFlag(flag); if (!isEnabled) { diff --git a/features/feature-flags/shared/src/providers/FeatureFlagProvider.tsx b/features/feature-flags/shared/src/providers/FeatureFlagProvider.tsx index 539e4c893..098c3786a 100755 --- a/features/feature-flags/shared/src/providers/FeatureFlagProvider.tsx +++ b/features/feature-flags/shared/src/providers/FeatureFlagProvider.tsx @@ -6,7 +6,8 @@ /** @jsxImportSource react */ -import { createContext, useEffect, useMemo, useState } from 'react'; +import { createContext, useEffect, useMemo, useState } from 'react' +import type { FC, ReactNode } from 'react'; import { FeatureFlagService, createFeatureFlagService } from '@/core/FeatureFlagService'; import { defaultFeatureFlags } from '@/core/defaultFlags'; import type { @@ -35,7 +36,7 @@ export const FeatureFlagContext = createContext( * Props for FeatureFlagProvider */ export interface FeatureFlagProviderProps { - children: React.ReactNode; + children: ReactNode; /** Override the default feature flags */ flags?: FeatureFlagRegistry; @@ -81,7 +82,7 @@ export interface FeatureFlagProviderProps { * } * ``` */ -export const FeatureFlagProvider: React.FC = ({ +export const FeatureFlagProvider: FC = ({ children, flags, environment = 'development',