Components & Design System
Author: Carmine Antonio Bonavoglia Creation Date: 29/10/2025
Last Reviewer: Carmine Antonio Bonavoglia Last Updated: 31/10/2025
Overview
Components.js is a component showcase and design system reference page serving as the central hub for:
- Component discovery: Browse all reusable UI components with live examples
- Design tokens: Visualize colors, typography, box styles, button variations
- Theme integration: Real-time display of colors from Redux-based theme store
- Development reference: Examples for developers to copy patterns and component configurations
The page operates as an interactive component library organized into three tabs:
- Global Components (ComponentsManager) — 20+ components including Cards, Buttons, DatePickers, Filters, Headers, Modals, Charts
- Dynamic Tables (DynamicTables) — Data visualization with LinearChartBox, TableBox, DoubleChartsBox
- Color System (ColorSystem) — Comprehensive theme color palette from Redux with 60+ color tokens
File location: /src/pages/Components.js
Key responsibilities:
- Display tabbed interface for component discovery and testing
- Showcase ComponentsManager with full component inventory
- Render responsive card-based grid layouts with clamp() sizing
- Integrate Redux theme store for dynamic color display
- Provide state management for date pickers and filters within showcase
- Serve as single source of truth for design system reference
Architecture & Component Hierarchy
Components (page - main entry point)
│
├─ Ant Design Tabs (3 tabs)
│
├─ Tab 1: "Global Components"
│ └─ ComponentsManager (comprehensive component showcase)
│ ├─ HeaderComponent showcase
│ ├─ ButtonsComponent (all button types)
│ ├─ CustomCard showcase (2 variations)
│ ├─ ModalSection (modal examples)
│ ├─ MessageSection (message/notification examples)
│ ├─ DatePickerComponent showcase
│ │ ├─ SingleDatePickerComponent
│ │ └─ RangePickerComponent
│ ├─ FilterComponent
│ ├─ CatalogueCard showcase (4 variations)
│ ├─ AssetMonitorItem showcase (5 variations with badges)
│ ├─ SummaryCard + ComparisonCard (KPI section)
│ ├─ SimpleChart (data visualization)
│ └─ LoadingCard showcase (3 variations)
│
├─ Tab 2: "Dynamic Tables"
│ └─ DynamicTables
│ ├─ LinearChartBox
│ ├─ TableBox
│ └─ DoubleChartsBox
│
└─ Tab 3: "Color System"
└─ ColorSystem (Redux-connected)
├─ Default Colors display (6 colors)
├─ Status Colors display (4 colors)
├─ Primary Shades display (7 shades 100-700)
├─ Secondary Shades display (7 shades)
├─ Complementary Shades display (7 shades)
├─ Grey Shades display (7 shades)
├─ Background Colors display (4 colors)
├─ Box Styles showcase (5 styles)
├─ Button/Link Styles showcase (10+ button variations)
└─ Typography showcase (H1-H5 + labels)
Components.js (Page Layer)
Structure & Logic
const Components = () => {
const items = [
{
key: "1",
label: "Global Components",
children: <ComponentsManager />,
},
{
key: "2",
label: "Dynamic Tables",
children: <DynamicTables />,
},
{
key: "3",
label: "Color System",
children: <ColorSystem />,
},
];
return (
<Tabs
defaultActiveKey="1" // Opens "Global Components" by default
items={items}
style={{
padding: "clamp(0.5rem, 1.5vw, 1rem)",
fontSize: "clamp(0.875rem, 1.6vw, 1rem)",
}}
/>
);
};
Responsive Design Patterns
The page uses CSS clamp() function extensively for responsive sizing:
/* Pattern: clamp(minSize, preferredSize, maxSize) */
/* Padding: min 0.5rem, preferred 1.5vw, max 1rem */
padding: clamp(0.5rem, 1.5vw, 1rem)
/* Font size: min 0.875rem, preferred 1.6vw, max 1rem */
fontSize: clamp(0.875rem, 1.6vw, 1rem)
Benefits:
- Fluid scaling between mobile and desktop without media queries
- Responsive without breakpoints
- Maintains readability at all viewport sizes
- Reduces CSS complexity
ComponentsManager (Tab 1 - Global Components)
Overview & Purpose
ComponentsManager is a comprehensive component showcase displaying 20+ reusable UI components across 12 sections. Each component is presented with live examples, state management, and documentation.
State Management
// Date picker states (local component state)
const [selectedDate, setSelectedDate] = useState(null);
const [dateRange, setDateRange] = useState(null);
// Handlers
const handleDateChange = (date) => {
setSelectedDate(date); // Update single date
};
const handleDateRangeChange = (dates) => {
setDateRange(dates); // Update [startDate, endDate]
};
// Display
<Text type="secondary">
Date range:{" "}
{dateRange
? `${dateRange[0].format("DD/MM/YYYY")} - ${dateRange[1].format(
"DD/MM/YYYY"
)}`
: "None"}
</Text>;
Sections & Components (Detailed Breakdown)
1. Header Component
Purpose: Display page headers with title + action button
Example Configuration:
<HeaderComponent
title="Gateways - Analytics"
buttonText="Create your report"
onButtonClick={handleCreateReport}
useSpaceBetween={false}
isVisible={true}
/>
Render location: Wrapped in SimpleCard for visual consistency
Related file: /src/components/Components/Headers/HeaderComponent.js
2. Buttons Component
Purpose: Showcase all button types and states
Section count: 9 subsections
- Standard Buttons — Primary, Outline, Secondary, Accent, Disabled
- Status Buttons — Success, Info, Warning, Error
- Validation Status — Incomplete, Modelist Rev., Spaarkly Rev., Client Rev., In Publication (rectangle + circle variants)
- Sizes — Small, Default, Large
- Buttons with Icons — 5 icon+text combinations
- Icon Only Buttons — 5 icon-only buttons with tooltips
- Button Shapes — Default, Circle (icon), Round, Rounded with icon
- Full Width Buttons — Block-width variants (3 styles)
- Ghost Buttons — On dark background with primary, default, dashed variants
- Link Buttons — Link button + Link danger
Component Variations Rendered:
<PrimaryButton>Primary</PrimaryButton>
<OutlineButton>Outline</OutlineButton>
<SecondaryButton>Secondary</SecondaryButton>
<AccentButton>Accent</AccentButton>
<SuccessButton>Success</SuccessButton>
<InfoButton>Information</InfoButton>
<WarningButton>Warning</WarningButton>
<ErrorButton>Error</ErrorButton>
<IconButton icon={<SearchOutlined />} tooltip="Search" />
<LinkButton>Link Button</LinkButton>
Related file: /src/components/Components/MainComponents/ButtonsComponent.js
Related components:
/src/components/Components/Buttons/Buttons.js— Button style definitions/src/components/Components/Buttons/ButtonState.js— Validation status badges
3. Custom Card Component
Purpose: Showcase flexible card component with custom headers, icons, and content
Example Configurations:
// Card 1: User Info (with icon + tooltip)
<CustomCard
title="Informazioni Utente"
icon={<InfoCircleOutlined />}
height="clamp(9.375rem, 20vw, 12.5rem)"
tooltipText="Informazioni dettagliate sull'utente"
>
<div style={{...}}>
<Text>Nome: Mario Rossi</Text>
<Text>Email: mario.rossi@example.com</Text>
<Text>Ruolo: Amministratore</Text>
</div>
</CustomCard>
// Card 2: Statistics (with custom header color)
<CustomCard
title="Statistiche Recenti"
headerColor={PRIMARY_300}
textColor={PRIMARY_700}
height="clamp(9.375rem, 20vw, 12.5rem)"
>
<div style={{...}}>
<Text style={{...}}>1,234</Text>
<Text style={{...}}>VISUALIZZAZIONI TOTALI</Text>
</div>
</CustomCard>
Layout Grid:
┌─────────────────────────────┐
│ 2 columns (flex, wrap) │
│ gap: clamp(0.625rem, 2vw, 1.25rem)
│ minWidth: clamp(15.625rem, 30vw, 18.75rem)
│
│ [Card 1] [Card 2] │
└─────────────────────────────┘
Component Props:
title(string) — Card header titleicon(React.ReactNode) — Icon to display in headerheight(string) — Responsive height with clamp()headerColor(hex) — Header background colortextColor(hex) — Header text colortooltipText(string) — Tooltip contentshowTooltip(boolean) — Show/hide tooltip icon
Related file: /src/components/Components/Cards/CustomCard.js
4. Modal Box Section
Purpose: Showcase modal components and workflows
Component: ModalSection
Related file: /src/components/Components/MainComponents/ModalSection.js
5. Messages Section
Purpose: Display notification/message component examples
Component: MessageSection
Related file: /src/components/Components/Modals/MessageSection.js
6. Date Pickers
Purpose: Showcase single date picker and date range picker components
Two-column layout:
┌─────────────────────────────────────┐
│ Left Column │ Right Column │
│ Single Date Picker │ Date Range Pick │
└─────────────────────────────────────┘
Single Date Picker Example:
<SingleDatePickerComponent
value={selectedDate}
onChange={handleDateChange}
/>
// Display selected date
<Text type="secondary">
Selected date: {selectedDate ? selectedDate.format('DD/MM/YYYY') : 'None'}
</Text>
Date Range Picker Example:
<RangePickerComponent
value={dateRange}
onChange={handleDateRangeChange}
/>
// Display selected range
<Text type="secondary">
Date range: {dateRange ?
`${dateRange[0].format('DD/MM/YYYY')} - ${dateRange[1].format('DD/MM/YYYY')}` :
'None'}
</Text>
State Flow:
- User selects date(s) in picker component
onChangehandler updates local state- Display text updates reactively
- Both pickers are independent
Related files:
/src/components/Components/MainComponents/DatePickerComponent.js/src/components/Components/Pickers/(if separate picker components exist)
7. Filter Component
Purpose: Showcase filter/search component
Component: FilterComponent
Related file: /src/components/Components/Filters/FilterComponent.js
8. Featured Box (Catalogue Cards)
Purpose: Display featured catalogues with asset counts and badges
Layout Grid:
┌────────────────────────────────────────┐
│ 4 columns (20% width each) │
│ [Card1] [Card2] [Card3] [Card4] │
└────────────────────────────────────────┘
Configurations:
// Card 1: Default
<CatalogueCard />
// Card 2: Custom title + asset count
<CatalogueCard
title="SUMMER TOUR"
assetCount={212}
/>
// Card 3: With badge count
<CatalogueCard
title="SMITH OPTICS"
assetCount={46}
badgeCount={2}
/>
// Card 4: Another example
<CatalogueCard
title="BOSS EYEWEAR"
assetCount={117}
/>
Component Props:
title(string) — Catalogue nameassetCount(number) — 3D asset countbadgeCount(number) — Badge/notification count
Related file: /src/components/Components/Cards/CatalogueCard.js
9. Info Box (Asset Monitor Items)
Purpose: Display asset statistics in a horizontal monitoring bar
Layout Grid:
┌────────────────────────────────────────┐
│ 5 columns (20% width each) │
│ [Stat1] [Stat2] [Stat3] [Stat4] [Stat5]
└────────────────────────────────────────┘
Five Statistics Displayed:
// 1. Total 3D Assets
<AssetMonitorItem
count="2544"
label="TOTAL 3D ASSETS"
isFirst={true}
/>
// 2. Main 3D Assets
<AssetMonitorItem
count="679"
label="MAIN 3D ASSETS"
/>
// 3. Published
<AssetMonitorItem
count="2138"
label="PUBLISHED"
sublabel="3D ASSETS"
/>
// 4. To Be Validated (with badge)
<AssetMonitorItem
count="144"
label="TO BE VALIDATED"
sublabel="3D ASSETS"
badgeCount={2}
/>
// 5. In The Making (with custom color)
<AssetMonitorItem
count="110"
label="IN THE MAKING"
sublabel="3D ASSETS"
color={token.colorPrimary}
isLast={true}
/>
Component Props:
count(string) — Number to displaylabel(string) — Primary labelsublabel(string) — Secondary label below primarybadgeCount(number) — Badge number (optional)color(hex) — Custom color overrideisFirst(boolean) — Add left border radiusisLast(boolean) — Add right border radius
Related file: /src/components/Components/Cards/AssetMonitorItem.js
10. Details Box (KPI Section)
Purpose: Display key performance indicators with trends
Layout Grid:
┌─────────────────────────────────────────┐
│ Left (20%) │ Center (58%) │ Right (20%)
│ Summary │ Chart │ Summary
│ + Compare │ │ + Compare
└─────────────────────────────────────────┘
Left Column (Users KPI):
<SummaryCard
title="Number of users (last 7 days)"
value="3307"
subtitle="TOTAL USER"
/>
<ComparisonCard
title="Gap between previous week"
value="1003"
subtitle="TOTAL USER"
isPositive={true}
/>
Center Column (Chart):
<SimpleChart /> // Data visualization
Right Column (Sessions KPI):
<SummaryCard
title="Number of sessions (last 7 days)"
value="6143"
subtitle="TOTAL SESSIONS"
/>
<ComparisonCard
title="Gap between previous week"
value="-13%"
subtitle="TOTAL SESSIONS"
isPositive={false}
/>
Component Props:
SummaryCard:
title(string) — KPI titlevalue(string) — Main metric valuesubtitle(string) — Metric label
ComparisonCard:
title(string) — Comparison titlevalue(string|number) — Value or percentagesubtitle(string) — LabelisPositive(boolean) — Green (true) or red (false) indicator
Related files:
/src/components/Components/Cards/SummaryCard.js/src/components/Components/Cards/ComparisonCard.js/src/components/Components/Charts/SimpleChart.js
11. Loading Card Section
Purpose: Showcase loading state component in multiple variations
Layout Grid:
┌────────────────────────────┐
│ 3 columns (30% width each) │
│ [Loading1] [Loading2] [L3] │
└────────────────────────────┘
Variations:
// Variation 1: Default
<LoadingCard />
// Variation 2: Small with custom message
<LoadingCard
size="small"
message="Caricamento dati..."
/>
// Variation 3: Custom height
<LoadingCard
height="200px"
message="Caricamento grafico..."
/>
Component Props:
size(string) — 'small', 'default', 'large'message(string) — Loading message textheight(string|number) — Custom container height
Related file: /src/components/Components/Cards/LoadingCard.js
Key Styling Patterns in ComponentsManager
Responsive Spacing
// Margin bottom between sections
marginBottom: "clamp(1rem, 2vw, 1.5rem)";
// Gap between grid items
gap: "clamp(0.625rem, 2vw, 1.25rem)";
// Minimum width for grid columns
minWidth: "clamp(15.625rem, 30vw, 18.75rem)";
Section Titles
<Title level={3} style={{
marginBottom: 'clamp(1rem, 2vw, 1.5rem)',
color: PRIMARY_700,
textAlign: 'left'
}}>
{Section Name}
</Title>
Card Wrapping
<SimpleCard>{children}</SimpleCard>
DynamicTables (Tab 2)
Overview
Tab 2 displays data visualization components for complex data rendering:
const DynamicTables = () => {
return (
<div style={{ padding: 'clamp(0.625rem, 2vw, 1.25rem)' }}>
<Title level={3} style={{...}}>Linear Chart Box</Title>
<LinearChartBox />
<Title level={3} style={{...}}>Table Box</Title>
<TableBox />
<Title level={3} style={{...}}>Double Charts Box</Title>
<DoubleChartsBox />
</div>
);
};
Components
1. LinearChartBox
Purpose: Display linear/trend charts for time-series data
Related file: /src/components/Components/Charts/LinearChartBox.js
2. TableBox
Purpose: Display dynamic/sortable data tables
Related file: /src/components/Components/Tables/TableBox.js
3. DoubleChartsBox
Purpose: Display two charts side-by-side for comparison
Related file: /src/components/Components/Charts/DoubleChartBox.js
ColorSystem (Tab 3 - Redux-Connected)
Overview & Redux Integration
The ColorSystem component is Redux-connected and displays the entire theme color palette from the Redux store in real-time.
import { useSelector } from "react-redux";
const ColorSystem = () => {
// Fetch theme from Redux store
const theme = useSelector((state) => state.theme);
// Extract all color categories
const PRIMARY = theme.variant.primary;
const ACCENT = theme.variant.accent;
// ... etc
};
Color Structure from Redux Store
The theme Redux store provides colors organized in 7 categories:
const theme = {
// 1. Variant Colors (6 colors)
variant: {
primary: "#...", // Primary brand color
accent: "#...", // Accent color
black: "#000000", // Black
secondary: "#...", // Secondary
complementary: "#...", // Complementary
white: "#FFFFFF", // White
},
// 2. Status Colors (4 colors)
status: {
success: "#52c41a", // Green
error: "#ff4d4f", // Red
warning: "#faad14", // Orange
info: "#1890ff", // Blue
},
// 3. Primary Shades (7 levels: 100-700)
primary: {
primary100: "#...", // Lightest
primary200: "#...",
primary300: "#...",
primary400: "#...",
primary500: "#...", // Mid-tone
primary600: "#...",
primary700: "#...", // Darkest
},
// 4. Secondary Shades (7 levels)
secondary: {
/* 100-700 */
},
// 5. Complementary Shades (7 levels)
complementary: {
/* 100-700 */
},
// 6. Grey Shades (7 levels)
grey: {
/* 100-700 */
},
// 7. Background Colors (4 colors)
background: {
primaryBg: "#...", // Primary background
whiteBg: "#FFFFFF", // White background
greyBg: "#...", // Grey background
secondaryBg: "#...", // Secondary background
},
};
Color Display Sections (8 sections)
1. Default Colors (6 colors)
Rendered:
- Primary, Accent, Black, Secondary, Complementary, White
Component:
<ColorBox color="primary" label="Primary" hexCode={PRIMARY} />
2. Status Colors (4 colors)
Rendered:
- Success (#52c41a), Error (#ff4d4f), Warning (#faad14), Info (#1890ff)
Usage: Alerts, validation states, badges
3. Primary Shades (7 colors: 100-700)
Light to Dark: primary100 → primary700
Usage: Backgrounds, text, hover states
4. Secondary Shades (7 colors: 100-700)
Light to Dark: secondary100 → secondary700
Usage: Borders, accents, secondary components
5. Complementary Shades (7 colors: 100-700)
Light to Dark: complementary100 → complementary700
Usage: Complementary design elements
6. Grey Shades (7 colors: 100-700)
Light to Dark: grey100 → grey700
Usage: Neutral backgrounds, borders, disabled states
7. Background Colors (4 colors)
Rendered:
- Primary Background, White Background, Grey Background, Secondary Background
Usage: Page backgrounds, card backgrounds
8. Box Styles (5 styles)
From theme.boxStyles:
const boxStyles = {
defaultBox: {...}, // Base box style
borderBox: {...}, // With border
greyBox: {...}, // Grey background
raisedBox: {...}, // Elevated/shadow
floatingBox: {...} // Floating effect
};
Rendered:
<BoxExample
title="Default Box"
style={boxStyles.defaultBox}
/>
<BoxExample
title="Border Box"
style={boxStyles.borderBox}
/>
// ... etc
9. Button/Link Styles (10+ variations)
Two rows of buttons:
Row 1 (Standard):
- Primary, Outline, Secondary, Accent, Disabled
Row 2 (Status):
- Success, Information, Warning, Error
Component: Ant Design Button with buttonStyles from theme
<Button type="primary" style={buttonStyles.primary}>Primary</Button>
<Button style={buttonStyles.outline}>Outline</Button>
<Button style={buttonStyles.success}>Success</Button>
10. Typography (6 levels)
Displayed:
- H1, H2, H3, H4, H5 + Label
- Font: Inter
- Shows font size from
typography.fontSizes
Styles Shown:
<Title level={1}>Inter - H1 - {typography.fontSizes.h1}</Title>
<Title level={2}>Inter - H2 - {typography.fontSizes.h2}</Title>
// ... H3-H5
<Text type="secondary">Inter - LABEL - {typography.fontSizes.label}</Text>
Typography Features:
- Underline examples
- Normal text examples
- Shows actual pixel sizes from theme
ColorBox Component (Helper)
Used throughout ColorSystem to display individual colors:
const ColorBox = ({ color, label, hexCode }) => (
<div
style={{
marginBottom: "clamp(0.625rem, 2vw, 1.25rem)",
width: "clamp(5rem, 10vw, 7.5rem)",
}}
>
{/* Color swatch */}
<div
style={{
backgroundColor: hexCode,
height: "clamp(1.875rem, 4vw, 2.8125rem)",
width: "100%",
borderRadius: "clamp(0.125rem, 0.5vw, 0.25rem)",
marginBottom: "clamp(0.25rem, 1vw, 0.5rem)",
border:
hexCode === "#FFFFFF"
? "clamp(0.0625rem, 0.2vw, 0.0625rem) solid #E0E0E0"
: "none",
}}
/>
{/* Label + hex code */}
<div style={{ textAlign: "left" }}>
<Text strong style={{ display: "block" }}>
{label}
</Text>
<Text
type="secondary"
style={{ fontSize: "clamp(0.625rem, 1.2vw, 0.75rem)" }}
>
{hexCode}
</Text>
</div>
</div>
);
Props:
color(string) — Color identifier (used as key)label(string) — Display name (e.g., "Primary 300")hexCode(string) — Hex color code
Special handling:
- White colors get a subtle border for visibility
- Responsive size using clamp()
- Displays hex code below color label
BoxExample Component (Helper)
Used to showcase box style variations:
const BoxExample = ({ title, style }) => (
<div
style={{
...style,
width: "100%",
height: "clamp(2.5rem, 5vw, 3.75rem)",
borderRadius: "clamp(0.125rem, 0.5vw, 0.25rem)",
padding: "clamp(0.5rem, 1.5vw, 1rem)",
marginBottom: "clamp(0.25rem, 1vw, 0.5rem)",
}}
>
<Text>{title}</Text>
</div>
);
Props:
title(string) — Box name/style labelstyle(object) — Style object from theme.boxStyles
Tab State Management & Navigation
Components.js Tab State
const items = [
{ key: "1", label: "Global Components", children: <ComponentsManager /> },
{ key: "2", label: "Dynamic Tables", children: <DynamicTables /> },
{ key: "3", label: "Color System", children: <ColorSystem /> },
];
<Tabs defaultActiveKey="1" items={items} />;
Default Behavior:
- Tab 1 ("Global Components") opens on page load
- User can click tabs to switch
- State managed by Ant Design Tabs component
- No additional state needed
Tab Content Lazy Loading
Each tab's content (ComponentsManager, DynamicTables, ColorSystem) is rendered conditionally by Ant Design:
- Only the active tab is rendered in DOM
- Other tabs' content is mounted/unmounted on tab switch
- Performance optimization: components not in view don't consume resources
Responsive Design Deep Dive
Clamp() Function Strategy
The entire Components page uses CSS clamp() function for responsive sizing without media queries.
Pattern: clamp(minSize, preferredSize, maxSize)
Examples used throughout:
/* Padding - min 0.5rem, preferred 1.5vw, max 1rem */
padding: clamp(0.5rem, 1.5vw, 1rem)
/* Margin - min 0.625rem, preferred 2vw, max 1.25rem */
margin: clamp(0.625rem, 2vw, 1.25rem)
/* Font size - min 0.875rem, preferred 1.6vw, max 1rem */
fontSize: clamp(0.875rem, 1.6vw, 1rem)
/* Height - min 2.5rem, preferred 5vw, max 3.75rem */
height: clamp(2.5rem, 5vw, 3.75rem)
/* Width - min 15.625rem, preferred 30vw, max 18.75rem */
minWidth: clamp(15.625rem, 30vw, 18.75rem)
/* Border radius - min 0.125rem, preferred 0.5vw, max 0.25rem */
borderRadius: clamp(0.125rem, 0.5vw, 0.25rem)
Breakpoint-Free Responsive Grid
Example: ComponentsManager grid layout
<div
style={{
marginBottom: "clamp(1.25rem, 3vw, 2.5rem)",
display: "flex",
gap: "clamp(0.625rem, 2vw, 1.25rem)",
flexWrap: "wrap",
}}
>
<div style={{ flex: "1", minWidth: "clamp(15.625rem, 30vw, 18.75rem)" }}>
<Card1 />
</div>
<div style={{ flex: "1", minWidth: "clamp(15.625rem, 30vw, 18.75rem)" }}>
<Card2 />
</div>
</div>
Behavior:
- Mobile: Cards stack (1 per row) due to minWidth constraint
- Tablet: Cards wrap naturally (2 per row)
- Desktop: Cards flow across with flex: 1
- All sizes: Gap and padding scale smoothly
No media queries needed!
Component Composition Patterns
Pattern 1: Wrapped Components in SimpleCard
<Title level={3}>Component Name</Title>
<SimpleCard>
<ActualComponent />
</SimpleCard>
Purpose: Consistent visual container with shadow + border radius
Related component: /src/components/Components/Cards/SimpleCard.js
Pattern 2: Section with Custom Grids
<div
style={{
marginBottom: "clamp(1.25rem, 3vw, 2.5rem)",
display: "flex",
flexWrap: "wrap",
justifyContent: "space-between",
}}
>
<div style={{ width: "20%" }}>
<ComponentVariation1 />
</div>
<div style={{ width: "20%" }}>
<ComponentVariation2 />
</div>
{/* ... more variations */}
</div>
Purpose: Multi-column layout with consistent proportions
Variations:
- 2 columns:
width: 50%with gap - 4 columns:
width: 22%with gap - 5 columns:
width: 20%with gap
Pattern 3: Flex with Gap and Wrap
<div
style={{
display: "flex",
gap: "clamp(0.9375rem, 2.5vw, 1.875rem)",
flexWrap: "wrap",
}}
>
<Component1 style={{ flex: "1", minWidth: "..." }} />
<Component2 style={{ flex: "1", minWidth: "..." }} />
</div>
Purpose: Responsive flow layout with auto-wrapping
SimpleCard Component (Key Helper)
Used throughout ComponentsManager for consistent card styling.
Source: /src/components/Components/Cards/SimpleCard.js
function SimpleCard({
children,
title,
onClick,
style,
className,
padding = "1rem",
borderRadius = "clamp(0.25rem, 2vw, 0.5rem)",
}) {
return (
<Card
title={title}
onClick={onClick}
hoverable
styles={{
body: { padding: padding },
}}
style={{
width: "100%",
boxShadow: `clamp(0rem, 0.1vw, 0rem) clamp(0.0625rem, 0.5vw, 0.125rem) clamp(0.25rem, 2vw, 0.5rem) rgba(0, 0, 0, 0.15)`,
cursor: onClick ? "pointer" : "default",
transition: "transform 0.2s",
borderRadius: borderRadius,
...style,
}}
className={className}
>
{children}
</Card>
);
}
Props:
children(ReactNode) — Contenttitle(string) — Optional header titleonClick(function) — Optional click handlerstyle(object) — Custom stylesclassName(string) — Custom CSS classpadding(string) — Custom body paddingborderRadius(string) — Custom border radius
Default styling:
- Hover effect: shadow + transform
- Box shadow: responsive blur + offset
- Border radius: clamp() for scaling
CustomCard Component (Complex Helper)
Used for cards with headers, icons, and custom content.
Source: /src/components/Components/Cards/CustomCard.js
const CustomCard = ({
title,
icon,
children,
backgroundColor = "#ffffff",
headerColor = PRIMARY_200,
textColor = PRIMARY_500,
height = "auto",
showTooltip = true,
tooltipText = "Card information",
}) => {
return (
<Card
style={{
borderRadius: "clamp(0.25rem, 2vw, 0.5rem)",
overflow: "hidden",
height: height,
boxShadow: `0 clamp(0.0625rem, 0.5vw, 0.125rem) clamp(0.25rem, 2vw, 0.5rem) rgba(0, 0, 0, 0.08)`,
backgroundColor: backgroundColor,
}}
styles={{
body: {
padding: title ? 0 : "clamp(0.75rem, 4vw, 1.25rem)",
height: "100%",
},
}}
>
{title ? (
<>
{/* Header with icon + tooltip */}
<div
style={{
backgroundColor: headerColor,
padding:
"clamp(0.5rem, 2vw, 0.625rem) clamp(0.75rem, 3vw, 0.9375rem)",
textAlign: "left",
fontWeight: "bold",
fontSize: "clamp(0.75rem, 2vw, 0.875rem)",
color: textColor,
display: "flex",
alignItems: "center",
justifyContent: "space-between",
}}
>
<div style={{ display: "flex", alignItems: "center" }}>
{icon && (
<span
style={{
marginRight:
"clamp(0.25rem, 2vw, 0.5rem)",
}}
>
{icon}
</span>
)}
{title}
</div>
{showTooltip && (
<CustomTooltip title={tooltipText}>
<InfoCircleOutlined
style={{
fontSize:
"clamp(0.75rem, 2vw, 0.875rem)",
color: textColor,
}}
/>
</CustomTooltip>
)}
</div>
{/* Content body */}
<div
style={{
padding: "clamp(0.75rem, 4vw, 1.25rem)",
height: "calc(100% - 2.5rem)",
}}
>
{children}
</div>
</>
) : (
children
)}
</Card>
);
};
Props:
title(string) — Header titleicon(ReactNode) — Header iconheaderColor(hex) — Header backgroundtextColor(hex) — Header text colorheight(string) — Container heightshowTooltip(boolean) — Show info icontooltipText(string) — Tooltip content
Key features:
- Icon + title in header
- Tooltip info icon (optional)
- Flexible height
- Responsive padding with clamp()
- Full-height content area
Integration Points & Dependencies
Imports (Components.js)
import { Tabs } from "antd";
import ComponentsManager from "../components/Components/ComponentsManager";
import DynamicTables from "../components/Components/DynamicTables";
import ColorSystem from "../components/Components/ColorSystem";
Imports (ComponentsManager.js)
import { useState } from "react";
import { Typography, theme } from "antd";
import { InfoCircleOutlined } from "@ant-design/icons";
import { primaryShades } from "../../theme/theme";
// 20+ component imports
import ButtonsComponent from "./MainComponents/ButtonsComponent";
import HeaderComponent from "./Headers/HeaderComponent";
import CustomCard from "./Cards/CustomCard";
// ... etc (all listed in file)
Imports (ColorSystem.js)
import React from "react";
import { Typography, Button, Divider } from "antd";
import { useSelector } from "react-redux";
import { boxStyles, buttonStyles, typography } from "../../theme/theme";
Redux Store Access
ColorSystem connects to Redux:
const theme = useSelector((state) => state.theme);
Store structure expected:
{
theme: {
variant: { primary, accent, black, secondary, complementary, white },
status: { success, error, warning, info },
primary: { primary100-700 },
secondary: { secondary100-700 },
complementary: { complementary100-700 },
grey: { grey100-700 },
background: { primaryBg, whiteBg, greyBg, secondaryBg }
}
}
Error Handling & Edge Cases
Edge Case 1: Missing Redux Theme
Scenario: Redux theme store is undefined
Current handling: Not explicitly handled in ColorSystem
Recommendation: Add fallback
const theme = useSelector((state) => state.theme) || defaultTheme;
Edge Case 2: Long Component Names
Scenario: Card titles overflow in narrow viewports
Current handling: Text truncates naturally with flex
Recommendation: Add text-overflow styles
{
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap'
}
Edge Case 3: Large Number of Color Boxes
Scenario: 60+ color boxes render in ColorSystem
Performance impact: Moderate (each box is simple div)
Optimization: Not needed for current scale; memoize if >200 items
Performance Considerations
Component Rendering
-
ComponentsManager: ~20 child components rendered on mount
- Heavy: ButtonsComponent (10 sections)
- Heavy: ColorSystem (60+ color boxes)
- Moderate: DatePickerComponent (2 pickers)
- Light: All others
-
Tabs Performance: Ant Design Tabs mounts/unmounts tab content on switch
- Good for initial load (only active tab rendered)
- Small delay when switching to inactive tab
Optimization Opportunities
- Memoize ColorBox component (prevents re-renders)
- Lazy-load DynamicTables and ColorSystem tab content
- Virtualize color boxes if count exceeds 100
- Move ComponentsManager state to custom hook
- Add React.memo() to ButtonsComponent sections
Memory Usage
- Components.js: Minimal (just Tabs component)
- ComponentsManager: High (20+ children)
- ColorSystem: High (60+ color boxes + Redux subscription)
- DynamicTables: Depends on data (LinearChartBox, TableBox, DoubleChartsBox)
Testing Strategy
Unit Tests
// Test ColorBox renders correct hex code
test("ColorBox displays correct hex code", () => {
const { getByText } = render(
<ColorBox label="Primary" hexCode="#007AFF" color="primary" />
);
expect(getByText("#007AFF")).toBeInTheDocument();
});
// Test CustomCard shows/hides tooltip
test("CustomCard shows tooltip when showTooltip=true", () => {
const { getByIcon } = render(
<CustomCard title="Test" showTooltip={true}>
Content
</CustomCard>
);
expect(getByIcon(InfoCircleOutlined)).toBeInTheDocument();
});
// Test tab switching
test("Tabs component renders correct active tab", () => {
const { getByText } = render(<Components />);
expect(getByText("Global Components")).toHaveClass("ant-tabs-tab-active");
});
Integration Tests
// Test ComponentsManager renders all sections
test("ComponentsManager renders all 11 sections", () => {
const { getByText } = render(<ComponentsManager />);
expect(getByText("Header")).toBeInTheDocument();
expect(getByText("Buttons")).toBeInTheDocument();
expect(getByText("Custom Card")).toBeInTheDocument();
// ... all 11 sections
});
// Test date picker state updates
test("Date picker updates state correctly", () => {
const { getByDisplayValue } = render(<ComponentsManager />);
const picker = getByTestId("single-date-picker");
userEvent.click(picker);
userEvent.click(getByText("15"));
expect(getByDisplayValue(/15/)).toBeInTheDocument();
});
// Test ColorSystem Redux integration
test("ColorSystem fetches colors from Redux", () => {
const initialState = {
theme: {
variant: { primary: "#007AFF" },
// ... full theme
},
};
const { getByText } = render(
<Provider store={createTestStore(initialState)}>
<ColorSystem />
</Provider>
);
expect(getByText("#007AFF")).toBeInTheDocument();
});
E2E Tests
// Full user journey
test("User navigates all three tabs and sees content", async () => {
// 1. Page loads, Tab 1 active
await expect(page.locator("text=Header")).toBeVisible();
// 2. Click Tab 2
await page.click("text=Dynamic Tables");
await expect(page.locator("text=Linear Chart Box")).toBeVisible();
// 3. Click Tab 3
await page.click("text=Color System");
await expect(page.locator("text=Default Colors")).toBeVisible();
// 4. Verify Redux colors displayed
const primaryColor = await page.locator("text=#007AFF").textContent();
expect(primaryColor).toBeTruthy();
});
State Flow Diagram
┌─────────────────────────────────────────────────────────┐
│ User visits Components page │
└──────────────────┬──────────────────────────────────────┘
│
↓
┌──────────────────────────┐
│ Components page renders │
│ • Tabs component mounts │
│ • defaultActiveKey="1" │
└──────────────┬───────────┘
│
↓
┌──────────────────────────────┐
│ Tab 1 Content Renders │
│ ComponentsManager mounts │
│ • 20 components initialize │
│ • DatePicker state created │
│ • All sections render │
└──────────────┬───────────────┘
│
┌──────────────┴────────────────┬────────────────┐
│ │ │
↓ ↓ ↓
[Tab 2 Click] [Tab 3 Click] [DatePicker Change]
│ │ │
↓ ↓ ↓
DynamicTables ColorSystem mounts handleDateChange()
mounts on demand (Redux connected) → setSelectedDate()
│ │ │
↓ ↓ ↓
Charts render Display 60+ colors Text updates
from data from Redux store reactively
Related Files & Architecture
Page layer: /src/pages/Components.js
Tab 1 - ComponentsManager:
/src/components/Components/ComponentsManager.js(main)/src/components/Components/MainComponents/— ButtonsComponent, DatePickerComponent, ModalSection/src/components/Components/Headers/— HeaderComponent/src/components/Components/Cards/— CustomCard, SimpleCard, CatalogueCard, AssetMonitorItem, SummaryCard, ComparisonCard, LoadingCard/src/components/Components/Modals/— MessageSection/src/components/Components/Filters/— FilterComponent/src/components/Components/Charts/— SimpleChart
Tab 2 - DynamicTables:
/src/components/Components/DynamicTables.js(main)/src/components/Components/Charts/LinearChartBox.js/src/components/Components/Charts/DoubleChartBox.js/src/components/Components/Tables/TableBox.js
Tab 3 - ColorSystem:
/src/components/Components/ColorSystem.js(main, Redux-connected)
Theme system:
/src/theme/theme.js— primaryShades, boxStyles, buttonStyles, typography- Redux store:
state.theme
Ant Design components used:
- Tabs, Card, Button, Typography (Title, Text), Divider, Space, Modal, Message, DatePicker
Key Constants & Configuration
// ComponentsManager Constants
const PRIMARY_300 = primaryShades.primary300;
const PRIMARY_500 = primaryShades.primary500;
const PRIMARY_700 = primaryShades.primary700;
// Card Grid Layouts
const CARD_FLEX_RATIO = 1; // Equal width cards
const CARD_MIN_WIDTH = "clamp(15.625rem, 30vw, 18.75rem)";
const CARD_GAP = "clamp(0.625rem, 2vw, 1.25rem)";
// Section Spacing
const SECTION_MARGIN = "clamp(1rem, 2vw, 1.5rem)";
const SECTION_MARGIN_LARGE = "clamp(1.25rem, 3vw, 2.5rem)";
// ColorSystem Constants
const COLOR_BOX_WIDTH = "clamp(5rem, 10vw, 7.5rem)";
const COLOR_BOX_HEIGHT = "clamp(1.875rem, 4vw, 2.8125rem)";
// Responsive Clamp Values
const PADDING_SMALL = "clamp(0.5rem, 1.5vw, 0.75rem)";
const PADDING_MEDIUM = "clamp(0.75rem, 3vw, 1rem)";
const PADDING_LARGE = "clamp(0.75rem, 4vw, 1.25rem)";