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

feat(CoverageTable): [EPIC-137] Improve CoverageTable #317

Merged
merged 18 commits into from
Jun 10, 2024
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
88d01fe
feat(CoverageTable): [EPIC-137] Add hideScrollBarsMobile prop
kimkwanka Jun 6, 2024
eaa47ad
feat(CoverageTable): [EPIC-137] Add detail button captions
kimkwanka Jun 6, 2024
17a039d
fix(CoverageTable): [EPIC-137] Truly disable TableArrows
kimkwanka Jun 6, 2024
b2e13b4
feat(CoverageTable): [EPIC-137] Expose onSelectionChanged callback
kimkwanka Jun 6, 2024
2823c35
chore(CoverageTable): [EPIC-137] Replace underline links with TableIn…
kimkwanka Jun 6, 2024
67b60d1
feat(CoverageTable): [EPIC-137] Expose classNameOverrides
kimkwanka Jun 6, 2024
3c99208
feat(CoverageTable): [EPIC-137] Add section overrides
kimkwanka Jun 6, 2024
e86bb46
fix(CoverageTable): [EPIC-137] Increase text contrast
kimkwanka Jun 7, 2024
bfd7c00
chore(CoverageTable): [EPIC-137] Adjust default spacing
kimkwanka Jun 7, 2024
4452452
fix(CoverageTable): [EPIC-137] Fix first section spacing
kimkwanka Jun 7, 2024
eab842d
fix(CoverageTable): [EPIC-137] Fix scroll bar hiding
kimkwanka Jun 7, 2024
36714f7
chore(CoverageTable): [EPIC-137] Adjust default sizes
kimkwanka Jun 7, 2024
74798b7
fix(CoverageTable): [EPIC-137] Fix addons card
kimkwanka Jun 7, 2024
2cc98cf
fix(CoverageTable): [EPIC-137] Accordion overflow
kimkwanka Jun 7, 2024
e767393
fix(CoverageTable): [EPIC-137] Adjust cell padding
kimkwanka Jun 7, 2024
d0bb189
test(CoverageTable): [EPIC-137] Fix tests
kimkwanka Jun 7, 2024
c10461a
fix(CoverageTable): [EPIC-137] Fix typo
kimkwanka Jun 7, 2024
379ecb1
feat(CoverageTable): [EPIC-137] Expose details button className
kimkwanka Jun 10, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@

.container {
width: var(--growContent, min-content);
margin: 0 auto;
}

.container + .container {
margin-top: 8px;
max-width: 100%;
margin-left: auto;
margin-right: auto;
}

.chevron {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export const AccordionItem = ({
};

return (
<div className={`d-flex fd-column ${className} ${styles.container}`}>
<section className={`d-flex fd-column ${styles.container} ${className}`}>
<button
className={`d-flex ai-center jc-between ${styles.headerButton} ${headerClassName}`}
onClick={handleClick}
Expand All @@ -69,6 +69,6 @@ export const AccordionItem = ({
<AnimateHeight duration={300} height={isOpen ? 'auto' : 0.1}>
{children}
</AnimateHeight>
</div>
</section>
);
};
29 changes: 16 additions & 13 deletions src/lib/components/comparisonTable/components/Row/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,36 @@ import React from 'react';

import type { Cell } from '../../index';
import styles from './style.module.scss';
import classNames from 'classnames';

interface RowProps<T> {
cell: Cell<T>;
data: Array<T>;
isRowHeader?: boolean;
rowId: string;
cellClassName?: string;
}

const Row = <T extends { id: number }>(props: RowProps<T>) => {
const { cell, data, isRowHeader, rowId } = props;
const { cell, data, isRowHeader, rowId, cellClassName } = props;

return (
<div
key={rowId}
className={`
d-flex
w-100
${isRowHeader ? styles.header : ''}
`}
className={classNames('d-flex w-100', {
[styles.header]: isRowHeader,
})}
>
<h4
className={`
${styles.cell}
${styles.sticky}
${isRowHeader ? `p-h2 p--serif ${styles.title}` : ''}
${typeof cell.key === 'undefined' ? styles.addon : ''}
`}
className={classNames(
styles.cell,
styles.sticky,
{
[`p-h2 p--serif ${styles.title}`]: isRowHeader,
[styles.addon]: typeof cell.key === 'undefined',
},
cellClassName
)}
>
{cell.label}
</h4>
Expand All @@ -44,7 +47,7 @@ const Row = <T extends { id: number }>(props: RowProps<T>) => {

return (
<div
className={`ta-center ${styles.cell}`}
className={classNames('ta-center', styles.cell, cellClassName)}
key={`${rowId}-${item.id}`}
>
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
@use "../../../../scss/public/colors" as *;
@use "../../../../scss/public/grid" as *;

$cell-min-width: var(--cellWidth, 256px);
$cell-min-width: var(--cellWidth, 211px); // 195 + 16px

.header {
position: relative;
Expand Down Expand Up @@ -31,9 +31,13 @@ $cell-min-width: var(--cellWidth, 256px);

line-height: 24px;

padding: 16px;
padding: 16px 8px;

color: $ds-grey-700;
&:first-child {
padding: 16px 8px 16px 16px;
}

color: $ds-grey-900;

width: 50vw;
max-width: calc(var(--tableWidth) / 2);
Expand All @@ -55,19 +59,19 @@ $cell-min-width: var(--cellWidth, 256px);
@include p-size-tablet {
flex: 1 0 $cell-min-width;
width: $cell-min-width;
padding: 24px;

&:last-child {
&:first-child {
padding: 24px 8px 24px 24px;
}

padding: 24px 8px;
}
}

h4.cell {
// Set the max width of the first column to the supplied firstColumnWidth (or 288px if not specified) but only
// Set the max width of the first column to the supplied firstColumnWidth (or 212px if not specified) but only
// if this value does not exceed half of the table's width.
// This is to ensure that the first column is at most as wide as half the table, which will be the case on mobile where only the first column and one other are shown.
max-width: min(var(--firstColumnWidth, 288px), calc(var(--tableWidth) / 2));
max-width: min(var(--firstColumnWidth, 212px), calc(var(--tableWidth) / 2));
}

.title {
Expand Down Expand Up @@ -116,7 +120,7 @@ h4.cell {
h4.addon {
border-right: none;
max-width: calc(100vw - 64px);
width: 100vw;
width: 100%;

@include p-size-desktop {
max-width: 976px;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const TableArrows = (props: TableArrowsProps) => {
[styles.active]: active.left,
}
)}
disabled={!active.left}
>
<ArrowIcon />
</button>
Expand All @@ -40,6 +41,7 @@ const TableArrows = (props: TableArrowsProps) => {
[styles.active]: active.right,
}
)}
disabled={!active.right}
>
<ArrowIcon />
</button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@
background-color: $ds-grey-200;
cursor: not-allowed;
}
&:disabled {
opacity: 1;
&:hover {
background-color: $ds-grey-200;
}
}
}

.active {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,22 @@ import TableButton from '.';

const mockOnClick = jest.fn();

const buttonContent = "Table Button label";
const buttonContent = 'Table Button label';

const setup = () => render(
<TableButton onClick={mockOnClick}>{buttonContent}</TableButton>
);
const setup = () =>
render(<TableButton onClick={mockOnClick}>{buttonContent}</TableButton>);

describe('TableButton component', () => {
it("should render button content", () => {
it('should render button content', () => {
const { getByText } = setup();

expect(getByText(buttonContent)).toBeInTheDocument();
});

it("should call onClick", async () => {
const { getByText, user } = setup();
it('should call onClick', async () => {
const { getByTestId, user } = setup();

await user.click(getByText(buttonContent));
await user.click(getByTestId('ds-table-info-button'));

expect(mockOnClick).toHaveBeenCalled();
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ReactNode } from 'react';
import styles from './style.module.scss';
import TableInfoButton from '../TableInfoButton';

interface Props {
children: ReactNode;
Expand All @@ -12,15 +13,14 @@ const TableButton: React.FC<Props> = ({
onClick,
className = '',
}) => (
<button
className={`${styles.button} ${className}`}
data-testid="ds-table-button"
onClick={onClick}
>
<span>
{children}
</span>
</button>
<div className={styles.wrapper}>
{children}
<TableInfoButton
className={`${styles.infoButton} ${className}`}
data-testid="ds-table-button"
onClick={onClick}
/>
</div>
);

export default TableButton;
Original file line number Diff line number Diff line change
@@ -1,26 +1,9 @@
@use "../../../../scss/public/colors" as *;

.button {
background-color: transparent;
color: $ds-grey-700;
cursor: pointer;
margin: 2px 0;
padding: 2px;
transition: color 0.3s ease;

span {
border-bottom: 2px dashed $ds-grey-600;
display: inline;
transition: border-color 0.3s ease;
}
.wrapper {
position: relative;
}

&:hover,
&:focus {
color: $ds-primary-500;
outline-color: $ds-primary-500;

span {
border-color: $ds-primary-500;
}
}
.infoButton {
position: absolute;
right: -32px;
top: 0;
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const TableInfoButton = ({
<button
className={`p-btn--secondary ${styles.button} ${className}`}
type="button"
data-testid="ds-table-info-button"
onClick={onClick}
>
<Info size={20} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,73 +5,69 @@ import TableRowHeader, { TableRowHeaderProps } from '.';

const mockOnClick = jest.fn();

const label = "Table label";
const subtitle = "Subtitle label";
const icon = "🎉";
const buttonTestId = "ds-table-button";

const setup = (props: Partial<TableRowHeaderProps> = {}) => render(
<TableRowHeader
label={label}
{...props}
/>
);
const label = 'Table label';
const subtitle = 'Subtitle label';
const icon = '🎉';
const buttonTestId = 'ds-table-info-button';

const setup = (props: Partial<TableRowHeaderProps> = {}) =>
render(<TableRowHeader label={label} {...props} />);

describe('TableRowHeader component', () => {
it("should render label", () => {
it('should render label', () => {
const { getByText } = setup();

expect(getByText(label)).toBeInTheDocument();
});

it("should not render subtitle", () => {
it('should not render subtitle', () => {
const { queryByText } = setup();

expect(queryByText(subtitle)).not.toBeInTheDocument();
});

it("should render subtitle", () => {
it('should render subtitle', () => {
const { getByText } = setup({ subtitle });

expect(getByText(subtitle)).toBeInTheDocument();
});

it("should not render icon", () => {
it('should not render icon', () => {
const { queryByText } = setup();

expect(queryByText(icon)).not.toBeInTheDocument();
});

it("should render icon", () => {
it('should render icon', () => {
const { getByText } = setup({ icon });

expect(getByText(icon)).toBeInTheDocument();
});

it("should not render button if onClickInfo is not defined", () => {
it('should not render button if onClickInfo is not defined', () => {
const { queryByTestId } = setup();

expect(queryByTestId(buttonTestId)).not.toBeInTheDocument();
});

it("should render button if onClickInfo is defined", () => {
it('should render button if onClickInfo is defined', () => {
const { getByTestId } = setup({ onClickInfo: mockOnClick });

expect(getByTestId(buttonTestId)).toBeInTheDocument();
});

it("should not call onClickInfo if not defined", async () => {
it('should not call onClickInfo if not defined', async () => {
const { getByText, user } = setup();

await user.click(getByText(label));

expect(mockOnClick).not.toHaveBeenCalled();
});

it("should call onClickInfo if defined", async () => {
const { getByText, user } = setup({ onClickInfo: mockOnClick });
it('should call onClickInfo if defined', async () => {
const { getByTestId, user } = setup({ onClickInfo: mockOnClick });

await user.click(getByText(label));
await user.click(getByTestId('ds-table-info-button'));

expect(mockOnClick).toHaveBeenCalled();
});
Expand Down
Loading
Loading