Add table header with arrow
This commit is contained in:
parent
2b0f2933ec
commit
3827f8b8c1
4 changed files with 422 additions and 0 deletions
83
src/components/TableCellHeader/TableCellHeader.stories.tsx
Normal file
83
src/components/TableCellHeader/TableCellHeader.stories.tsx
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
import Card from "@material-ui/core/Card";
|
||||||
|
import Table from "@material-ui/core/Table";
|
||||||
|
import TableBody from "@material-ui/core/TableBody";
|
||||||
|
import TableCell from "@material-ui/core/TableCell";
|
||||||
|
import TableHead from "@material-ui/core/TableHead";
|
||||||
|
import TableRow from "@material-ui/core/TableRow";
|
||||||
|
import { storiesOf } from "@storybook/react";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
import Decorator from "../../storybook/Decorator";
|
||||||
|
import TableCellHeader, {
|
||||||
|
TableCellHeaderArrowDirection
|
||||||
|
} from "./TableCellHeader";
|
||||||
|
|
||||||
|
type Field = "name" | "type";
|
||||||
|
interface StoryProps {
|
||||||
|
direction: TableCellHeaderArrowDirection;
|
||||||
|
field?: Field;
|
||||||
|
onHeaderClick?: (field: Field) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Story: React.FC<StoryProps> = ({
|
||||||
|
direction,
|
||||||
|
field = "name",
|
||||||
|
onHeaderClick = () => undefined
|
||||||
|
}) => (
|
||||||
|
<Card style={{ margin: "auto", width: 400 }}>
|
||||||
|
<Table>
|
||||||
|
<TableHead>
|
||||||
|
<TableRow>
|
||||||
|
<TableCellHeader
|
||||||
|
arrowPosition="right"
|
||||||
|
direction={field === "name" ? direction : undefined}
|
||||||
|
onClick={() => onHeaderClick("name")}
|
||||||
|
>
|
||||||
|
Name
|
||||||
|
</TableCellHeader>
|
||||||
|
<TableCellHeader
|
||||||
|
direction={field === "type" ? direction : undefined}
|
||||||
|
onClick={() => onHeaderClick("type")}
|
||||||
|
>
|
||||||
|
Type
|
||||||
|
</TableCellHeader>
|
||||||
|
</TableRow>
|
||||||
|
</TableHead>
|
||||||
|
<TableBody>
|
||||||
|
<TableRow>
|
||||||
|
<TableCell>Apple Juice</TableCell>
|
||||||
|
<TableCell>Juice</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
const InteractiveStory: React.FC = () => {
|
||||||
|
const [direction, setDirection] = React.useState<
|
||||||
|
TableCellHeaderArrowDirection
|
||||||
|
>("asc");
|
||||||
|
const [field, setField] = React.useState<Field>("name");
|
||||||
|
|
||||||
|
const handleHeaderClick = (selectedField: Field) => {
|
||||||
|
if (field === selectedField) {
|
||||||
|
setDirection(direction === "asc" ? "desc" : "asc");
|
||||||
|
} else {
|
||||||
|
setField(selectedField);
|
||||||
|
setDirection("asc");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Story
|
||||||
|
direction={direction}
|
||||||
|
field={field}
|
||||||
|
onHeaderClick={handleHeaderClick}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
storiesOf("Generics / Table header", module)
|
||||||
|
.addDecorator(Decorator)
|
||||||
|
.add("ascending", () => <Story direction="asc" />)
|
||||||
|
.add("descending", () => <Story direction="desc" />)
|
||||||
|
.add("interactive", () => <InteractiveStory />);
|
70
src/components/TableCellHeader/TableCellHeader.tsx
Normal file
70
src/components/TableCellHeader/TableCellHeader.tsx
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
import { Theme } from "@material-ui/core/styles";
|
||||||
|
import TableCell, { TableCellProps } from "@material-ui/core/TableCell";
|
||||||
|
import makeStyles from "@material-ui/styles/makeStyles";
|
||||||
|
import classNames from "classnames";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
import ArrowSort from "../../icons/ArrowSort";
|
||||||
|
|
||||||
|
const useStyles = makeStyles((theme: Theme) => ({
|
||||||
|
arrow: {
|
||||||
|
transition: theme.transitions.duration.short + "ms"
|
||||||
|
},
|
||||||
|
arrowLeft: {
|
||||||
|
marginLeft: -24
|
||||||
|
},
|
||||||
|
arrowUp: {
|
||||||
|
transform: "rotate(180deg)"
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
alignSelf: "center",
|
||||||
|
display: "inline-block"
|
||||||
|
},
|
||||||
|
labelContainer: {
|
||||||
|
display: "flex",
|
||||||
|
height: 24
|
||||||
|
},
|
||||||
|
root: {
|
||||||
|
cursor: "pointer"
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
export type TableCellHeaderArrowDirection = "asc" | "desc";
|
||||||
|
export type TableCellHeaderArrowPosition = "left" | "right";
|
||||||
|
export interface TableCellHeader extends TableCellProps {
|
||||||
|
arrowPosition?: TableCellHeaderArrowPosition;
|
||||||
|
direction?: TableCellHeaderArrowDirection;
|
||||||
|
}
|
||||||
|
|
||||||
|
const TableCellHeader: React.FC<TableCellHeader> = props => {
|
||||||
|
const classes = useStyles(props);
|
||||||
|
const { arrowPosition, children, className, direction, ...rest } = props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TableCell {...rest} className={classNames(className, classes.root)}>
|
||||||
|
<div className={classes.labelContainer}>
|
||||||
|
{!!direction && arrowPosition === "left" && (
|
||||||
|
<ArrowSort
|
||||||
|
className={classNames(classes.arrow, classes.arrowLeft, {
|
||||||
|
[classes.arrowUp]: direction === "asc"
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<div className={classes.label}>{children}</div>
|
||||||
|
{!!direction && arrowPosition === "right" && (
|
||||||
|
<ArrowSort
|
||||||
|
className={classNames(classes.arrow, {
|
||||||
|
[classes.arrowUp]: direction === "asc"
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</TableCell>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
TableCellHeader.displayName = "TableCellHeader";
|
||||||
|
TableCellHeader.defaultProps = {
|
||||||
|
arrowPosition: "left"
|
||||||
|
};
|
||||||
|
export default TableCellHeader;
|
2
src/components/TableCellHeader/index.ts
Normal file
2
src/components/TableCellHeader/index.ts
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
export { default } from "./TableCellHeader";
|
||||||
|
export * from "./TableCellHeader";
|
|
@ -4591,6 +4591,273 @@ exports[`Storyshots Generics / StatusLabel when success 1`] = `
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`Storyshots Generics / Table header ascending 1`] = `
|
||||||
|
<div
|
||||||
|
style="padding:24px"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="MuiPaper-root-id MuiPaper-elevation1-id MuiPaper-rounded-id MuiCard-root-id"
|
||||||
|
style="margin:auto;width:400px"
|
||||||
|
>
|
||||||
|
<table
|
||||||
|
class="MuiTable-root-id"
|
||||||
|
>
|
||||||
|
<thead
|
||||||
|
class="MuiTableHead-root-id"
|
||||||
|
>
|
||||||
|
<tr
|
||||||
|
class="MuiTableRow-root-id MuiTableRow-head-id"
|
||||||
|
>
|
||||||
|
<th
|
||||||
|
class="MuiTableCell-root-id MuiTableCell-head-id Hook-root-id"
|
||||||
|
scope="col"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="Hook-labelContainer-id"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="Hook-label-id"
|
||||||
|
>
|
||||||
|
Name
|
||||||
|
</div>
|
||||||
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
class="MuiSvgIcon-root-id Hook-arrow-id Hook-arrowUp-id"
|
||||||
|
focusable="false"
|
||||||
|
role="presentation"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<rect
|
||||||
|
fill="transparent"
|
||||||
|
height="24"
|
||||||
|
width="24"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
clip-rule="evenodd"
|
||||||
|
d="M11.0328 17.1401V4H12.9672V17.1401L14.6322 15.4751L16 16.8429L12 20.8429L8 16.8429L9.36782 15.4751L11.0328 17.1401Z"
|
||||||
|
fill="currentColor"
|
||||||
|
fill-rule="evenodd"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</th>
|
||||||
|
<th
|
||||||
|
class="MuiTableCell-root-id MuiTableCell-head-id Hook-root-id"
|
||||||
|
scope="col"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="Hook-labelContainer-id"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="Hook-label-id"
|
||||||
|
>
|
||||||
|
Type
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody
|
||||||
|
class="MuiTableBody-root-id"
|
||||||
|
>
|
||||||
|
<tr
|
||||||
|
class="MuiTableRow-root-id"
|
||||||
|
>
|
||||||
|
<td
|
||||||
|
class="MuiTableCell-root-id MuiTableCell-body-id"
|
||||||
|
>
|
||||||
|
Apple Juice
|
||||||
|
</td>
|
||||||
|
<td
|
||||||
|
class="MuiTableCell-root-id MuiTableCell-body-id"
|
||||||
|
>
|
||||||
|
Juice
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`Storyshots Generics / Table header descending 1`] = `
|
||||||
|
<div
|
||||||
|
style="padding:24px"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="MuiPaper-root-id MuiPaper-elevation1-id MuiPaper-rounded-id MuiCard-root-id"
|
||||||
|
style="margin:auto;width:400px"
|
||||||
|
>
|
||||||
|
<table
|
||||||
|
class="MuiTable-root-id"
|
||||||
|
>
|
||||||
|
<thead
|
||||||
|
class="MuiTableHead-root-id"
|
||||||
|
>
|
||||||
|
<tr
|
||||||
|
class="MuiTableRow-root-id MuiTableRow-head-id"
|
||||||
|
>
|
||||||
|
<th
|
||||||
|
class="MuiTableCell-root-id MuiTableCell-head-id Hook-root-id"
|
||||||
|
scope="col"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="Hook-labelContainer-id"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="Hook-label-id"
|
||||||
|
>
|
||||||
|
Name
|
||||||
|
</div>
|
||||||
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
class="MuiSvgIcon-root-id Hook-arrow-id"
|
||||||
|
focusable="false"
|
||||||
|
role="presentation"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<rect
|
||||||
|
fill="transparent"
|
||||||
|
height="24"
|
||||||
|
width="24"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
clip-rule="evenodd"
|
||||||
|
d="M11.0328 17.1401V4H12.9672V17.1401L14.6322 15.4751L16 16.8429L12 20.8429L8 16.8429L9.36782 15.4751L11.0328 17.1401Z"
|
||||||
|
fill="currentColor"
|
||||||
|
fill-rule="evenodd"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</th>
|
||||||
|
<th
|
||||||
|
class="MuiTableCell-root-id MuiTableCell-head-id Hook-root-id"
|
||||||
|
scope="col"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="Hook-labelContainer-id"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="Hook-label-id"
|
||||||
|
>
|
||||||
|
Type
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody
|
||||||
|
class="MuiTableBody-root-id"
|
||||||
|
>
|
||||||
|
<tr
|
||||||
|
class="MuiTableRow-root-id"
|
||||||
|
>
|
||||||
|
<td
|
||||||
|
class="MuiTableCell-root-id MuiTableCell-body-id"
|
||||||
|
>
|
||||||
|
Apple Juice
|
||||||
|
</td>
|
||||||
|
<td
|
||||||
|
class="MuiTableCell-root-id MuiTableCell-body-id"
|
||||||
|
>
|
||||||
|
Juice
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`Storyshots Generics / Table header interactive 1`] = `
|
||||||
|
<div
|
||||||
|
style="padding:24px"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="MuiPaper-root-id MuiPaper-elevation1-id MuiPaper-rounded-id MuiCard-root-id"
|
||||||
|
style="margin:auto;width:400px"
|
||||||
|
>
|
||||||
|
<table
|
||||||
|
class="MuiTable-root-id"
|
||||||
|
>
|
||||||
|
<thead
|
||||||
|
class="MuiTableHead-root-id"
|
||||||
|
>
|
||||||
|
<tr
|
||||||
|
class="MuiTableRow-root-id MuiTableRow-head-id"
|
||||||
|
>
|
||||||
|
<th
|
||||||
|
class="MuiTableCell-root-id MuiTableCell-head-id Hook-root-id"
|
||||||
|
scope="col"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="Hook-labelContainer-id"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="Hook-label-id"
|
||||||
|
>
|
||||||
|
Name
|
||||||
|
</div>
|
||||||
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
class="MuiSvgIcon-root-id Hook-arrow-id Hook-arrowUp-id"
|
||||||
|
focusable="false"
|
||||||
|
role="presentation"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<rect
|
||||||
|
fill="transparent"
|
||||||
|
height="24"
|
||||||
|
width="24"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
clip-rule="evenodd"
|
||||||
|
d="M11.0328 17.1401V4H12.9672V17.1401L14.6322 15.4751L16 16.8429L12 20.8429L8 16.8429L9.36782 15.4751L11.0328 17.1401Z"
|
||||||
|
fill="currentColor"
|
||||||
|
fill-rule="evenodd"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</th>
|
||||||
|
<th
|
||||||
|
class="MuiTableCell-root-id MuiTableCell-head-id Hook-root-id"
|
||||||
|
scope="col"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="Hook-labelContainer-id"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="Hook-label-id"
|
||||||
|
>
|
||||||
|
Type
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody
|
||||||
|
class="MuiTableBody-root-id"
|
||||||
|
>
|
||||||
|
<tr
|
||||||
|
class="MuiTableRow-root-id"
|
||||||
|
>
|
||||||
|
<td
|
||||||
|
class="MuiTableCell-root-id MuiTableCell-body-id"
|
||||||
|
>
|
||||||
|
Apple Juice
|
||||||
|
</td>
|
||||||
|
<td
|
||||||
|
class="MuiTableCell-root-id MuiTableCell-body-id"
|
||||||
|
>
|
||||||
|
Juice
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`Storyshots Generics / TablePagination both previous and next pages are available 1`] = `
|
exports[`Storyshots Generics / TablePagination both previous and next pages are available 1`] = `
|
||||||
<div
|
<div
|
||||||
style="padding:24px"
|
style="padding:24px"
|
||||||
|
|
Loading…
Reference in a new issue