import React from "react";
import { ReactComponent as LeftIcon } from "@Static/Icons/west_300_opsz24.svg";
import { ReactComponent as RightIcon } from "@Static/Icons/east_wght300_opsz24.svg";
type TextIconButtonProp = {
disabled?: boolean;
leftIcon?: boolean;
rightIcon?: boolean;
children?: React.ReactNode;
};
const TextIconButton = ({
disabled = false,
leftIcon = false,
rightIcon = false,
children,
}: TextIconButtonProp) => {
const iconStyle = "w-m24 aspect-square " + "tablet:w-t24 desktop:w-d24";
const shapeStyle = "links text-black ";
const layoutStyle =
"relative flex flex-row place-content-center place-items-center w-fit gap-m4 " +
"tablet:gap-t4 desktop:gap-d4 ";
const beforeHoverStyle =
"pointerhover:hover:before:content-[''] " +
"pointerhover:hover:before:absolute " +
"pointerhover:hover:before:left-0 " +
"pointerhover:hover:before:bottom-0 " +
"pointerhover:hover:before:w-full " +
"pointerhover:hover:before:h-[0.31vw] " +
"pointerhover:hover:before:bg-black " +
"tablet:pointerhover:hover:before:h-[0.13vw] " +
"desktop:pointerhover:hover:before:h-[0.06vw] ";
const beforeActiveStyle =
"active:before:content-[''] " +
"active:before:absolute " +
"active:before:left-0 " +
"active:before:bottom-0 " +
"active:before:w-full " +
"active:before:h-[0.31vw] " +
"active:before:bg-black " +
"tablet:active:before:h-[0.13vw] " +
"desktop:active:before:h-[0.06vw] ";
const stateStyle =
beforeHoverStyle +
beforeActiveStyle +
"disabled:text-gray disabled:pointerhover:hover:before:content-none " +
"active:text-black active:pointerhover:hover:text-black " +
"pointerhover:hover:text-gray ";
const buttonStyle = shapeStyle + layoutStyle + stateStyle;
return (
<button disabled={disabled} className={buttonStyle}>
{leftIcon && <LeftIcon className={iconStyle} />}
{children}
{rightIcon && <RightIcon className={iconStyle} />}
</button>
);
};
export default TextIconButton;
디자이너 분이 디자인을 참... 애매하게 하셨다. 나였으면 아이콘까지 색을 바꿨을 텐데, 아이콘의 변화는 없다. 아참, 그리고 hover 이슈가 있었는데, 이 포스팅으로 갈무리하겠다.
import React from "react";
import { ReactComponent as CheckIcon } from "@Static/Icons/check_FILL0_wght300_GRAD0_opsz24.svg";
type CheckboxProp = {
active?: boolean;
text: string;
selected?: boolean;
};
const Checkbox = ({ text, active = true, selected = true }: CheckboxProp) => {
const checkboxShapeStyle =
"appearance-none bg-lightgray border border-black ";
const checkboxLayoutStyle =
"peer aspect-square " + "w-m24 h-m24 " + "tablet:w-t24 desktop:w-d24 ";
const checkboxStateStyle =
"disabled:border-darkgray " +
`checked:bg-[url('data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTkuNTUxNTYgMTcuNjQ5Nkw0LjIyNjU2IDEyLjMyNDZMNS4yNzY1NiAxMS4yNDk2TDkuNTUxNTYgMTUuNTI0NkwxOC43MjY2IDYuMzQ5NjFMMTkuNzc2NiA3LjQyNDYxTDkuNTUxNTYgMTcuNjQ5NloiLz48L3N2Zz4NCg==')] ` +
"checked:bg-[length:100%_100%] " +
(!active && selected
? "checked:bg-[url('data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxwYXRoIGQ9Ik05LjU1MTU2IDE3LjY0OTZMNC4yMjY1NiAxMi4zMjQ2TDUuMjc2NTYgMTEuMjQ5Nkw5LjU1MTU2IDE1LjUyNDZMMTguNzI2NiA2LjM0OTYxTDE5Ljc3NjYgNy40MjQ2MUw5LjU1MTU2IDE3LjY0OTZaIiBmaWxsPSIjODA4MDgwIi8+Cjwvc3ZnPg==')] "
: "");
const checkboxStyle =
checkboxShapeStyle + checkboxLayoutStyle + checkboxStateStyle;
return (
<>
<label
className="flex w-fit flex-row gap-m12 tablet:gap-t12 desktop:gap-d12"
htmlFor={text}
>
<input
disabled={!active}
className={checkboxStyle}
checked={!active ? selected : undefined}
type="checkbox"
id={text}
name={text}
/>
<p className="caption peer-disabled:text-gray">{text}</p>
</label>
</>
);
};
export default Checkbox;
의외로 많이 어려웠던 Checkbox. 심지어 이거 실무에서 사용하려면 value랑 이벤트랑 또 다르게 바꿔줘야 해서 진짜 껍데기인 것 .... 😇
- SVG파일 관련
- 나는 svg파일을 svgr plugin을 이용해서 컴포넌트화 했는데, 이걸 background-image로 넣는 법을 몰랐다.
- 그래서 svg코드 그대로 넣으면 된다는 말을 듣고 해봤는데, 안 됐다.
- 왜 안 됐냐면, tailwind에서 값은 띄어쓰기를 쓰면 안 된다는 걸 개삽질 후에 알았다. 스페이스(whitespace)는 모두 _로 처리해줘야 했다.
- 대안으로 Base64 인코딩을 통해서 넣어줬다. 성공!
- 그런데 disabled시 이 svg의 색을 바꿔줘야 했는데, 이게 쉽지 않았다.
- filter로 가능하지 않을까 했는데, 의외로 특정 색으로 바꾸는 filter는 존재하지 않았따.
- 또, tailwind는 동적으로 생성한 스타일은 적용되지 않는다.
- 이것때문에 또 개삽질하다가, 결국 svg 코드에 fill을 넣어서 새로운 Base64 인코딩을 한 뒤 배경 이미지를 갈아끼우는 방식을 선택했다. 이게 맞냐?
- aspect-ratio 관련
- 내가 겪은 현상이 aspect-ratio에 관한 건지, 아니면 브라우저 마다 DOM Tree를 구성하는 방법에 관련한 건지 잘 모르겠지만, 아마 후자가 아닐까 싶다. 아닌가?
- 내가 겪은 현상은, width를 설정해준 다음에 height는 aspect-ratio로 1/1 비율을 맞춰주었다. 크롬에선 잘 되는데, 사파리에선 동작하지 않았다.
- aspect-ratio의 browser compatibility를 확인해봤지만 호환 가능한 속성이었다.
- 이때 약간 삼천포로 빠져서, @supports not 쿼리를 이용해서 aspect-ratio: 1/1를 지원하지 않으면 height를 따로 설정해주는 tailwind 문법을 계속 검색해보고 있었다.
- 근데 tailwind에서 @supports는 supports-[]로 지원함시롱 @supports not ()은 지원하지 않더라.
- 공식문서를 읽어보니, addVariant를 이용해서 plugin을 만들어 사용해라! 라고 해서 supports-not이라는 arbitrary variants를 만들어서 하려고 했는데 디지게 안 되더라
- 머가 문제야! 이러고 공식 문서에 있는 예제 그대로 가져다가 썼는데도 작동이 안 되는 걸 보고, 걍 플러그인이 문제였군 싶었다. 왜 안 돌아가는지는 아직도 불명(ㅋㅋ)
- 결국 height를 설정해주었다. aspect-ratio는 왜 안 먹는 건지 아직도 모르겠다~
- 꼼수를 알아내긴 했다. height: calc(width * 9/16) 뭐 이런 느낌인데, 나중에 1/1 비율이 아닐 때 써먹어봐야 겠다.