diff --git a/lib/src/resultsetTable/Icons.tsx b/lib/src/resultsetTable/Icons.tsx new file mode 100644 index 000000000..f9ab7ad20 --- /dev/null +++ b/lib/src/resultsetTable/Icons.tsx @@ -0,0 +1,24 @@ +import React from "react"; + +const icons = { + arrowUp: ( + + + + + ), + arrowDown: ( + + + + + ), + bothArrows: ( + + + + + ), +}; + +export default icons; diff --git a/lib/src/resultsetTable/ResultsetTable.stories.tsx b/lib/src/resultsetTable/ResultsetTable.stories.tsx index 2ca48f673..838c57b74 100644 --- a/lib/src/resultsetTable/ResultsetTable.stories.tsx +++ b/lib/src/resultsetTable/ResultsetTable.stories.tsx @@ -4,6 +4,7 @@ import DxcButton from "../button/Button"; import Title from "../../.storybook/components/Title"; import ExampleContainer from "../../.storybook/components/ExampleContainer"; import { userEvent, within } from "@storybook/testing-library"; +import styled from "styled-components"; export default { title: "Resultset Table", @@ -48,6 +49,24 @@ const columnsSortable = [ { displayValue: "City", isSortable: false }, ]; +const longValues = [ + [ + { displayValue: "000000000000000001", sortValue: "000000000000000001" }, + { displayValue: "Peter Larsson González", sortValue: "Peter" }, + { displayValue: "Miami: The city that never sleeps", sortValue: "Miami" }, + ], + [ + { displayValue: "002", sortValue: "002" }, + { displayValue: "Louis", sortValue: "Louis" }, + { displayValue: "London", sortValue: "London" }, + ], + [ + { displayValue: "003", sortValue: "003" }, + { displayValue: "Aida", sortValue: "Aida" }, + { displayValue: "Wroclaw", sortValue: "Wroclaw" }, + ], +]; + const rowsSortable = [ [ { displayValue: "001", sortValue: "001" }, @@ -167,89 +186,95 @@ export const Chromatic = () => ( <> - <DxcResultsetTable columns={columnsSortable} rows={rowsSortable}></DxcResultsetTable> + <DxcResultsetTable columns={columnsSortable} rows={rowsSortable} /> </ExampleContainer> <ExampleContainer> <Title title="With action" theme="light" level={4} /> - <DxcResultsetTable columns={columns} rows={rowsIcon}></DxcResultsetTable> + <DxcResultsetTable columns={columns} rows={rowsIcon} /> </ExampleContainer> <ExampleContainer> <Title title="With items per page option" theme="light" level={4} /> - <DxcResultsetTable - columns={columns} - rows={rows} - itemsPerPage={2} - itemsPerPageOptions={[2, 3]} - ></DxcResultsetTable> + <DxcResultsetTable columns={columns} rows={rows} itemsPerPage={2} itemsPerPageOptions={[2, 3]} /> </ExampleContainer> <ExampleContainer> <Title title="Scroll resultset table" theme="light" level={4} /> - <DxcResultsetTable columns={longColumns} rows={longRows}></DxcResultsetTable> + <DxcResultsetTable columns={longColumns} rows={longRows} /> + </ExampleContainer> + <ExampleContainer> + <SmallContainer> + <Title title="Small container and text overflow" theme="light" level={4} /> + <DxcResultsetTable columns={columnsSortable} rows={longValues} /> + </SmallContainer> </ExampleContainer> <Title title="Margins" theme="light" level={2} /> <ExampleContainer> <Title title="Xxsmall" theme="light" level={4} /> - <DxcResultsetTable columns={columns} rows={rows} margin={"xxsmall"}></DxcResultsetTable> + <DxcResultsetTable columns={columns} rows={rows} margin={"xxsmall"} /> </ExampleContainer> <ExampleContainer> <Title title="Xsmall" theme="light" level={4} /> - <DxcResultsetTable columns={columns} rows={rows} margin={"xsmall"}></DxcResultsetTable> + <DxcResultsetTable columns={columns} rows={rows} margin={"xsmall"} /> </ExampleContainer> <ExampleContainer> <Title title="Small" theme="light" level={4} /> - <DxcResultsetTable columns={columns} rows={rows} margin={"small"}></DxcResultsetTable> + <DxcResultsetTable columns={columns} rows={rows} margin={"small"} /> </ExampleContainer> <ExampleContainer> <Title title="Medium" theme="light" level={4} /> - <DxcResultsetTable columns={columns} rows={rows} margin={"medium"}></DxcResultsetTable> + <DxcResultsetTable columns={columns} rows={rows} margin={"medium"} /> </ExampleContainer> <ExampleContainer> <Title title="Large" theme="light" level={4} /> - <DxcResultsetTable columns={columns} rows={rows} margin={"large"}></DxcResultsetTable> + <DxcResultsetTable columns={columns} rows={rows} margin={"large"} /> </ExampleContainer> <ExampleContainer> <Title title="Xlarge" theme="light" level={4} /> - <DxcResultsetTable columns={columns} rows={rows} margin={"xlarge"}></DxcResultsetTable> + <DxcResultsetTable columns={columns} rows={rows} margin={"xlarge"} /> </ExampleContainer> - <ExampleContainer> + <ExampleContainer expanded> <Title title="Xxlarge" theme="light" level={4} /> - <DxcResultsetTable columns={columns} rows={rows} margin={"xxlarge"}></DxcResultsetTable> - <hr /> + <DxcResultsetTable columns={columns} rows={rows} margin={"xxlarge"} /> </ExampleContainer> </> ); +const SmallContainer = styled.div` + width: 500px; +`; + const ResultsetTableAsc = () => ( <ExampleContainer> <Title title="Ascendant sorting" theme="light" level={4} /> - <DxcResultsetTable columns={columnsSortable} rows={rowsSortable}></DxcResultsetTable> + <DxcResultsetTable columns={columnsSortable} rows={rowsSortable} /> </ExampleContainer> ); export const AscendentSorting = ResultsetTableAsc.bind({}); AscendentSorting.play = async ({ canvasElement }) => { const canvas = within(canvasElement); - await userEvent.click(canvas.queryByText("Name")); + const idHeader = canvas.getAllByRole("button")[0]; + await userEvent.click(idHeader); }; const ResultsetTableDesc = () => ( <ExampleContainer> <Title title="Descendant sorting" theme="light" level={4} /> - <DxcResultsetTable columns={columnsSortable} rows={rowsSortable}></DxcResultsetTable> + <DxcResultsetTable columns={columnsSortable} rows={rowsSortable} /> </ExampleContainer> ); export const DescendantSorting = ResultsetTableDesc.bind({}); DescendantSorting.play = async ({ canvasElement }) => { const canvas = within(canvasElement); - await userEvent.click(canvas.queryByText("Name")); - await userEvent.click(canvas.queryByText("Name")); + const nameHeader = canvas.getAllByRole("button")[1]; + await userEvent.click(nameHeader); + await userEvent.click(nameHeader); }; const ResultsetTableMiddle = () => ( <ExampleContainer> <Title title="Middle page" theme="light" level={4} /> - <DxcResultsetTable columns={columns} rows={rows} itemsPerPage={2}></DxcResultsetTable> + <DxcResultsetTable columns={columns} rows={rows} itemsPerPage={2} /> </ExampleContainer> ); @@ -263,7 +288,7 @@ MiddlePage.play = async ({ canvasElement }) => { const ResultsetTableLast = () => ( <ExampleContainer> <Title title="Last page" theme="light" level={4} /> - <DxcResultsetTable columns={columns} rows={rows} itemsPerPage={2}></DxcResultsetTable> + <DxcResultsetTable columns={columns} rows={rows} itemsPerPage={2} /> </ExampleContainer> ); diff --git a/lib/src/resultsetTable/ResultsetTable.test.js b/lib/src/resultsetTable/ResultsetTable.test.js index cf7aa92a1..0ba8a0b45 100644 --- a/lib/src/resultsetTable/ResultsetTable.test.js +++ b/lib/src/resultsetTable/ResultsetTable.test.js @@ -34,7 +34,6 @@ const columns = [ isSortable: false, }, ]; - const rows = [ [ { @@ -63,9 +62,6 @@ const rows = [ displayValue: "Oviedo", sortValue: "Oviedo", }, - { - displayValue: "", - }, ], [ { @@ -122,9 +118,6 @@ const rows = [ displayValue: "Barcelona", sortValue: "Barcelona", }, - { - displayValue: "", - }, ], [ { @@ -167,9 +160,6 @@ const rows = [ displayValue: "Oviedo", sortValue: "Oviedo", }, - { - displayValue: "", - }, ], [ { @@ -184,12 +174,8 @@ const rows = [ displayValue: "Barcelona", sortValue: "Barcelona", }, - { - displayValue: "", - }, ], ]; - const rows2 = [ [ { @@ -238,77 +224,59 @@ const rows2 = [ ], ]; -describe("ResultsetTable component tests", () => { - test("ResultsetTable rendered correctly", () => { - const { getByText } = render( - <DxcResultsetTable columns={columns} rows={rows} itemsPerPage={3}></DxcResultsetTable> - ); +describe("Resultset table component tests", () => { + test("Resultset table rendered correctly", () => { + const { getByText } = render(<DxcResultsetTable columns={columns} rows={rows} itemsPerPage={3} />); expect(getByText("Peter")).toBeTruthy(); }); - test("Resultsettable shows as many rows as itemsPerPage", () => { - const { getAllByRole } = render( - <DxcResultsetTable columns={columns} rows={rows} itemsPerPage={3}></DxcResultsetTable> - ); + test("Resultset table shows as many rows as itemsPerPage", () => { + const { getAllByRole } = render(<DxcResultsetTable columns={columns} rows={rows} itemsPerPage={3} />); expect(getAllByRole("row").length - 1).toEqual(3); }); - - test("Resultsettable shows rows on second page", () => { - const { getByText, getAllByRole } = render( - <DxcResultsetTable columns={columns} rows={rows} itemsPerPage={3}></DxcResultsetTable> - ); + test("Resultset table shows rows on second page", () => { + const { getByText, getAllByRole } = render(<DxcResultsetTable columns={columns} rows={rows} itemsPerPage={3} />); expect(getByText("Peter")).toBeTruthy(); expect(getByText("Louis")).toBeTruthy(); expect(getByText("Lana")).toBeTruthy(); expect(getAllByRole("row").length - 1).toEqual(3); - const nextButton = getAllByRole("button")[2]; + const nextButton = getAllByRole("button")[3]; fireEvent.click(nextButton); expect(getByText("4 to 6 of 10")).toBeTruthy(); - // expect(getByText("Page: 2 of 4")).toBeTruthy(); expect(getByText("Rick")).toBeTruthy(); expect(getByText("Mark")).toBeTruthy(); expect(getByText("Cris")).toBeTruthy(); expect(getAllByRole("row").length - 1).toEqual(3); }); - - test("Resultsettable goToPage works as expected", () => { + test("Resultset table goToPage works as expected", () => { window.HTMLElement.prototype.scrollIntoView = () => {}; window.HTMLElement.prototype.scrollTo = () => {}; - const { getByText, getAllByRole, getByRole } = render( - <DxcResultsetTable columns={columns} showGoToPage={true} rows={rows} itemsPerPage={3}></DxcResultsetTable> + const { getByText, getAllByRole } = render( + <DxcResultsetTable columns={columns} showGoToPage={true} rows={rows} itemsPerPage={3} /> ); expect(getByText("Peter")).toBeTruthy(); expect(getByText("Louis")).toBeTruthy(); expect(getByText("Lana")).toBeTruthy(); expect(getAllByRole("row").length - 1).toEqual(3); - const goToPageSelect = getAllByRole("button")[2]; - act(() => { - userEvent.click(goToPageSelect); - }); + const goToPageSelect = getAllByRole("button")[3]; + userEvent.click(goToPageSelect); const goToPageOption = getByText("2"); - act(() => { - userEvent.click(goToPageOption); - }); - + userEvent.click(goToPageOption); expect(getByText("4 to 6 of 10")).toBeTruthy(); expect(getByText("Rick")).toBeTruthy(); expect(getByText("Mark")).toBeTruthy(); expect(getByText("Cris")).toBeTruthy(); expect(getAllByRole("row").length - 1).toEqual(3); }); - - test("Resultsettable going to the last page shows only one row", () => { - const { getByText, getAllByRole } = render( - <DxcResultsetTable columns={columns} rows={rows} itemsPerPage={3}></DxcResultsetTable> - ); - const lastButton = getAllByRole("button")[3]; + test("Resultset table going to the last page shows only one row", () => { + const { getByText, getAllByRole } = render(<DxcResultsetTable columns={columns} rows={rows} itemsPerPage={3} />); + const lastButton = getAllByRole("button")[4]; fireEvent.click(lastButton); expect(getByText("10 to 10 of 10")).toBeTruthy(); expect(getAllByRole("row")).toHaveLength(2); expect(getByText("Cosmin")).toBeTruthy(); }); - - test("Resultsettable sort rows by column", () => { - const component = render(<DxcResultsetTable columns={columns} rows={rows} itemsPerPage={3}></DxcResultsetTable>); + test("Resultset table sort rows by column", () => { + const component = render(<DxcResultsetTable columns={columns} rows={rows} itemsPerPage={3} />); expect(component.queryByText("Peter")).toBeTruthy(); fireEvent.click(component.queryByText("Name")); expect(component.queryByText("Tina")).not.toBeTruthy(); @@ -318,29 +286,19 @@ describe("ResultsetTable component tests", () => { expect(component.queryByText("Tina")).toBeTruthy(); expect(component.queryByText("Cosmin")).not.toBeTruthy(); }); - test("Resultsettable change rows should go to first page", () => { - const { queryByText, rerender } = render( - <DxcResultsetTable columns={columns} rows={rows} itemsPerPage={3}></DxcResultsetTable> - ); + test("Resultset table change rows should go to first page", () => { + const { queryByText, rerender } = render(<DxcResultsetTable columns={columns} rows={rows} itemsPerPage={3} />); expect(queryByText("Peter")).toBeTruthy(); - rerender(<DxcResultsetTable columns={columns} rows={rows2} itemsPerPage={3}></DxcResultsetTable>); + rerender(<DxcResultsetTable columns={columns} rows={rows2} itemsPerPage={3} />); expect(queryByText("1 to 3 of 3")).toBeTruthy(); }); - - test("Resultsettable change itemsPerPage should go to first page", () => { - const { getAllByRole, queryByText, rerender } = render( - <DxcResultsetTable - columns={columns} - rows={rows} - itemsPerPage={3} - itemsPerPageOptions={[2, 3]} - ></DxcResultsetTable> + test("Resultset table change itemsPerPage should go to first page", () => { + const { getAllByRole } = render( + <DxcResultsetTable columns={columns} rows={rows} itemsPerPage={3} itemsPerPageOptions={[2, 3]} /> ); - const lastButton = getAllByRole("button")[3]; + const lastButton = getAllByRole("button")[4]; + expect(getAllByRole("row").length - 1).toEqual(3); fireEvent.click(lastButton); expect(getAllByRole("row").length - 1).toEqual(1); - rerender(<DxcResultsetTable columns={columns} rows={rows} itemsPerPage={6}></DxcResultsetTable>); - expect(getAllByRole("row").length - 1).toEqual(6); - expect(queryByText("Peter")).toBeTruthy(); }); }); diff --git a/lib/src/resultsetTable/ResultsetTable.tsx b/lib/src/resultsetTable/ResultsetTable.tsx index 2da2762f7..558fc4616 100644 --- a/lib/src/resultsetTable/ResultsetTable.tsx +++ b/lib/src/resultsetTable/ResultsetTable.tsx @@ -1,18 +1,17 @@ -// @ts-nocheck import React, { useState, useMemo, useEffect } from "react"; import styled, { ThemeProvider } from "styled-components"; import { spaces } from "../common/variables.js"; import DxcTable from "../table/Table"; import DxcPaginator from "../paginator/Paginator"; import useTheme from "../useTheme"; -import ResultsetTablePropsType from "./types"; +import ResultsetTablePropsType, { Margin, Space } from "./types"; +import icons from "./Icons"; +import { getMargin } from "../common/utils.js"; -function normalizeSortValue(sortValue) { - return typeof sortValue === "string" ? sortValue.toUpperCase() : sortValue; -} +const normalizeSortValue = (sortValue) => (typeof sortValue === "string" ? sortValue.toUpperCase() : sortValue); -function sortArray(index, order, resultset) { - return resultset.slice().sort((element1, element2) => { +const sortArray = (index, order, resultset) => + resultset.slice().sort((element1, element2) => { const sortValueA = normalizeSortValue(element1[index].sortValue || element1[index].displayValue); const sortValueB = normalizeSortValue(element2[index].sortValue || element2[index].displayValue); let comparison = 0; @@ -25,36 +24,15 @@ function sortArray(index, order, resultset) { } else if (sortValueA < sortValueB) { comparison = -1; } - return order === "desc" ? comparison * -1 : comparison; + return order === "descending" ? comparison * -1 : comparison; }); -} + const getMinItemsPerPageIndex = (currentPageInternal, itemsPerPage, page) => currentPageInternal === 1 ? 0 : itemsPerPage * (page - 1); const getMaxItemsPerPageIndex = (minItemsPerPageIndex, itemsPerPage, resultset, page) => minItemsPerPageIndex + itemsPerPage > resultset.length ? resultset.length : itemsPerPage * page - 1; -const ArrowUp = () => ( - <svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24" fill="currentColor"> - <path d="M0 0h24v24H0V0z" fill="none" /> - <path d="M4 12l1.41 1.41L11 7.83V20h2V7.83l5.58 5.59L20 12l-8-8-8 8z" /> - </svg> -); - -const ArrowDown = () => ( - <svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24" fill="currentColor"> - <path d="M0 0h24v24H0V0z" fill="none" /> - <path d="M20 12l-1.41-1.41L13 16.17V4h-2v12.17l-5.58-5.59L4 12l8 8 8-8z" /> - </svg> -); - -const BothArrows = () => ( - <svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24" fill="currentColor"> - <path d="M0 0h24v24H0z" fill="none" /> - <path d="M12 5.83L15.17 9l1.41-1.41L12 3 7.41 7.59 8.83 9 12 5.83zm0 12.34L8.83 15l-1.41 1.41L12 21l4.59-4.59L15.17 15 12 18.17z" /> - </svg> -); - const DxcResultsetTable = ({ columns, rows, @@ -67,126 +45,119 @@ const DxcResultsetTable = ({ }: ResultsetTablePropsType): JSX.Element => { const colorsTheme = useTheme(); const [page, changePage] = useState(1); - const [sortColumnIndex, changeSortColumnIndex] = useState(""); - const [sortOrder, changeSortOrder] = useState("asc"); + const [sortColumnIndex, changeSortColumnIndex] = useState(-1); + const [sortOrder, changeSortOrder] = useState<"ascending" | "descending">("ascending"); const minItemsPerPageIndex = useMemo(() => getMinItemsPerPageIndex(page, itemsPerPage, page), [itemsPerPage, page]); const maxItemsPerPageIndex = useMemo( () => getMaxItemsPerPageIndex(minItemsPerPageIndex, itemsPerPage, rows, page), [itemsPerPage, minItemsPerPageIndex, page, rows] ); + const sortedResultset = useMemo( + () => (sortColumnIndex !== -1 ? sortArray(sortColumnIndex, sortOrder, rows) : rows), + [sortColumnIndex, sortOrder, rows] + ); + const filteredResultset = useMemo( + () => sortedResultset && sortedResultset.slice(minItemsPerPageIndex, maxItemsPerPageIndex + 1), + [sortedResultset, minItemsPerPageIndex, maxItemsPerPageIndex] + ); - const goToPage = (newPage) => { + const goToPage = (newPage: number) => { changePage(newPage); }; - const changeSorting = (columnIndex) => { + + const changeSorting = (columnIndex: number) => { changePage(1); changeSortColumnIndex(columnIndex); changeSortOrder( - sortColumnIndex === "" || sortColumnIndex !== columnIndex ? "asc" : sortOrder === "asc" ? "desc" : "asc" + sortColumnIndex === -1 || sortColumnIndex !== columnIndex + ? "ascending" + : sortOrder === "ascending" + ? "descending" + : "ascending" ); }; - const getIconForSortableColumn = (clickedColumnIndex) => { - return sortColumnIndex === clickedColumnIndex ? sortOrder === "asc" ? <ArrowUp /> : <ArrowDown /> : <BothArrows />; - }; useEffect(() => { - if (rows.length > 0) { - changePage(1); - } else { - changePage(0); - } - }, [rows.length, itemsPerPage]); - - const sortedResultset = useMemo( - () => (sortColumnIndex !== "" ? sortArray(sortColumnIndex, sortOrder, rows) : rows), - [sortColumnIndex, sortOrder, rows] - ); - const filteredResultset = useMemo( - () => sortedResultset && sortedResultset.slice(minItemsPerPageIndex, maxItemsPerPageIndex + 1), - [sortedResultset, minItemsPerPageIndex, maxItemsPerPageIndex] - ); + rows.length > 0 ? changePage(1) : changePage(0); + }, [rows]); return ( <ThemeProvider theme={colorsTheme.table}> <DxcResultsetTableContainer margin={margin}> - <TableContainer> - <DxcTable> - <HeaderRow> - <tr> - {columns.map((column, index) => ( - <TableHeader key={`tableHeader_${index}`}> - <HeaderContainer - key={`headerContainer_${index}`} - onClick={() => column.isSortable && changeSorting(index)} - tabIndex={column.isSortable ? tabIndex : -1} - isSortable={column.isSortable} - > - <TitleDiv isSortable={column.isSortable}>{column.displayValue}</TitleDiv> - {column.isSortable && <SortIcon>{getIconForSortableColumn(index)}</SortIcon>} - </HeaderContainer> - </TableHeader> + <DxcTable> + <thead> + <tr> + {columns.map((column, index) => ( + <th + key={`tableHeader_${index}`} + aria-sort={column.isSortable ? (sortColumnIndex === index ? sortOrder : "none") : undefined} + > + <HeaderContainer + role={column.isSortable ? "button" : undefined} + key={`headerContainer_${index}`} + onClick={() => { + column.isSortable && changeSorting(index); + }} + tabIndex={column.isSortable ? tabIndex : -1} + isSortable={column.isSortable} + > + <span>{column.displayValue}</span> + {column.isSortable && ( + <SortIcon> + {sortColumnIndex === index + ? sortOrder === "ascending" + ? icons.arrowUp + : icons.arrowDown + : icons.bothArrows} + </SortIcon> + )} + </HeaderContainer> + </th> + ))} + </tr> + </thead> + <tbody> + {filteredResultset.map((cells, index) => ( + <tr key={`resultSetTableCell_${index}`}> + {cells.map((cellContent, index) => ( + <td key={`resultSetTableCellContent_${index}`}>{cellContent.displayValue}</td> ))} </tr> - </HeaderRow> - <TableRowGroup> - {filteredResultset.map((cells, index) => ( - <tr key={`resultSetTableCell_${index}`}> - {cells.map((cellContent, index) => ( - <td key={`resultSetTableCellContent_${index}`}>{cellContent.displayValue}</td> - ))} - </tr> - ))} - </TableRowGroup> - </DxcTable> - </TableContainer> - <PaginatorContainer> - <DxcPaginator - totalItems={rows.length} - itemsPerPage={itemsPerPage} - itemsPerPageOptions={itemsPerPageOptions} - itemsPerPageFunction={itemsPerPageFunction} - currentPage={page} - showGoToPage={showGoToPage} - onPageChange={goToPage} - tabIndex={tabIndex} - /> - </PaginatorContainer> + ))} + </tbody> + </DxcTable> + <DxcPaginator + totalItems={rows.length} + itemsPerPage={itemsPerPage} + itemsPerPageOptions={itemsPerPageOptions} + itemsPerPageFunction={itemsPerPageFunction} + currentPage={page} + showGoToPage={showGoToPage} + onPageChange={goToPage} + tabIndex={tabIndex} + /> </DxcResultsetTableContainer> </ThemeProvider> ); }; -const TableContainer = styled.div` - & table { - table-layout: auto; - } -`; -const PaginatorContainer = styled.div``; -const TableRowGroup = styled.tbody` - > div:nth-child(1) { - position: absolute; - left: calc(50% - 68.5px); - bottom: calc(50% - 68.5px - 30px); - } -`; -const SortIcon = styled.div` - top: 409px; - left: 390px; - height: 14px; - cursor: pointer; - color: ${(props) => props.theme.sortIconColor}; - svg { - height: 100%; - width: 100%; - } -`; +const calculateWidth = (margin) => `calc(100% - ${getMargin(margin, "left")} - ${getMargin(margin, "right")})`; -const TitleDiv = styled.div` - cursor: ${(props) => (props.isSortable && "pointer") || "default"}; +const DxcResultsetTableContainer = styled.div<{ margin: Space | Margin }>` + width: ${(props) => calculateWidth(props.margin)}; + margin: ${(props) => (props.margin && typeof props.margin !== "object" ? spaces[props.margin] : "0px")}; + margin-top: ${(props) => + props.margin && typeof props.margin === "object" && props.margin.top ? spaces[props.margin.top] : ""}; + margin-right: ${(props) => + props.margin && typeof props.margin === "object" && props.margin.right ? spaces[props.margin.right] : ""}; + margin-bottom: ${(props) => + props.margin && typeof props.margin === "object" && props.margin.bottom ? spaces[props.margin.bottom] : ""}; + margin-left: ${(props) => + props.margin && typeof props.margin === "object" && props.margin.left ? spaces[props.margin.left] : ""}; `; -const TableHeader = styled.th``; -const HeaderContainer = styled.div` + +const HeaderContainer = styled.span<{ isSortable: boolean }>` display: flex; align-items: center; justify-content: ${(props) => @@ -195,28 +166,30 @@ const HeaderContainer = styled.div` : props.theme.headerTextAlign === "right" ? "flex-end" : "flex-start"}; + gap: 8px; width: fit-content; - :focus { - ${(props) => - props.isSortable && - `outline: #0095ff solid 2px; - outline-offset: 4px;`} - } -`; -const HeaderRow = styled.thead` - height: 60px; + border: 1px solid transparent; + border-radius: 2px; + padding: 3px; + cursor: ${(props) => (props.isSortable ? "pointer" : "default")}; + + ${(props) => + props.isSortable && + `&:focus { + outline: #0095ff solid 2px; + }`} `; -const DxcResultsetTableContainer = styled.div` - font-size: ${(props) => props.theme.fontSizeBase}; - margin: ${(props) => (props.margin && typeof props.margin !== "object" ? spaces[props.margin] : "0px")}; - margin-top: ${(props) => - props.margin && typeof props.margin === "object" && props.margin.top ? spaces[props.margin.top] : ""}; - margin-right: ${(props) => - props.margin && typeof props.margin === "object" && props.margin.right ? spaces[props.margin.right] : ""}; - margin-bottom: ${(props) => - props.margin && typeof props.margin === "object" && props.margin.bottom ? spaces[props.margin.bottom] : ""}; - margin-left: ${(props) => - props.margin && typeof props.margin === "object" && props.margin.left ? spaces[props.margin.left] : ""}; + +const SortIcon = styled.span` + display: flex; + height: 14px; + width: 14px; + color: ${(props) => props.theme.sortIconColor}; + + svg { + height: 100%; + width: 100%; + } `; export default DxcResultsetTable; diff --git a/lib/src/resultsetTable/types.ts b/lib/src/resultsetTable/types.ts index 305d3de9f..89faa50a8 100644 --- a/lib/src/resultsetTable/types.ts +++ b/lib/src/resultsetTable/types.ts @@ -1,10 +1,11 @@ -type Space = "xxsmall" | "xsmall" | "small" | "medium" | "large" | "xlarge" | "xxlarge"; -type Margin = { +export type Space = "xxsmall" | "xsmall" | "small" | "medium" | "large" | "xlarge" | "xxlarge"; +export type Margin = { top?: Space; bottom?: Space; left?: Space; right?: Space; }; + type Column = { /** * Column display value. @@ -15,6 +16,7 @@ type Column = { */ isSortable?: boolean; }; + type Row = { /** * Value to be displayed in the cell.