Skip to content

Commit aacd7b6

Browse files
author
ugogo
committed
switch to emotion
1 parent a8d853e commit aacd7b6

File tree

5 files changed

+240
-89
lines changed

5 files changed

+240
-89
lines changed

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@
4141
"react": "^16.0.0"
4242
},
4343
"devDependencies": {
44+
"@emotion/core": "^10.0.28",
45+
"@emotion/styled": "^10.0.27",
4446
"@testing-library/jest-dom": "^4.2.4",
4547
"@testing-library/react": "^9.5.0",
4648
"@testing-library/user-event": "^7.2.1",

src/index.css

Lines changed: 0 additions & 44 deletions
This file was deleted.

src/index.tsx

Lines changed: 47 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import * as React from 'react';
2-
import './index.css';
2+
import { Global, css } from '@emotion/core';
3+
import { Container, Input, Item } from './styles';
34

45
const KEY_CODE = {
56
BACKSPACE: 8,
@@ -104,47 +105,52 @@ export default ({ length = 4, onChange, placeholder = '·' }: Props) => {
104105
}, [value]);
105106

106107
return (
107-
<div
108-
className='ReactInputVerificationCode__container'
109-
style={
110-
{
111-
'--activeIndex': activeIndex,
112-
'--itemsCount': length,
113-
'--itemWidth': '4.5rem',
114-
'--itemHeight': '5rem',
115-
'--itemSpacing': '1rem',
116-
} as React.CSSProperties
117-
}
118-
>
119-
<input
120-
ref={codeInputRef}
121-
className='ReactInputVerificationCode__input'
122-
autoComplete='one-time-code'
123-
type='text'
124-
inputMode='decimal'
125-
id='one-time-code'
126-
// use onKeyUp rather than onChange for a better control
127-
// onChange is still needed to handle the autocompletion
128-
// when receiving a code by SMS
129-
onChange={onInputChange}
130-
onKeyUp={onInputKeyUp}
131-
onBlur={onInputBlur}
108+
<React.Fragment>
109+
<Global
110+
styles={css`
111+
:root {
112+
--ReactInputVerificationCode-itemWidth: 4.5rem;
113+
--ReactInputVerificationCode-itemHeight: 5rem;
114+
--ReactInputVerificationCode-itemSpacing: 1rem;
115+
}
116+
`}
132117
/>
133118

134-
{itemsRef.map((ref, i) => (
135-
<div
136-
key={i}
137-
ref={ref}
138-
role='button'
139-
tabIndex={0}
140-
className={`ReactInputVerificationCode__item ${
141-
activeIndex === i ? 'is-active' : ''
142-
}`}
143-
onFocus={onItemFocus(i)}
144-
>
145-
{value[i] || placeholder}
146-
</div>
147-
))}
148-
</div>
119+
<Container
120+
// needed for styling
121+
itemsCount={length}
122+
>
123+
<Input
124+
ref={codeInputRef}
125+
className='ReactInputVerificationCode__input'
126+
autoComplete='one-time-code'
127+
type='text'
128+
inputMode='decimal'
129+
id='one-time-code'
130+
// use onKeyUp rather than onChange for a better control
131+
// onChange is still needed to handle the autocompletion
132+
// when receiving a code by SMS
133+
onChange={onInputChange}
134+
onKeyUp={onInputKeyUp}
135+
onBlur={onInputBlur}
136+
// needed for styling
137+
activeIndex={activeIndex}
138+
/>
139+
140+
{itemsRef.map((ref, i) => (
141+
<Item
142+
key={i}
143+
ref={ref}
144+
role='button'
145+
tabIndex={0}
146+
onFocus={onItemFocus(i)}
147+
// needed for emotion-styled
148+
isActive={i === activeIndex}
149+
>
150+
{value[i] || placeholder}
151+
</Item>
152+
))}
153+
</Container>
154+
</React.Fragment>
149155
);
150156
};

src/styles.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import styled from '@emotion/styled';
2+
3+
type ContainerProps = { itemsCount: number };
4+
export const Container = styled.div`
5+
display: flex;
6+
position: relative;
7+
justify-content: space-between;
8+
width: ${(props: ContainerProps) => `
9+
calc(var(--ReactInputVerificationCode-itemWidth) * ${props.itemsCount}
10+
+ var(--ReactInputVerificationCode-itemSpacing)
11+
* (${props.itemsCount} - 1)
12+
`}
13+
);
14+
`;
15+
16+
// input
17+
18+
type InputProps = {
19+
activeIndex: number;
20+
};
21+
22+
export const Input = styled.input`
23+
position: absolute;
24+
top: 0;
25+
left: ${(props: InputProps) =>
26+
`calc(${props.activeIndex} * var(--ReactInputVerificationCode-itemWidth) + var(--ReactInputVerificationCode-itemSpacing) * ${props.activeIndex})`};
27+
opacity: 0;
28+
width: var(--ReactInputVerificationCode-itemWidth);
29+
height: var(--ReactInputVerificationCode-itemHeight);
30+
`;
31+
32+
// item
33+
34+
type ItemProps = {
35+
isActive: boolean;
36+
};
37+
38+
export const Item = styled.div<ItemProps>`
39+
width: var(--ReactInputVerificationCode-itemWidth);
40+
height: var(--ReactInputVerificationCode-itemHeight);
41+
padding: 0;
42+
border-radius: 4px;
43+
font-size: 1.5rem;
44+
font-weight: 800;
45+
line-height: var(--ReactInputVerificationCode-itemHeight);
46+
text-align: center;
47+
border: 0;
48+
box-shadow: ${(props) =>
49+
`inset 0 0 0 ${props.isActive ? '2px' : '1px'}
50+
${props.isActive ? '#888' : '#ccc'}`};
51+
transition: box-shadow 0.2s ease-out;
52+
`;

0 commit comments

Comments
 (0)