Skip to content

Commit

Permalink
Add ComparisonTable component
Browse files Browse the repository at this point in the history
  • Loading branch information
bluprince13 committed Jun 1, 2024
1 parent c923203 commit 1d4e8ef
Show file tree
Hide file tree
Showing 4 changed files with 450 additions and 1 deletion.
144 changes: 144 additions & 0 deletions src/components/ComparisonTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
import * as React from 'react'
import {
Table,
TableBody,
TableCell,
TableContainer,
TableHead,
TableRow,
Paper,
Typography,
Divider,
Box
} from '@mui/material'

interface CellContent {
content: string | React.ReactNode
status: 'bad' | 'neutral' | 'good'
}

interface Header {
name: string
description?: string
}

interface TableProps {
columnHeaders: Header[]
rowHeaders: Header[]
rows: CellContent[][]
summary: string
}

const getStatusColor = (status: 'bad' | 'neutral' | 'good') => {
switch (status) {
case 'bad':
return '#FFEBEE'
case 'neutral':
return '#FFFDE7'
case 'good':
return '#E8F5E9'
default:
return 'white'
}
}

const tableCellSx = {
backgroundColor: 'background.paper',
border: '1px solid rgba(224, 224, 224, 1)',
'&:hover': {
backgroundColor: 'grey.200'
}
}

const TableHeaderCell: React.FC<{ name: string; description?: string }> = ({
name,
description
}) => {
return (
<TableCell sx={tableCellSx}>
<Typography
variant="subtitle1"
sx={{ fontWeight: 'bold', textAlign: 'center' }}
>
{name}
</Typography>
{description && (
<Typography
variant="body2"
sx={{
fontSize: '0.8rem',
textAlign: 'center',
maxWidth: 200,
wordWrap: 'break-word',
margin: 'auto'
}}
>
{description}
</Typography>
)}
</TableCell>
)
}

export const ComparisonTable: React.FC<TableProps> = ({
columnHeaders,
rowHeaders,
rows,
summary
}) => {
return (
<Box>
<TableContainer component={Paper}>
<Table sx={{ minWidth: 650 }} aria-label="comparison table">
<TableHead>
<TableRow>
<TableCell sx={tableCellSx}></TableCell>
{columnHeaders.map(({ name, description }) => (
<TableHeaderCell
key={name}
name={name}
description={description}
/>
))}
</TableRow>
</TableHead>
<TableBody>
{rows.map((row, rowIndex) => (
<TableRow key={rowIndex}>
<TableHeaderCell
key={rowHeaders[rowIndex].name}
name={rowHeaders[rowIndex].name}
description={
rowHeaders[rowIndex].description
}
/>
{row.map((cell, cellIndex) => (
<TableCell
key={cellIndex}
align="center"
sx={{
...tableCellSx,
backgroundColor: getStatusColor(
cell.status
)
}}
>
<span>{cell.content}</span>
</TableCell>
))}
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
<Typography
variant="body1"
sx={{ fontWeight: 'bold', marginTop: 2 }}
>
Summary:
</Typography>
<Typography variant="body1">{summary}</Typography>
<Divider sx={{ marginTop: 2, marginBottom: 4 }} />
</Box>
)
}
3 changes: 2 additions & 1 deletion src/pages/blog/[slug].js
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,11 @@ import Youtube from '@Components/Youtube'
import Timeline from '@Components/Timeline'
import Table from '@Components/Table'
import Alert from '@Components/Alert'
import { ComparisonTable } from '@Components/ComparisonTable'

import 'prism-theme-night-owl'

const components = { Figure, Youtube, Timeline, Table, Alert }
const components = { Figure, Youtube, Timeline, Table, Alert, ComparisonTable }
export default function Posts({ source, data }) {
return (
<div style={{ maxWidth: '960px', margin: 'auto' }}>
Expand Down
94 changes: 94 additions & 0 deletions tst/components/ComparisonTable.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import { render } from '@testing-library/react'
import { ComparisonTable } from '@Components/ComparisonTable'

describe('ComparisonTable', () => {
const setup = ({} = {}) => {
const queries = render(
<ComparisonTable
columnHeaders={[
{
name: 'Feature A',
description: 'Description for Feature A'
},
{
name: 'Feature B',
description: 'Description for Feature B'
},
{
name: 'Feature C',
description: 'Description for Feature C'
}
]}
rowHeaders={[
{
name: 'Option 1',
description: 'Description for Option 1'
},
{
name: 'Option 2',
description: 'Description for Option 2'
},
{
name: 'Option 3',
description: `A very long descripition that needs more than one line`
}
]}
rows={[
[
{
content: 'Good',
status: 'good'
},
{
content: 'Average',
status: 'neutral'
},
{
content: 'Poor',
status: 'bad'
}
],
[
{
content: 'Poor',
status: 'bad'
},
{
content: 'Good',
status: 'good'
},
{
content: 'Average',
status: 'neutral'
}
],
[
{
content: 'Average',
status: 'neutral'
},
{
content: 'Poor',
status: 'bad'
},
{
content:
'Very long content that needs more than one line',
status: 'good'
}
]
]}
summary="summary"
/>
)
return queries
}

it('renders correctly', () => {
setup()

const { asFragment } = setup()

expect(asFragment()).toMatchSnapshot()
})
})
Loading

1 comment on commit 1d4e8ef

@vercel
Copy link

@vercel vercel bot commented on 1d4e8ef Jun 1, 2024

Choose a reason for hiding this comment

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

Please sign in to comment.