diff --git a/docs/src/components/Sidebar.js b/docs/src/components/Sidebar.js index 18478b4..8888707 100644 --- a/docs/src/components/Sidebar.js +++ b/docs/src/components/Sidebar.js @@ -56,6 +56,10 @@ const sidebarLinks = [ name: 'Tabs', ref: '/tab', }, + { + name:'Table', + ref:'/table' + } ]; export const cssNavLink = css` diff --git a/docs/src/pages/table.md b/docs/src/pages/table.md new file mode 100644 index 0000000..5aa4146 --- /dev/null +++ b/docs/src/pages/table.md @@ -0,0 +1,64 @@ +# Table + +Primitive checkbox component styled as Switch. + + + +```jsx + { + if (columnData >= 25) { + return

{columnData}

; + } + return

{columnData}

; + }, + }, + ]} + hoverable={true} +/> +``` + + + + + +### Props + +| Prop | Type | Description | +| ------------------------ | ------------------------ | ------------------------------------------------------------------------------------------------------------------ | +| `dataSource` | object | Source of the data applied to the table. . | +| `colNames` | object | Column names of the table. | +| `bordered` | boolean | Apply borders for the table. | +| `stripped` | boolean | Makes the table with zebra stripped pattern. | +| `hoverable` | boolean | Apply hover effect on the table. | +| `headerColor` | string | Change the header colour of the table.| +| `variant` | string | Property to apply customize modal styles with theme.json. Click [here](/theming) to know more about theming modals | diff --git a/docs/src/theme.js b/docs/src/theme.js index 8901d56..a0b851b 100644 --- a/docs/src/theme.js +++ b/docs/src/theme.js @@ -126,6 +126,26 @@ export default { }, }, }, + table: { + primary: { + container: { + width: 750, + bg: 'white', + }, + td: { + fontSize: 14, + p: 10, + }, + th: { + fontSize: 16, + p: 10, + fontWeight: 'bold', + }, + headerText: { + mr: 10, + }, + }, + }, switch: { sm: { @@ -245,7 +265,7 @@ export default { }, }, }, - + inputGroup: { primary: { marginTop: '10px', @@ -298,7 +318,6 @@ export default { separater: { mx: 3, }, - }, }, }; diff --git a/src/components/index.js b/src/components/index.js index dfddf7d..f6f0fbe 100644 --- a/src/components/index.js +++ b/src/components/index.js @@ -1,24 +1,25 @@ -export * from 'theme-ui'; +export * from "theme-ui"; -export { Relative, Absolute, Fixed, Sticky } from './position'; -export { Inline, InlineBlock, InlineFlex } from './layout'; -export Background from './background'; -export Input from './input'; -export Textarea from './textArea'; -export Select from './select'; -export IconButton from './iconButton'; -export Truncate from './truncate'; -export ReadMore from './readMore'; -export Hide from './hide'; -export withBeforeAfter from './withBeforeAfter'; -export Tooltip from './tooltip'; -export { Modal, openModal, closeModal, PortableModalContainer } from './modal'; -export { Toast, openToast, PortableToastContainer } from './toast'; -export DropdownMenu from './dropdownMenu'; -export Pill from './pill'; -export Switch from './switch'; -export ButtonGroup from './buttonGroup'; -export InputGroup from './inputGroup'; -export Tabs from './tab'; -export Collapse from './collapse'; -export Breadcrumbs from './breadcrumbs'; +export { Relative, Absolute, Fixed, Sticky } from "./position"; +export { Inline, InlineBlock, InlineFlex } from "./layout"; +export Background from "./background"; +export Input from "./input"; +export Textarea from "./textArea"; +export Select from "./select"; +export IconButton from "./iconButton"; +export Truncate from "./truncate"; +export ReadMore from "./readMore"; +export Hide from "./hide"; +export withBeforeAfter from "./withBeforeAfter"; +export Tooltip from "./tooltip"; +export { Modal, openModal, closeModal, PortableModalContainer } from "./modal"; +export { Toast, openToast, PortableToastContainer } from "./toast"; +export DropdownMenu from "./dropdownMenu"; +export Pill from "./pill"; +export Switch from "./switch"; +export ButtonGroup from "./buttonGroup"; +export InputGroup from "./inputGroup"; +export Tabs from "./tab"; +export Collapse from "./collapse"; +export Breadcrumbs from "./breadcrumbs"; +export Table from "./table"; diff --git a/src/components/table/components.js b/src/components/table/components.js new file mode 100644 index 0000000..774eace --- /dev/null +++ b/src/components/table/components.js @@ -0,0 +1,86 @@ +import styled from '@emotion/styled'; +import { Box, Text, css } from 'theme-ui'; +import { applyVariation } from '../../utils/getStyles'; + +const TableContainer = styled(Box)` + ${({ theme }) => + css({ + overflowX: 'auto', + })(theme)} + ${({ theme, variant }) => + applyVariation(theme, `${variant}.container`, 'table')} +`; + +const DefaultTable = styled.table` + ${({ theme }) => + css({ + borderCollapse: 'collapse', + width: '100%', + })(theme)} + ${({ theme, variant }) => applyVariation(theme, `${variant}.table`, 'table')} +`; + +const Tr = styled.tr` + ${({ theme, stripped = false, hoverable = false, bordered = true }) => + css({ + textAlign: 'left', + ...(stripped ? { ':nth-child(odd)': { bg: '#f2f2f2' } } : null), + ...(hoverable ? { '&:hover': { bg: '#f2f2f2' } } : null), + ...(bordered ? { border: '1px solid #dddddd' } : null), + })(theme)} + ${({ theme, variant }) => applyVariation(theme, `${variant}.tr`, 'table')} +`; + +const Td = styled.td` + ${({ theme }) => + css({ + bg: 'inherit', + color: 'inherit', + })(theme)} + ${({ theme, variant }) => applyVariation(theme, `${variant}.td`, 'table')} +`; + +const Th = styled.th` + ${({ theme, headerColor, sortable }) => + css({ + bg: headerColor.length > 0 ? headerColor : 'inherit', + cursor: sortable ? 'pointer' : 'default', + color: 'inherit', + })(theme)} + ${({ theme, variant }) => applyVariation(theme, `${variant}.th`, 'table')} +`; + +const ArrowIcon = styled(Box)` + ${({ theme, ascendingOrder }) => + css({ + transition: 'all 0.3s ease-in-out', + cursor: 'pointer', + transform: ascendingOrder === 'true' ? 'rotate(0)' : 'rotate(-180deg)', + })(theme)} + ${({ theme, variant }) => + applyVariation(theme, `${variant}.arrowIcon`, 'table')} +`; + +const HeaderContainer = styled(Box)` + ${({ theme }) => + css({ + display: 'flex', + alignItems: 'center', + })(theme)} + ${({ theme, variant }) => + applyVariation(theme, `${variant}.headerContainer`, 'table')} +`; +const HeaderText = styled(Text)(({ theme, variant = 'primary' }) => + applyVariation(theme, `${variant}.headerText`, 'table') +); + +export { + TableContainer, + DefaultTable, + Tr, + Td, + Th, + ArrowIcon, + HeaderContainer, + HeaderText, +}; diff --git a/src/components/table/index.js b/src/components/table/index.js new file mode 100644 index 0000000..a55788e --- /dev/null +++ b/src/components/table/index.js @@ -0,0 +1,179 @@ +/* eslint-disable react/jsx-props-no-spreading */ +import React, { useEffect, useState } from 'react'; +import PropTypes from 'prop-types'; + +import { + DefaultTable, + TableContainer, + Tr, + Td, + Th, + ArrowIcon, + HeaderContainer, + HeaderText, +} from './components'; + +const Table = ({ + dataSource, + colNames, + headerColor, + variant, + sortIcon, + stripped, + hoverable, + bordered, + ...rest +}) => { + const [obtainedDataSource, setObtainedDataSource] = useState(dataSource); + const [ascendingOrder, setAscendingOrder] = useState([]); + + const sort = (key, index, desc = false) => { + const newObtainedDataSource = [...obtainedDataSource]; + newObtainedDataSource.sort((a, b) => { + const value1 = String(a[key]).toLowerCase(); + const value2 = String(b[key]).toLowerCase(); + if (value1 > value2) return desc ? 1 : -1; + if (value1 < value2) return desc ? -1 : 1; + return 0; + }); + setObtainedDataSource(newObtainedDataSource); + const newSortIndex = [...ascendingOrder]; + newSortIndex[index] = !newSortIndex[index]; + setAscendingOrder(newSortIndex); + }; + useEffect(() => { + const newAscendingOrder = colNames.map((colName) => { + if (colName.sortable) { + return true; + } + return null; + }); + setAscendingOrder(newAscendingOrder); + }, []); + + const tableHeaderClickHandler = (sortable, colSortOrder, key, index) => { + if (sortable) { + if (colSortOrder) { + sort(key, index, true); + } else { + sort(key, index); + } + } + }; + + return ( + + + + + {colNames.map((colName, index) => ( + + ))} + + + + {obtainedDataSource.map((data, index) => { + return ( + + {colNames.map((colName, columnIndex) => { + if (colName.render !== undefined) { + if (colName.key in data) { + return ( + + ); + } + + return null; + } + if (colName.key in data) { + return ( + + ); + } + return null; + })} + + ); + })} + + + + ); +}; + +Table.propTypes = { + dataSource: PropTypes.arrayOf(PropTypes.object).isRequired, + colNames: PropTypes.arrayOf(PropTypes.object).isRequired, + headerColor: PropTypes.string, + variant: PropTypes.string, + sortIcon: PropTypes.node, + stripped: PropTypes.bool, + hoverable: PropTypes.bool, + bordered: PropTypes.bool, +}; +Table.defaultProps = { + headerColor: '', + variant: 'primary', + sortIcon: ( + + + + ), + stripped: false, + hoverable: false, + bordered: true, +}; + +export default Table;
+ tableHeaderClickHandler( + colName.sortable, + ascendingOrder[index], + colName.key, + index + ) + } + > + {colName.sortable ? ( + + {colName.title} + + {sortIcon} + + + ) : ( + {colName.title} + )} +
+ {colName.render(data[colName.key])} + + {data[colName.key]} +