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>
|
||||
`;
|
||||
|
||||
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`] = `
|
||||
<div
|
||||
style="padding:24px"
|
||||
|
|
Loading…
Reference in a new issue