feat(custom): implement SubscriptionTable scaffolding and register global module exports#1660
Conversation
…ule exports Signed-off-by: Abhinav Deval <abhinavkdeval08@gmail.com>
There was a problem hiding this comment.
Code Review
This pull request introduces a new SubscriptionTable component to compare free, team, and enterprise subscription plans, along with its custom styled components. The feedback suggests integrating the newly defined custom styled components from style.tsx into the main table component to clean up unused Material-UI imports, and exposing hardcoded UI strings as configurable props to support internationalization (i18n).
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| 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'; |
There was a problem hiding this comment.
Import the custom styled components from ./style and clean up the unused MUI imports (Paper, TableCell, TableContainer, TableRow) to keep the code clean and leverage the custom styling defined for this component.
| 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'; | |
| import CheckIcon from '@mui/icons-material/Check'; | |
| import CloseIcon from '@mui/icons-material/Close'; | |
| import { | |
| Box, | |
| Button, | |
| Table, | |
| TableBody, | |
| TableHead, | |
| Typography | |
| } from '@mui/material'; | |
| import React from 'react'; | |
| import { | |
| StyledTableContainer, | |
| StyledHeaderRow, | |
| StyledTableCell, | |
| FeatureHeaderCell | |
| } from './style'; |
| export interface SubscriptionTableProps { | ||
| title?: string; | ||
| features: PlanFeature[]; | ||
| onPlanSelect?: (planType: 'free' | 'team' | 'enterprise') => void; | ||
| } | ||
|
|
||
| export const SubscriptionTable: React.FC<SubscriptionTableProps> = ({ | ||
| title = 'Subscription Plans Comparison', | ||
| features, | ||
| onPlanSelect | ||
| }) => { |
There was a problem hiding this comment.
To support internationalization (i18n) and localization, avoid hardcoding UI strings (such as table headers and button labels) in shared components. Expose these strings as configurable props with default values to maintain backward compatibility. Additionally, default the features prop to an empty array [] to prevent runtime errors if it is not provided.
export interface SubscriptionTableProps {
title?: string;
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<SubscriptionTableProps> = ({
title = 'Subscription Plans Comparison',
features = [],
onPlanSelect,
featuresLabel = 'Features',
freePlanLabel = 'Free Plan',
freePlanButtonLabel = 'Get Started',
teamPlanLabel = 'Team Plan',
teamPlanButtonLabel = 'Upgrade',
enterprisePlanLabel = 'Enterprise Plan',
enterprisePlanButtonLabel = 'Contact Us'
}) => {
References
- Avoid hardcoding UI strings (such as button labels) in shared components. Expose these strings as configurable props to support internationalization (i18n) and localization.
- When exposing UI strings as configurable props in shared components to support localization, provide a default value to maintain backward compatibility.
| <TableContainer component={Paper} elevation={2} sx={{ borderRadius: 2, overflow: 'hidden' }}> | ||
| <Table sx={{ minWidth: 650 }} aria-label="subscription comparison table"> | ||
| <TableHead sx={{ backgroundColor: 'action.hover' }}> | ||
| <TableRow> | ||
| <TableCell sx={{ fontWeight: 'bold', fontSize: '1.1rem' }}>Features</TableCell> | ||
| <TableCell align="center" sx={{ fontWeight: 'bold', fontSize: '1.1rem' }}> | ||
| Free Plan | ||
| <Box sx={{ mt: 1 }}> | ||
| <Button size="small" variant="outlined" onClick={() => onPlanSelect?.('free')}> | ||
| Get Started | ||
| </Button> | ||
| </Box> | ||
| </TableCell> | ||
| <TableCell align="center" sx={{ fontWeight: 'bold', fontSize: '1.1rem' }}> | ||
| Team Plan | ||
| <Box sx={{ mt: 1 }}> | ||
| <Button | ||
| size="small" | ||
| variant="contained" | ||
| color="primary" | ||
| onClick={() => onPlanSelect?.('team')} | ||
| > | ||
| Upgrade | ||
| </Button> | ||
| </Box> | ||
| </TableCell> | ||
| <TableCell align="center" sx={{ fontWeight: 'bold', fontSize: '1.1rem' }}> | ||
| Enterprise Plan | ||
| <Box sx={{ mt: 1 }}> | ||
| <Button | ||
| size="small" | ||
| variant="contained" | ||
| color="secondary" | ||
| onClick={() => onPlanSelect?.('enterprise')} | ||
| > | ||
| Contact Us | ||
| </Button> | ||
| </Box> | ||
| </TableCell> | ||
| </TableRow> | ||
| </TableHead> | ||
|
|
||
| <TableBody> | ||
| {features.map((row, index) => ( | ||
| <TableRow | ||
| key={index} | ||
| sx={{ | ||
| '&:last-child td, &:last-child th': { border: 0 }, | ||
| '&:hover': { backgroundColor: 'action.hover' } | ||
| }} | ||
| > | ||
| <TableCell | ||
| component="th" | ||
| scope="row" | ||
| sx={{ fontWeight: 600, color: 'text.primary' }} | ||
| > | ||
| {row.featureName} | ||
| </TableCell> | ||
| <TableCell align="center">{renderValue(row.freePlan)}</TableCell> | ||
| <TableCell align="center">{renderValue(row.teamPlan)}</TableCell> | ||
| <TableCell align="center">{renderValue(row.enterprisePlan)}</TableCell> | ||
| </TableRow> | ||
| ))} | ||
| </TableBody> | ||
| </Table> | ||
| </TableContainer> |
There was a problem hiding this comment.
Update the table rendering to use the imported custom styled components (StyledTableContainer, StyledHeaderRow, StyledTableCell, FeatureHeaderCell) and the configurable localization props instead of hardcoded strings and standard MUI components with inline styles.
<StyledTableContainer>
<Table sx={{ minWidth: 650 }} aria-label="subscription comparison table">
<TableHead>
<StyledHeaderRow>
<StyledTableCell sx={{ fontWeight: 'bold', fontSize: '1.1rem' }}>{featuresLabel}</StyledTableCell>
<StyledTableCell align="center" sx={{ fontWeight: 'bold', fontSize: '1.1rem' }}>
{freePlanLabel}
<Box sx={{ mt: 1 }}>
<Button size="small" variant="outlined" onClick={() => onPlanSelect?.('free')}>
{freePlanButtonLabel}
</Button>
</Box>
</StyledTableCell>
<StyledTableCell align="center" sx={{ fontWeight: 'bold', fontSize: '1.1rem' }}>
{teamPlanLabel}
<Box sx={{ mt: 1 }}>
<Button
size="small"
variant="contained"
color="primary"
onClick={() => onPlanSelect?.('team')}
>
{teamPlanButtonLabel}
</Button>
</Box>
</StyledTableCell>
<StyledTableCell align="center" sx={{ fontWeight: 'bold', fontSize: '1.1rem' }}>
{enterprisePlanLabel}
<Box sx={{ mt: 1 }}>
<Button
size="small"
variant="contained"
color="secondary"
onClick={() => onPlanSelect?.('enterprise')}
>
{enterprisePlanButtonLabel}
</Button>
</Box>
</StyledTableCell>
</StyledHeaderRow>
</TableHead>
<TableBody>
{features.map((row, index) => (
<TableRow
key={index}
sx={{
'&:last-child td, &:last-child th': { border: 0 },
'&:hover': { backgroundColor: 'action.hover' }
}}
>
<FeatureHeaderCell component="th" scope="row">
{row.featureName}
</FeatureHeaderCell>
<StyledTableCell align="center">{renderValue(row.freePlan)}</StyledTableCell>
<StyledTableCell align="center">{renderValue(row.teamPlan)}</StyledTableCell>
<StyledTableCell align="center">{renderValue(row.enterprisePlan)}</StyledTableCell>
</TableRow>
))}
</TableBody>
</Table>
</StyledTableContainer>
434a2c2 to
b7298c4
Compare
…ule exports Signed-off-by: Abhinav Deval <abhinavkdeval08@gmail.com>
56442e9 to
812e1ac
Compare
Description
This PR addresses issue #606 by implementing the missing structural baseline scaffolding for the new
SubscriptionTablecomponent pattern wrapper matrix within the Sistent design system (src/custom).Changes Proposed
src/custom/SubscriptionTable/directory module.SubscriptionTable.tsxutilizing strict type definitions (PlanFeatureprops) to dynamically map features.style.tsxutilizing specialized MUI styled engines and Figma typography token overrides (Qanelas SoftandOpen Sans).src/custom/index.tsandsrc/custom/index.tsx) to expose the API interface.Notes for Reviewers
Signed commits
cc @KhushamBansal @leecalcote @Bhumikagarggg