버그 이슈: https://github.com/shadcn-ui/ui/issues/4654#issue-2491018149
[bug]: Duplicate classNames(border) in checkbox, radio group · Issue #4654 · shadcn-ui/ui
Describe the bug If I install checkbox in CLI, I encountered duplicate border-color issue. PR#1089 said that this problem has fixed... I found accurate comment on related first bug issue, and I che...
github.com
버그 이슈에 대한 제 코멘트: https://github.com/shadcn-ui/ui/issues/4654#issuecomment-2323113138
[bug]: Duplicate classNames(border) in checkbox, radio group · Issue #4654 · shadcn-ui/ui
Describe the bug If I install checkbox in CLI, I encountered duplicate border-color issue. PR#1089 said that this problem has fixed... I found accurate comment on related first bug issue, and I che...
github.com
이를 기반으로 올린 PR: https://github.com/shadcn-ui/ui/pull/4745#issue-2506748491
fix: “border-boder” “border-primary” duplicates (e.g. “checkbox”, “radio-group”) by joseph0926 · Pull Request #
What was the problem If you didn't include css variables in your initial setup, we converted them, and the special treatment for “border” resulted in duplicate styling for “border”. Where'...
github.com
배경
평소처럼 shadcn-ui를 사용하고 있었고, 위의 이슈와는 다른 이슈로 shadcn-ui 깃허브 이슈 탭을 살펴보던 와중에 간단해보이는 버그 이슈를 발견하였습니다 (위 링크 이슈)
이를 해결해보기 위해 우선 문제 상황을 재현해보려 했습니다.
위의 버그 제보자가 버그를 재현하기 위해서 해보라고 한 지침을 그대로 수행하였지만, 저한테는 해당 문제가 발생하지 않았습니다.
How to reproduce
enter pnpm dlx shadcn-ui@latest add checkbox or radio-group on your project.
go to ui/checkbox...ui/radio-group
you'll see the error.
(버그 제보자 글 중,,)
그래서 왜 나한테는 일어나지 않는 일이 저분한테는 일어날까 해서, 이분의 깃허브를 보았습니다.
그중에 한 프로젝트에서 shadcn-ui를 사용하고 계셨고, 저랑 다른 점을 발견했습니다.
바로 shadcn init 과정에서 css 변수를 추가할거냐는 물음에 저는 yes를, 저분은 아마 no를 선택하신거같았습니다 (저 분 프로젝트 globals.css를 보고 추정)
그래서 저도 위의 옵션을 no로 하니 같은 버그가 발생하였습니다.
해결해보기
우선 이 문제는 init 과정에서 발생한 문제로 shadcn을 사용하는 파일에서는 수정이 불가능하다고 판단하였습니다.
그래서 shadcn 레포를 포크한 후 코드들을 살펴봤습니다.
또한 무작정 모든 코드를 살펴본것이 아닌, 위의 이슈 글에서도 언급되어있지만, 이미 비슷한 이슈 - 해결에 관한 글이 있었습니다
저기서 많은 이야기가 나왔지만, 핵심은 "transformCssVars" 이 부분이 문제라는 점을 알수있었습니다.
그래서 포크한 파일들에서 해당 부분을 찾아봤습니다.
결과적으로 "utils/transformers/transform-csss-vars.ts"에서 "applyColorMapping"이라는 함수가 css 변수를 변환해준다는 것을 알았고, 이 부분을 살펴보았습니다.
문제 코드
if (input.includes(” border ”)) {
input = input.replace(” border ‘, ’ border border-border ”)
}
위의 코드에서 알수있듯이 "border"에 대한 특별한 처리가 이루어지고있었습니다.
뱐환하려는 tailwind에서 "border가 있으면 "border boder-boder"로 바꾸라는 분기 처리였습니다.
이제 문제가 되는 shadcn 컴포넌트("checkbox")의 tailwind 코드를 보았습니다.
"peer h-4 w-4 shrink-0 rounded-sm border border-primary ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground",
여기 집중한 부분은 "border boder-primary"였습니다.
다시 위의 if문으로 돌아가서, 위의 checkbox 코드를 넣고 변환한다고 가정해보면 아래처럼 나올것입니다 (border 부분만)
"border border-boder boder-primary"
이러면 "applyColorMapping" 함수에서 boder에 대한 처리를 두 번하게 됩니다 "boder-boder" -> "boder-xxx" / "boder-primary" -> "border-yyy"
만약 이 "boder-xxx"와 "boder-yyy"가 겹치면 "applyColorMapping"의 로직중에 중복제거 코드에 의해서 문제가 발생하지 않지만 (실제로 input의 경우도 boder boder-input이 있지만, boder-input과 boder-boder는 같은 tailwind로 변환되어 문제가 없습니다)
"border-primary"의 경우는 "neutral-900"으로, "border-boder"는 "neutral-200"으로 변환됩니다 (neutral 테마에 light 기준)
따라서 중복제거가 되지 않고 결과적으로는 아래처럼 변환됩니다
"border-neutral-200 border-neutral-900" ...
그러면 이제 해결을 해야하는데, 제가 생각한 해결법은 아래와 같았습니다.
단순히 "boder-primary"는 저 if문을 안통하게 하면 되겠다
if (input.includes(" border ") && !input.includes("border-primary")) {
input = input.replace(" border ", " border border-border ")
}
이를 기반으로 테스트를 돌려봤습니다
import { describe, expect, it } from "vitest"
import { applyColorMapping } from "../utils/transformers/transform-css-vars"
import neutral from "./neutral.json"
describe("applyColorMapping transformation", () => {
const realMapping = neutral.inlineColors
it("should correctly transform class names with color mapping", () => {
const input =
"peer h-4 w-4 shrink-0 rounded-sm border border-primary ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground"
const expectedOutput =
"peer h-4 w-4 shrink-0 rounded-sm border border-neutral-900 ring-offset-white focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-neutral-400 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-neutral-900 data-[state=checked]:text-neutral-50 dark:border-neutral-50 dark:ring-offset-neutral-950 dark:focus-visible:ring-neutral-800 dark:data-[state=checked]:bg-neutral-50 dark:data-[state=checked]:text-neutral-900"
const result = applyColorMapping(input, realMapping)
expect(result).toBe(expectedOutput)
})
})
테스트를 통과하는 결론이 나왔습니다.
물론 위의 해결책이 100% 해결책이 아닐수 있고, 틀린 해결책일수도있지만, 문제의 원인이 될수있는 부분을 찾았다는 거에서 의미를 두고싶습니다
'기타' 카테고리의 다른 글
[Project_react-router-file-routing] 01 - 프로젝트 구성하기 (0) | 2024.10.09 |
---|---|
[radix-ui] radix-ui 깃허브에 올라온 버그 이슈 수정해보기 (0) | 2024.09.19 |
[기타] 네이버 카페 페이지 이동 시 url에 반영하기 (0) | 2024.08.24 |
[Frontend] 요구사항에 따른 디자인 시스템 설계하기 (0) | 2023.07.15 |