@retailmenot/anchor
Version:
A React UI Library by RetailMeNot
167 lines (153 loc) • 5.93 kB
JavaScript
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
// REACT
import * as React from 'react';
// VENDOR
import classNames from 'classnames';
import styled, { css } from '@xstyled/styled-components';
import { variant as createVariant, th, space as spaceStyles, } from '@xstyled/system';
// Components
import { ChevronDown, ChevronUp } from '../Icon';
export const DEFAULT_OPENED_TEXT = 'Close';
export const DEFAULT_CLOSED_TEXT = 'Open';
const DEFAULT_VARIANT = 'comfortable';
const variants = {
comfortable: css `
padding: 1rem 2rem;
border-top: solid thin ${th.color('borders.base')};
border-bottom: solid thin ${th.color('borders.base')};
.anchor-collapse-button {
appearance: none;
background-color: transparent; /* All but Chrome show a grey button bg color despite 'appearance: none' */
cursor: pointer;
display: flex;
justify-content: space-between;
width: 100%;
text-align: left;
border-style: none;
font-weight: 500;
font-size: 0.875rem;
padding: 0.5rem 0;
user-select: none;
&:focus {
outline: none;
}
> *:last-child {
flex: 0 0 auto;
margin-left: 0.5em;
}
}
.anchor-collapse-content {
font-size: 1rem;
text-align: left;
padding: 0.5rem 0;
}
`,
compact: css `
color: text.light;
.anchor-collapse-button {
appearance: none;
background-color: white; /* All but Chrome show a grey button bg color despite 'appearance: none' */
border-style: none;
border-bottom: light;
border-top: light;
color: text.light;
cursor: pointer;
display: flex;
justify-content: space-between;
font-weight: bold;
height: 3rem;
padding: 0 1.3125rem;
text-align: left;
user-select: none;
width: 100%;
&:focus {
outline: none;
}
> *:last-child {
flex: 0 0 auto;
margin-left: 0.5em;
}
}
.anchor-collapse-content {
background-color: background.light;
ul {
padding: 0;
margin: 0;
list-style-type: none;
}
// TODO: we shouldn't be using as many fragile nested selectors and we should be using Typography
li a {
display: block;
padding-left: 3.4375rem;
height: 2.6875rem;
line-height: 2.6875rem;
cursor: pointer;
font-size: 0.875rem;
color: #222;
&:hover {
background-color: rgba(0, 126, 205, 0.1);
}
}
}
`,
none: css({}),
};
const variantStyles = createVariant({
key: 'collapse.variants',
prop: 'variant',
default: DEFAULT_VARIANT,
variants: variants,
});
const StyledCollapse = styled('div') `
display: block;
box-sizing: border-box;
font-family: base;
${variantStyles}
&.no-bottom-border {
border-bottom-style: none;
.anchor-collapse-button {
border-bottom-style: none;
}
}
.anchor-collapse-content.inactive {
display: none;
}
${spaceStyles}
`;
StyledCollapse.displayName = 'StyledCollapse';
export const Collapse = (_a) => {
var { isOpen = false, openedText = DEFAULT_OPENED_TEXT, closedText = DEFAULT_CLOSED_TEXT, openedIcon, closedIcon, variant = DEFAULT_VARIANT, onClick, hasBottomBorder = true, removeInactive = true, className, children } = _a, props = __rest(_a, ["isOpen", "openedText", "closedText", "openedIcon", "closedIcon", "variant", "onClick", "hasBottomBorder", "removeInactive", "className", "children"]);
const [open, toggleOpen] = React.useState(isOpen);
const IconOpened = openedIcon || React.createElement(ChevronUp, null);
const IconClosed = closedIcon || React.createElement(ChevronDown, null);
// If the user provides custom openedText but not custom closedText
// then use openedText for closedText as well
const textClosed = openedText !== DEFAULT_OPENED_TEXT && closedText === DEFAULT_CLOSED_TEXT
? openedText
: closedText;
// Allows for the programmatic opening/closing of the Collapse
// without a user having to click it
React.useEffect(() => {
toggleOpen(isOpen);
}, [isOpen]);
return (React.createElement(StyledCollapse, Object.assign({ variant: variant, className: classNames('anchor-collapse', open && 'open', variant, !hasBottomBorder && 'no-bottom-border', className) }, props),
React.createElement("button", { onClick: onClick || (() => toggleOpen(!open)), className: "anchor-collapse-button" }, open ? (React.createElement(React.Fragment, null,
openedText,
" ",
IconOpened)) : (React.createElement(React.Fragment, null,
textClosed,
" ",
IconClosed))),
(open || !removeInactive) && (React.createElement("section", { className: classNames('anchor-collapse-content', !open && 'inactive') }, children))));
};
//# sourceMappingURL=Collapse.component.js.map