Skip to content
This repository was archived by the owner on Jun 22, 2021. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 28 additions & 21 deletions .storybook/styled.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,27 +12,35 @@ const Table = styled.table`
`;
const Tr = styled.tr``;
const Td = styled.td`
padding: 0.75rem;
padding: ${props => (props.sortable ? 0 : "0.75rem")};
border-top: 1px solid #eee;
`;
const Th = Td.extend`
text-align: left;
&:focus,
&:hover {
cursor: ${props => (props.sortable ? "pointer" : "default")};
background-color: ${props => (props.sortable ? "#ffc" : "inherit")};
}
`.withComponent("th");

function getSortDirection(props) {
if (props.direction && props.visible) {
return props.direction === "asc" ? "↓" : "↑";
switch (props.direction) {
case "ascending":
return "↓";
case "descending":
return "↑";
default:
return "↓↑";
}
}

const Sort = styled.span`
display: block;
padding: 0.75rem;
&:focus,
&:hover {
cursor: pointer;
background-color: #ffc;
}
&::after {
content: "${getSortDirection}";
width: .25rem;
width: .75rem;
font-size: .75rem;
color: #666;
display: inline-block;
Expand All @@ -43,23 +51,22 @@ function StyledTable({ rows, ...props }: { rows: Row[] }) {
return (
<Unsort
{...props}
render={({ getSortProps, sortKey, sortDirection }) => {
render={({
getTableProps,
getSortProps,
getSortButtonProps,
sortKey,
sortDirection
}) => {
return (
<Table>
<Table {...getTableProps()}>
<thead>
<Tr>
<Th sortable {...getSortProps("name")}>
Name
<Sort
visible={sortKey === "name"}
direction={sortDirection}
/>
<Sort {...getSortButtonProps("name")}>Name</Sort>
</Th>
<Th sortable {...getSortProps("age")}>
Age<Sort
visible={sortKey === "age"}
direction={sortDirection}
/>
<Sort {...getSortButtonProps("age")}>Age</Sort>
</Th>
<Th>Country (not sortable)</Th>
</Tr>
Expand Down Expand Up @@ -91,6 +98,6 @@ storiesOf("With styled-components", module)
rows={initialRows}
onSort={action("onSort")}
initialSortKey="name"
initialSortDirection="asc"
initialSortDirection="ascending"
/>
));
20 changes: 15 additions & 5 deletions .storybook/table.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,26 @@ export function Table({ rows, ...props }: { rows: Row[] }) {
return (
<Unsort
{...props}
render={({ getSortProps, sortKey, sortDirection }) => {
render={({
getTableProps,
getSortProps,
getSortButtonProps,
sortKey,
sortDirection
}) => {
return (
<table>
<table {...getTableProps()}>
<thead>
<tr>
<th {...getSortProps("name")}>
Name <span>{sortKey === "name" && sortDirection}</span>
<span {...getSortButtonProps("name")}>
Name {sortKey === "name" && sortDirection}
</span>
</th>
<th {...getSortProps("age")}>
Age <span>{sortKey === "age" && sortDirection}</span>
<span {...getSortButtonProps("age")}>
Age {sortKey === "age" && sortDirection}
</span>
</th>
<th>Country (not sortable)</th>
</tr>
Expand Down Expand Up @@ -69,6 +79,6 @@ storiesOf("Table", module)
rows={initialRows}
onSort={action("onSort")}
initialSortKey="name"
initialSortDirection="asc"
initialSortDirection="ascending"
/>
));
2 changes: 1 addition & 1 deletion .storybook/with-sorting.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class WithSorting extends React.Component<Props, State> {

const rows = this.state.rows.sort(compare(sortKey));

if (sortDirection === "desc") {
if (sortDirection === "descending") {
rows.reverse();
}

Expand Down
54 changes: 33 additions & 21 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,12 @@ import type {
RenderProps
} from "./types";

export const ariaSortMap = {
asc: "ascending",
desc: "descending"
};

const sortDirections = [...Object.keys(ariaSortMap), null];

export default class Unsort extends React.Component<Props, State> {
props: Props;

static defaultProps = {
onSort: () => {}
onSort: () => {},
sortDirections: ["none", "ascending", "descending"]
};

constructor(props: Props) {
Expand All @@ -32,47 +26,65 @@ export default class Unsort extends React.Component<Props, State> {
};
}

getSortDirection = (key: string): ?SortDirection => {
getNextSortDirection = (key: string): ?SortDirection => {
const { sortDirections } = this.props;
const { sortDirection } = this.state;
if (!sortDirection) {
return sortDirections[1];
}
// if sortKey is changed or not set, return default sortDirections
if (this.state.sortKey !== key) {
return sortDirections[0];
return sortDirections[1];
}
const sortDirectionIndex = sortDirections.indexOf(this.state.sortDirection);
const sortDirectionIndex = sortDirections.indexOf(sortDirection);
return sortDirections[(sortDirectionIndex + 1) % sortDirections.length];
};

handleSortChange = (key: string) => {
const sortDirection = this.getSortDirection(key);
const sortDirection = this.getNextSortDirection(key);
const sortKey = sortDirection === null ? null : key;
const newState = { sortKey, sortDirection };
this.props.onSort(newState);
this.setState(newState);
};

getSortProps = (key: string): SortProps => {
getSortDirection = (key: string): SortDirection => {
const { sortDirections } = this.props;
const { sortKey, sortDirection } = this.state;
return key === sortKey && sortDirection ? sortDirection : sortDirections[0];
};

getSortProps = (key: string): SortProps => {
return {
["aria-sort"]: this.getSortDirection(key)
};
};

const sortProps: SortProps = {
getTableProps = () => {
return { role: "grid" };
};

getSortButtonProps = (key: string) => {
return {
role: "button",
tabIndex: 0,
onClick: () => this.handleSortChange(key),
onKeyUp: event => {
onKeyUp: (event: SyntheticKeyboardEvent<*>) => {
// 13 = enter keyCode
if (event.keyCode === 13) {
this.handleSortChange(key);
}
}
},
direction: this.getSortDirection(key)
};
if (key === sortKey && sortDirection) {
sortProps["aria-sort"] = ariaSortMap[sortDirection];
}
return sortProps;
};

render() {
const renderProps: RenderProps = {
...this.state,
getSortProps: this.getSortProps
getSortProps: this.getSortProps,
getTableProps: this.getTableProps,
getSortButtonProps: this.getSortButtonProps
};
return this.props.render(renderProps);
}
Expand Down
28 changes: 17 additions & 11 deletions src/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,30 @@

import { type Node as ReactNode } from "react";

export type SortDirection = "asc" | "desc";
export type SortDirection = "ascending" | "descending" | "none" | "other";

type AriaSortDirection = "ascending" | "descending";

export type SortProps = {|
role: "button",
tabIndex: 0,
"aria-sort"?: AriaSortDirection,
onClick: (event: SyntheticMouseEvent<*>) => void,
onKeyUp: (event: SyntheticKeyboardEvent<*>) => void
|};
export type SortProps = {
"aria-sort": SortDirection
};

export type RenderProps = State & {
getSortProps: (key: string) => SortProps
getSortProps: (key: string) => SortProps,
getTableProps: () => {|
role: "grid"
|},
getSortButtonProps: (
key: string
) => {
role: "button",
tabIndex: 0,
onClick: (event: SyntheticMouseEvent<*>) => void,
onKeyUp: (event: SyntheticKeyboardEvent<*>) => void
}
};

export type Props = {
render: RenderProps => ReactNode,
sortDirections: Array<SortDirection>,
initialSortKey?: string,
initialSortDirection?: SortDirection,
onSort: State => void
Expand Down
Loading