Skip to content
This repository has been archived by the owner on May 24, 2024. It is now read-only.

[terra-table] New Terra table #3917

Merged
merged 57 commits into from
Oct 13, 2023
Merged

[terra-table] New Terra table #3917

merged 57 commits into from
Oct 13, 2023

Conversation

kenk2
Copy link
Contributor

@kenk2 kenk2 commented Sep 20, 2023

Summary

What was changed:
Implementing new Terra Table. Terra Outline Table is deleted.

Why it was changed:
Implementing new table for datagrid initiatives. Terra Outline Table is obsolete and not being worked on.

Testing

This change was tested using:

  • WDIO
  • Jest
  • Visual testing (please attach a screenshot or recording)
  • Other (please describe below)
  • No tests are needed

Reviews

In addition to engineering reviews, this PR needs:

  • UX review
  • Accessibility review
  • Functional review

Additional Details

This PR resolves:

UXPLATFORM-XXXX


Thank you for contributing to Terra.
@cerner/terra

@kenk2 kenk2 self-assigned this Sep 20, 2023
@kenk2 kenk2 requested review from cm9361 and sdadn October 11, 2023 14:49
columnHeaderHeight: '2.5rem',
rowHeight: '2.5rem',
pinnedColumns: [],
overflowColumns: [],
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we add a default empty array for rows as well?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Right now I'm requiring rows to be supplied (but it can be empty) since in DataGrid this is actually a bug right now (component will not render otherwise). But I could also see a case where we might want to default to [] if rows is not specified.

Copy link
Contributor

Choose a reason for hiding this comment

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

I might suggest also making it optional if we allow rows to be empty, as that puts less burden on the consumer. If we leave it like it is here, we'd need to make sure the component doesn't completely break when nothing is provided for rows, as is happening with DataGrid.

Copy link
Contributor Author

@kenk2 kenk2 Oct 11, 2023

Choose a reason for hiding this comment

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

On second thought you're right, and after thinking about it the pattern does feel awkward to pass in an empty array.

Done.

isMasked: false,
};

function Cell(props) {
Copy link
Contributor

Choose a reason for hiding this comment

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

So just wanting to make sure, this package will be where all these subcomponents will live instead of in data-grid? So we plan on removing them from data-grid when consuming Table? I have some in-flight changes to both Row and Cell as part of Flowsheet that, depending on the PR review, I would need to make sure don't get lost in the process of migrating these.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In the future, yes these components will all live inside this Table package. If you finish first, then I'll be adding your changes into this PR. If I finish first with this then we'll have to make another PR to add in-fight work to this PR when it happens. But most of it should be copy-paste and not require significant rework.

Copy link
Contributor

Choose a reason for hiding this comment

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

Disregard, I'm changing my code to no longer affect Cell or Row.

@@ -36,6 +36,7 @@
},
"dependencies": {
"@cerner/terra-docs": "^1.9.0",
"legacy-terra-table": "npm:terra-table@^4.36.0",
Copy link
Contributor

Choose a reason for hiding this comment

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

nice use of an alias


## Changes from 4.x to 5.0

Terra table will no longer support grid-like (focus, keyboard navigation, etc) functionality and now behaves more like a native, accessible table. See the Docs for new functionality.
Copy link
Contributor

Choose a reason for hiding this comment

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

I believe this should be more detailed and list out all the features that are no longer available in 5.0. However, it can be fleshed out in a future doc upgrade Jira and shouldn't prevent merging for now.

Comment on lines 152 to 154
const [cellAriaLiveMessage, setCellAriaLiveMessage] = useState(null);

const [pinnedColumnOffsets, setPinnedColumnOffsets] = useState([0]);
Copy link
Contributor

Choose a reason for hiding this comment

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

shouldn't these be defined in utils/ColumnContext.jsx?

Copy link
Contributor Author

@kenk2 kenk2 Oct 11, 2023

Choose a reason for hiding this comment

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

At some point I'd love to re-factor this and move the code around but like the original table columns logic from datagrid this would be non-trivial to change since AriaLiveMessage is used pretty much everywhere for the screen reader as is the pinned column offsets. We could probably log another JIRA to do this or flesh out the re-factor in another story.

Copy link
Contributor

Choose a reason for hiding this comment

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

Makes sense. That's fine then.

/**
* Boolean indicating if cell contents are masked.
*/
isMasked: PropTypes.bool,
Copy link
Contributor

Choose a reason for hiding this comment

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

The cell shape still does not have all of its props from the DataGrid package implementation.

* A string identifier used to describe the row contents. This value will be used to construct additional labels
* for internal controls (e.g. row selection cells).
*/
ariaLabel: PropTypes.string,
Copy link
Contributor

Choose a reason for hiding this comment

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

The rowShape object does not have all of its props from the DataGrid implementation.

maximumWidth={column.maximumWidth}
headerHeight={headerHeight}
isResizable={column.isResizable}
isSelectable={isGridContext ? column.isSelectable !== false : column.isSelectable}
Copy link
Contributor

@cm9361 cm9361 Oct 12, 2023

Choose a reason for hiding this comment

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

The check for column.isSelectable != false is not a present on the current ColumnHeader. With this logic, you are really adding a WorklistDataGrid specific requirement to the Table component. We should probably remove these checks and have WDG pass the appropriate value as Flowsheet does.

key={`${id}_${displayedColumns[cellColumnIndex].id}`}
isSelected={!hasRowSelection && cellData.isSelected}
isMasked={cellData.isMasked}
isSelectable={isGridContext ? cellData.isSelectable !== false : false}
Copy link
Contributor

Choose a reason for hiding this comment

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

You don't need a ternary operator here. You could just check
isGridContext && cellData.isSelectable !== false

@@ -0,0 +1,19 @@
// Source: https://www.npmjs.com/package/element-closest-polyfill
Copy link
Contributor

@cm9361 cm9361 Oct 12, 2023

Choose a reason for hiding this comment

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

I cannot find where this polyfill file is being used? Maybe this file can be removed.


const GridContext = React.createContext({
role: 'table',
cellAriaLiveMessage: '',
Copy link
Contributor

Choose a reason for hiding this comment

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

This property should not be required. Nobody is reading the value. The table just needs the ability to call the callback.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

@kenk2 kenk2 requested a review from cm9361 October 13, 2023 16:19
return (
<CellTag
ref={cellRef}
aria-selected={isGridContext ? isSelected : undefined}
Copy link
Contributor

Choose a reason for hiding this comment

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

We should not have the isGridContext check here. We can just set it based on the selection state.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There is an edge case where aria-selected={false} in tables creates an accessibility violation, but since since we're saying that cell selection is a grid functionality (which setting the value is allowed) then we can just honor the value from the cell data. Done.

draggable
role="slider"
tabIndex={isGridContext ? -1 : 0}
aria-hidden={isGridContext ? !isActive : undefined}
Copy link
Contributor

Choose a reason for hiding this comment

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

Does this really depend on the grid context?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I was facing an issue earlier where I was getting accessibility errors, but this works now. Done.

const theme = useContext(ThemeContext);
const columnHeaderCell = useRef();

const isGridContext = gridContext.role === GridConstants.GRID;
Copy link
Contributor

Choose a reason for hiding this comment

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

Are we able to just made this a function in the GridContext that can be called instead of having to duplicate the logic in multiple files?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So it turns out that React contexts are read-only and we can't reference the values of a context inside itself. So This will have to do for now.

@github-actions github-actions bot temporarily deployed to preview-pr-3917 October 13, 2023 18:03 Destroyed
@kenk2 kenk2 merged commit bbfc1ca into table-mvb Oct 13, 2023
21 checks passed
@kenk2 kenk2 deleted the new-terra-table branch October 13, 2023 18:26
@mjpalazzo
Copy link
Contributor

@kenk2 - Great work on Table and the examples! I have a few observations:
Keyboard navigation - there are no keyboard requirements for the Table pattern. I was able to tab to the table. For examples with scroll bars I was able use the down arrow keys to scroll through the table content. This provides sighted users with access to off screen content, so that is a valid behavior.
The Pinned Column table navigation with the Down Arrow key worked well. When I Down Arrowed to the right most cell and then pressed Down again, the cells hiddenb behind the pinned columns were visible again. However, when using the Up Arrow, I could not get the columns hidden behind the pinned columns completely visible.
JAWS Screen reader - From the Default Table header I used down arrow to go to the table. JAWS announced "Table with 10 columns and 3 rows." I used Down arrow to navigate the cells. For the table header cells, JAWS announced the role "button" even though there was no sorting enabled. For example, "Patient button." I think JAWS should announce "column header" @eawww - what are your thoughts on the header cell announcements?
Once I was in the body of the table, JAWS announced the cell content correctly. When I pressed Down Arrow from the last cell, JAWS announced, "Table end"
For the Sorted Table example:
APG recommends the following:
"To help screen reader users understand the purpose of the buttons in the column headers, an off-screen description of the sort functionality of the buttons is appended to the caption text. The description is added to the caption instead of to each button to prevent repetitious verbosity that could interfere with understanding of the column titles." I suggest that we add this suggested description to our example.
when I pressed Down Arrow to navigate to the first header cell, JAWS announced "Patient column header sorted ascending column 1" I pressed Enter which changed the sort order. JAWS did not announce the sort order. I tabbed to the column 2 header. JAWS announced "Location column header, column 2" The sort icon did not display (it should) and JAWS did not announce that the column is sortable or the sort order. JAWS should announce that the cell is interactable and how to interact with it. I pressed Enter and the sort order changed, but JAWS only announced "Enter" (Note that on the APG Sortable Table example page, JAWS did not announce the change in sort order either.)
That's all for now. I want to get these observations posted. Let me know if you would like to discuss.
I will continue testing the examples with focusable elements and also test with VoiceOver

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants