Skip to content

Commit

Permalink
feat: base card atom
Browse files Browse the repository at this point in the history
  • Loading branch information
gvieiraschwade committed Aug 9, 2020
1 parent 3387877 commit e20a4f8
Show file tree
Hide file tree
Showing 9 changed files with 494 additions and 105 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,6 @@ yarn-error.log*

# VScode settings
/.vscode

# meld
*.orig
19 changes: 10 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,6 @@
"version": "0.0.0",
"private": true,
"dependencies": {
"@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.3.2",
"@testing-library/user-event": "^7.1.2",
"@types/jest": "^24.0.0",
"@types/node": "^12.0.0",
"@types/react": "^16.9.0",
"@types/react-dom": "^16.9.0",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-jss": "^10.3.0",
Expand All @@ -29,7 +22,7 @@
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"test": "react-scripts test --env=jest-environment-jsdom-sixteen",
"eject": "react-scripts eject",
"version": "conventional-changelog -p angular -i CHANGELOG.md -t v -s",
"lint": "eslint . --ext .ts --ext .tsx --fix"
Expand All @@ -47,6 +40,13 @@
]
},
"devDependencies": {
"@testing-library/jest-dom": "^5.11.2",
"@testing-library/react": "^10.4.8",
"@testing-library/user-event": "^12.1.1",
"@types/jest": "^24.0.0",
"@types/node": "^12.0.0",
"@types/react": "^16.9.0",
"@types/react-dom": "^16.9.0",
"@commitlint/cli": "^9.1.1",
"@commitlint/config-conventional": "^9.1.1",
"@types/react-router-dom": "^5.1.5",
Expand All @@ -63,6 +63,7 @@
"eslint-plugin-react-hooks": "^4.0.8",
"husky": "^4.2.5",
"lint-staged": "^10.2.11",
"prettier": "^2.0.5"
"prettier": "^2.0.5",
"jest-environment-jsdom-sixteen": "^1.0.3"
}
}
49 changes: 49 additions & 0 deletions src/components/atoms/BaseCard/BaseCard.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import React from 'react';
import { fireEvent, render } from '@testing-library/react';
import { BaseCard } from './BaseCard';

describe('BaseCard', () => {
it('should render the card', () => {
const { getByTestId, getByRole } = render(<BaseCard />);
expect(getByRole('button')).toBeInTheDocument();
expect(getByTestId('BaseCard')).toBeInTheDocument();
});

describe('when rendered', () => {
let cardContainer: HTMLElement;
let frontFace: HTMLElement;
let backFace: HTMLElement;
beforeEach(() => {
const { getByTestId, getByRole } = render(
<BaseCard
frontFace={<div data-testid="front-face">MY FRONT</div>}
backFace={<div data-testid="back-face">MY BACK</div>}
/>,
);
cardContainer = getByRole('button');
frontFace = getByTestId('front-face');
backFace = getByTestId('back-face');
});

it('should display the front face by default', () => {
expect(frontFace).toBeVisible();
});

it('should hide the back face by default', () => {
expect(backFace).not.toBeVisible();
});

it('should flip when clicked', async () => {
fireEvent.click(cardContainer);
expect(backFace).toBeVisible();
expect(frontFace).not.toBeVisible();
});

it('should flip again when clicked again', async () => {
fireEvent.click(cardContainer);
fireEvent.click(cardContainer);
expect(backFace).not.toBeVisible();
expect(frontFace).toBeVisible();
});
});
});
95 changes: 95 additions & 0 deletions src/components/atoms/BaseCard/BaseCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import React, { useState, KeyboardEvent } from 'react';
import { createUseStyles } from 'react-jss';

/**
* Properties for BaseCard component
*/
export interface BaseCardProps {
/** Element to show at card front face */
frontFace?: JSX.Element;
/** Element to show at card back face */
backFace?: JSX.Element;
/** Defines the card height */
height?: number;
/** Defines the card width */
width?: number;
}

const useStyles = createUseStyles({
// Generic classes
cardFace: {
backfaceVisibility: 'hidden',
position: 'absolute',
top: 0,
left: 0,
color: 'cornSilk',
textAlign: 'center',
font: `3em/240px 'Helvetica Neue', Helvetica, sans-serif`,
boxShadow: '-5px 5px 5px #aaa',
transition: '0.6s',
},
// Modal classes
backVisible: {},
frontVisible: {},
// Style classes
card: ({ width, height }) => ({
width: width || 600,
height: height || 400,
perspective: 1000,
cursor: 'pointer',
'&$backVisible $cardFlipper': { transform: 'rotateY(180deg)' },
'&$backVisible $cardFront': { opacity: 0 },
'&$backVisible $cardBack': { opacity: 1 },
'&$frontVisible $cardFront': { opacity: 1 },
'&$frontVisible $cardBack': { opacity: 0 },
outline: 'none',
overflow: 'hidden',
}),
cardFlipper: {
transition: '0.6s',
transformStyle: 'preserve-3d',
position: 'relative',
},
cardFront: {
extend: 'cardFace',
zIndex: 2,
transform: 'rotateY(0deg)',
},
cardBack: {
extend: 'cardFace',
transform: 'rotateY(180deg)',
},
});

/**
* Base card molecule
* @param props Card props
*/
export const BaseCard: React.FC<BaseCardProps> = ({
frontFace,
backFace,
width = undefined,
height = undefined,
} = {}) => {
const { backVisible, frontVisible, card, cardFlipper, cardFront, cardBack } = useStyles({ width, height });
const [visibleFace, setVisibleFace] = useState<'front' | 'back'>('front');

const turnCard = (): void => setVisibleFace(visibleFace === 'front' ? 'back' : 'front');
const onKeyDown = (event: KeyboardEvent<HTMLDivElement>) => event.keyCode === 32 && turnCard();

return (
<div
data-testid="BaseCard"
role="button"
onClick={turnCard}
onKeyDown={onKeyDown}
className={`${card} ${visibleFace === 'back' ? backVisible : frontVisible}`}
tabIndex={0}
>
<div className={cardFlipper}>
<div className={cardFront}>{frontFace}</div>
<div className={cardBack}>{backFace}</div>
</div>
</div>
);
};
10 changes: 8 additions & 2 deletions src/components/pages/HomePage/HomePage.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import React from 'react';
import { createUseStyles } from 'react-jss';
import { BaseCard } from '../../atoms/BaseCard/BaseCard';

const useStyles = createUseStyles({
homePage: {
background: '#1941e3',
background: '#cccccc',
height: '100%',
color: 'white',
},
Expand All @@ -12,7 +13,12 @@ const useStyles = createUseStyles({
const HomePage: React.FC = () => {
const classes = useStyles();

return <div className={classes.homePage}>I am on homepage</div>;
return (
<div className={classes.homePage}>
I am on homepage
<BaseCard frontFace={<div>MY FRONT</div>} backFace={<div>MY BACK</div>} />
</div>
);
};

export default HomePage;
2 changes: 1 addition & 1 deletion src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
document.getElementById('root'),
);

// If you want your app to work offline and load faster, you can change
Expand Down
6 changes: 3 additions & 3 deletions src/serviceWorker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const isLocalhost = Boolean(
// [::1] is the IPv6 localhost address.
window.location.hostname === '[::1]' ||
// 127.0.0.0/8 are considered localhost for IPv4.
window.location.hostname.match(/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/)
window.location.hostname.match(/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/),
);

type Config = {
Expand Down Expand Up @@ -37,7 +37,7 @@ export function register(config?: Config): void {
navigator.serviceWorker.ready.then(() => {
console.log(
'This web app is being served cache-first by a service ' +
'worker. To learn more, visit https://bit.ly/CRA-PWA'
'worker. To learn more, visit https://bit.ly/CRA-PWA',
);
});
} else {
Expand Down Expand Up @@ -67,7 +67,7 @@ function registerValidSW(swUrl: string, config?: Config): void {
// content until all client tabs are closed.
console.log(
'New content is available and will be used when all ' +
'tabs for this page are closed. See https://bit.ly/CRA-PWA.'
'tabs for this page are closed. See https://bit.ly/CRA-PWA.',
);

// Execute callback
Expand Down
3 changes: 2 additions & 1 deletion src/setupTests.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/* eslint-disable import/no-extraneous-dependencies */
// jest-dom adds custom jest matchers for asserting on DOM nodes.
// allows you to do things like:
// expect(element).toHaveTextContent(/react/i)
// learn more: https://github.com/testing-library/jest-dom
import '@testing-library/jest-dom/extend-expect';
import '@testing-library/jest-dom';
Loading

0 comments on commit e20a4f8

Please sign in to comment.