refactor(rtk-query): simplify sort order control

This commit is contained in:
FaberVitale 2021-06-21 20:11:39 +02:00
parent e5ce000a27
commit 136fd02ff8
6 changed files with 105 additions and 84 deletions

View File

@ -1,13 +1,3 @@
module.exports = {
extends: '../../.eslintrc',
overrides: [
{
files: ['*.ts', '*.tsx'],
extends: '../../eslintrc.ts.react.base.json',
parserOptions: {
tsconfigRootDir: __dirname,
project: ['./tsconfig.json'],
},
},
],
extends: ['react-app'],
};

View File

@ -0,0 +1,27 @@
import React, { HTMLAttributes } from 'react';
export type ArrowUpIconProps = Omit<
HTMLAttributes<SVGElement>,
'xmlns' | 'children' | 'viewBox'
>;
/* eslint-disable max-len */
/**
* @see https://icons.getbootstrap.com/icons/arrow-up/
*/
export function ArrowUpIcon(props: ArrowUpIconProps): JSX.Element {
return (
<svg
fill="currentColor"
{...props}
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
>
<path
fillRule="evenodd"
d="M8 15a.5.5 0 0 0 .5-.5V2.707l3.146 3.147a.5.5 0 0 0 .708-.708l-4-4a.5.5 0 0 0-.708 0l-4 4a.5.5 0 1 0 .708.708L7.5 2.707V14.5a.5.5 0 0 0 .5.5z"
/>
</svg>
);
}
/* eslint-enable max-len */

View File

@ -6,7 +6,7 @@ import { SelectOption } from '../types';
import debounce from 'lodash.debounce';
import { sortQueryOptions, QueryComparators } from '../utils/comparators';
import { QueryFilters, filterQueryOptions } from '../utils/filters';
import { SortOrderButtons } from './SortOrderButtons';
import { SortOrderButton } from './SortOrderButton';
export interface QueryFormProps {
values: QueryFormValues;
@ -156,7 +156,8 @@ export class QueryForm extends React.PureComponent<
options={sortQueryOptions}
onChange={this.handleSelectComparatorChange}
/>
<SortOrderButtons
<SortOrderButton
id={'rtk-query-sort-order-button'}
isAsc={isAsc}
onChange={this.handleButtonGroupClick}
/>

View File

@ -0,0 +1,46 @@
import React, { CSSProperties } from 'react';
import { ArrowUpIcon } from './ArrowUpIcon';
import { StyleUtilsContext } from '../styles/createStylingFromTheme';
export interface SortOrderButtonProps {
readonly isAsc?: boolean;
readonly onChange: (isAsc: boolean) => void;
id?: string;
}
export function SortOrderButton({
isAsc,
onChange,
id,
}: SortOrderButtonProps): JSX.Element {
const handleButtonClick = (): void => {
if (!isAsc) {
onChange(true);
} else onChange(false);
};
const buttonLabel = isAsc ? 'asc' : 'desc';
const arrowStyles: CSSProperties = {
width: '1em',
height: '1em',
transform: !isAsc ? 'scaleY(-1)' : undefined,
};
return (
<StyleUtilsContext.Consumer>
{({ styling }) => (
<button
type="button"
id={id}
onClick={handleButtonClick}
aria-pressed={isAsc}
{...styling(['sortButton'])}
>
<ArrowUpIcon style={arrowStyles} />
{buttonLabel}
</button>
)}
</StyleUtilsContext.Consumer>
);
}

View File

@ -1,67 +0,0 @@
import React, { MouseEvent } from 'react';
import { StyleUtilsContext } from '../styles/createStylingFromTheme';
export const ascId = 'rtk-query-rb-asc';
export const descId = 'rtk-query-rb-desc';
export interface SortOrderButtonsProps {
readonly isAsc?: boolean;
readonly onChange: (isAsc: boolean) => void;
}
export function SortOrderButtons({
isAsc,
onChange,
}: SortOrderButtonsProps): JSX.Element {
const handleButtonGroupClick = ({
target,
}: MouseEvent<HTMLElement>): void => {
const targetId = (target as HTMLElement)?.id ?? null;
if (targetId === ascId && !isAsc) {
onChange(true);
} else if (targetId === descId && isAsc) {
onChange(false);
}
};
const isDesc = !isAsc;
return (
<StyleUtilsContext.Consumer>
{({ styling }) => (
<div
tabIndex={0}
role="radiogroup"
aria-activedescendant={isAsc ? ascId : descId}
onClick={handleButtonGroupClick}
>
<button
role="radio"
type="button"
id={ascId}
aria-checked={isAsc}
{...styling(
['selectorButton', isAsc && 'selectorButtonSelected'],
isAsc
)}
>
asc
</button>
<button
id={descId}
role="radio"
type="button"
aria-checked={isDesc}
{...styling(
['selectorButton', isDesc && 'selectorButtonSelected'],
isDesc
)}
>
desc
</button>
</div>
)}
</StyleUtilsContext.Consumer>
);
}

View File

@ -215,6 +215,29 @@ const getSheetFromColorMap = (map: ColorMap) => {
'background-color': map.TAB_BACK_SELECTED_COLOR,
},
sortButton: {
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
flexFlow: 'row nowrap',
cursor: 'pointer',
position: 'relative',
padding: '0 8px',
color: map.TEXT_COLOR,
borderStyle: 'solid',
borderWidth: '1px',
borderRadius: '3px',
backgroundColor: map.TAB_BACK_COLOR,
borderColor: map.TAB_BORDER_COLOR,
height: 30,
fontSize: 12,
width: 64,
'&:active': {
backgroundColor: map.TAB_BACK_SELECTED_COLOR,
},
},
queryForm: {
display: 'flex',
flexFlow: 'column nowrap',
@ -222,10 +245,6 @@ const getSheetFromColorMap = (map: ColorMap) => {
sortBySection: {
display: 'flex',
padding: '0.4em',
'& > [role="radiogroup"]': {
flex: '0 0 auto',
padding: '0 0 0 0.4em',
},
'& label': {
display: 'flex',
flex: '0 0 auto',
@ -233,6 +252,11 @@ const getSheetFromColorMap = (map: ColorMap) => {
alignItems: 'center',
paddingRight: '0.4em',
},
'& > :last-child': {
flex: '0 0 auto',
marginLeft: '0.4em',
},
},
querySearch: {