diff --git a/package-lock.json b/package-lock.json index b7c0fd2..7e020ac 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5087,7 +5087,6 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -5245,7 +5244,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -5260,7 +5258,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -5275,7 +5272,6 @@ "version": "2.3.5", "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.3.5.tgz", "integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==", - "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -5294,7 +5290,6 @@ "version": "0.5.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "optional": true, "requires": { "minimist": "0.0.8" } @@ -5388,7 +5383,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "optional": true, "requires": { "wrappy": "1" } @@ -5511,7 +5505,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -5531,7 +5524,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "optional": true, "requires": { "ansi-regex": "^2.0.0" } diff --git a/src/components/UI/atoms/StyledLink/StyledLink.jsx b/src/components/UI/atoms/StyledLink/StyledLink.jsx new file mode 100644 index 0000000..2a42107 --- /dev/null +++ b/src/components/UI/atoms/StyledLink/StyledLink.jsx @@ -0,0 +1,106 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import styled from 'styled-components'; +import { Link } from 'react-router-dom'; +import { fontSizes } from '/fonts'; +import { backgroundColors } from '/colorPalette'; +import spacing from '/spacing'; + +/** + * @description - StyledLink Component + * + * @prop {string} to + * @prop {boolean} tag + * @prop {boolean} isExternal + * @prop {string} fontSize + * @prop {string} margin + * @prop {function} onClick + * @prop {children} children + * + * @return {component} StyledLink + */ + +const StyledLink = ({ + to, + tag, + isExternal, + fontSize, + margin, + onClick, + children, +}) => { + return isExternal + ? ( + {children} + ) + : ( + + {children} + + ); +}; + +StyledLink.propTypes = { + children: PropTypes.oneOfType([ + PropTypes.string, + PropTypes.number, + PropTypes.element, + ]).isRequired, + to: PropTypes.string.isRequired, + tag: PropTypes.bool, + isExternal: PropTypes.bool, + fontSize: PropTypes.oneOf(Object.keys(fontSizes)), + onClick: PropTypes.func, + margin: PropTypes.oneOf(Object.keys(spacing)), +}; + +StyledLink.defaultProps = { + fontSize: 'normal', + margin: 'zero', + to: '#', + isExternal: false, + backgroundColor: 'transparent', +}; + +const linkStyle = ({ + margin, fontSize, theme, tag, +}) => ` + text-decoration: none; + display: inline-block; + text-align: center; + transition: .5s border ease-in-out; + border: solid 1px transparent; + font-family: 'Roboto'; + margin: ${spacing[margin]}; + font-size: ${theme.fontSizes[fontSize]}; + color: ${theme.textColors.primary}; + background: ${(tag && backgroundColors.lightPink) || 'transparent'}; + padding: ${(tag && theme.spacing.xs) || '0'}; + box-shadow: ${(tag && theme.boxShadows.articleCard) || 'none'}; + width: ${(tag && theme.spacing.smd) || 'auto'}; + &:visited { + color: ${theme.textColors.primary}; + } + &:hover { + border: ${tag && `solid 1px ${theme.textColors.primary}`}; + }; +`; + +StyledLink.Internal = styled(Link)`${linkStyle}`; + +StyledLink.External = styled.a`${linkStyle}`; + +export default StyledLink; diff --git a/src/components/UI/atoms/StyledLink/StyledLink.md b/src/components/UI/atoms/StyledLink/StyledLink.md new file mode 100644 index 0000000..6e459ad --- /dev/null +++ b/src/components/UI/atoms/StyledLink/StyledLink.md @@ -0,0 +1,26 @@ +StyledLink Default: + +```jsx +import { BrowserRouter as Router } from 'react-router-dom'; + + Google Link + +``` + +StyledLink With All Props: + +```jsx +import { BrowserRouter as Router } from 'react-router-dom'; + + + Google Link + + +``` \ No newline at end of file diff --git a/src/components/UI/atoms/StyledLink/StyledLink.spec.js b/src/components/UI/atoms/StyledLink/StyledLink.spec.js new file mode 100644 index 0000000..31352c6 --- /dev/null +++ b/src/components/UI/atoms/StyledLink/StyledLink.spec.js @@ -0,0 +1,96 @@ +import React from 'react'; +import { fireEvent } from '@testing-library/react'; +import { MemoryRouter } from 'react-router-dom'; +import { render, cleanup } from '/helpers/testUtils'; +import StyledLink from './StyledLink'; +import Title from '../Title/Title'; +import '@testing-library/jest-dom/extend-expect'; + +afterEach(cleanup); + +describe('StyledLink', () => { + it('should render the Link component', () => { + const { getByText } = render( + + Authors Haven + , + ); + + expect(getByText('Authors Haven')).toBeTruthy(); + }); + + it('should apply default style', () => { + const { getByText } = render( + + Authors Haven + , + ); + + expect(getByText('Authors Haven')).toHaveStyle(` + font-size: '1.6' + display: inline-block; + text-decoration: none; + `); + }); + + it('should render an external tag styled link', () => { + const { container, getByText } = render( + + + Welcome + + , + ); + fireEvent.click(getByText('Welcome')); + expect(container.firstChild).toBeTruthy(); + }); + + it('should render a tag styled component', () => { + const { container, getByText } = render( + + + Welcome + + , + ); + fireEvent.click(getByText('Welcome')); + expect(container.firstChild).toBeTruthy(); + }); + + it('should render react component as children', () => { + const { container } = render( + + + Google Link + + , + ); + expect(container.firstChild).toBeTruthy(); + }); + + it('should render react component as children', () => { + const { container } = render( + + + Google Link + + , + ); + expect(container.firstChild).toBeTruthy(); + }); +}); diff --git a/src/styles/variables/spacing.js b/src/styles/variables/spacing.js index 2309b16..6bf367f 100644 --- a/src/styles/variables/spacing.js +++ b/src/styles/variables/spacing.js @@ -2,6 +2,7 @@ const spacing = { zero: '0rem', xs: '0.9rem', sm: '1.6rem', + smd: '25.8rem', md: '3.2rem', xxl: '8.2rem', };