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(Table): new component #1129

Merged
merged 22 commits into from
Jun 5, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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 .storybook/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ module.exports = {
stories,
addons: [
'@storybook/addon-links',
'@storybook/addon-controls',
{
name: '@storybook/addon-storysource',
options: {
Expand All @@ -88,7 +89,6 @@ module.exports = {
'./platform-selector-addon/register',
'./dark-mode-addon/register',
'./font-size-addon/register',
'@storybook/addon-controls',
],
webpackFinal: async (config) => {
config.watchOptions = {
Expand Down
2 changes: 2 additions & 0 deletions playroom/snippets.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,7 @@ const tableSnippets: Array<Snippet> = [
'Rarity',
'Average Rating',
]}
columnTextAlign={["left", "right", "right", "right", "center", "right"]}
content={[
['Slice of pizza', '450', '95%', '5,00€', <Tag>Common</Tag>, '8/10'],
['Hamburger', '350', '87%', '3,50€', <Tag>Common</Tag>, '7.5/10'],
Expand All @@ -422,6 +423,7 @@ const tableSnippets: Array<Snippet> = [
'Rarity',
'Average Rating',
]}
columnTextAlign={["left", "right", "right", "right", "center", "right"]}
content={[
['Slice of pizza', '450', '95%', '5,00€', <Tag>Common</Tag>, '8/10'],
['Hamburger', '350', '87%', '3,50€', <Tag>Common</Tag>, '7.5/10'],
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Visually stunning

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
marcoskolodny marked this conversation as resolved.
Show resolved Hide resolved
marcoskolodny marked this conversation as resolved.
Show resolved Hide resolved
8 changes: 8 additions & 0 deletions src/__stories__/table-story.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ type Args = {
numItems: number;
emptyCase: string;
columnTextAlign: Array<'left' | 'right' | 'center'>;
rowVerticalAlign: 'top' | 'middle';
columnWidth: Array<number | string>;
};

Expand All @@ -54,6 +55,7 @@ export const Default: StoryComponent<Args> = ({
numItems,
emptyCase,
columnTextAlign,
rowVerticalAlign,
columnWidth,
}) => {
return (
Expand All @@ -74,6 +76,7 @@ export const Default: StoryComponent<Args> = ({
]}
columnTextAlign={columnTextAlign}
columnWidth={columnWidth}
rowVerticalAlign={rowVerticalAlign}
content={foodList.slice(0, numItems)}
emptyCase={emptyCase}
/>
Expand All @@ -92,6 +95,7 @@ Default.args = {
numItems: 5,
emptyCase: 'No food items found',
columnTextAlign: ['left', 'right', 'right', 'right', 'center', 'right'],
rowVerticalAlign: 'middle',
columnWidth: ['auto', 'auto', 'auto', 'auto', 'auto', 'auto'],
};
Default.argTypes = {
Expand All @@ -105,4 +109,8 @@ Default.argTypes = {
numItems: {
control: {type: 'range', min: 0, max: foodList.length, step: 1},
},
rowVerticalAlign: {
options: ['top', 'middle'],
control: {type: 'select'},
},
};
12 changes: 9 additions & 3 deletions src/table.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,18 +62,24 @@ export const scrollContainer = style({
},
});

export const verticalAlign = styleVariants({
top: {verticalAlign: 'top'},
middle: {verticalAlign: 'middle'},
});

// we can only apply sticky head to boxed tables, because non-boxed tables don't have a background
globalStyle(`${boxed} thead`, {
position: 'sticky',
top: 0,
background: skinVars.colors.backgroundContainer,
});

const ROW_MIN_HEIGHT = 56;

globalStyle(`${table} th, ${table} td`, {
borderBottom: `1px solid ${skinVars.colors.divider}`,
padding: '16px 12px',
minHeight: 56,
verticalAlign: 'middle',
height: ROW_MIN_HEIGHT, // height behaves like a min-height in table layout
});

globalStyle(`${table}:not(${boxed}) th:first-child, ${table}:not(${boxed}) td:first-child`, {
Expand Down Expand Up @@ -125,7 +131,7 @@ globalStyle(`${collapsedRowsInMobile} tbody td`, {
[mq.tabletOrSmaller]: {
verticalAlign: 'initial',
border: 'none',
minHeight: 0,
height: 'auto', // reset min-height
padding: '0 0 8px 0',
},
},
Expand Down
51 changes: 41 additions & 10 deletions src/table.tsx
yceballost marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know this is a wrong usage, but if you write a string in columnTextAlign prop, the alignment changes for each letter. That's weird and I don't know if it is something to avoid

columnTextAlign.-.Table.-.bug.mov

yceballost marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,13 @@ import {InternalBoxed} from './boxed';
import classNames from 'classnames';
import Box from './box';
import {applyCssVars} from './utils/css';
import ResponsiveLayout, {ResetResponsiveLayout} from './responsive-layout';

import type {DataAttributes} from './utils/types';

type TextAlign = 'left' | 'right' | 'center';
type VerticalAlign = 'top' | 'middle';

type TableProps = {
Copy link
Contributor

@yceballost yceballost May 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing alignItems prop to align content horizontally

image

heading: Array<string>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you confirm if headers also support custom elements @aweell ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not according the spec, and I think it could be problematic, how would you show them in mobile (collapse-rows mode)?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep, I remember talking to Alex about this but I don't remember what the outcome was. I thought that the custom item would be included and that in mobile it is the product's responsibility... that's why I wanted Alex's confirmation.

The product could use strings in mobile and custom composition in desktop, for example.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That was the idea yes, allow slots in headers mostly for desktop views. It was changed in a small paragraph in the desktop behaviour but not in the anatomy, is already fixed in the specs

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

content?: Array<Array<React.ReactNode>>;
Expand All @@ -20,7 +24,8 @@ type TableProps = {
* render every row as a card
*/
responsive?: 'scroll' | 'collapse-rows';
columnTextAlign?: Array<'left' | 'right' | 'center'>;
columnTextAlign?: Array<TextAlign> | TextAlign;
rowVerticalAlign?: VerticalAlign;
columnWidth?: Array<number | string>;
/**
* by default, the table expands to all the available width, if you want the table to have the minimum width to fit the rows content, set fullWidth to false.
Expand Down Expand Up @@ -51,11 +56,23 @@ export const Table = React.forwardRef(
maxHeight,
emptyCase,
columnTextAlign,
rowVerticalAlign = 'middle',
columnWidth,
...otherProps
}: TableProps,
ref: React.Ref<HTMLDivElement>
) => {
const getColumnTextAlign = (column: number) => {
const defaultTextAlign = 'left';
if (columnTextAlign) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps you can use a default parameter to simplify this to: return Array.isArray(columnTextAlign) ? columnTextAlign[column] : columnTextAlign

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not really, it whould be something like:

Array.isArray(columnTextAlign) ? columnTextAlign[column] ?? defaultTextAlign : columnTextAlign;

Copy link
Contributor

@Marcosld Marcosld May 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I see, that's in case the user just sends the textAlign for some of the columns... but given input parameter is an array and not something like a map[columnIdx->alignment]... is that a good use of the API? 🤔

if (Array.isArray(columnTextAlign)) {
return columnTextAlign[column] ?? defaultTextAlign;
}
return columnTextAlign;
}
return defaultTextAlign;
};

const collapsedRowsMode = responsive === 'collapse-rows';
const table = (
<table
Expand All @@ -80,7 +97,10 @@ export const Table = React.forwardRef(
<th
scope="col"
key={idx}
className={styles.cellTextAlign[columnTextAlign?.[idx] ?? 'left']}
className={classNames(
styles.cellTextAlign[getColumnTextAlign(idx)],
styles.verticalAlign[rowVerticalAlign]
)}
style={{width: columnWidth?.[idx]}}
>
{header}
Expand All @@ -90,10 +110,10 @@ export const Table = React.forwardRef(
</thead>
<tbody>
{content && content.length ? (
content.map((row, idx) => (
<tr key={idx}>
content.map((row, rowIdx) => (
<tr key={rowIdx}>
{row.map((cell, idx) => (
<td key={idx}>
<td key={idx} className={styles.verticalAlign[rowVerticalAlign]}>
{/**
* In collapsedRowsMode, we render the row heading text before every cell content, except for the first cell
* of every row, which is rendered with a medium weight font, as it's the row title.
Expand All @@ -114,7 +134,7 @@ export const Table = React.forwardRef(
>
<div
className={classNames(
styles.cellTextAlign[columnTextAlign?.[idx] ?? 'left'],
styles.cellTextAlign[getColumnTextAlign(idx)],
{
[styles.collapsedRowTittle]:
idx === 0 && collapsedRowsMode,
Expand Down Expand Up @@ -169,16 +189,27 @@ export const Table = React.forwardRef(
dataAttributes={{'component-name': 'Table', ...dataAttributes}}
>
<div {...scrollContainerStyles}>
<Box paddingX={{desktop: 8, mobile: collapsedRowsMode ? 0 : 8}}>{table}</Box>
<Box
paddingX={{desktop: 16, mobile: collapsedRowsMode ? 0 : 8}}
paddingY={{desktop: 8, mobile: 0}}
>
{table}
</Box>
</div>
</InternalBoxed>
);
}

return (
<div ref={ref} {...getPrefixedDataAttributes(dataAttributes, 'Table')} {...scrollContainerStyles}>
{table}
</div>
<ResetResponsiveLayout>
<div
ref={ref}
{...getPrefixedDataAttributes(dataAttributes, 'Table')}
{...scrollContainerStyles}
>
<ResponsiveLayout>{table}</ResponsiveLayout>
</div>
</ResetResponsiveLayout>
);
}
);
Loading