@navinc/base-react-components
Version:
Nav's Pattern Library
442 lines (436 loc) • 18.5 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;
};
import { jsx as _jsx } from "react/jsx-runtime";
import styled from 'styled-components';
import isRebrand from './is-rebrand.js';
import Link from './link.js';
import LoadingDots from './loading-dots.js';
const sizeVariants = {
'nav-blue': {
small: {
padding: '0.5em 1.33em',
fontSize: '12px',
borderRadius: '12px',
lineHeight: '1',
},
medium: {
padding: '0.64em 1.71em',
fontSize: '14px',
borderRadius: '12px',
lineHeight: '1',
},
large: {
padding: '0.75em 2em',
fontSize: '16px',
borderRadius: '12px',
lineHeight: '1',
},
extraLarge: {
padding: '0.9em 1.6em',
fontSize: '20px',
borderRadius: '16px',
lineHeight: '1',
},
cardButton: {
padding: '8px',
fontSize: '16px',
borderRadius: '12px',
lineHeight: '1',
},
},
'nav-purple': {
small: {
padding: '0.5em 1.33em',
fontSize: '12px',
borderRadius: '8px',
lineHeight: '1',
},
medium: {
padding: '6px 16px 6px 16px',
fontSize: '14px',
borderRadius: '8px',
lineHeight: '1',
},
large: {
padding: '8px 24px 8px 24px',
fontSize: '16px',
borderRadius: '8px',
lineHeight: '1',
},
extraLarge: {
padding: '16px 32px 16px 32px',
fontSize: '20px',
borderRadius: '8px',
lineHeight: '1',
},
cardButton: {
padding: '8px',
fontSize: '16px',
borderRadius: '12px',
lineHeight: '1',
},
},
};
const getSize = ({ size = 'medium', themeName = 'nav-blue' }) => {
var _a;
return (_a = sizeVariants[themeName][size]) !== null && _a !== void 0 ? _a : sizeVariants[themeName].medium;
};
const getVariation = ({ variation = 'main', theme, size = 'medium', }) => {
var _a, _b, _c;
const lineHeightMap = {
small: '18px',
medium: '20px',
large: '24px',
extraLarge: '28px',
};
const styleVariation = {
main: {
borderColor: 'transparent',
backgroundColor: theme.navPrimary,
/* Imposes a background radial gradient too small to detect, that upon activation will expand 100% of the container like a ripple from the click */
background: `${theme.navPrimary200} radial-gradient(circle, transparent 1%, ${theme.navPrimary700} 1%) center/15000%`,
/*
Despite remaining the same, the font color must be defined
for both hover/focus so as to override nested link styling
*/
color: theme.navNeutralLight,
hover: {
backgroundColor: isRebrand(theme) ? theme.navPrimary500 : theme.navStatusPositive500,
color: theme.navNeutralLight,
},
focus: Object.assign({ backgroundColor: isRebrand(theme) ? theme.navPrimary : theme.navStatusPositive500 }, (isRebrand(theme)
? {
outline: 'none',
boxShadow: isRebrand(theme) ? `0 0 0 4px ${theme.navStatusPositive500}` : `0 0 0 1px ${theme.azure}`,
}
: {})),
active: Object.assign(Object.assign({}, (isRebrand(theme) ? { backgroundColor: theme.navPrimary700 } : {})), { backgroundSize: '100%', transition: 'background 0s' }),
},
outline: {
borderColor: theme.navPrimary,
backgroundColor: theme.transparentWhite,
/* Imposes a background radial gradient too small to detect, that upon activation will expand 100% of the container like a ripple from the click */
background: `${theme.navPrimary200} radial-gradient(circle, transparent 1%, ${theme.navPrimary300} 1%) center/15000%`,
color: theme.navPrimary,
hover: {
backgroundColor: theme.navPrimary200,
},
focus: {
backgroundColor: isRebrand(theme) ? theme.transparentWhite : theme.bubbleBlue100,
outline: 'none',
boxShadow: isRebrand(theme) ? `0 0 0 4px ${theme.navStatusPositive500}` : `0 0 0 1px ${theme.azure}`,
},
active: {
backgroundColor: theme.navPrimary300,
/* Tied to the background property, these will create the click impression effect */
backgroundSize: '100%',
transition: 'background 0s',
},
},
shade: {
borderColor: 'transparent',
backgroundColor: theme.navPrimary200,
/* Imposes a background radial gradient too small to detect, that upon activation will expand 100% of the container like a ripple from the click */
background: `${theme.navPrimary200} radial-gradient(circle, transparent 1%, ${theme.navPrimary300} 1%) center/15000%`,
color: theme.navPrimary,
hover: {
backgroundColor: theme.navPrimary100,
},
focus: {
outline: 'none',
boxShadow: isRebrand(theme) ? `0 0 0 4px ${theme.navStatusPositive500}` : `0 0 0 1px ${theme.azure}`,
},
active: {
backgroundColor: theme.navPrimary300,
/* Tied to the background property, these will create the click impression effect */
backgroundSize: '100%',
transition: 'background 0s',
},
},
white: {
borderColor: 'transparent',
backgroundColor: theme.navNeutralLight,
/* Imposes a background radial gradient too small to detect, that upon activation will expand 100% of the container like a ripple from the click */
background: `${theme.navPrimary200} radial-gradient(circle, transparent 1%, ${theme.navPrimary300} 1%) center/15000%`,
color: theme.navPrimary,
hover: {
backgroundColor: theme.navPrimary200,
},
focus: {
outline: 'none',
boxShadow: isRebrand(theme) ? `0 0 0 4px ${theme.navStatusPositive500}` : `0 0 0 1px ${theme.azure}`,
},
active: {
backgroundColor: theme.navPrimary300,
/* Tied to the background property, these will create the click impression effect */
backgroundSize: '100%',
transition: 'background 0s',
},
},
tan: {
borderColor: 'transparent',
backgroundColor: theme.navSecondary,
/* Imposes a background radial gradient too small to detect, that upon activation will expand 100% of the container like a ripple from the click */
background: `${theme.navSecondary200} radial-gradient(circle, transparent 1%, ${theme.navSecondary300} 1%) center/15000%`,
color: theme.navPrimary400,
hover: {
backgroundColor: theme.navSecondary100,
color: theme.navPrimary500,
},
focus: {
outline: 'none',
boxShadow: isRebrand(theme) ? `0 0 0 4px ${theme.navStatusPositive500}` : `0 0 0 1px ${theme.azure}`,
},
active: {
backgroundColor: theme.navSecondary300,
color: theme.navPrimary500,
/* Tied to the background property, these will create the click impression effect */
backgroundSize: '100%',
transition: 'background 0s',
},
},
destructive: {
borderColor: 'transparent',
backgroundColor: theme.navStatusNegative,
/* Imposes a background radial gradient too small to detect, that upon activation will expand 100% of the container like a ripple from the click */
background: `${theme.navStatusNegative} radial-gradient(circle, transparent 1%, ${theme.navStatusNegative700} 1%) center/15000%`,
color: theme.navNeutralLight,
hover: {
backgroundColor: theme.navStatusNegative500,
},
focus: {
outline: 'none',
boxShadow: isRebrand(theme) ? `0 0 0 4px ${theme.navStatusPositive500}` : `0 0 0 1px ${theme.azure}`,
},
active: {
backgroundColor: theme.navStatusNegative700,
/* Tied to the background property, these will create the click impression effect */
backgroundSize: '100%',
transition: 'background 0s',
},
},
accent: {
borderColor: 'transparent',
backgroundColor: theme.navStatusPositive,
/* Imposes a background radial gradient too small to detect, that upon activation will expand 100% of the container like a ripple from the click */
background: `${theme.navStatusPositive} radial-gradient(circle, transparent 1%, ${theme.navStatusPositive700} 1%) center/15000%`,
color: theme.navNeutralLight,
hover: {
backgroundColor: theme.navStatusPositive500,
},
focus: {
outline: 'none',
boxShadow: isRebrand(theme) ? `0 0 0 4px ${theme.navStatusPositive500}` : `0 0 0 1px ${theme.azure}`,
},
active: {
backgroundColor: theme.navStatusPositive700,
/* Tied to the background property, these will create the click impression effect */
backgroundSize: '100%',
transition: 'background 0s',
},
},
buttonLink: {
borderColor: 'transparent',
backgroundColor: theme.transparentWhite,
color: theme.navPrimary400,
padding: 0,
lineHeight: (_a = lineHeightMap[size]) !== null && _a !== void 0 ? _a : lineHeightMap.medium,
hover: {
color: isRebrand(theme) ? theme.navPrimary500 : theme.oceanBoat,
},
focus: Object.assign({}, (isRebrand(theme)
? {
outline: 'none',
boxShadow: `0 0 0 4px ${theme.navStatusPositive500}`,
borderRadius: '2px',
}
: {
borderColor: 'transparent',
color: theme.oceanBoat,
})),
active: {
color: isRebrand(theme) ? theme.navPrimary500 : theme.oceanBoat,
},
},
buttonAction: {
borderColor: 'transparent',
backgroundColor: theme.transparentWhite,
color: theme.navNeutral400,
padding: 0,
lineHeight: (_b = lineHeightMap[size]) !== null && _b !== void 0 ? _b : lineHeightMap.medium,
},
noOutline: {
borderColor: 'transparent',
backgroundColor: theme.transparentWhite,
color: theme.navPrimary400,
hover: Object.assign({}, (isRebrand(theme) ? { color: theme.navPrimary500 } : { borderColor: theme.navStatusPositive500 })),
focus: Object.assign({ borderColor: theme.navStatusPositive500 }, (isRebrand(theme) ? { outline: 'none', boxShadow: `0 0 0 4px ${theme.navStatusPositive500}` } : {})),
active: Object.assign({}, (isRebrand(theme)
? { color: theme.navPrimary500 }
: { backgroundColor: theme.navPrimary300, borderColor: 'transparent' })),
},
whiteOutline: {
borderColor: theme.white,
backgroundColor: theme.transparentWhite,
color: theme.white,
hover: {
backgroundColor: theme.navPrimary200,
color: theme.navPrimary,
},
focus: {
backgroundColor: theme.navPrimary200,
color: theme.navPrimary,
},
active: {
backgroundColor: theme.navPrimary300,
color: theme.navPrimary,
borderColor: 'transparent',
},
},
neutral: {
borderColor: 'transparent',
backgroundColor: theme.scuttleGray200,
background: `${theme.navPrimary200} radial-gradient(circle, transparent 1%, ${theme.navPrimary300} 1%) center/15000%`,
color: theme.scuttleGray600,
hover: {
backgroundColor: theme.bubbleBlue200,
},
focus: {
outline: 'none',
},
active: {
backgroundColor: theme.navPrimary700,
backgroundSize: '100%',
transition: 'background 0s',
borderColor: 'transparent',
},
},
};
return (_c = styleVariation[variation]) !== null && _c !== void 0 ? _c : styleVariation.main;
};
const getRule = (rulePath) => ({ size, variation, theme }) => {
const rules = Object.assign(Object.assign({}, getSize({ size, themeName: theme.name })), getVariation({ variation, theme, size }));
const rule = rulePath.split('.').reduce((rules, pathPart) => { var _a; return (_a = rules[pathPart]) !== null && _a !== void 0 ? _a : ''; }, rules);
return typeof rule === 'function' ? rule({ theme }) : rule;
};
const getDisabledStyleByVariation = ({ variation, theme }) => {
switch (variation) {
case 'buttonLink':
case 'noOutline':
return '';
case 'outline':
return isRebrand(theme) ? '' : `border-color: ${theme.neutral300};`;
default:
return `background-color: ${theme.neutral200};`;
}
};
export const StyledButton = styled.button.withConfig({ displayName: "brc-sc-StyledButton", componentId: "brc-sc-bkuhcf" }) `
display: inline-flex;
align-items: center;
box-sizing: border-box;
font-family: ${({ theme }) => theme.fontPrimary};
padding: ${getRule('padding')};
border: 1px solid ${getRule('borderColor')};
border-radius: ${getRule('borderRadius')};
background: ${getRule('background')};
background-color: ${getRule('backgroundColor')};
color: ${getRule('color')};
font-size: ${getRule('fontSize')};
line-height: ${getRule('lineHeight')};
text-align: center;
white-space: ${({ wrap }) => (wrap ? 'normal' : 'nowrap')};
cursor: pointer;
outline: none;
font-weight: 700;
transition: ease-out background 0.4s;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
&:hover:not([disabled]) {
background-color: ${getRule('hover.backgroundColor')};
color: ${getRule('hover.color')};
border-color: ${getRule('hover.borderColor')};
}
/* Override hover styles, b/c when pressed the hover event is also active */
&:hover:active {
background-color: ${getRule('active.backgroundColor')};
color: ${getRule('active.color')};
border-color: ${getRule('active.borderColor')};
}
&:focus {
background-color: ${getRule('focus.backgroundColor')};
color: ${getRule('focus.color')};
outline: ${getRule('focus.outline')};
box-shadow: ${getRule('focus.boxShadow')};
border-radius: ${getRule('focus.borderRadius')};
}
&:focus:active {
outline: none;
box-shadow: none;
}
&[disabled] {
${({ $isLoading, variation = 'main', theme, size }) => $isLoading
? ''
: `
${getDisabledStyleByVariation({ variation, theme })}
${isRebrand(theme) ? `opacity: 38%;` : `color: ${theme.neutral400};`}
${isRebrand(theme) ? `background: ${getRule('backgroundColor')({ size, variation, theme })} !important;` : ''}
cursor: not-allowed;
`}
}
&:active {
background-color: ${getRule('active.backgroundColor')};
background-size: ${getRule('active.backgroundSize')};
transition: ${getRule('active.transition')};
}
`;
const ButtonBase = (_a) => {
var { children, $isLoading, onClick = () => { } } = _a, props = __rest(_a, ["children", "$isLoading", "onClick"]);
let dotColor = 'purple';
switch (props.variation) {
case 'main':
case 'destructive':
case 'accent':
case undefined:
dotColor = 'white';
break;
default:
break;
}
return (_jsx(StyledButton, Object.assign({ disabled: $isLoading, onClick: (event) => {
event.persist();
onClick(event);
} }, props, { children: $isLoading ? _jsx(LoadingDots, { dotColor: dotColor, "data-testid": "button-loading-dots" }) : children })));
};
ButtonBase.displayName = 'ButtonBase';
const ButtonLink = styled(StyledButton).attrs(() => ({ as: Link })) `
text-decoration: none;
`;
ButtonLink.displayName = 'ButtonLink';
const ButtonAnchor = styled(StyledButton).attrs(() => ({ as: 'a' })).withConfig({ displayName: "brc-sc-ButtonAnchor", componentId: "brc-sc-1uee4oc" }) `
text-decoration: none;
`;
ButtonAnchor.displayName = 'ButtonAnchor';
export const Button = (_a) => {
var { href, asAnchor, isLoading } = _a, props = __rest(_a, ["href", "asAnchor", "isLoading"]);
if (!href) {
return _jsx(ButtonBase, Object.assign({ "$isLoading": isLoading }, props));
}
if (asAnchor) {
return _jsx(ButtonAnchor, Object.assign({ "$isLoading": isLoading, href: href }, props));
}
return _jsx(ButtonLink, Object.assign({ "$isLoading": isLoading, href: href }, props));
};
Button.displayName = 'Button';
const StyledButtonExp = styled(Button).withConfig({ displayName: "brc-sc-StyledButtonExp", componentId: "brc-sc-1jq7psv" }) ``;
export default StyledButtonExp;
//# sourceMappingURL=button.js.map