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

refactor(SimpleTable): drop BEM, use Mantine TASK-1377 #5366

Open
wants to merge 18 commits into
base: kalvis/mantine-setup
Choose a base branch
from

Conversation

magicznyleszek
Copy link
Member

@magicznyleszek magicznyleszek commented Dec 18, 2024

🗒️ Checklist

  1. run linter locally
  2. update all related docs (API, README, inline, etc.), if any
  3. draft PR with a title <type>(<scope>)<!>: <title> TASK-1234
  4. tag PR: at least frontend or backend unless it's global
  5. fill in the template below and delete template comments
  6. review thyself: read the diff and repro the preview as written
  7. open PR & confirm that CI passes
  8. request reviewers, if needed
  9. delete this section before merging

📣 Summary

Replace bem.SimpleTable with Mantine-based SimpleTable component (a wrapper over Table from @mantine/core). The change for users is mainly visual.

📖 Description

The tables that are affected by this are:

  • BulkEditSubmissionsForm
  • BulkEditRowForm
  • ProjectExportsList
  • SubmissionDataTable (just responses for geopoint questions)

💭 Notes

I based the looks of the SimpleTable on our UniversalTable as this is the latest design we have of "a table". This means it would look different from what we had, and it's ok.

The steps I took to accomplish this Mantine based replacement:

  1. Create js/components/common/SimpleTable.tsx
    1. import Table from @mantine/core
    2. make wrapper that renders <Table> with some props passed to it (e.g. data)
  2. Create js/components/common/SimpleTable.stories.tsx
  3. Create js/theme/kobo/Table.ts
    1. import Table from @mantine/core
    2. export const TableThemeKobo = Table.extend({ with defaultProps changed and vars changing CSS variable colors
  4. Find out I want to add border-radius to my SimpleTable and change background-color for header
    1. Discovered in https://mantine.dev/styles/styles-api/ that I need to know what are the names of selectors in Table
    2. Followed the import back in the code editor, found TableStylesNames, and found table :fanfare:
  5. Back in js/theme/kobo/Table.ts I've added styles.table object to TableThemeKobo and changed the style properties I wanted to change 👌
  6. I needed to override border-collapse so border-radius would work. Now I needed to fix the missing borders:
    1. thead gets background color
    2. td gets border top styles
  7. Now replacing all bem.SimpleTable was pretty straightforward, some bumps on the road:
    1. had to figure out how to center column text - used Text from Mantine wrapped around array items, rather than making this part of SimpleTable (this was my initial idea, but couldn't find a way to do it with Mantine without hacking things too much)
    2. hat to figure out how to sometimes add margins around the table - used Box from Mantine, rather than having the optinal margins be part of SimpleTable (still not sure if this is the "proper" way of using Box)
  8. I discovered that Storybook sometimes doesn't render the styles upon browser tab reload (some clicking around and scrolling forces the styles to be loaded). So I followed the official guide to using Storybook with Mantine and updated the base branch: 27e8f95
  9. Code review happened
  10. Migrating TableThemeKobo.styles from js/theme/kobo/Table.ts to CSS module in js/components/common/SimpleTable.module.scss
    • Using classNames property on <Table>
    • Also using CSS variables in the file, to match the theme
  11. Rather than using <Box> to apply margins, we pass mt to SimpleTable directly. To make this work, SimpleTable is accepting MantineStyleProps besides its own custom props.

👀 Preview steps

Run Storybook and make sure that SimpleTable looks ok

  1. run storybook (there's an npm action)
  2. go to http://localhost:6006/?path=/docs/common-simpletable--docs
  3. 🟢 notice that the example table looks good

Verify that BulkEditSubmissionsForm works correctly

  1. ℹ️ have a form (at least some simple quesiton types) with multiple submissions
  2. go to Project -> Data -> Table
  3. select multiple rows (leftmost column has a checkbox) or all rows
  4. at the top of the table "edit" button will appear, click it
  5. 🟢 notice a table with a list of questions from the form
  6. 🟢 verify it has the same functionalities as same table from beta

Verify that BulkEditRowForm works correctly
8. ℹ️ follow all the above steps
9. for one of the rows click "edit" button from "Action" column
10. 🟢 notice a table with proposed existing responses appear
11. 🟢 verify it has the same functionalities as same table from beta

Verify that ProjectExportsList works correctly

  1. ℹ️ have a form with submissions
  2. go to Project -> Data -> Downloads
  3. use "Export" button few times to generate multiple exports
  4. 🟢 notice that a table appeared below
  5. 🟢 verify it has the same functionalities as same table from beta

Verify that SubmissionDataTable works correctly

  1. ℹ️ have a form (at least some geopoint quesiton types) with multiple submissions
  2. go to Project -> Data -> Table
  3. for one of the rows click "Open" button (eye icon in the leftmost column)
  4. in the modal that appears, scroll down to a geopoint question (one with a response!)
  5. 🟢 notice that there is a table (Point, latitude, longitude, altitude, accuracy)
  6. 🟢 verify it renders properly (it doesn't have any functionalities besides displaying data)

@magicznyleszek magicznyleszek added UI & UX User interface problems and improvements Front end refactor Internal code clanup labels Dec 18, 2024
@magicznyleszek magicznyleszek self-assigned this Dec 18, 2024
@magicznyleszek magicznyleszek marked this pull request as ready for review December 18, 2024 13:48
Comment on lines 11 to 33
styles: (theme) => {
return {
table: {
backgroundColor: theme.colors.gray[9],
borderCollapse: 'separate',
borderRadius: theme.radius.md,
},
thead: {
backgroundColor: theme.colors.gray[8],
},
th: {
fontSize: theme.fontSizes.sm,
color: theme.colors.gray[2],
fontWeight: '400',
},
td: {
fontSize: theme.fontSizes.md,
borderTopWidth: '1px',
borderTopColor: theme.colors.gray[7],
borderTopStyle: 'solid',
},
};
},
Copy link
Contributor

@Akuukis Akuukis Dec 19, 2024

Choose a reason for hiding this comment

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

let's prefer CSS Modules file over styles prop, because that edits CSS class once, instead of adding style="font-size: calc(0.875rem * var(--mantine-scale)); border-top: 1px solid rgb(237, 238, 242);" to every cell individually (see DOM of storybook). Also, that's officially recommended.

Furthermore, would you agree to prefer vars prop over CSS Modules file, because that's a simple parameterization of the CSS Modules? Although performance is unknown and official docs lacks an opinion on using vars prop vs "hardcoded" values in CSS Modules.

Comment on lines +277 to +278
<Text key='include-groups' ta='center'>{t('Include Groups')}</Text>,
<Text key='multiple-versions' ta='center'>{t('Multiple Versions')}</Text>,
Copy link
Contributor

@Akuukis Akuukis Dec 19, 2024

Choose a reason for hiding this comment

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

Looks OK to use <Text> 👌

{Array.from(this.getUniqueResponses()).map(this.renderResponseRow)}
</bem.SimpleTable__body>
</bem.SimpleTable>
<Box mt='lg'>
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd prefer that mt='lg' would be applicable to SimpleTable itself. See suggestion over there

Comment on lines 2 to 36

interface SimpleTableProps {
head: TableData['head'];
body: TableData['body'];
/**
* Passing minimum width enables contextual horizontal scrollbar (i.e. without
* it the table will never display scrollbar - regardless of how small
* the screen is).
*/
minWidth?: number;
}

/**
* A wrapper component for `Table` from `@mantine/core`. It requires column
* headings, column data, and has optional minimum width.
*/
export default function SimpleTable(props: SimpleTableProps) {
const table = (
<Table
data={{head: props.head, body: props.body}}
horizontalSpacing='sm'
verticalSpacing='sm'
/>
);

if (props.minWidth) {
return (
<Table.ScrollContainer minWidth={props.minWidth} type='native'>
{table}
</Table.ScrollContainer>
);
}

return table;
}
Copy link
Contributor

@Akuukis Akuukis Dec 19, 2024

Choose a reason for hiding this comment

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

Let's support and pass-through style props, to avoid the need for <Box> wrappers (see above)

Suggested change
interface SimpleTableProps {
head: TableData['head'];
body: TableData['body'];
/**
* Passing minimum width enables contextual horizontal scrollbar (i.e. without
* it the table will never display scrollbar - regardless of how small
* the screen is).
*/
minWidth?: number;
}
/**
* A wrapper component for `Table` from `@mantine/core`. It requires column
* headings, column data, and has optional minimum width.
*/
export default function SimpleTable(props: SimpleTableProps) {
const table = (
<Table
data={{head: props.head, body: props.body}}
horizontalSpacing='sm'
verticalSpacing='sm'
/>
);
if (props.minWidth) {
return (
<Table.ScrollContainer minWidth={props.minWidth} type='native'>
{table}
</Table.ScrollContainer>
);
}
return table;
}
interface SimpleTableProps extends MantineStyleProps {
head: TableData['head'];
body: TableData['body'];
/**
* Passing minimum width enables contextual horizontal scrollbar (i.e. without
* it the table will never display scrollbar - regardless of how small
* the screen is).
*/
minWidth?: number;
}
/**
* A wrapper component for `Table` from `@mantine/core`. It requires column
* headings, column data, and has optional minimum width.
*/
export default function SimpleTable({head, body, minWidth, ...styleProps}: SimpleTableProps) {
const table = (
<Table
{...styleProps}
data={{head, body}}
horizontalSpacing='sm'
verticalSpacing='sm'
/>
);
if (minWidth) {
return (
<Table.ScrollContainer minWidth={minWidth} type='native'>
{table}
</Table.ScrollContainer>
);
}
return table;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Front end refactor Internal code clanup UI & UX User interface problems and improvements
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants