-
Notifications
You must be signed in to change notification settings - Fork 560
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
Add sorting bar to note list #2542
Conversation
dee1479
to
ea1785a
Compare
This comment has been minimized.
This comment has been minimized.
Looks fine as it is but I left a few comments that you might consider. Feel free to merge it after responding to or rejecting my suggestions. |
Next steps on this:
Dropdown should be:
|
d1689ed
to
0cd62c1
Compare
Refactored with some data attributes, thanks @dmsnell for the suggestion. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The design looks good! Thanks @codebykat
lib/sort-order-selector/index.tsx
Outdated
if (selectedSortType !== sortType) { | ||
setSortType(selectedSortType as T.SortType); | ||
} | ||
if ((selectedSortReversed === 'false') === sortReversed) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is confusing me, specifically because we're comparing against the string value of false
I think we're doing it funny-like because it's a string value and not a real value. in this case parsing it could go a long way for readability. what I expect is to find something like selectedSortReversed !== sortReversed
const selectedSortReversed = selectedOption.dataset.reversed === 'true'; // true if 'true' else false
const selectedSortReversed = JSON.parse(selectedOption.dataset.reversed); // 'true' and 'false' decode properly
if (selectedSortReversed !== sortReversed) {
…
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops, I should have refactored that out actually.
lib/sort-order-selector/index.tsx
Outdated
toggleSortOrder, | ||
}) => { | ||
const changeSort = (event: React.ChangeEvent<HTMLSelectElement>) => { | ||
const selectedOption = event.currentTarget.selectedOptions[0]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
did you find HTMLSelectElement.selectedIndex
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes but is dropdown.options[selectedIndex] better in some way than dropdown.selectedOptions[0]?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
only in the sense that it relies on named things vs. the assumption of 0. I know that I wouldn't expect the selected option to always be the first one in the list, or that's how I read this line. I'm guessing this is a list of all possible selections because a drop down can have multiple selected items?
otherwise we're getting the actual option I think, if using seletedIndex
lib/sort-order-selector/index.tsx
Outdated
order: 'modificationDate', | ||
reversed: true, | ||
}, | ||
]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if we want to simplify the flow of data and types through the select component then we can do another thing and that is directly index into this list. consider if this sortTypes
array were outside of the component and in the module scope and we had a function to find the current setting. our HTMLSelectElement
could refer to an index into the array as the choice, and although that's less meaningful in itself, it does preserve the types the eliminates the processing and parsing needed to re-connect the data.
type SortOption = {
label: string,
order: T.SortOrder,
isReversed: boolean
}
const sortTypes: SortOption[] = [{
label: 'Name: A-Z',
order: 'alphabetical',
isReversed: false
}, {
…
}];
const onChange = ({currentTarget: {selectedIndex}}) => {
if (-1 === selectedIndex) {
return;
}
const sort = sortTypes[selectedIndex];
if (sort.sortOrder !== sortOrder) {
…
}
if (sort.isReversed !== sortReversed) {
…
}
}
const sortTypesIndex = (sortOrder, isReversed) => sortTypes.findIndex(type => type.order === sortOrder && type.isReversed === isReversed);
<select id="sort-selection" value={sortTypesIndex(sortOrder, reversed)} onChange={…}>
{sortTypes.map((type, index) => (
<option key={type.label} value={index}>{type.label}</option>
))}
</select>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's rare to use an index as the React key but here since the sortTypes
array is static the indices will never change and it's safe to use that value
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That works like a charm! a7d6f62
lib/sort-order-selector/index.tsx
Outdated
|
||
const mapDispatchToProps: S.MapDispatch<DispatchProps> = { | ||
setSortType, | ||
toggleSortOrder, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
calling two separate Redux actions introduces another partial update into our app. that is, if we change both sort properties then we're asking React to update after the first Redux dispatch and then again after the second. that intervening time represents a state that was never requested by the customer.
should we examine the setSortType
action and give it the ability to also change the reversing of the search? if we did that, add an optional reversed: boolean
property to the action, then we could perform the update in one go and we could eliminate the conditionals at the same time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very cool! I do end up checking for undefined
a bit, not sure if that's the right way to do this. 3e8bac4
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the logic is more readable to me after using the array of sort options vs. the data-passing. good detail work making sure the search index updates ✅
[testing] fix/feature verified on Dell Latitude 7400 | Win 10 | Simplenote 2.7.0-beta1 |
Fix
Adds a "Sort by" bar to the bottom of the notes list. See p2XJRt-2Ct-p2
Designs are at:
https://app.zeplin.io/project/5d795a3d8ed5261aa146e057/screen/5fd77f1846903987b1b40e75 (light mode)
https://app.zeplin.io/project/5d795a3d8ed5261aa146e057/screen/5fd77f196e43637c2cb2889f (dark mode)
Also shortens the search results bar to 44px to match the height of the sorting bar and the new toolbar-height.
Fixes #1625
Test
Screenshots
Note that in all browsers except Firefox, the dropdown styling is determined by the system theme, so it looks like this if you have a light system theme and the dark Simplenote theme:
In Firefox, we have to style the dropdown since otherwise it takes the styles from the parent, so I have added dark mode styles for Firefox that will be shown regardless of the system setting (in Simplenote dark theme):
The weird thing is that setting a background on the
select
seems to wipe out the padding and rounded edges (only in dark mode), but if we don't set it, we get this:Firefox light theme changes the white background to a light gray, which matches default styling:
Search results bar shortened to match:
Release
Added sort order bar to note list