Skip to content

feat(custom): implement SubscriptionTable scaffolding and register global module exports - #1660

Open
abhinavkdeval08-design wants to merge 10 commits into
layer5io:masterfrom
abhinavkdeval08-design:feature/subscription-comparison-table
Open

feat(custom): implement SubscriptionTable scaffolding and register global module exports#1660
abhinavkdeval08-design wants to merge 10 commits into
layer5io:masterfrom
abhinavkdeval08-design:feature/subscription-comparison-table

Conversation

@abhinavkdeval08-design

@abhinavkdeval08-design abhinavkdeval08-design commented Jun 29, 2026

Copy link
Copy Markdown

Description

This PR addresses issue #606 by implementing the missing structural baseline scaffolding for the new SubscriptionTable component pattern wrapper matrix within the Sistent design system (src/custom).

Changes Proposed

  • Created a dedicated src/custom/SubscriptionTable/ directory module.
  • Engineered the core table blueprint inside SubscriptionTable.tsx utilizing strict type definitions (PlanFeature props) to dynamically map features.
  • Injected custom layout extensions inside style.tsx utilizing specialized MUI styled engines and Figma typography token overrides (Qanelas Soft and Open Sans).
  • Registered local endpoints globally via both root module index files (src/custom/index.ts and src/custom/index.tsx) to expose the API interface.

Notes for Reviewers

  • The setup is verified locally and ready for seamless integration. I have already initiated a query on the main tracker thread to obtain the explicit production code reference link from the Meshery Cloud UI repository to finalize concrete subscription tier matrices.

Signed commits

  • Yes, I signed my commits. (DCO check passes)

cc @KhushamBansal @leecalcote @Bhumikagarggg

Summary by CodeRabbit

  • New Features
    • Added a subscription-plan comparison table displaying Free, Team, and Enterprise plans.
    • Supports feature comparisons using text values and visual success or unavailable indicators.
    • Added optional plan-selection actions for each plan.
    • Styled the table for light and dark themes with consistent borders, typography, spacing, and visual hierarchy.

…ule exports

Signed-off-by: Abhinav Deval <abhinavkdeval08@gmail.com>

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment on lines +1 to +15
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';

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

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.

Suggested change
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';

Comment on lines +25 to +35
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
}) => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

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
  1. Avoid hardcoding UI strings (such as button labels) in shared components. Expose these strings as configurable props to support internationalization (i18n) and localization.
  2. When exposing UI strings as configurable props in shared components to support localization, provide a default value to maintain backward compatibility.

Comment on lines +68 to +133
<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>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

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>

@abhinavkdeval08-design
abhinavkdeval08-design force-pushed the feature/subscription-comparison-table branch from 434a2c2 to b7298c4 Compare June 29, 2026 17:38
…ule exports

Signed-off-by: Abhinav Deval <abhinavkdeval08@gmail.com>
@abhinavkdeval08-design
abhinavkdeval08-design force-pushed the feature/subscription-comparison-table branch from 56442e9 to 812e1ac Compare June 29, 2026 17:46
@abhinavkdeval08-design

Copy link
Copy Markdown
Author

@KhushamBansal @leecalcote
Plz review this PR..

@abhinavkdeval08-design

Copy link
Copy Markdown
Author

@leecalcote @KhushamBansal @rishiraj38 @Bhumikagarggg
Kindly review my pr..

@Bhumikagarggg Bhumikagarggg left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@abhinavkdeval08-design Please review all the suggestions raised by Copilot. If a suggestion is valid, please address it. If not, please reply to the comment explaining why no change is needed so that all comments are resolved.

Signed-off-by: Abhinav Deval <abhinavkdeval08@gmail.com>
@abhinavkdeval08-design
abhinavkdeval08-design force-pushed the feature/subscription-comparison-table branch from b1b798c to 43af05b Compare July 6, 2026 06:36
@abhinavkdeval08-design

Copy link
Copy Markdown
Author

@Bhumikagarggg @leecalcote @KhushamBansal
I've made the changes kindly review..

@abhinavkdeval08-design

Copy link
Copy Markdown
Author

@leecalcote @KhushamBansal @Bhumikagarggg kindly review the PR

@hortison

Copy link
Copy Markdown
Contributor

@leecalcote @KhushamBansal @Bhumikagarggg kindly review the PR

@abhinavkdeval08-design consider and reply to all feedback offered.

@abhinavkdeval08-design

Copy link
Copy Markdown
Author

@hortison Bro I've already made all the changes you can see and it's ready to review and if this is correct then kindly merge.
@Bhumikagarggg @leecalcote @KhushamBansal
Thanks..

@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a themed SubscriptionTable React component with configurable plan labels, feature values, selection callbacks, boolean status icons, and public exports through the custom module barrels.

Changes

Subscription table

Layer / File(s) Summary
Table contract and themed primitives
src/custom/SubscriptionTable/SubscriptionTable.tsx, src/custom/SubscriptionTable/style.tsx
Defines subscription feature and component prop interfaces, plus theme-aware container, header-row, and cell styling.
Table rendering and plan actions
src/custom/SubscriptionTable/SubscriptionTable.tsx
Renders plan headers, action buttons, feature rows, boolean status icons, and text values, invoking the optional plan-selection callback.
Public module exports
src/custom/SubscriptionTable/index.ts, src/custom/index.ts, src/custom/index.tsx
Re-exports the component and its public types through the subscription-table and custom entry points.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Suggested reviewers: bhumikagarggg

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the new SubscriptionTable scaffolding and the added module export registration.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/custom/SubscriptionTable/style.tsx`:
- Around line 13-29: Replace raw colors and font-family/weight overrides with
Sistent theme palette and typography tokens across all affected sites: in
src/custom/SubscriptionTable/style.tsx lines 13-29, update StyledHeaderRow,
StyledTableCell, and FeatureHeaderCell to derive colors and typography from the
theme, including theme.palette.text.primary or its Sistent equivalent; in
src/custom/SubscriptionTable/SubscriptionTable.tsx lines 49-65 and 74-104, apply
the appropriate Sistent typography token to the feature and plan header cells
instead of literal family and weight values.
- Around line 5-10: Update the StyledTableContainer styles to allow horizontal
scrolling on narrow viewports instead of clipping the table with overflow
hidden. Preserve the existing visual styles and ensure the 650px-minimum-width
table remains accessible, including later plan columns.

In `@src/custom/SubscriptionTable/SubscriptionTable.tsx`:
- Around line 40-52: Add an accessible text alternative to both boolean branches
in renderValue: label the CheckIcon for the included state and the CloseIcon for
the excluded state using titleAccess, aria-label, or visually hidden text, while
preserving their existing visual styling and test IDs.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: a195d272-9565-414b-9f9a-519c7ff87d0c

📥 Commits

Reviewing files that changed from the base of the PR and between 2bb6802 and 0034b96.

📒 Files selected for processing (5)
  • src/custom/SubscriptionTable/SubscriptionTable.tsx
  • src/custom/SubscriptionTable/index.ts
  • src/custom/SubscriptionTable/style.tsx
  • src/custom/index.ts
  • src/custom/index.tsx

Comment on lines +5 to +10
export const StyledTableContainer = styled(Paper)(({ theme }) => ({
borderRadius: theme.shape.borderRadius * 2,
overflow: 'hidden',
boxShadow: theme.shadows[2],
border: `1px solid ${theme.palette.divider}`
}));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Allow narrow viewports to scroll the table horizontally.

overflow: 'hidden' clips the 650px-minimum-width table on small screens, preventing access to later plan columns.

Proposed fix
-  overflow: 'hidden',
+  overflowX: 'auto',
+  overflowY: 'hidden',
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const StyledTableContainer = styled(Paper)(({ theme }) => ({
borderRadius: theme.shape.borderRadius * 2,
overflow: 'hidden',
boxShadow: theme.shadows[2],
border: `1px solid ${theme.palette.divider}`
}));
export const StyledTableContainer = styled(Paper)(({ theme }) => ({
borderRadius: theme.shape.borderRadius * 2,
overflowX: 'auto',
overflowY: 'hidden',
boxShadow: theme.shadows[2],
border: `1px solid ${theme.palette.divider}`
}));
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/custom/SubscriptionTable/style.tsx` around lines 5 - 10, Update the
StyledTableContainer styles to allow horizontal scrolling on narrow viewports
instead of clipping the table with overflow hidden. Preserve the existing visual
styles and ensure the 650px-minimum-width table remains accessible, including
later plan columns.

Comment on lines +13 to +29
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'
}));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Use Sistent semantic palette and typography tokens throughout this component. color: 'text.primary' in styled() is emitted as a literal CSS value and is not resolved through MUI’s sx token parser, while the raw hex colors and font-family overrides bypass theme configuration.

  • src/custom/SubscriptionTable/style.tsx#L13-L29: derive header colors, feature-cell color, and typography from Sistent theme exports; use theme.palette.text.primary (or the Sistent equivalent) rather than the literal text.primary.
  • src/custom/SubscriptionTable/SubscriptionTable.tsx#L49-L65: replace literal typography weight/family styling with the appropriate Sistent typography token.
  • src/custom/SubscriptionTable/SubscriptionTable.tsx#L74-L104: apply the same tokenized typography to plan header cells.

As per coding guidelines, “Theme-aware UI must use Sistent theme exports and semantic palette tokens rather than raw MUI defaults.”

📍 Affects 2 files
  • src/custom/SubscriptionTable/style.tsx#L13-L29 (this comment)
  • src/custom/SubscriptionTable/SubscriptionTable.tsx#L49-L65
  • src/custom/SubscriptionTable/SubscriptionTable.tsx#L74-L104
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/custom/SubscriptionTable/style.tsx` around lines 13 - 29, Replace raw
colors and font-family/weight overrides with Sistent theme palette and
typography tokens across all affected sites: in
src/custom/SubscriptionTable/style.tsx lines 13-29, update StyledHeaderRow,
StyledTableCell, and FeatureHeaderCell to derive colors and typography from the
theme, including theme.palette.text.primary or its Sistent equivalent; in
src/custom/SubscriptionTable/SubscriptionTable.tsx lines 49-65 and 74-104, apply
the appropriate Sistent typography token to the feature and plan header cells
instead of literal family and weight values.

Source: Coding guidelines

Comment on lines +40 to +52
const renderValue = (value: boolean | string) => {
if (typeof value === 'boolean') {
return value ? (
<CheckIcon color="success" data-testid="check-icon" />
) : (
<CloseIcon color="error" data-testid="close-icon" />
);
}
return (
<Typography variant="body2" sx={{ fontWeight: 500 }}>
{value}
</Typography>
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

sed -n '1,220p' src/custom/SubscriptionTable/SubscriptionTable.tsx

Repository: layer5io/sistent

Length of output: 4928


🏁 Script executed:

cat -n src/custom/SubscriptionTable/SubscriptionTable.tsx | sed -n '1,220p'

Repository: layer5io/sistent

Length of output: 5887


Expose a text alternative for the boolean icons in src/custom/SubscriptionTable/SubscriptionTable.tsx:40-46. The check/close icons need an accessible name so screen readers can tell whether a feature is included; add titleAccess, aria-label, or hidden text for both states.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/custom/SubscriptionTable/SubscriptionTable.tsx` around lines 40 - 52, Add
an accessible text alternative to both boolean branches in renderValue: label
the CheckIcon for the included state and the CloseIcon for the excluded state
using titleAccess, aria-label, or visually hidden text, while preserving their
existing visual styling and test IDs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants