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

367 site kit tables UI #21951

Merged
merged 27 commits into from
Jan 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
4106aac
WIP site kit tables
vraja-pro Jan 3, 2025
9736b1b
WIP site kit table component
vraja-pro Jan 6, 2025
6cf6219
add sorting functionality and fix layout
vraja-pro Jan 7, 2025
e73b7d1
simplify sort direction prop
vraja-pro Jan 7, 2025
462b89a
add tests to SiteKitTable
vraja-pro Jan 7, 2025
848e423
remove hard coded padding
vraja-pro Jan 7, 2025
d9c5640
center bullets
vraja-pro Jan 7, 2025
d05d22c
remove classes and align bullet to the end center
vraja-pro Jan 7, 2025
70939fe
refactor dashboard table
vraja-pro Jan 10, 2025
dc14803
revert dashboard changes
vraja-pro Jan 10, 2025
827f5b7
add type for columns and data, fix table overflow
vraja-pro Jan 13, 2025
8bfa47c
remove sortable column
vraja-pro Jan 15, 2025
9169efb
add minimal variant to ui library and update storybook
vraja-pro Jan 15, 2025
87a9e20
drop sorting
vraja-pro Jan 15, 2025
ef5a2ed
add reusable widget table
vraja-pro Jan 21, 2025
febd022
align seo score header
vraja-pro Jan 22, 2025
c49cf49
add formatters
vraja-pro Jan 23, 2025
4cddd27
Revert "add formatters"
vraja-pro Jan 23, 2025
8156e79
add classes to align data
vraja-pro Jan 23, 2025
370622f
update warnings threshold
vraja-pro Jan 23, 2025
2c0be6a
change the table width
vraja-pro Jan 23, 2025
075b19e
fix styling with classes and fix space
vraja-pro Jan 23, 2025
2b1ffa2
fix spacing
vraja-pro Jan 23, 2025
fae50a9
fix spacing
vraja-pro Jan 23, 2025
7fd66b3
remove key prop
vraja-pro Jan 23, 2025
9e99782
remove container class
vraja-pro Jan 23, 2025
5ce72c4
fix paddings and colors
vraja-pro Jan 24, 2025
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
2 changes: 1 addition & 1 deletion packages/js/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"scripts": {
"build": "cd ../.. && wp-scripts build --config config/webpack/webpack.config.js",
"test": "jest",
"lint": "eslint . --max-warnings=64"
"lint": "eslint . --max-warnings=63"
},
"dependencies": {
"@draft-js-plugins/mention": "^5.0.0",
Expand Down
46 changes: 46 additions & 0 deletions packages/js/src/dashboard/components/most-popular-table.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { __ } from "@wordpress/i18n";
import { TableWidget } from "./table-widget";

/**
* @type {import("../index").MostPopularContent} Most popular content
*/

/**
* The top 5 most popular content table component.
*
* @param {[MostPopularContent]} Data The component props.
*
* @returns {JSX.Element} The element.
*/
export const MostPopularTable = ( { data } ) => {
return <TableWidget title={ __( "Top 5 most popular content", "wordpress-seo" ) }>
<TableWidget.Head>
<TableWidget.Header>{ __( "Landing page", "wordpress-seo" ) }</TableWidget.Header>
<TableWidget.Header className="yst-text-end">{ __( "Clicks", "wordpress-seo" ) }</TableWidget.Header>
<TableWidget.Header className="yst-text-end">{ __( "Impressions", "wordpress-seo" ) }</TableWidget.Header>
<TableWidget.Header className="yst-text-end">{ __( "CTR", "wordpress-seo" ) }</TableWidget.Header>
<TableWidget.Header className="yst-text-end">
{ __( "Average position", "wordpress-seo" ) }
</TableWidget.Header>
<TableWidget.Header className="yst-text-center">
<div className="yst-flex yst-justify-end yst-items-end">
<div className="yst-flex yst-justify-center yst-w-16">
{ __( "SEO score", "wordpress-seo" ) }
</div>
</div>
</TableWidget.Header>
</TableWidget.Head>
<TableWidget.Body>
{ data.map( ( { subject, clicks, impressions, ctr, averagePosition, seoScore }, index ) => (
<TableWidget.Row key={ `most-popular-content-${ index }` } index={ index }>
<TableWidget.Cell className="yst-text-slate-900 yst-font-medium">{ subject }</TableWidget.Cell>
<TableWidget.Cell className="yst-text-end">{ clicks }</TableWidget.Cell>
<TableWidget.Cell className="yst-text-end">{ impressions }</TableWidget.Cell>
<TableWidget.Cell className="yst-text-end">{ ctr }</TableWidget.Cell>
<TableWidget.Cell className="yst-text-end">{ averagePosition }</TableWidget.Cell>
<TableWidget.Cell><TableWidget.ScoreBullet score={ seoScore } /></TableWidget.Cell>
</TableWidget.Row>
) ) }
</TableWidget.Body>
</TableWidget>;
};
80 changes: 80 additions & 0 deletions packages/js/src/dashboard/components/table-widget.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import classNames from "classnames";
import { Paper, Table, Title } from "@yoast/ui-library";
import { SCORE_META } from "../scores/score-meta";

/**
* The score bullet component.
*
* @param {string} score The score.
* @returns {JSX.Element} The element.
*/
const ScoreBullet = ( { score } ) => (
<div className="yst-flex yst-justify-end yst-items-center">
<div className="yst-flex yst-justify-center yst-w-16">
<span className={ classNames( "yst-shrink-0 yst-w-3 yst-aspect-square yst-rounded-full", SCORE_META[ score ].color ) }>
<span className="yst-sr-only">{ SCORE_META[ score ].label }</span>
</span>
</div>
</div>
);

/**
* The table head component.
*
* @param {JSX.Element} children The table headers.
* @returns {JSX.Element} The element.
*/
const TableHead = ( { children } ) => {
return <Table.Head>
<Table.Row>
<Table.Header className="yst-px-0">{ "" }</Table.Header>
{ children }
</Table.Row>
</Table.Head>;
};

/**
* The table row component for the table widget includes numbering of first cell.
*
* @param {children} children The row cells.
* @param {number} index The row index.
*
* @returns {JSX.Element} The row element.
*/
const TableRow = ( { children, index } ) => {
return <Table.Row>
<Table.Cell className="yst-px-0 yst-text-slate-500">{ index + 1 }. </Table.Cell>
{ children }
</Table.Row>;
};

/**
* The Site Kit table component.
*
* @param {string} title The table title.
* @param {JSX.Element} children The table rows.
*
* @returns {JSX.Element} The element.
*/
export const TableWidget = ( { title, children } ) => {
return (
<Paper className="yst-grow yst-p-8 yst-shadow-md yst-mt-6">
<Title as="h3" size="2" className="yst-text-slate-900 yst-font-medium">
{ title }
</Title>
<div className="yst-overflow-auto">
<Table variant="minimal">
{ children }
</Table>
</div>
</Paper>
);
};

TableWidget.Head = TableHead;
TableWidget.Row = TableRow;
TableWidget.ScoreBullet = ScoreBullet;
TableWidget.Cell = Table.Cell;
TableWidget.Header = Table.Header;
TableWidget.Body = Table.Body;

10 changes: 10 additions & 0 deletions packages/js/src/dashboard/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,13 @@ export { Dashboard } from "./components/dashboard";
* @typedef {Object} Links The links.
* @property {string} dashboardLearnMore The dashboard information link.
*/

/**
* @typedef {Object} MostPopularContent The most popular content data.
* @property {string} subject The landing page.
* @property {number} clicks The number of clicks.
* @property {number} impressions The number of impressions.
* @property {number} ctr The click-through rate.
* @property {number} position The average position.
* @property {number} seoScore The seo score.
*/
1 change: 1 addition & 0 deletions packages/ui-library/src/elements/table/docs/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ export { default as tableCell } from "./table-cell.md";
export { default as tableHead } from "./table-head.md";
export { default as tableHeader } from "./table-header.md";
export { default as tableRow } from "./table-row.md";
export { default as minimal } from "./table-variant-minimal.md";
2 changes: 1 addition & 1 deletion packages/ui-library/src/elements/table/docs/table-row.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
The sub component `Table.Row`.
The sub component `Table.Row`. The row has a variant props which can be set to `striped`.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The minial variant is the table without the table border.
22 changes: 15 additions & 7 deletions packages/ui-library/src/elements/table/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const rowClassNameMap = {
* @returns {JSX.Element} The element.
*/
const Cell = ( { children, className = "", ...props } ) => (
<td className={ classNames( "yst-table-cell yst-px-3 yst-py-4 yst-text-sm yst-text-slate-600", className ) } { ...props }>
<td className={ classNames( "yst-table-cell", className ) } { ...props }>
{ children }
</td>
);
Expand Down Expand Up @@ -54,7 +54,7 @@ Row.propTypes = {
*/
const Header = ( { children, className = "", ...props } ) => (
<th
className={ classNames( "yst-table-header yst-px-3 yst-py-4 yst-text-start yst-text-sm yst-font-semibold yst-text-slate-900", className ) }
className={ classNames( "yst-table-header", className ) }
{ ...props }
>
{ children }
Expand All @@ -73,7 +73,7 @@ Header.propTypes = {
* @returns {JSX.Element} The element.
*/
const Head = ( { children, className = "", ...props } ) => (
<thead className={ classNames( "yst-bg-slate-50", className ) } { ...props }>{ children }</thead>
<thead className={ className } { ...props }>{ children }</thead>
);

Head.propTypes = {
Expand All @@ -88,23 +88,29 @@ Head.propTypes = {
* @returns {JSX.Element} The element.
*/
const Body = ( { children, className = "", ...props } ) => (
<tbody className={ classNames( "yst-divide-y yst-divide-gray-200 yst-bg-white", className ) } { ...props }>{ children }</tbody>
<tbody className={ className } { ...props }>{ children }</tbody>
);

Body.propTypes = {
children: PropTypes.node.isRequired,
className: PropTypes.string,
};

const tableVariants = {
"default": "yst-table--default",
minimal: "yst-table--minimal",
};

/**
* @param {JSX.node} children The content.
* @param {string} [className] Optional class name.
* @param {string} [variant] The variant of the table.
* @param {Object} [props] Optional table props.
* @returns {JSX.Element} The element.
*/
const Table = forwardRef( ( { children, className = "", ...props }, ref ) => (
<div className="yst-table-wrapper yst-shadow yst-ring-1 yst-ring-black yst-ring-opacity-5">
<table className={ classNames( "yst-min-w-full yst-divide-y yst-divide-slate-300", className ) } { ...props } ref={ ref }>
const Table = forwardRef( ( { children, className = "", variant = "default", ...props }, ref ) => (
<div className={ classNames( "yst-table-wrapper", tableVariants[ variant ] ) }>
<table className={ className } { ...props } ref={ ref }>
{ children }
</table>
</div>
Expand All @@ -114,9 +120,11 @@ Table.displayName = "Table";
Table.propTypes = {
children: PropTypes.node.isRequired,
className: PropTypes.string,
variant: PropTypes.string,
};
Table.defaultProps = {
className: "",
variant: "default",
};

Table.Head = Head;
Expand Down
38 changes: 36 additions & 2 deletions packages/ui-library/src/elements/table/stories.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from "react";
import Table from ".";
import { InteractiveDocsPage } from "../../../.storybook/interactive-docs-page";
import { component, tableBody, tableCell, tableHead, tableHeader, tableRow } from "./docs";
import { component, tableBody, tableCell, tableHead, tableHeader, tableRow, minimal } from "./docs";

export const Factory = {
parameters: {
Expand Down Expand Up @@ -199,6 +199,40 @@ export const TableCell = {
},
};

export const MinimalVariant = {
name: "Table variant minimal",
parameters: {
controls: { disable: false },
docs: { description: { story: minimal } },
},
args: {
variant: "minimal",
children: (
<>
<Table.Head>
<Table.Row>
<Table.Header>Header 1</Table.Header>
<Table.Header>Header 2</Table.Header>
<Table.Header>Header 3</Table.Header>
</Table.Row>
</Table.Head>
<Table.Body>
<Table.Row>
<Table.Cell>Cell 1</Table.Cell>
<Table.Cell>Cell 2</Table.Cell>
<Table.Cell>Cell 3</Table.Cell>
</Table.Row>
<Table.Row>
<Table.Cell>Cell 1</Table.Cell>
<Table.Cell>Cell 2</Table.Cell>
<Table.Cell>Cell 3</Table.Cell>
</Table.Row>
</Table.Body>
</>
),
},
};

export default {
title: "1) Elements/Table",
component: Table,
Expand All @@ -208,7 +242,7 @@ export default {
parameters: {
docs: {
description: { component },
page: () => <InteractiveDocsPage stories={ [ TableHead, TableRow, TableHeader, TableBody, TableCell ] } />,
page: () => <InteractiveDocsPage stories={ [ TableHead, TableRow, TableHeader, TableBody, TableCell, MinimalVariant ] } />,
},
},
};
54 changes: 49 additions & 5 deletions packages/ui-library/src/elements/table/style.css
Original file line number Diff line number Diff line change
@@ -1,15 +1,59 @@
@layer components {
.yst-root {
.yst-table-wrapper {
@apply yst-rounded-lg;
table {
@apply yst-min-w-full;

.yst-table-header {
@apply yst-px-3 yst-py-4 yst-text-start yst-text-sm yst-font-semibold yst-text-slate-900;
}

.yst-table-cell {
@apply yst-px-3 yst-py-4 yst-text-sm yst-text-slate-600;
vraja-pro marked this conversation as resolved.
Show resolved Hide resolved
}
}
}

.yst-table-header {
@apply first:yst-rounded-ss-lg last:yst-rounded-se-lg;
.yst-table--default {
@apply yst-rounded-lg yst-shadow yst-ring-1 yst-ring-black yst-ring-opacity-5;

table {
@apply yst-divide-y yst-divide-slate-300;

thead {
@apply yst-bg-slate-50;

.yst-table-header {
@apply first:yst-rounded-ss-lg last:yst-rounded-se-lg;
}
}

tbody {
@apply yst-divide-y yst-divide-gray-200 yst-bg-white;
}

.yst-table-row:last-of-type .yst-table-cell {
@apply first:yst-rounded-es-lg last:yst-rounded-ee-lg;
}
}
}

.yst-table-row:last-of-type .yst-table-cell {
@apply first:yst-rounded-es-lg last:yst-rounded-ee-lg;
.yst-table--minimal {
table {
@apply yst-divide-y yst-divide-slate-300;

.yst-table-header {
@apply yst-align-bottom yst-py-2;
}

.yst-table-cell {
@apply yst-py-2;
}

tbody {
@apply yst-divide-y yst-divide-gray-200 yst-bg-white;
}
}
}
}
}
Loading