From b7298c4585e020bc4924e1f05281f79c72b2a89f Mon Sep 17 00:00:00 2001 From: Abhinav Deval Date: Mon, 29 Jun 2026 22:41:09 +0530 Subject: [PATCH 1/2] feat: implement SubscriptionTable scaffolding and register global module exports Signed-off-by: Abhinav Deval --- .../SubscriptionTable/SubscriptionTable.tsx | 138 ++++++++++++++++++ src/custom/SubscriptionTable/index.ts | 1 + src/custom/SubscriptionTable/style.tsx | 29 ++++ src/custom/index.ts | 1 + src/custom/index.tsx | 3 + 5 files changed, 172 insertions(+) create mode 100644 src/custom/SubscriptionTable/SubscriptionTable.tsx create mode 100644 src/custom/SubscriptionTable/index.ts create mode 100644 src/custom/SubscriptionTable/style.tsx diff --git a/src/custom/SubscriptionTable/SubscriptionTable.tsx b/src/custom/SubscriptionTable/SubscriptionTable.tsx new file mode 100644 index 000000000..ec5ea3469 --- /dev/null +++ b/src/custom/SubscriptionTable/SubscriptionTable.tsx @@ -0,0 +1,138 @@ +import CheckIcon from '@mui/icons-material/Check'; +import CloseIcon from '@mui/icons-material/Close'; +import { + Box, + Button, + Paper, + Table, + TableBody, + TableCell, + TableContainer, + TableHead, + TableRow, + Typography +} from '@mui/material'; +import React from 'react'; + +// Strict TypeScript interfaces to handle dynamic table data +export interface PlanFeature { + featureName: string; + freePlan: boolean | string; + teamPlan: boolean | string; + enterprisePlan: boolean | string; +} + +export interface SubscriptionTableProps { + title?: string; + features: PlanFeature[]; + onPlanSelect?: (planType: 'free' | 'team' | 'enterprise') => void; +} + +export const SubscriptionTable: React.FC = ({ + title = 'Subscription Plans Comparison', + features, + onPlanSelect +}) => { + // Helper function to render true/false values as Crisp Icons or Text + const renderValue = (value: boolean | string) => { + if (typeof value === 'boolean') { + return value ? ( + + ) : ( + + ); + } + return ( + + {value} + + ); + }; + + return ( + + {title && ( + + {title} + + )} + + + + + + Features + + Free Plan + + + + + + Team Plan + + + + + + Enterprise Plan + + + + + + + + + {features.map((row, index) => ( + + + {row.featureName} + + {renderValue(row.freePlan)} + {renderValue(row.teamPlan)} + {renderValue(row.enterprisePlan)} + + ))} + +
+
+
+ ); +}; + +SubscriptionTable.displayName = 'SubscriptionTable'; diff --git a/src/custom/SubscriptionTable/index.ts b/src/custom/SubscriptionTable/index.ts new file mode 100644 index 000000000..121092eba --- /dev/null +++ b/src/custom/SubscriptionTable/index.ts @@ -0,0 +1 @@ +export * from './SubscriptionTable'; diff --git a/src/custom/SubscriptionTable/style.tsx b/src/custom/SubscriptionTable/style.tsx new file mode 100644 index 000000000..c487461a6 --- /dev/null +++ b/src/custom/SubscriptionTable/style.tsx @@ -0,0 +1,29 @@ +import { Paper, TableCell, TableRow } from '@mui/material'; +import { styled } from '@mui/material/styles'; + +// Custom Styled Container aligned with Sistent Theme +export const StyledTableContainer = styled(Paper)(({ theme }) => ({ + borderRadius: theme.shape.borderRadius * 2, + overflow: 'hidden', + boxShadow: theme.shadows[2], + border: `1px solid ${theme.palette.divider}` +})); + +// Custom Styled Header Row +export const StyledHeaderRow = styled(TableRow)(({ theme }) => ({ + backgroundColor: theme.palette.mode === 'light' ? '#f9fafb' : '#1e1e1e' +})); + +// Custom Styled Table Cell for Typography token enforcement +export const StyledTableCell = styled(TableCell)(({ theme }) => ({ + fontFamily: 'Open Sans, sans-serif', + borderColor: theme.palette.divider, + fontWeight: 500 +})); + +// Feature Name Column styling (High Emphasis) +export const FeatureHeaderCell = styled(StyledTableCell)(() => ({ + fontFamily: 'Qanelas Soft, sans-serif', + fontWeight: 700, + color: 'text.primary' +})); diff --git a/src/custom/index.ts b/src/custom/index.ts index 3f35c351e..1900311ea 100644 --- a/src/custom/index.ts +++ b/src/custom/index.ts @@ -5,3 +5,4 @@ export * from './Markdown'; export * from './Modal'; export * from './RJSFFormWrapper'; export * from './StyledAccordion'; +export * from './SubscriptionTable'; diff --git a/src/custom/index.tsx b/src/custom/index.tsx index 51a104ce5..0b5f97969 100644 --- a/src/custom/index.tsx +++ b/src/custom/index.tsx @@ -44,6 +44,7 @@ import ResponsiveDataTable, { } from './ResponsiveDataTable'; import SearchBar, { SearchBarProps } from './SearchBar'; import { StyledCardProps } from './StyledCard/StyledCard'; +import { SubscriptionTable } from './SubscriptionTable'; import { getCopyDeepLinkAction, TableAction } from './TableActions'; import { TeamTable, TeamTableConfiguration } from './TeamTable'; import { TooltipIcon } from './TooltipIconButton'; @@ -111,6 +112,7 @@ export { StyledDialogActions, StyledDialogContent, StyledDialogTitle, + SubscriptionTable, TeamTable, TeamTableConfiguration, TooltipIcon, @@ -173,5 +175,6 @@ export * from './permissions'; export * from './ResourceDetailFormatters'; export * from './RJSFFormWrapper'; export * from './ShareModal'; +export * from './SubscriptionTable'; export * from './UserSearchField'; export * from './Workspaces'; From 812e1ac8e1c4dc6f632dd70bed3a96317303ffbd Mon Sep 17 00:00:00 2001 From: Abhinav Deval Date: Mon, 29 Jun 2026 23:15:06 +0530 Subject: [PATCH 2/2] feat: implement SubscriptionTable scaffolding and register global module exports Signed-off-by: Abhinav Deval --- .../SubscriptionTable/SubscriptionTable.tsx | 92 +++++++++---------- 1 file changed, 43 insertions(+), 49 deletions(-) diff --git a/src/custom/SubscriptionTable/SubscriptionTable.tsx b/src/custom/SubscriptionTable/SubscriptionTable.tsx index ec5ea3469..441e7f73d 100644 --- a/src/custom/SubscriptionTable/SubscriptionTable.tsx +++ b/src/custom/SubscriptionTable/SubscriptionTable.tsx @@ -1,37 +1,33 @@ import CheckIcon from '@mui/icons-material/Check'; import CloseIcon from '@mui/icons-material/Close'; -import { - Box, - Button, - Paper, - Table, - TableBody, - TableCell, - TableContainer, - TableHead, - TableRow, - Typography -} from '@mui/material'; +import { Box, Button, Table, TableBody, TableHead, Typography } from '@mui/material'; import React from 'react'; // Strict TypeScript interfaces to handle dynamic table data -export interface PlanFeature { - featureName: string; - freePlan: boolean | string; - teamPlan: boolean | string; - enterprisePlan: boolean | string; -} - export interface SubscriptionTableProps { title?: string; - features: PlanFeature[]; + features?: PlanFeature[]; onPlanSelect?: (planType: 'free' | 'team' | 'enterprise') => void; + featuresLabel?: string; + freePlanLabel?: string; + freePlanButtonLabel?: string; + teamPlanLabel?: string; + teamPlanButtonLabel?: string; + enterprisePlanLabel?: string; + enterprisePlanButtonLabel?: string; } export const SubscriptionTable: React.FC = ({ title = 'Subscription Plans Comparison', - features, - onPlanSelect + features = [], + onPlanSelect, + featuresLabel = 'Features', + freePlanLabel = 'Free Plan', + freePlanButtonLabel = 'Get Started', + teamPlanLabel = 'Team Plan', + teamPlanButtonLabel = 'Upgrade', + enterprisePlanLabel = 'Enterprise Plan', + enterprisePlanButtonLabel = 'Contact Us' }) => { // Helper function to render true/false values as Crisp Icons or Text const renderValue = (value: boolean | string) => { @@ -65,21 +61,23 @@ export const SubscriptionTable: React.FC = ({ )} - + - - - Features - - Free Plan + + + + {featuresLabel} + + + {freePlanLabel} - - - Team Plan + + + {teamPlanLabel} - - - Enterprise Plan + + + {enterprisePlanLabel} - - + + @@ -116,21 +114,17 @@ export const SubscriptionTable: React.FC = ({ '&:hover': { backgroundColor: 'action.hover' } }} > - + {row.featureName} - - {renderValue(row.freePlan)} - {renderValue(row.teamPlan)} - {renderValue(row.enterprisePlan)} + + {renderValue(row.freePlan)} + {renderValue(row.teamPlan)} + {renderValue(row.enterprisePlan)} ))}
-
+ ); };