Skip to content

Commit

Permalink
Merge pull request #21951 from Yoast/367-site-kit-tables-ui
Browse files Browse the repository at this point in the history
367 site kit tables UI
  • Loading branch information
vraja-pro authored Jan 24, 2025
2 parents 37106cf + 5ce72c4 commit b0de067
Show file tree
Hide file tree
Showing 10 changed files with 240 additions and 16 deletions.
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;
}
}
}

.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;
}
}
}
}
}

0 comments on commit b0de067

Please sign in to comment.