Skip to content

Commit

Permalink
Optimize table code and make it responsive
Browse files Browse the repository at this point in the history
  • Loading branch information
vineethasok committed Nov 6, 2023
1 parent 991955c commit ca18089
Show file tree
Hide file tree
Showing 2 changed files with 134 additions and 85 deletions.
29 changes: 12 additions & 17 deletions src/components/Table/Table.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
import { Table } from "./Table";

const headers = [{ label: "Company" }, { label: "Contact" }, { label: "Country" }];
const rows = [
[{ label: "Alfreds Futterkiste" }, { label: "Maria Anders" }, { label: "Germany" }],
[
{ label: "Centro comercial Moctezuma" },
{ label: "Francisco Chang" },
{ label: "Mexico" },
],
];

export default {
component: Table,
title: "Display/Table",
Expand All @@ -8,22 +18,7 @@ export default {

export const Playground = {
args: {
children: [
<Table.Tr type="header">
<Table.Th>Company</Table.Th>
<Table.Th>Contact</Table.Th>
<Table.Th>Country</Table.Th>
</Table.Tr>,
<Table.Tr>
<Table.Td>Alfreds Futterkiste</Table.Td>
<Table.Td>Maria Anders</Table.Td>
<Table.Td>Germany</Table.Td>
</Table.Tr>,
<Table.Tr>
<Table.Td>Centro comercial Moctezuma</Table.Td>
<Table.Td>Francisco Chang</Table.Td>
<Table.Td>Mexico</Table.Td>
</Table.Tr>,
],
headers,
rows,
},
};
190 changes: 122 additions & 68 deletions src/components/Table/Table.tsx
Original file line number Diff line number Diff line change
@@ -1,100 +1,161 @@
import { Icon, IconName } from "@/components";
import { HTMLAttributes, forwardRef } from "react";
import { HorizontalDirection, Icon, IconName } from "@/components";
import { HTMLAttributes, ReactNode, forwardRef } from "react";
import styled from "styled-components";

type TableHeaderProps = {
children: React.ReactNode;
leftIcon?: IconName;
rightIcon?: IconName;
};
type TableRowType = "header" | "default";
interface TableHeaderProps extends HTMLAttributes<HTMLTableCellElement> {
icon?: IconName;
iconDir?: HorizontalDirection;
label: ReactNode;
}
const StyledHeader = styled.th`
padding: 0.75rem 1rem;
font: ${props => props.theme.click.table.header.title.default};
color: ${props => props.theme.click.table.header.color.title.default};
gap: 4px;
${({ theme }) => `
padding: ${theme.click.table.header.cell.space.md.y}
${theme.click.table.body.cell.space.md.x};
font: ${theme.click.table.header.title.default};
color: ${theme.click.table.header.color.title.default};
`}
gap: 0.25rem;
text-align: left;
`;

const HeaderContentWrapper = styled.div`
display: flex;
align-items: center;
justify-content: start;
gap: 4px;
gap: inherit;
`;

const TableHeader = ({
leftIcon,
rightIcon,
children,
icon,
iconDir = "end",
label,
...delegated
}: TableHeaderProps) => (
<StyledHeader {...delegated}>
<HeaderContentWrapper>
{leftIcon && (
{icon && iconDir == "start" && (
<Icon
name={leftIcon}
width="12px"
height="12px"
name={icon}
size="sm"
/>
)}
{children}
{rightIcon && (
{label}
{icon && iconDir == "end" && (
<Icon
name={rightIcon}
width="12px"
height="12px"
name={icon}
size="sm"
/>
)}
</HeaderContentWrapper>
</StyledHeader>
);

const StyledTableRow = styled.tr<{ $type?: TableRowType }>`
const TableRow = styled.tr`
overflow: hidden;
${({ $type = "default", theme }) =>
$type === "default"
? `
background-color: ${theme.click.table.row.color.background.default};
border-bottom: 1px solid ${theme.click.table.row.color.stroke.default};
&:active {
background-color: ${theme.click.table.row.color.background.active};
}
&:hover {
background-color: ${theme.click.table.row.color.background.hover};
}
`
: `background-color: ${theme.click.table.header.color.background.default};`}
${({ theme }) => `
background-color: ${theme.click.table.row.color.background.default};
border-bottom: 1px solid ${theme.click.table.row.color.stroke.default};
&:active {
background-color: ${theme.click.table.row.color.background.active};
}
&:hover {
background-color: ${theme.click.table.row.color.background.hover};
}
`}
&:last-of-type {
border-bottom: none;
}
`;
const TableRow = ({
type,
...props
}: HTMLAttributes<HTMLTableRowElement> & { type?: TableRowType }) => {
return (
<StyledTableRow
$type={type}
{...props}
/>
);
};
@media (max-width: 768px) {
display: flex;
flex-wrap: wrap;
${({ theme }) => `
border: 1px solid ${theme.click.table.row.color.stroke.default};
border-radius: ${theme.click.table.radii.all};
`}
}
`;

const TableData = styled.td`
font: ${props => props.theme.click.table.cell.label.default};
padding: 0.75rem 1rem;
overflow: hidden;
${({ theme }) => `
color: ${theme.click.table.row.color.text.default};
font: ${theme.click.table.cell.text.default};
padding: ${theme.click.table.body.cell.space.md.y} ${theme.click.table.body.cell.space.md.x};
`}
@media (max-width: 768px) {
width: auto;
min-width: 40%;
padding: ${({ theme }) => theme.click.table.body.cell.space.sm.y}
${({ theme }) => theme.click.table.body.cell.space.sm.x};
}
`;

const THead = styled.thead`
tr {
overflow: hidden;
background-color: ${({ theme }) => theme.click.table.header.color.background.default};
}
@media (max-width: 768px) {
display: none;
}
`;

const Table = forwardRef<HTMLTableElement, HTMLAttributes<HTMLTableElement>>(
(props, ref) => (
const MobileHeader = styled.span`
display: none;
${({ theme }) => `
color: ${theme.click.table.row.color.label.default};
font: ${theme.click.table.cell.label.default};
`}
@media (max-width: 768px) {
display: block;
}
`;
const Tbody = styled.tbody`
@media (max-width: 768px) {
display: flex;
flex-direction: column;
gap: 0.25rem;
}
`;
interface TableCellType extends HTMLAttributes<HTMLTableCellElement> {
label: ReactNode;
}
type TableRowType = Array<TableCellType>;
interface TableProps extends HTMLAttributes<HTMLTableElement> {
headers: Array<TableHeaderProps>;
rows: Array<TableRowType>;
}
const Table = forwardRef<HTMLTableElement, TableProps>(
({ headers, rows, ...props }, ref) => (
<StyledTable
ref={ref}
{...props}
/>
>
<THead>
<tr>
{headers.map((headerProps, index) => (
<TableHeader
key={`table-header-${index}`}
{...headerProps}
/>
))}
</tr>
</THead>
<Tbody>
{rows.map(row => (
<TableRow>
{row.map(({ label, ...cellProps }, index) => (
<TableData {...cellProps}>
{headers[index] && <MobileHeader>{headers[index].label}</MobileHeader>}
<span>{label}</span>
</TableData>
))}
</TableRow>
))}
</Tbody>
</StyledTable>
)
);

Expand All @@ -105,17 +166,10 @@ const StyledTable = styled.table`
border-radius: ${theme.click.table.radii.all};
border: 1px solid ${theme.click.table.global.color.stroke.default};
`}
`;

TableHeader.displayName = "Table.Th";
TableData.displayName = "Table.Td";

TableRow.displayName = "Table.Tr";
@media (max-width: 768px) {
border: none;
}
`;

const TableNamespace = Object.assign(Table, {
Th: TableHeader,
Td: TableData,
Tr: TableRow,
});
export { TableNamespace as Table };
export { Table };

0 comments on commit ca18089

Please sign in to comment.