Skip to content

Add table sorting #3950

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

Merged
merged 49 commits into from
Mar 10, 2021
Merged

Add table sorting #3950

merged 49 commits into from
Mar 10, 2021

Conversation

sknep
Copy link
Contributor

@sknep sknep commented Jan 19, 2021

Adds table sorting to existing table component.

Component / Fractal Federalist Link: https://federalist-3b6ba08e-0df4-44c9-ac73-6fc193b0e19c.app.cloud.gov/preview/uswds/uswds/accelerator/3935-sortable-table/components/detail/table--sortable.html

USWDS Site Federalist Link: https://federalist-ead78f8d-8948-417c-a957-c21ec5617a57.app.cloud.gov/preview/uswds/uswds-site/accelerator/3935-table-sorting/components/table/

Addresses #3935
See also: #1643 , #1079

Draft usage documentation

The following will be added to existing table page here (subject to change):

Guidance

Enable sort where useful. Add row sorting to individual columns of long tables where the data can be logically ordered either alphabetically or numerically. To activate row sorting, add the data-sortable attribute to the table header element (<th>) of any column with sortable data, and insert an element with the aria-live=”polite” attribute and the class “.usa-table__announcement-region” immediately following the table.

Set a default sort column and direction. To sort a table’s rows by a specific sortable column on load, add the attribute aria-sort equal to a sort direction such as “ascending” or “descending” to that column header. For example,

<th data-sortable aria-sort="ascending" scope=”col”>.

Provide raw values for cells with formatted number content. If you have formatted your cell content for display (such as using percent, currency, or comma formatting) or if your cell content is non-numeric but should be sorted in a numeric order (such as months, days of the week, or dates), then provide a numeric-sortable value in a data-sort-value attribute on each table cell. For example:

Numbers without currency or comma formatting:

<td data-sort-value="132773.54"> $132,773.54 </td>

Percentages or fractions, converted to decimal:

<td data-sort-value="0.943"> 94.3% </td>

Months, weekdays, or other orderable text:

<td data-sort-value="2”> February </td>

Dates, in Unix timestamp:

<td data-sort-value="327092400"> Aug. 21, 1959 </td>

Don’t use row sorting with merged cells. Sorting will not work properly if your table contains colspan or rowspan attributes on the cells.

Don’t use row sorting with the mobile stacked variants. With these variants, the column headers at the top of the table do not appear at narrow widths, and are instead moved into the cell content in each row as prefixing headers.

Accessibility

Add an aria-live region to the page when enabling row sorting. An aria-live region immediately following the <table> element automatically announces when the sort state changes for visitors using screen readers, but it must be added to the HTML document before load:

<div class="usa-sr-only usa-table__announcement-region" aria-live="polite">
  <!-- this content will change when sort changes -->
</div>

Enabling row sorting automatically adds aria-label attributes to the sortable column headers and their toggle sort buttons via JavaScript. These labels are updated to reflect each column’s current sort state (ascending, descending, or unsorted) whenever sort changes. You don’t need to apply these to sortable headers yourself.

Implementation

(these will be added to the existing table)

Variable Description Default
$theme-table-sorted-border-color Defines a border color for the outline of the column that is currently sorted "accent-cool-darker"
$theme-table-sorted-header-background-color Defines a background color for the header of the column that is currently sorted "accent-cool-light"
$theme-table-sorted-background-color Defines a background color for the cells of the column that is currently sorted "accent-cool-lighter"
$theme-table-sorted-stripe-background-color Defines a background color for the alternating horizontal stripes applied to cells of the column that is currently sorted "blue-cool-10v"
$theme-table-sorted-icon-color Defines a fill color for the activated toggle sort button in a sortable column header "ink"
$theme-table-unsorted-icon-color Defines a fill color for the unactivated toggle sort button in a sortable column header "base"

Other

  • Follow the 18F Front End Coding Style Guide and Accessibility Guide.
  • Run npm test and make sure the tests for the files you have changed have passed.
  • Run your code through HTML_CodeSniffer and make sure it’s error free.
  • Title your pull request using this format: [Website] - [UI component]: Brief statement describing what this pull request solves.

@sknep
Copy link
Contributor Author

sknep commented Jan 21, 2021

Status Update 1/20/21

This provides basic alphabetical or numeric sort using localeCompare and the browser's inferred language.

Table header implementation notes

  • matches accordion implementation (size, button, etc)
  • background icon SVG - pros and cons
  • button fills header cell
  • omit button element and sortable class on th to remove sort from a column
  • Need both button element and data-sortable in th to work
  • screenreader reads aloud whether a column is sortable, whether it has been sorted and if so, what direction, and then what sort will occur when the button is clicked (and dynamically updates whenever sort changes), per example from CMS.gov referenced here
    "Sortable column, sorted descending, activate to sort by Year in ascending order"
    "Sortable column, unsorted, activate to sort by Month in ascending order"

Todo:

  • Announce sort on sort, likely though aria-live="polite" around the caption
  • make button themeable / not whole-header click area
  • Add unit tests
  • Get feedback from g-accessibility in #TTS Slack
  • Come up with a reasonable max # of rows? cells? perf

What we don’t get today from this implementation

  • row header sort (this works for column headers only)
  • custom sort / comparator function options
  • row numbering
  • rowspan or colspan (merged cells)
  • Sort by 2+ columns (Last name, then First, etc)
  • Pagination for long, long tables (performance could be iffy with a lot of rows)
  • event emission / callbacks for onSort, such as what header was sorted, in what direction
  • selectable cells or rows
  • theme-able or colorable icons

Trying to think of better example content to describe various data types. Following existing orthogonal sort pattern from datatables.net: https://datatables.net/manual/data/orthogonal-data where an implementing user provides a non-formatted value to sort using instead of the content displayed within the cell (for example, omitting "Honorable" or other prefixes, spelling out full names, or providing non-formatted number, currency, or date strings.) This seemed less error-prone than trying to guess what what kind of content the cell represented by its punctuation or character contents.

I hesitate to suggest we do too much more with tables, as we're veering into data grid territory, which is cool but a whole other ball of wax: https://www.w3.org/TR/wai-aria-practices/examples/grid/dataGrids.html

Resources:

@sknep sknep mentioned this pull request Jan 21, 2021
33 tasks
@jaredcunha
Copy link
Contributor

Though we discussed, I'm adding some other ideas worth exploring here.

  • Deque has a nice accessible sortable table: https://dequeuniversity.com/library/aria/table-sortable I was able to review it using Voice Over and the audible feedback and instructions were quite nice.
  • Exploring role="grid" and aria-readonly="true", which are also used in the Deque example for improving keyboard navigation around cells.
  • There's a visually hidden live region below the table that updates when tables are sorted.

@sknep
Copy link
Contributor Author

sknep commented Jan 22, 2021

Thanks Jared! I added a "todo" section to my original comment based on your suggestions.

@sknep sknep self-assigned this Feb 4, 2021
@sknep sknep linked an issue Feb 4, 2021 that may be closed by this pull request
33 tasks
@mejiaj
Copy link
Contributor

mejiaj commented Feb 16, 2021

@mejiaj What command did you use to do this? the only one I see is npm run prettier:scss

Just modified the prettier:scss command to target the table.js. We should create a prettier:js command.

npx prettier --write ./src/js/components/table.js

<tr>
<th scope="row" role="rowheader">Hawaii</th>
<td data-sort-value="50">50th</td>
<td data-sort-value="331844400">Jun. 27, 1959</td>
Copy link
Contributor

Choose a reason for hiding this comment

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

where are these sort values coming from?

Copy link
Contributor Author

@sknep sknep Feb 16, 2021

Choose a reason for hiding this comment

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

this number is a Unix timestamp. For usage, see the "guidance" section in the first comment of the PR

Copy link
Contributor

Choose a reason for hiding this comment

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

Would it be worth in the guidance adding indicating supporting additional formats like YYYY:MM:DD? Thinking of support for tools where Unix timestamps might be as readily available.

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've deferred parsing dates from strings because they're finicky and would probably have weird issues across timezones unless we included a library like Moment.JS or one of its successors (which I am loathe to do).

@sknep sknep requested a review from thisisdano February 19, 2021 21:40
@thisisdano thisisdano changed the base branch from develop to uswds-2.11.0 March 1, 2021 20:54
@thisisdano thisisdano removed the request for review from mitchmoccia March 1, 2021 20:54
@thisisdano thisisdano changed the title USWDS - Tables: Add Sorting [#3935] Add table sorting Mar 1, 2021
@thisisdano thisisdano mentioned this pull request Mar 1, 2021
19 tasks
Copy link
Contributor

@scottqueen-bixal scottqueen-bixal left a comment

Choose a reason for hiding this comment

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

I spent some time this morning building with this component in a React application and pulling data from https://www.ftc.gov/developer/api/v0/endpoints/do-not-call-dnc-reported-calls-data-api.

Implementation

  • I was able to get up and running within just a few minutes following the guidance from the documentation.

table.js

  • slice.call() is good for those NodeLists
  • readability is good/clear
  • great comments

spec

  • these assertions are deprecated, can we update? ie. equal() -> strictEqual() etc.

Everything works well for me, nice job

@thisisdano
Copy link
Contributor

@scottqueen-bixal @mejiaj Updated those deprecated assertions in this PR.

Also, updated settings to use default colors for text. This will pull the color from either $theme-text-color or $theme-text-reverse-color based on background colors, unless specifically overridden in the setting.

@thisisdano thisisdano merged commit 831ceeb into uswds-2.11.0 Mar 10, 2021
@thisisdano thisisdano deleted the accelerator/3935-sortable-table branch March 10, 2021 22:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add table sorting
8 participants