Skip to content

Instantly share code, notes, and snippets.

@fabien0102
Created August 13, 2018 10:58
Show Gist options
  • Save fabien0102/c2c98145e28536e271908b3b774b9123 to your computer and use it in GitHub Desktop.
Save fabien0102/c2c98145e28536e271908b3b774b9123 to your computer and use it in GitHub Desktop.
SideFilters
import React from "react";
import styled, { keyframes } from "react-emotion";
import { getConfig } from "../../getConfig";
import Wrapper from "./Wrapper";
export interface SelectFilterProps {
field: {
id: string;
name: string;
options: {
values: string[];
};
};
values: string[];
onChange: (values: string[]) => void;
}
const toggleCheckboxAnimation = keyframes`
0% {
opacity: 0;
transform: translateY(-50%) scale(0) rotate(45deg);
}
70% {
opacity: 1;
transform: translateY(-50%) scale(1.2) rotate(45deg);
}
100% {
transform: translateY(-50%) scale(1) rotate(45deg);
}
`;
// ref: https://codersblock.com/blog/checkbox-trickery-with-css/
const Checkbox = styled("input")`
position: absolute;
left: -9999px;
:checked + label::after {
content: "";
display: block;
width: 5px;
height: 11px;
position: absolute;
left: 7px;
margin: 0 auto;
top: 48%;
transform: translateY(-50%) rotate(45deg);
border-right: 2px solid ${getConfig("color")};
border-bottom: 2px solid ${getConfig("color")};
cursor: pointer;
animation: ${toggleCheckboxAnimation} 0.2s ease forwards;
}
`;
const Label = styled("label")`
position: relative;
cursor: pointer;
height: 20px;
display: block;
margin-bottom: 10px;
padding-left: 30px;
line-height: 20px;
user-select: none;
font-size: 12px;
color: #545454;
:hover {
color: ${getConfig("color")};
::before {
border: solid 1px ${getConfig("color")};
}
}
::before {
content: "";
cursor: pointer;
position: absolute;
display: block;
top: 0;
left: 0;
width: 20px;
height: 20px;
border-radius: 2px;
background-color: #f2f2f2;
border: solid 1px #c0c0c0;
}
`;
export const SelectFilter: React.SFC<SelectFilterProps> = ({
field,
values,
onChange
}) => (
<Wrapper label={field.name} collapsable>
{field.options.values.map(val => (
<div key={val}>
<Checkbox
id={`${field.name}-${val}`}
key={val}
type="checkbox"
checked={values.includes(val)}
onChange={() => {
if (values.includes(val)) {
onChange(values.filter(i => i !== val));
} else {
onChange([...values, val]);
}
}}
/>
<Label htmlFor={`${field.name}-${val}`}>{val}</Label>
</div>
))}
</Wrapper>
);
import { Icon } from "@operational/components";
import { kebab, title } from "case";
import isEmpty from "lodash/isEmpty";
import React from "react";
import styled from "react-emotion";
import { FormattedMessage } from "react-intl";
import { getConfig } from "../../getConfig";
export interface WrapperProps {
label: string;
collapsable?: boolean;
}
export interface WrapperState {
isOpen: boolean;
}
const Label = styled("label")`
font-size: 12px;
font-weight: bold;
font-style: normal;
font-stretch: normal;
line-height: 1.25;
letter-spacing: normal;
text-align: left;
color: #909090;
display: block;
user-select: none;
/* Expand the hitbox */
margin: -20px;
padding: 20px;
/* Clickable label */
${(props: { clickable: boolean }) =>
props.clickable
? `
cursor: pointer;
:hover {
color: ${getConfig("color")};
}
:hover + svg {
fill: ${getConfig("color")};
}
`
: ""};
`;
const Arrow = styled(Icon)`
position: absolute;
right: 20px;
top: 20px;
pointer-events: none;
`;
export class Wrapper extends React.Component<WrapperProps, WrapperState> {
public readonly state = {
isOpen: true
};
public render() {
const { children, label, collapsable, ...props } = this.props;
return (
<div
style={{
padding: 20,
minHeight: 50,
borderBottom: "solid 1px #e8e8e8",
position: "relative"
}}
{...props}
>
{!isEmpty(label) && (
<Label
clickable={Boolean(collapsable)}
onClick={() => this.setState(({ isOpen }) => ({ isOpen: !isOpen }))}
>
<FormattedMessage
id={`usecases.labels.${kebab(label)}`}
defaultMessage={title(label)}
/>
</Label>
)}
{collapsable && (
<Arrow
name={this.state.isOpen ? "ChevronUp" : "ChevronRight"}
color={this.state.isOpen ? "#909090" : "#e8e8e8"}
/>
)}
{(!collapsable || this.state.isOpen) && (
<div style={{ marginTop: 12 }}>{children}</div>
)}
</div>
);
}
}
export default Wrapper;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment