우선 값이 많아질경우 나중에 적기 귀찮아 질것같은 부분부터 수정했다.
아래 코드에서 font size에 관한 부분인데 추후 사이즈가 추가될 경우 fsXX 이런식으로
여러줄을 쓰게 될 가능성이 있었다. 그래서 조금 수정했다.
// 전역스타일 before
declare module 'styled-components' {
export interface DefaultTheme {
font: {
bold: string,
},
size: {
fs18: string,
fs22: string,
}
},
color : {
primary1: string,
},
deviceSizes : {
mobile: string,
tablet: string,
desktop: string,
},
}
}
// 전역스타일 After
import 'styled-components';
type FontSizes = 18 | 22 | 60;
type FontSizeType = `fs${FontSizes}`;
type FontWeights = 700;
type FontWeighType = `fw${FontWeights}`;
declare module 'styled-components' {
export interface DefaultTheme {
font: {
bold: string,
},
size: {
[size in FontSizeType]: string;
},
weight: {
[weight in FontWeighType]: number;
}
},
...
}
이렇게 추후 숫자만 추가하면 자동으로 fsXX, fwXX가 추가될 수 있게 수정했다.
Banner에서 하는 일은 두개밖에 없다.
그래서 생각보다 금방 끝날줄 알았으나 예상외의 곳에서 시간을 잡아먹었다.
우선 store에서 상태를 받아와 반영하는 기능은 금방 만들어서 적용을 했다.
// App.tsx
const App = () => {
const dispatch = useAppDispatch();
useEffect(()=>{
dispatch(changeBackgroundColor(getRandomColor()));
dispatch(changeForegroundColor(getRandomColor()));
dispatch(changeBorderColor(getRandomColor()));
},[]);
위의 getRandomColor()
함수는 16진수의 랜덤한 값을 생성해
#XXXXXXff
의 형식으로 색상을 리턴하는 함수다.
이렇게 색상을 랜덤으로 생성해서 background, foreground, border의 색상을 바꿔준다.
처음에 redux를 사용해 store를 생성해뒀기 때문에 이 작업도 역시 금방 끝났다.
값을 받아와서 styled-components로 작성한 div에 값을 넘겨주기만 하면 됐기 때문이다.
// Banner/index.tsx
...
const Banner = () => {
const options = useAppSelector(state => state.option);
return (
<BannerBlock options={options} >
Edit Me
</BannerBlock>
);
}
// Banner/style.ts
...
${({options}) => css`
color: ${options.foregroundColor};
height: ${options.heightRatio}vw;
background: ${options.backgroundColor};
border ${options.borderWidth}px solid ${options.borderColor};
font-size: ${options.fontSize}px;
font-weight: ${theme.font.weight.fw700};
display: flex;
justify-content: ${options.textAlignment.justifyContent};
align-items: ${options.textAlignment.alignItems};
text-shadow: ${options.textShadow.x}px ${options.textShadow.y}px ${options.textShadow.blur}px ${options.textShadow.color};
& ::selection {
color: ${options.backgroundColor};
background: ${options.foregroundColor};
}
`}
`;
...
이런식으로 props로 options를 받아와 바로바로 모든 값들을 적용 시켜줬다.
이부분이 생각보다 시간을 많이 잡아먹었는데 결국 간단했었다.
여기에 해결과정을 자세히 적어놨다.
간단히 다시 설명하면 div의 값을 수정해주려면
contenteditable
와 suppressContentEditableWarning
속성을 true로 주면 된다.
그리고 값의 변경감지는 onInput()
함수로 하면 된다.
해당 이유 설명도 위의 링크로 대체한다.
그래서 아래의 코드가 나왔다.
// Banner/index.tsx
...
<BannerBlock options={options} >
<BannerText
onInput={handleInput}
contentEditable
suppressContentEditableWarning
>
Edit Me
</BannerText>
</BannerBlock>
...
// Banner/index.tsx
...
const handleInput = (e: React.FormEvent<HTMLDivElement>) => {
dispatch(changeText(e.currentTarget.innerText));
}
...
값 수정은 handleInput()
함수로 해주어 banner 작성을 끝냈다.
그렇게 큰 문제가 있던 버그는 아닌데
랜덤한 16진수 값을 생성할 때 16진수값이 아닌 값이 생성될 때가 있었다.
export function getRandomColor() {
return "#" + Math.round(Math.random() * 0xffffff).toString(16) + "ff";
}
이 함수인데 아래처럼 16진수로 최대값이 아니라 10진수로 16진수의 최대치를 적어줘 해결했다.
export function getRandomColor() {
return "#" + Math.round(Math.random() * 16777215).toString(16) + "ff";
}
이제 팀원들이 Button, InputNumber 컴포넌트 작성을 완료해주면 그걸로
Randomize버튼과 Text Alignment 기능을 내가 작성하면 이번 토이프로젝트는 끝난다.
혼자하면 며칠이면 끝날 프로젝트 였지만 팀원과 같이 했다는것에 의의를 둔다.