React
by alexb
HTML
<div id="root"></div>
CSS
html {
box-sizing: border-box;
}
html * {
box-sizing: inherit;
}
body {
background: #ccb;
font-family: Helvetica;
margin: 0;
padding: 54px;
}
.root {
display: flex;
justify-content: center;
}
.app {
display: flex;
align-items: center;
flex-direction: column;
}
.payment-card {
position: relative;
width: 344px;
height: 216px;
perspective: 500px;
transform-style: preserve-3d;
}
.payment-card .front,
.payment-card .back {
border: 2px solid #000;
border-radius: 12px;
transition: transform 10s ease;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.payment-card .front {
background: cornflowerblue;
}
.payment-card .back {
background: firebrick;
transform: translateZ(-1px) rotate3d(0, 1, 0, -180deg);
}
.payment-card_flipped .front {
transform: translateZ(-1px) rotate3d(0, 1, 0, 180deg);
}
.payment-card_flipped .back {
transform: none;
}
.payment-card .name {
position: absolute;
left: 5%;
bottom: 5%;
}
.payment-card .number {
position: absolute;
left: 50%;
bottom: 40%;
transform: translateX(-50%);
}
.payment-card .expires {
position: absolute;
left: 50%;
bottom: 25%;
transform: translateX(-50%);
}
.payment-card .cvv {
position: absolute;
left: 50%;
bottom: 40%;
transform: translateX(-50%);
}
.fields {
display: flex;
flex-direction: column;
margin-top: 2em;
width: 344px;
}
label {
display: flex;
flex-direction: column;
}
.label-text {
font-size: 0.75em;
margin-bottom: 0.25em;
}
input {
border: none;
border-radius: 2px;
font-size: 16px;
margin-bottom: 0.5em;
padding: 0.5em;
}
input:focus {
outline: none;
}
React
const PaymentCard = ({ className, name, number, expires, cvv }) => (
<div className={`payment-card ${className}`}>
<div className="front">
<span className="name">{name}</span>
<span className="number">{number}</span>
<span className="expires">{expires}</span>
</div>
<div className="back">
<span className="cvv">{cvv}</span>
</div>
</div>
);
const Field = ({ label, ...props }) => (
<label>
<span className="label-text">{label}</span>
<input {...props} />
</label>
)
const App = () => {
const [showBackOfCard, setShowBackOfCard] = React.useState(false);
const cardDetails = {
name: 'Mr A Barrett',
number: '4242 4242 4242 4242',
expires: '11/22',
cvv: '369'
}
return (
<div className="app">
<PaymentCard
className={showBackOfCard ? 'payment-card_flipped' : ''}
{...cardDetails}
/>
<div className="fields">
<Field label="Name on card" value={cardDetails.name} />
<Field label="Card number" value={cardDetails.number} />
<Field label="Expiry date" value={cardDetails.expires} />
<Field
label="Security code"
value={cardDetails.cvv}
onFocus={() => setShowBackOfCard(true)}
onBlur={() => setShowBackOfCard(false)}
/>
</div>
</div>
);
};
ReactDOM.render(<App />, document.querySelector("#root"))