From dbd907693d8b8451eab739740fa5cd055084d755 Mon Sep 17 00:00:00 2001 From: Steven Date: Fri, 6 Dec 2024 08:10:53 +0100 Subject: [PATCH] feat(ui): extra styling variant of the table component (#2715) --- .changeset/nervous-turtles-heal.md | 5 + .../rwa-demo/src/app/(app)/assets/page.tsx | 1 + .../src/components/AgentsList/AgentsList.tsx | 1 + .../components/InvestorList/InvestorList.tsx | 1 + .../kode-ui/src/components/Table/Body.tsx | 32 ++- .../kode-ui/src/components/Table/Header.tsx | 20 +- .../kode-ui/src/components/Table/Table.css.ts | 234 ++++++++++++++---- .../src/components/Table/Table.stories.tsx | 69 +++++- .../kode-ui/src/components/Table/Table.tsx | 23 +- .../components/Table/TableSelectAllCell.tsx | 5 +- .../components/Table/TableSelectionCell.tsx | 3 + .../CompactTable/CompactTable.stories.tsx | 63 ++++- .../patterns/CompactTable/CompactTable.tsx | 11 +- .../CompactTableDesktop.tsx | 11 +- .../CompactTableDesktop/styles.css.ts | 28 ++- .../CompactTableMobile/CompactTableMobile.tsx | 3 +- .../CompactTableMobile/styles.css.ts | 35 ++- .../kode-ui/src/styles/tokens/contract.css.ts | 86 ++++--- .../kode-ui/src/styles/tokens/dark.css.ts | 32 ++- .../kode-ui/src/styles/tokens/light.css.ts | 32 ++- 20 files changed, 511 insertions(+), 184 deletions(-) create mode 100644 .changeset/nervous-turtles-heal.md diff --git a/.changeset/nervous-turtles-heal.md b/.changeset/nervous-turtles-heal.md new file mode 100644 index 0000000000..6bb663b972 --- /dev/null +++ b/.changeset/nervous-turtles-heal.md @@ -0,0 +1,5 @@ +--- +'@kadena/kode-ui': minor +--- + +add an extra styling variant to the table component diff --git a/packages/apps/rwa-demo/src/app/(app)/assets/page.tsx b/packages/apps/rwa-demo/src/app/(app)/assets/page.tsx index 75f529954b..d5f383a94e 100644 --- a/packages/apps/rwa-demo/src/app/(app)/assets/page.tsx +++ b/packages/apps/rwa-demo/src/app/(app)/assets/page.tsx @@ -10,6 +10,7 @@ const Assets = () => { return ( <> { /> { { item: GridNode; state: TableState | TreeGridState; children: ReactNode; selectionMode: TableProps['selectionMode']; + variant: ITableProps['variant']; } export function TableRow({ item, children, state, + variant, }: ITableRowProps) { const ref = useRef(null); const { rowProps, isSelected } = useTableRow( @@ -36,27 +39,32 @@ export function TableRow({ const { isHovered, hoverProps } = useHover({ isDisabled: false }); return ( - - {children} - + <> + {variant === 'open' && } + + {children} + + ); } interface ITableCellProps { cell: GridNode; state: TableState; + variant: ITableProps['variant']; } export function TableCell({ cell, state, + variant = 'default', }: ITableCellProps) { const ref = useRef(null); const { gridCellProps } = useTableCell({ node: cell }, state, ref); @@ -65,7 +73,7 @@ export function TableCell({ return ( diff --git a/packages/libs/kode-ui/src/components/Table/Header.tsx b/packages/libs/kode-ui/src/components/Table/Header.tsx index 45ed5cf785..d9caf882ce 100644 --- a/packages/libs/kode-ui/src/components/Table/Header.tsx +++ b/packages/libs/kode-ui/src/components/Table/Header.tsx @@ -8,22 +8,18 @@ import { useTableColumnHeader, useTableHeaderRow, } from 'react-aria'; +import type { ITableProps } from '..'; import { Stack } from '..'; import { MonoExpandLess, MonoExpandMore } from '@kadena/kode-icons/system'; -import classNames from 'classnames'; -import { - columnHeader, - defaultHeader, - headerBase, - subtleHeader, -} from './Table.css'; +import { columnHeader, headerBase } from './Table.css'; interface ITableHeaderRowProps { item: GridNode; state: TableState; children: ReactNode; isSubtle?: boolean; + variant: ITableProps['variant']; } export function TableHeaderRow({ @@ -31,16 +27,14 @@ export function TableHeaderRow({ state, children, isSubtle = false, + variant = 'default', }: ITableHeaderRowProps) { const ref = useRef(null); const { rowProps } = useTableHeaderRow({ node: item }, state, ref); return ( @@ -65,11 +59,13 @@ interface ITableColumnHeaderProps { column: GridNode; state: TableState; isSubtle?: boolean; + variant: ITableProps['variant']; } export function TableColumnHeader({ column, state, + variant, }: ITableColumnHeaderProps) { const ref = useRef(null); const { columnHeaderProps } = useTableColumnHeader( @@ -87,7 +83,7 @@ export function TableColumnHeader({ = { }, options: ['single', 'multiple', 'none'], }, + variant: { + control: { + type: 'radio', + }, + options: ['default', 'open'], + }, }, }; @@ -109,11 +115,46 @@ export const Primary: Story = { }, }; +export const OpenStyle: Story = { + name: 'Openstyle Table', + args: { + isStriped: false, + isCompact: false, + variant: 'open', + }, + render: (args) => { + return ( + + + {columns.map((column) => ( + + {column.name} + + ))} + + + {rows.map((row) => ( + + {row.name} + {row.type} + {row.date} + + ))} + +
+ ); + }, +}; + export const Striped: Story = { name: 'Striped Table', - render: () => { + render: (args) => { return ( - +
{(column) => ( {column.name} @@ -135,9 +176,14 @@ export const Striped: Story = { export const Compact: Story = { name: 'Compact Table', - render: () => { + render: (args) => { return ( -
+
{(column) => ( {column.name} @@ -159,9 +205,9 @@ export const Compact: Story = { export const Link: Story = { name: 'Link Table', - render: () => { + render: (args) => { return ( -
+
{(column) => ( {column.name} @@ -187,7 +233,7 @@ export const Sorting: Story = { * feature. Reference react-aria docs for more advanced examples: * https://react-spectrum.adobe.com/react-aria/useTable.html#sorting. */ - render: () => { + render: (args) => { const [items, setItems] = useState(rows); const [sortDescriptor, setSortDescriptor] = useState({}); @@ -212,6 +258,7 @@ export const Sorting: Story = { return (
{ + render: (args) => { return ( -
+
100px @@ -277,9 +324,9 @@ export const FixedWidth: Story = { export const NestedHeader: Story = { name: 'Table with Nested Columns', - render: () => { + render: (args) => { return ( -
+
First Name diff --git a/packages/libs/kode-ui/src/components/Table/Table.tsx b/packages/libs/kode-ui/src/components/Table/Table.tsx index b902c567b2..142a6340f1 100644 --- a/packages/libs/kode-ui/src/components/Table/Table.tsx +++ b/packages/libs/kode-ui/src/components/Table/Table.tsx @@ -8,7 +8,7 @@ import { useTableState } from 'react-stately'; import { TableCell, TableRow } from './Body'; import { TableColumnHeader, TableHeaderRow } from './Header'; -import { table, tableWrapper } from './Table.css'; +import { table, tableVariants, tableWrapper } from './Table.css'; import { TableSelectAllCell } from './TableSelectAllCell'; import { TableSelectionCell } from './TableSelectionCell'; @@ -18,6 +18,7 @@ export interface ITableProps Omit, 'children'> { isStriped?: boolean; isCompact?: boolean; + variant?: 'default' | 'open'; } export function Table(props: ITableProps) { @@ -37,10 +38,16 @@ export function Table(props: ITableProps) {
@@ -50,6 +57,7 @@ export function Table(props: ITableProps) { return ( (props: ITableProps) { {[...headerRow.childNodes].map((column) => column.props?.isSelectionCell ? ( (props: ITableProps) { /> ) : ( (props: ITableProps) { {[...collection.body.childNodes].map((row) => ( (props: ITableProps) { {[...row.childNodes].map((cell) => cell.props.isSelectionCell ? ( (props: ITableProps) { /> ) : ( { column: GridNode; state: ITableRowProps['state']; inverse?: boolean; + variant: ITableProps['variant']; } export function TableSelectAllCell({ column, state, inverse = false, + variant, }: ITableSelectAllCellProps) { const ref = useRef(null); const { columnHeaderProps } = useTableColumnHeader( @@ -34,7 +37,7 @@ export function TableSelectAllCell({
{state.selectionManager.selectionMode === 'single' ? ( {checkboxProps['aria-label']} diff --git a/packages/libs/kode-ui/src/components/Table/TableSelectionCell.tsx b/packages/libs/kode-ui/src/components/Table/TableSelectionCell.tsx index faa4306a1c..7628d15619 100644 --- a/packages/libs/kode-ui/src/components/Table/TableSelectionCell.tsx +++ b/packages/libs/kode-ui/src/components/Table/TableSelectionCell.tsx @@ -8,12 +8,14 @@ import { Checkbox } from '../Form'; import { boxClass, iconClass } from '../Form/RadioGroup/Radio.css'; import { RadioGroup } from '../Form/RadioGroup/RadioGroup'; import type { ITableRowProps } from './Body'; +import type { ITableProps } from './Table'; import { selectorCell, tableDataCell } from './Table.css'; interface ITableSelectionCell { cell: GridNode; state: ITableRowProps['state']; selectionMode?: 'single' | 'multiple' | 'none'; + variant: ITableProps['variant']; } const Dot = ({ className }: { className: string }) => ( @@ -41,6 +43,7 @@ export function TableSelectionCell({ cell, state, selectionMode, + variant, }: ITableSelectionCell) { const ref = useRef(null); const { gridCellProps } = useTableCell({ node: cell }, state, ref); diff --git a/packages/libs/kode-ui/src/patterns/CompactTable/CompactTable.stories.tsx b/packages/libs/kode-ui/src/patterns/CompactTable/CompactTable.stories.tsx index 32ce797d31..09de283f41 100644 --- a/packages/libs/kode-ui/src/patterns/CompactTable/CompactTable.stories.tsx +++ b/packages/libs/kode-ui/src/patterns/CompactTable/CompactTable.stories.tsx @@ -24,6 +24,12 @@ const meta: Meta = { isLoading: { type: 'boolean', }, + variant: { + control: { + type: 'radio', + }, + options: ['default', 'open'], + }, }, }; @@ -73,10 +79,11 @@ export const Primary: Story = { args: { isLoading: false, }, - render: ({ isLoading }) => { + render: ({ isLoading, variant }) => { return ( { + render: ({ isLoading, variant }) => { return ( { + render: ({ isLoading, variant }) => { return ( { + render: ({ isLoading, variant }) => { return ( { + render: ({ isLoading, variant }) => { return ( { + render: ({ isLoading, variant }) => { return ( { + render: ({ isLoading, variant }) => { const callAction = (value: any) => { alert(value); }; return ( { + return ( + + + + ); + }, +}; diff --git a/packages/libs/kode-ui/src/patterns/CompactTable/CompactTable.tsx b/packages/libs/kode-ui/src/patterns/CompactTable/CompactTable.tsx index 63ef638d7e..3e80340caa 100644 --- a/packages/libs/kode-ui/src/patterns/CompactTable/CompactTable.tsx +++ b/packages/libs/kode-ui/src/patterns/CompactTable/CompactTable.tsx @@ -1,4 +1,5 @@ import React from 'react'; +import type { ITableProps } from 'src/components'; import { Media } from './../../components/Media'; import { CompactTableDesktop } from './CompactTableDesktop/CompactTableDesktop'; import { CompactTableMobile } from './CompactTableMobile/CompactTableMobile'; @@ -15,6 +16,7 @@ export interface ICompactTableProps { totalCount?: number; pageSize?: number; setPage?: (page: ITablePaginationPageOptions) => void; + variant?: ITableProps['variant']; pageInfo?: { endCursor?: string | null; startCursor?: string | null; @@ -29,6 +31,7 @@ export const CompactTable: React.FC = ({ label, isLoading = false, totalCount, + variant = 'default', pageSize, setPage, pageInfo, @@ -36,10 +39,16 @@ export const CompactTable: React.FC = ({ return ( <> - + = ({ fields, label = 'Table', isLoading = false, + variant = 'default', }) => { return ( - +
{fields.map((field, idx) => ( diff --git a/packages/libs/kode-ui/src/patterns/CompactTable/CompactTableDesktop/styles.css.ts b/packages/libs/kode-ui/src/patterns/CompactTable/CompactTableDesktop/styles.css.ts index 0f3a423682..53987b465d 100644 --- a/packages/libs/kode-ui/src/patterns/CompactTable/CompactTableDesktop/styles.css.ts +++ b/packages/libs/kode-ui/src/patterns/CompactTable/CompactTableDesktop/styles.css.ts @@ -1,5 +1,5 @@ import { globalStyle, style } from '@vanilla-extract/css'; -import { atoms } from './../../../styles'; +import { atoms, recipe } from './../../../styles'; export const tableClass = style({ width: '100%', @@ -14,12 +14,20 @@ globalStyle(`${tableClass} td > span`, { whiteSpace: 'nowrap', }); -export const tableBorderClass = style([ - atoms({ - borderRadius: 'lg', - borderColor: 'base.subtle', - borderWidth: 'hairline', - borderStyle: 'solid', - }), - {}, -]); +export const tableBorderClass = recipe({ + base: {}, + variants: { + variant: { + default: [ + atoms({ + padding: 'sm', + borderRadius: 'lg', + borderColor: 'base.subtle', + borderWidth: 'hairline', + borderStyle: 'solid', + }), + ], + open: {}, + }, + }, +}); diff --git a/packages/libs/kode-ui/src/patterns/CompactTable/CompactTableMobile/CompactTableMobile.tsx b/packages/libs/kode-ui/src/patterns/CompactTable/CompactTableMobile/CompactTableMobile.tsx index 1046857b4d..eef9620207 100644 --- a/packages/libs/kode-ui/src/patterns/CompactTable/CompactTableMobile/CompactTableMobile.tsx +++ b/packages/libs/kode-ui/src/patterns/CompactTable/CompactTableMobile/CompactTableMobile.tsx @@ -13,9 +13,10 @@ export const CompactTableMobile: FC = ({ data, fields, isLoading = false, + variant, }) => { return data.map((item, idx) => ( -
+
{fields.map((field, idx) => (
{field.label} diff --git a/packages/libs/kode-ui/src/patterns/CompactTable/CompactTableMobile/styles.css.ts b/packages/libs/kode-ui/src/patterns/CompactTable/CompactTableMobile/styles.css.ts index 47337910e5..ff4866e014 100644 --- a/packages/libs/kode-ui/src/patterns/CompactTable/CompactTableMobile/styles.css.ts +++ b/packages/libs/kode-ui/src/patterns/CompactTable/CompactTableMobile/styles.css.ts @@ -1,12 +1,31 @@ -import { atoms, style, tokens } from './../../../styles'; +import { atoms, recipe, style, tokens } from './../../../styles'; -export const sectionClass = style([ - atoms({ - padding: 'n6', - backgroundColor: 'base.default', - marginBlockEnd: 'md', - }), -]); +export const sectionClass = recipe({ + base: [ + atoms({ + marginBlockEnd: 'n2', + }), + ], + variants: { + variant: { + default: [ + atoms({ + padding: 'n6', + backgroundColor: 'base.default', + }), + ], + open: [ + atoms({ + paddingBlock: 'n3', + paddingInline: 'n4', + border: 'hairline', + borderRadius: 'sm', + backgroundColor: 'layer.default', + }), + ], + }, + }, +}); export const headerClass = style([ atoms({ diff --git a/packages/libs/kode-ui/src/styles/tokens/contract.css.ts b/packages/libs/kode-ui/src/styles/tokens/contract.css.ts index c1a4f516d3..274c689fd8 100644 --- a/packages/libs/kode-ui/src/styles/tokens/contract.css.ts +++ b/packages/libs/kode-ui/src/styles/tokens/contract.css.ts @@ -783,6 +783,42 @@ export const tokens = createThemeContract({ */ toast: '', }, + effect: { + shadow: { + /** + * This is the shadow 1 description + * @light `"4px 0.5rem tokens.kda.foundation.size.n2 4px #000000"` + * @dark `"4px 0.5rem tokens.kda.foundation.size.n2 4px #000000"` + */ + level1: '', + /** + * This is the shadow 2 description + * @light `"4rem 4rem tokens.kda.foundation.size.n2 2rem #000000"` + * @dark `"4rem 4rem tokens.kda.foundation.size.n2 2rem #000000"` + */ + level2: '', + /** + * This is the shadow 3 description updated + * @light `"0px 0px tokens.kda.foundation.size.n2 24px #000000"` + * @dark `"0px 0px tokens.kda.foundation.size.n2 24px #000000"` + */ + level3: '', + }, + }, + layout: { + content: { + /** + * @light `"33.75rem"` + * @dark `"33.75rem"` + */ + minWidth: '', + /** + * @light `"42.5rem"` + * @dark `"42.5rem"` + */ + maxWidth: '', + }, + }, color: { accent: { /** @@ -1593,6 +1629,20 @@ export const tokens = createThemeContract({ */ default: '', }, + table: { + row: { + /** + * @light {@link tokens.kda.foundation.color.background.layer.default} + * @dark {@link tokens.kda.foundation.color.background.layer.default} + */ + default: '', + /** + * @light {@link tokens.kda.foundation.color.neutral.n1@alpha80} + * @dark {@link tokens.kda.foundation.color.neutral.n10@alpha80} + */ + '@hover': '', + }, + }, }, border: { base: { @@ -5041,28 +5091,6 @@ export const tokens = createThemeContract({ }, }, }, - effect: { - shadow: { - /** - * This is the shadow 1 description - * @light `"4px 0.5rem tokens.kda.foundation.size.n2 4px #000000"` - * @dark `"4px 0.5rem tokens.kda.foundation.size.n2 4px #000000"` - */ - level1: '', - /** - * This is the shadow 2 description - * @light `"4rem 4rem tokens.kda.foundation.size.n2 2rem #000000"` - * @dark `"4rem 4rem tokens.kda.foundation.size.n2 2rem #000000"` - */ - level2: '', - /** - * This is the shadow 3 description updated - * @light `"0px 0px tokens.kda.foundation.size.n2 24px #000000"` - * @dark `"0px 0px tokens.kda.foundation.size.n2 24px #000000"` - */ - level3: '', - }, - }, icon: { size: { /** @@ -5102,20 +5130,6 @@ export const tokens = createThemeContract({ xxl: '', }, }, - layout: { - content: { - /** - * @light `"33.75rem"` - * @dark `"33.75rem"` - */ - minWidth: '', - /** - * @light `"42.5rem"` - * @dark `"42.5rem"` - */ - maxWidth: '', - }, - }, typography: { family: { /** diff --git a/packages/libs/kode-ui/src/styles/tokens/dark.css.ts b/packages/libs/kode-ui/src/styles/tokens/dark.css.ts index 90be2f4159..c746f9558e 100644 --- a/packages/libs/kode-ui/src/styles/tokens/dark.css.ts +++ b/packages/libs/kode-ui/src/styles/tokens/dark.css.ts @@ -207,6 +207,19 @@ export const darkThemeValues = { sticky: '100', toast: '10000', }, + effect: { + shadow: { + level1: `4px 0.5rem ${tokens.kda.foundation.size.n2} 4px #000000`, + level2: `4rem 4rem ${tokens.kda.foundation.size.n2} 2rem #000000`, + level3: `0px 0px ${tokens.kda.foundation.size.n2} 24px #000000`, + }, + }, + layout: { + content: { + minWidth: '33.75rem', + maxWidth: '42.5rem', + }, + }, color: { accent: { blue: tokens.kda.foundation.color.palette.blue.n50, @@ -449,6 +462,12 @@ export const darkThemeValues = { skeleton: { default: tokens.kda.foundation.color.neutral['n20@alpha80'], }, + table: { + row: { + default: tokens.kda.foundation.color.background.layer.default, + '@hover': tokens.kda.foundation.color.neutral['n10@alpha80'], + }, + }, }, border: { base: { @@ -1309,13 +1328,6 @@ export const darkThemeValues = { }, }, }, - effect: { - shadow: { - level1: `4px 0.5rem ${tokens.kda.foundation.size.n2} 4px #000000`, - level2: `4rem 4rem ${tokens.kda.foundation.size.n2} 2rem #000000`, - level3: `0px 0px ${tokens.kda.foundation.size.n2} 24px #000000`, - }, - }, icon: { size: { xxs: tokens.kda.foundation.size.n3, @@ -1327,12 +1339,6 @@ export const darkThemeValues = { xxl: tokens.kda.foundation.size.n16, }, }, - layout: { - content: { - minWidth: '33.75rem', - maxWidth: '42.5rem', - }, - }, typography: { family: { primaryFont: 'Inter', diff --git a/packages/libs/kode-ui/src/styles/tokens/light.css.ts b/packages/libs/kode-ui/src/styles/tokens/light.css.ts index 35f731494d..f2dac26c73 100644 --- a/packages/libs/kode-ui/src/styles/tokens/light.css.ts +++ b/packages/libs/kode-ui/src/styles/tokens/light.css.ts @@ -207,6 +207,19 @@ export const lightThemeValues = { sticky: '100', toast: '10000', }, + effect: { + shadow: { + level1: `4px 0.5rem ${tokens.kda.foundation.size.n2} 4px #000000`, + level2: `4rem 4rem ${tokens.kda.foundation.size.n2} 2rem #000000`, + level3: `0px 0px ${tokens.kda.foundation.size.n2} 24px #000000`, + }, + }, + layout: { + content: { + minWidth: '33.75rem', + maxWidth: '42.5rem', + }, + }, color: { accent: { blue: tokens.kda.foundation.color.palette.blue.n50, @@ -449,6 +462,12 @@ export const lightThemeValues = { skeleton: { default: tokens.kda.foundation.color.neutral.n10, }, + table: { + row: { + default: tokens.kda.foundation.color.background.layer.default, + '@hover': tokens.kda.foundation.color.neutral['n1@alpha80'], + }, + }, }, border: { base: { @@ -1309,13 +1328,6 @@ export const lightThemeValues = { }, }, }, - effect: { - shadow: { - level1: `4px 0.5rem ${tokens.kda.foundation.size.n2} 4px #000000`, - level2: `4rem 4rem ${tokens.kda.foundation.size.n2} 2rem #000000`, - level3: `0px 0px ${tokens.kda.foundation.size.n2} 24px #000000`, - }, - }, icon: { size: { xxs: tokens.kda.foundation.size.n3, @@ -1327,12 +1339,6 @@ export const lightThemeValues = { xxl: tokens.kda.foundation.size.n16, }, }, - layout: { - content: { - minWidth: '33.75rem', - maxWidth: '42.5rem', - }, - }, typography: { family: { primaryFont: 'Inter',