[v10] Add option to make tables sortable#1654
Conversation
7fcc8c4 to
724441e
Compare
|
Question of icons…
On the later point, when I was using sortable tables in my service, I used the following SVG: <svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 27 27">
<path fill="#212b32" d="m13 18.6-7-7.2c-.6-.5-.6-1.4 0-2 .5-.5 1.3-.5 2 0l6 6.2 6-6.2c.7-.5 1.5-.5 2 0 .6.6.6 1.5 0 2l-7 7.2c-.3.3-.6.4-1 .4s-.7-.1-1-.4Z"/>
</svg> |
724441e to
72a2926
Compare
Task list does the same. On the other hand the combined logo + service name link in the header has the focus style cover the whole clickable area, including the logo. |
|
Probably need an audit of focus styles… part of me wants to suggest making focus styles big and obvious, now that Firefox doesn’t show them on click (or can at least be avoided) |
|
Seems all the other components expand the click area by placing an absolutely positioned I've now removed that so that the focus is placed only on the natural sized buttons, and added a hover state to the header cells to illustrate how I'd like them to be, but of course this doesn't trigger the buttons. Can someone help me add a click event to the table heads? Or maybe there's a better way? I also notice a possible slight bug where the |
There's an event listener on the this.$head.addEventListener('click', this.onSortButtonClick.bind(this))But later on you'll see it ignores all clicks unless it bubbled up from a onSortButtonClick(event) {
const $target = /** @type {HTMLElement} */ (event.target)
const $button = $target.closest('button')
if (!$button?.parentElement) {
return
}
// …
}In theory you could change this code to allow clicks from non-clickable things But we shouldn't do really Is it a bad thing that only the |
76b6c3b to
1c1d476
Compare
|
Rebased with Table examples will now be in |
The MOJ one doesn't have any hover state. We’ve added a hover state (background colour change to grey) for the whole Would one option be to make button size expand to fill the entirety of the I also just spotted that the task list rows are using |
This is what I had first, which kinda worked but relied on some hacky CSS to get the button to grow to fill the I'm not sure on the best approach from a frontend dev perspective but what I want to achieve is the whole
Ohh, well spotted, will need to take a look at this. I think I was using pagination as my reference. |
|
@anandamaryon1 the task list trick is to use this to generate a bigger click area, but then the focus background colour only applies to the smaller .nhsuk-task-list__link::after {
content: "";
display: block;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}Bit of a hack but it seems to work?! There might be a better way though. |
1c1d476 to
42bd4e4
Compare
|
Sorry for the rebase, but I've updated this branch to pick up the new status check names |
Based on discussion, we've decided to switch to a boolean `initialSortColumn` to set the initial sort column on page load, in combination with `sortFirstDirection` for the initial sort direction for that column.
As this represents the current status of the table, past tense should be clearer.
|
@anandamaryon1 @colinrotherham @edwardhorsford ok I’ve updated the param name in 7279943 from Now instead of setting Hopefully this will be clearer! (Avoids having 2 params which both accept ascending/descending as options). |
| if ( | ||
| !$heading || | ||
| !$sortButton || | ||
| !(sortDirection === 'ascending' || sortDirection === 'descending') | ||
| ) { | ||
| return | ||
| } |
There was a problem hiding this comment.
Have you had a look at the Sonar check?
There isn't any code coverage for this bit
| const sortDirection = $heading.getAttribute('aria-sort') | ||
| const sortFirstDirection = $heading.dataset.sortFirstDirection | ||
|
|
||
| const columnNumber = Number.parseInt($button.dataset.index ?? '0', 10) |
There was a problem hiding this comment.
Similarly no coverage for this bit
Is it correct for us to assume '0' when no index is in the HTML?
E.g. Let's say if one of the NHS.UK frontend ports omit it (or allow it to be overridden)
| if ( | ||
| !(direction === 'ascending' || direction === 'descending') || | ||
| !$button.parentElement || | ||
| !config.statusMessage || | ||
| !$status | ||
| ) { | ||
| return | ||
| } |
There was a problem hiding this comment.
We haven't got code coverage here for when the direction isn't ascending/descending
There was a problem hiding this comment.
I've refactored this a bit to use Typescript annotations for the directions, so that bit of the guard clause is no longer necessary.
Also renamed the function a bit to make it clearer.
Other ideas for refactoring welcome!
And add a comment so we remember what we've done.
Previously the arrow icons were added as SVG images within the DOM (either server-side or client-side). This switches to using CSS to add the images as background-images. It uses CSS 'masks', where supported, to set the colour of the icons to be the `currentcolor` so that the colour will change in forced-colours mode.
This avoids some of the need for the guard clause.
Update it to accept the $heading element rather than the $button, and then rename it to `updateColumnState`. This makes the intent clearer and removes some of the need for the guard clause.
|
|
Couple of bugs I found just now:
Fixed by: 1bc4fab (adding
Not sure on the fix for this? Was this expected with the rejig of Nunjucks options? @frankieroberto And one new thought: |
If the `sortFirstDirection` is missing on a column with `initialSortColumn: true` then it was showing a blue box. It could default to a particular direction, but I think it's better to treat it as a required attribute, and if it's missing fall back to no inital sort direction on that column?
|
@anandamaryon1 fixed the second bug in b4cfc28. There are 2 options if
I think the second option is safer, so I've gone with that. |
Thanks! I'd have maybe gone with option 1. Since columns already kind of have a default of sorting ascending. But not too precious. Any thoughts on Q3, icon sizing? |
| // NHS pages have a grey background, so we need a slightly darker colour for the hover | ||
| // This produces 1.1:1 contrast, the same as GOV.UK’s | ||
| // This is also used by the Task list component | ||
| $sortable-table-hover-colour: color.adjust(nhsuk-colour("grey-5"), $lightness: -6%); |
There was a problem hiding this comment.
Just to flag that this is identical to the task list hover colour
We should wrap it in nhsuk-colour-compatible() and maybe share it as an applied colour?
| $sortable-table-hover-colour: color.adjust(nhsuk-colour("grey-5"), $lightness: -6%); | |
| $nhsuk-task-list-hover-colour: nhsuk-colour-compatible(color.adjust(nhsuk-colour("grey-5"), $lightness: -6%)); |
| {% if item.href %} | ||
| <a href="{{ item.href }}">{{ item.html | safe | trim | indent(8) if item.html else item.text }}</a> | ||
| {% else %} | ||
| {{ item.html | safe | trim | indent(8) if item.html else item.text }} |
There was a problem hiding this comment.
Whilst indent(8) is correct, this first line will be indented with 10 spaces
If you can check the HTML output in the code details (on the review app)
| { | ||
| "name": "nhsuk-frontend", | ||
| "version": "10.4.2", | ||
| "version": "11.0.0", |
There was a problem hiding this comment.
Just a reminder to remove this before we merge
We probably did it for the branch preview
There was a problem hiding this comment.
We've got 60 commits in this PR so ideally we rebase and drop the one that changed it
There was a problem hiding this comment.
Conflicts need resolving anyway
Co-authored-by: Colin Rotherham <work@colinr.com>
|
@anandamaryon1 @colinrotherham dropped the icon size down to 20px on mobile: d687d90. About right? |
Yep looks good to me, thank you |













Description
This expands the existing Table component to enable a new option to make some or all of the columns sortable by clicking the column header.
This is partly inspired by sortable table component from MOJ Frontend.
The table sorting feature is done using JavaScript as a progressive enhancement. If javascript is unavailable or not supported, then the table remains in its initial state, and no sort buttons are added.
It works by adding
aria-sortattributes to the headers of columns that you want to be sortable.The
aria-sortattribute should be set toascendingordescendingon the 1 column which is initially sorted, andnoneon all other columns that you want to be sortable:By default, the JavaScript will sort the column numerically if all cells contain a number, or will otherwise sort them alphabetically (or reverse-alphabetical).
If you need to specify an alternative sort order, you can do this by setting
data-sort-valueattributes on individual cells:Screenshots
Checklist