Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ActionsCell added to table and resultsetTable #1836

Merged
merged 8 commits into from Feb 21, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 16 additions & 0 deletions lib/src/common/variables.ts
Expand Up @@ -284,8 +284,14 @@ export const componentTokens = {
buttonPaddingBottom: "0px",
buttonPaddingLeft: "16px",
buttonPaddingRight: "16px",
buttonHeight: "40px",
buttonBorderRadius: "4px",
buttonBorderStyle: CoreTokens.border_none,
buttonBorderThickness: CoreTokens.border_width_0,
buttonBorderColor: CoreTokens.color_transparent,
disabledColor: CoreTokens.color_grey_500,
disabledButtonBackgroundColor: CoreTokens.color_transparent,
disabledButtonBorderColor: CoreTokens.color_transparent,
Mil4n0r marked this conversation as resolved.
Show resolved Hide resolved
disabledBorderColor: CoreTokens.color_transparent,
optionBackgroundColor: CoreTokens.color_white,
hoverOptionBackgroundColor: CoreTokens.color_grey_100,
Expand Down Expand Up @@ -867,6 +873,16 @@ export const componentTokens = {
scrollBarThumbColor: CoreTokens.color_grey_700,
scrollBarTrackColor: CoreTokens.color_grey_300,
sortIconColor: CoreTokens.color_white,
actionIconColor: CoreTokens.color_purple_700,
disabledActionIconColor: CoreTokens.color_grey_500,
hoverActionIconColor: CoreTokens.color_purple_700,
focusActionIconColor: CoreTokens.color_purple_700,
activeActionIconColor: CoreTokens.color_purple_700,
actionBackgroundColor: CoreTokens.color_transparent,
disabledActionBackgroundColor: CoreTokens.color_transparent,
hoverActionBackgroundColor: CoreTokens.color_grey_100,
focusActionBorderColor: CoreTokens.color_blue_600,
activeActionBackgroundColor: CoreTokens.color_grey_300,
Mil4n0r marked this conversation as resolved.
Show resolved Hide resolved
},
tabs: {
fontFamily: CoreTokens.type_sans,
Expand Down
16 changes: 6 additions & 10 deletions lib/src/dropdown/Dropdown.tsx
Expand Up @@ -242,10 +242,7 @@ const calculateWidth = (margin, size) =>
: sizes[size];

const DropdownContainer = styled.div<{ margin: DropdownPropsType["margin"]; size: DropdownPropsType["size"] }>`
display: inline-block;
width: ${(props) => calculateWidth(props.margin, props.size)};
text-overflow: ellipsis;
overflow: hidden;
Mil4n0r marked this conversation as resolved.
Show resolved Hide resolved
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] : ""};
Expand All @@ -267,12 +264,12 @@ const DropdownTrigger = styled.button<{
align-items: center;
gap: ${(props) => props.theme.caretIconSpacing};
width: 100%;
min-height: 40px;
height: ${(props) => props.theme.buttonHeight};
min-width: ${(props) => (props.label === "" ? "0px" : calculateWidth(props.margin, props.size))};
border-radius: ${(props) => props.theme.borderRadius};
border-width: ${(props) => props.theme.borderThickness};
border-style: ${(props) => props.theme.borderStyle};
border-color: ${(props) => (props.disabled ? props.theme.disabledBorderColor : props.theme.borderColor)};
border-radius: ${(props) => props.theme.buttonBorderRadius};
border-width: ${(props) => props.theme.buttonBorderThickness};
border-style: ${(props) => props.theme.buttonBorderStyle};
border-color: ${(props) => (props.disabled ? props.theme.disabledButtonBorderColor : props.theme.buttonBorderColor)};
padding-top: ${(props) => props.theme.buttonPaddingTop};
padding-bottom: ${(props) => props.theme.buttonPaddingBottom};
padding-left: ${(props) => props.theme.buttonPaddingLeft};
Expand All @@ -286,8 +283,7 @@ const DropdownTrigger = styled.button<{
!props.disabled &&
`
&:focus {
outline: ${props.theme.focusColor} solid 2px;
outline-offset: -2px;
outline: 2px solid ${props.theme.focusColor};
}
&:hover {
background-color: ${props.theme.hoverButtonBackgroundColor};
Expand Down
83 changes: 78 additions & 5 deletions lib/src/resultset-table/ResultsetTable.stories.tsx
@@ -1,6 +1,5 @@
import React from "react";
import DxcResultsetTable from "./ResultsetTable";
import DxcButton from "../button/Button";
import Title from "../../.storybook/components/Title";
import ExampleContainer from "../../.storybook/components/ExampleContainer";
import { userEvent, within } from "@storybook/testing-library";
Expand All @@ -13,7 +12,7 @@ export default {

const deleteIcon = (
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24">
<path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z" />
<path fill="currentColor" d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z" />
<path d="M0 0h24v24H0z" fill="none" />
</svg>
Jialecl marked this conversation as resolved.
Show resolved Hide resolved
);
Expand All @@ -29,17 +28,77 @@ const rows = [
[{ displayValue: "006" }, { displayValue: "Cris" }, { displayValue: "Paris" }],
];

const actions = [
{
icon: (
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="currentColor">
<path d="M0 0h24v24H0V0z" fill="none" />
<path d="M7.77 6.76L6.23 5.48.82 12l5.41 6.52 1.54-1.28L3.42 12l4.35-5.24zM7 13h2v-2H7v2zm10-2h-2v2h2v-2zm-6 2h2v-2h-2v2zm6.77-7.52l-1.54 1.28L20.58 12l-4.35 5.24 1.54 1.28L23.18 12l-5.41-6.52z" />
</svg>
Jialecl marked this conversation as resolved.
Show resolved Hide resolved
),
title: "icon",
onClick: (value?) => {
console.log(value);
},
options: [
{
value: "1",
label: "Amazon with a very long text",
},
{
value: "2",
label: "Ebay",
},
{
value: "3",
label: "Apple",
},
],
},
{
icon: (
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="currentColor">
<path d="M0 0h24v24H0V0zm0 0h24v24H0V0z" fill="none" />
<path d="M1 9l2 2c4.97-4.97 13.03-4.97 18 0l2-2C16.93 2.93 7.08 2.93 1 9zm8 8l3 3 3-3c-1.65-1.66-4.34-1.66-6 0zm-4-4l2 2c2.76-2.76 7.24-2.76 10 0l2-2C15.14 9.14 8.87 9.14 5 13z" />
</svg>
Jialecl marked this conversation as resolved.
Show resolved Hide resolved
),
title: "icon",
onClick: () => {},
},
{
icon: (
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24">
<path fill="currentColor" d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z" />
<path d="M0 0h24v24H0z" fill="none" />
</svg>
Jialecl marked this conversation as resolved.
Show resolved Hide resolved
),
title: "icon",
onClick: () => {},
disabled: true,
},
];

const rowsIcon = [
[
{ displayValue: "001", sortValue: "001" },
{ displayValue: "Peter" },
{ displayValue: <DxcButton icon={deleteIcon} /> },
{
displayValue: <DxcResultsetTable.ActionsCell actions={actions} />,
},
],
[
{ displayValue: "002", sortValue: "002" },
{ displayValue: "Louis" },
{
displayValue: <DxcResultsetTable.ActionsCell actions={actions} />,
},
],
[{ displayValue: "002", sortValue: "002" }, { displayValue: "Louis" }, { displayValue: "" }],
[
{ displayValue: "003", sortValue: "003" },
{ displayValue: "Mark" },
{ displayValue: <DxcButton icon={deleteIcon} /> },
{
displayValue: <DxcResultsetTable.ActionsCell actions={actions} />,
},
],
];

Expand Down Expand Up @@ -317,3 +376,17 @@ LastPage.play = async ({ canvasElement }) => {
const nextButton = canvas.getAllByRole("button")[3];
await userEvent.click(nextButton);
};

const ResultsetActionsCellDropdown = () => (
<ExampleContainer>
<Title title="Dropdown Action" theme="light" level={4} />
<DxcResultsetTable columns={columns} rows={rowsIcon} itemsPerPage={2} />
</ExampleContainer>
);

export const DropdownAction = ResultsetActionsCellDropdown.bind({});
DropdownAction.play = async ({ canvasElement }) => {
const canvas = within(canvasElement);
const nextButton = canvas.getAllByRole("button")[3];
await userEvent.click(nextButton);
};
70 changes: 69 additions & 1 deletion lib/src/resultset-table/ResultsetTable.test.js
@@ -1,5 +1,5 @@
import React from "react";
import { render, fireEvent } from "@testing-library/react";
import { render, fireEvent, act } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import DxcResultsetTable from "./ResultsetTable.tsx";

Expand All @@ -14,6 +14,13 @@ global.ResizeObserver = class ResizeObserver {
disconnect() {}
};

const icon = (
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="currentColor">
<path d="M0 0h24v24H0V0zm0 0h24v24H0V0z" fill="none" />
<path d="M1 9l2 2c4.97-4.97 13.03-4.97 18 0l2-2C16.93 2.93 7.08 2.93 1 9zm8 8l3 3 3-3c-1.65-1.66-4.34-1.66-6 0zm-4-4l2 2c2.76-2.76 7.24-2.76 10 0l2-2C15.14 9.14 8.87 9.14 5 13z" />
</svg>
);

const columns = [
{
displayValue: "Id",
Expand Down Expand Up @@ -302,4 +309,65 @@ describe("Resultset table component tests", () => {
fireEvent.click(lastButton);
expect(getAllByRole("row").length - 1).toEqual(1);
});

test("Resultset table with ActionsCell", () => {
const onSelectOption = jest.fn();
const onClick = jest.fn();
const actions = [
{
icon: icon,
title: "icon1",
onClick: onSelectOption,
options: [
{
value: "1",
label: "Amazon",
},
{
value: "2",
label: "Ebay",
},
{
value: "3",
label: "Aliexpress",
},
],
},
{
icon: icon,
title: "icon2",
onClick: onClick,
},
];
const actionRows = [
[
{
displayValue: "001",
sortValue: "001",
},
{
displayValue: "Peter",
sortValue: "Peter",
},
{
displayValue: <DxcResultsetTable.ActionsCell actions={actions} />,
sortValue: "Actions",
},
],
];
const { getAllByRole, getByRole, getByText } = render(
<DxcResultsetTable columns={columns} rows={actionRows} itemsPerPage={3} />
);
const dropdown = getAllByRole("button")[1];
act(() => {
userEvent.click(dropdown);
});
expect(getByRole("menu")).toBeTruthy();
const option = getByText("Aliexpress");
userEvent.click(option);
expect(onSelectOption).toHaveBeenCalledWith("3");
const action = getAllByRole("button")[2];
userEvent.click(action);
expect(onClick).toHaveBeenCalled();
});
});
3 changes: 3 additions & 0 deletions lib/src/resultset-table/ResultsetTable.tsx
Expand Up @@ -2,6 +2,7 @@ import React, { useState, useMemo, useEffect } from "react";
import styled, { ThemeProvider } from "styled-components";
import { spaces } from "../common/variables";
import DxcTable from "../table/Table";
import DxcActionsCell from "../table/ActionsCell";
import DxcPaginator from "../paginator/Paginator";
import useTheme from "../useTheme";
import ResultsetTablePropsType, { Column } from "./types";
Expand Down Expand Up @@ -194,4 +195,6 @@ const SortIcon = styled.span`
}
`;

DxcResultsetTable.ActionsCell = DxcActionsCell;

export default DxcResultsetTable;
36 changes: 36 additions & 0 deletions lib/src/table/ActionsCell.tsx
@@ -0,0 +1,36 @@
import React from "react";
import { ActionIconPropsType } from "./types";
import DxcActionIcon from "../action-icon/ActionIcon";
import { DxcDropdown, DxcFlex, HalstackProvider } from "../main";
import DropdownTheme from "./DropdownTheme";

const DxcActionsCell = ({ actions }: ActionIconPropsType): JSX.Element => {
return (
<DxcFlex gap={"0.5rem"}>
{actions.map((action) =>
action.options?.length ? (
<HalstackProvider advancedTheme={DropdownTheme}>
<DxcDropdown
options={action.options}
onSelectOption={action.onClick}
disabled={action.disabled}
icon={action.icon}
tabIndex={action.tabIndex}
caretHidden
></DxcDropdown>
</HalstackProvider>
) : (
<DxcActionIcon
icon={action.icon}
title={action.title}
onClick={action.onClick}
disabled={action.disabled ?? false}
tabIndex={action.tabIndex ?? 0}
/>
)
)}
</DxcFlex>
);
};

export default DxcActionsCell;
52 changes: 52 additions & 0 deletions lib/src/table/DropdownTheme.jsx
@@ -0,0 +1,52 @@
export default {
dropdown: {
// Breadcrumbs tokens
buttonIconSize: "16px",
buttonPaddingTop: "4px",
buttonPaddingBottom: "4px",
buttonPaddingLeft: "4px",
buttonPaddingRight: "4px",
buttonHeight: "24px",
buttonBorderRadius: "2px",
buttonBorderColor: "transparent",
optionFontSize: "14px",
optionPaddingTop: "0px",
optionPaddingBottom: "0px",
optionPaddingLeft: "16px",
optionPaddingRight: "16px",

// Dropdown tokens
buttonBackgroundColor: "#ffffff",
hoverButtonBackgroundColor: "#f2f2f2",
activeButtonBackgroundColor: "#cccccc",
buttonFontFamily: "Open Sans, sans-serif",
buttonFontSize: "1rem",
buttonFontStyle: "normal",
buttonFontWeight: "400",
buttonFontColor: "#000000",
buttonIconSpacing: "10px",
buttonIconColor: "#5f249f",
disabledColor: "#999999",
disabledButtonBackgroundColor: "transparent",
disabledBorderColor: "transparent",
optionBackgroundColor: "#ffffff",
hoverOptionBackgroundColor: "#f2f2f2",
activeOptionBackgroundColor: "#cccccc",
optionFontFamily: "Open Sans, sans-serif",
optionFontStyle: "normal",
optionFontWeight: "400",
optionFontColor: "#000000",
optionIconSize: "20px",
optionIconSpacing: "10px",
optionIconColor: "#000000",
caretIconSize: "24px",
caretIconColor: "#000000",
caretIconSpacing: "12px",
borderRadius: "4px",
borderStyle: "none",
borderThickness: "0px",
borderColor: "transparent",
scrollBarThumbColor: "#666666",
scrollBarTrackColor: "#cccccc",
},
};